> ## 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.

# Toolchains

> Hermetic, rbs-managed language toolchains: declare a version in your WORKSPACE and rbs downloads, caches, and shares it across workspaces.

rbs manages language toolchains itself. Declare the version you want in
`WORKSPACE.rbs`, and rbs downloads the official distribution, verifies it, and builds
with it — **no system installation of Go, Node.js, or Python required**, and no drift
between what's on a developer's machine and what the build uses. Two machines with
the same workspace build with byte-identical toolchains.

## Declaring a toolchain

Each language ships a one-liner for `WORKSPACE.rbs`:

<Tabs>
  <Tab title="Go">
    ```python theme={null}
    load("@rbs//go/toolchain.rbs", "go_toolchain")

    go_toolchain(
        name = "go",
        version = "1.24.3",
    )
    ```
  </Tab>

  <Tab title="Node.js">
    ```python theme={null}
    load("@rbs//nodejs/toolchain.rbs", "nodejs_toolchain")

    nodejs_toolchain(
        name = "nodejs",
        version = "22.15.1",
    )
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    load("@rbs//python/toolchain.rbs", "python_toolchain")

    python_toolchain(
        name = "python3",
        version = "3.12",
    )
    ```
  </Tab>
</Tabs>

That single call downloads the toolchain for your platform on first build and
registers it for the workspace — every `go_binary`, `nodejs_binary`, `py_binary`, and
related rule then uses it automatically.

Versions come from a curated registry inside the rules; if you ask for a version the
registry doesn't know, the load fails immediately and lists the available versions.
Python versions are selected by `major.minor` (`"3.11"`, `"3.12"`, `"3.13"`) and
resolve to hermetic standalone CPython builds; patch-level strings like `"3.12.7"`
are accepted as aliases.

When you build for a different platform than your host (for example a Linux
container image built from macOS), rbs also downloads the *host* toolchain so
build-time tools (like the TypeScript compiler) still run locally — you don't
have to declare anything extra.

## Where toolchains live

Toolchains are stored **once per user**, not once per workspace:

```text theme={null}
~/.cache/rbs/toolchains/<name>/<platform>-<digest>/
```

(The location follows `RBS_CACHE_DIR` if you've relocated the
[shared cache](/build/caching).)

Entries are keyed by platform and content digest, so:

* Two workspaces on the same toolchain version **share one copy** — the second
  workspace links it instantly instead of re-downloading.
* Two workspaces pinned to **different versions coexist** without conflict; bumping a
  version in one workspace never disturbs another.

Inside a workspace, `.rbs/toolchains/<platform>/<name>` is a link into that store.
`rbs cache stats` reports the store's total size under "Toolchains", and
`rbs cache gc` ages out toolchains that haven't been used recently — a swept
toolchain reinstalls itself automatically on the next build.

<Note>
  On Windows, toolchains are installed per-workspace under `.rbs/toolchains` instead
  of being linked into the shared store.
</Note>

## Hermeticity

Builds use the downloaded toolchain exclusively — rules invoke the toolchain's own
binaries, never whatever happens to be on `PATH`. Go builds, for example, run with
module fetching disabled during compilation, so the compiler can't quietly reach the
network mid-build. The result: a workspace builds the same way on a fresh machine as
it does on yours.

## Custom tools

Beyond language toolchains, you can pull in any standalone tool hermetically with
the same machinery — pin the URL and checksum in `WORKSPACE.rbs`:

```python theme={null}
native.http_file(
    name = "jq_tool",
    url = "https://github.com/jqlang/jq/releases/download/jq-1.7.1/jq-macos-arm64",
    sha256 = "0bbe619e663e0de2c550be2fe0d240d076799d6f8a652b70fa04aea8a8362e8a",
    executable = True,
    output_name = "jq",
)
```

`native.http_archive` does the same for archives (with `strip_prefix` to peel off a
top-level directory), and `native.tool_binary` wraps a downloaded tool so build rules
can invoke it.

<Tip>
  Always pin a `sha256` and a specific release URL. A checksum makes the download
  verifiable; a "latest" URL makes the build unreproducible.
</Tip>
