> ## Documentation Index
> Fetch the complete documentation index at: https://docs.reasonos.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Adopt an existing repo

> Run rbs in any repo with zero config — run/build/test detect the project type automatically, and rbs adopt materializes the same config as editable files

rbs works in a repository that has never heard of it. In a directory with
no `WORKSPACE.rbs`, the everyday commands detect the project type
themselves and run against a synthesized workspace — and `rbs adopt`
materializes that same config as real files when you want to start editing
it.

## Zero config: just run it

```bash theme={null}
cd my-existing-service   # a plain Go / Node / Python repo
rbs run                  # ⚡ detects the stack, builds, runs the app
rbs build                # builds everything it synthesized
rbs test                 # runs the detected test targets
```

Detection fingerprints the project (a `go.mod`, a `package.json`, a
`requirements.txt`, …) and generates config under `.rbs/zero-config/` —
rbs-owned state, never your checkout; rbs even adds `.rbs/` to
`.git/info/exclude` so `git status` stays clean. Bare `rbs run` runs the
detected default target. Run the commands from a subdirectory and rbs
detects at the enclosing git root. `rbs query` and `rbs graph` show the
synthesized targets too, and agents running on the branch server see the
same graph.

Opening a non-rbs repo in the ReasonOS editor shows the same thing as a
slim banner: *"Zero-config: detected go — build, run and test already
work."* Its **Adopt** button writes the exact config zero-config has been
executing into the repo — the same files `rbs adopt` produces.

## Adopt: materialize the config

`rbs adopt` writes the `WORKSPACE.rbs` and `BUILD.rbs` a person familiar
with rbs would have written by hand — toolchain pinned from your version
files, dependencies declared from your manifest, a runnable binary target,
test targets when tests exist. It is byte-identical to what zero-config
mode was executing, so nothing changes behavior — the config just becomes
yours to edit.

```bash theme={null}
cd my-existing-service
rbs adopt

# then it's a normal rbs workspace:
rbs build :all
rbs run //:my_service
rbs test
```

The generated files are yours: they carry a "review and edit" header, and
`rbs adopt` never rewrites them afterwards. There is no hidden
configuration layer — what adopt generates is exactly the config you edit
as the project grows.

## Command forms

```bash theme={null}
rbs adopt                     # adopt the current directory
rbs adopt path/to/repo        # adopt another directory
rbs adopt --list              # show every matching converter, ranked
rbs adopt --dry-run           # print the generated files without writing
rbs adopt --converter python  # override detection ranking
rbs adopt --force             # overwrite previously generated files
```

Adopt refuses a directory that already contains a `WORKSPACE.rbs`, and
refuses to nest a workspace inside an existing one — add a `BUILD.rbs`
package to the enclosing workspace instead.

## What gets detected

| Converter   | Fingerprints                                                                       | Generated config                                                                                                                                                                                                                                                                                                             |
| ----------- | ---------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **go**      | `go.mod`, `go.work`, `main.go`                                                     | `go_toolchain` matched to the `go.mod` directive; `go_binary` for the root package or one per `cmd/*`; `go_test` over `./...` when `*_test.go` exist; an `oci_image` so `rbs build //:image` produces a container image                                                                                                      |
| **java**    | `pom.xml`, `build.gradle`, `build.gradle.kts`, `gradlew`                           | `java_toolchain` from `java.version`/`maven.compiler.*`/`sourceCompatibility` (any JDK major works); `java_repository` per declared Maven/Gradle dependency; `java_library` + `java_binary` (main class auto-detected, `@SpringBootApplication` preferred); `java_test` with JUnit auto-included when `src/test/java` exists |
| **python**  | `pyproject.toml`, `requirements.txt`, `Pipfile`, `manage.py`, `main.py`/`app.py`/… | `python_toolchain` from `.python-version` or `runtime.txt`; `py_repository` per pinned requirement; `py_binary` (Django gets `manage.py runserver`); `py_test` when tests exist                                                                                                                                              |
| **kotlin**  | `*.kt` sources (usually Gradle)                                                    | `java_toolchain` + `kotlin_toolchain`; `kotlin_repository` per Gradle dependency; `kotlin_binary` with the detected top-level main; `kotlin_test`                                                                                                                                                                            |
| **node**    | `package.json`                                                                     | `nodejs_toolchain` (an exact `engines.node` pin is honored); `nodejs_repository` per production dependency; `nodejs_binary` from `scripts.start`, the `main` field, or `server`/`index`/`app` in `.js` or `.ts`; `vitest_test` when vitest and test files are present                                                        |
| **vite**    | `vite.config.*`                                                                    | `nodejs_toolchain`; `nodejs_repository` deps; `vite_app` for the detected `src/main.*` entry; `vitest_test` — takes precedence over plain node for Vite apps                                                                                                                                                                 |
| **dotnet**  | `*.csproj`                                                                         | `dotnet_toolchain` (SDK from `<TargetFramework>`); `dotnet_binary` with sources plus the project file                                                                                                                                                                                                                        |
| **c / c++** | `*.c` / `*.cpp` sources                                                            | hermetic zig-based `c_toolchain`/`cxx_toolchain`; `c_binary`/`cxx_binary` (CMake/meson/Makefile definitions are reported, not parsed)                                                                                                                                                                                        |

## Container image out of the box

For Go projects the generated config includes a container image: a
cross-compiled linux binary on a minimal `scratch` base. Building it needs
no Docker daemon — rbs assembles the image itself:

```bash theme={null}
rbs build //:image
docker load < .rbs/bin/<host-platform>/image/image.tar
docker run <app>:latest
```

The generated file explains how to switch the base image (for CA
certificates or a shell) and how to upgrade to a multi-arch image index.
Node and Python images aren't generated yet — they need a linux-native
runtime inside the image; the converter tells you so during adopt.

When a repo matches several converters, ranking follows language priority
first (a Go service with a docs `package.json` adopts as Go), then
detection confidence. Anything a converter can't translate — an unpinned
requirement, a `file:` dependency, TypeScript builds — is reported as a
note during adopt, never silently dropped.

## Extending detection

Converters are Starlark, not compiled-in logic. Rule authors register one
with `native.define_project_converter(name, detect, convert, priority)`,
and detection is extensible without rebuilding rbs — point at an external
converter pack:

```bash theme={null}
rbs adopt --rules https://git.example/acme-converters@v1.0.0
# or, for every adopt and zero-config run on this machine/node:
export RBS_CONVERTER_RULES=https://git.example/acme-converters@v1.0.0
```

A pack is a git repo (fetched pinned to the ref, same as `rbs ext`) or a
local directory whose `convert.rbs` modules register converters. A pack
converter that re-declares an embedded name overrides it. See
[Custom rules](/reference/custom-rules) for the rule-authoring surface.
