# Build on Limrun
URL: /docs/bazel/build-on-limrun
LLM index: /llms.txt
Description: Run a Bazel workspace's iOS and Android actions on Limrun, with one cache shared across your organization.

# Build on Limrun

Point a Bazel workspace at Limrun's build plane and keep running `bazel build` where you already do: a laptop, a CI runner, or a coding agent's machine. Apple actions run on Limrun's Macs, Android actions run on Limrun's Linux workers, and every build in your organization reads and writes the same remote cache, so a target one machine built comes back as a cache hit on the next.

## Before you start

You need:

- The `lim` CLI, version 0.44.0 or later, installed from npm. The npm package also installs `lim-bazel-credentials`, the credential helper Bazel calls for the build plane.
- An API key. Run `lim login` on your machine, or set `LIM_API_KEY` where Bazel runs, such as in CI. The [Quickstart](/docs/quickstart) covers both.
- A Bazel workspace on Bazel 8 or later, with `rules_apple` or `rules_android` in its root `MODULE.bazel`.

Install or update the CLI:

```bash
npm install -g lim
```

<Note>
The standalone tarball and DotSlash builds of `lim` do not put `lim-bazel-credentials` on your `PATH`, so Bazel cannot authenticate to the build plane with them. Install from npm on any machine that runs Bazel builds.
</Note>

## Set up the workspace

Run the setup command inside the workspace:

```bash
lim bazel setup
```

It writes a `.limrun/` directory with a `--config=limrun` Bazel configuration and adds a `try-import` for it to your `.bazelrc`. `.limrun/` carries its own `.gitignore`, so it stays out of version control, and it holds no secrets: Bazel asks `lim-bazel-credentials` for a short-lived token for each build.

Setup picks the closest region that runs a build plane. To use a specific region instead, pass it by name:

```bash
lim bazel setup --region eu-north1
```

Run `lim bazel setup` again after you upgrade the CLI, or when the workspace starts using Apple or Android rules. It rewrites `.limrun/` in place.

### Android workspaces

Android actions on Linux workers need a few modules in the root `MODULE.bazel`: `rules_cc`, `rules_java`, `protobuf`, and `hermetic_android_toolchains` with its Android SDK. Setup prints the lines the module is missing and asks before it adds them. To add them without the prompt, for example in a script:

```bash
lim bazel setup --yes
```

Setup never edits `MODULE.bazel` without your answer or `--yes`. Without a terminal and without `--yes`, it stops and prints the lines to add yourself.

If your `.bazelrc` already sets `--java_runtime_version`, setup keeps your choice. Otherwise the Limrun configuration uses `remotejdk_17`.

## Build

Build any target with the `limrun` config:

```bash
bazel build --config=limrun //your:target
```

Build actions run remotely: compiles, links, resource processing, and signing run on the build plane, and Bazel downloads only the top-level outputs, such as the `.ipa` or `.apk`, to your machine. Without `--config=limrun`, Bazel builds the way it did before.

To add your own flags to the Limrun build path, put them in `user.limrun.bazelrc` at the workspace root. The generated configuration imports it last, so your `build:limrun --...` lines win and survive the next `lim bazel setup`.

## Build in CI

In CI, install the CLI from npm and set `LIM_API_KEY` as a secret. Run setup with `--yes` if the workspace is Android, then build:

```bash
npm install -g lim
lim bazel setup --yes
bazel build --config=limrun //your:target
```

The credential helper reads `LIM_API_KEY` from the environment Bazel runs in. A key passed to `lim bazel setup` with `--api-key` reaches only that command, so set `LIM_API_KEY` instead.

## See your builds

The Bazel page in the [console](https://console.limrun.com/bazel) lists your organization's builds from every region. Select a build to see its output, which streams live while it runs, and how many of its actions came from the remote cache. The Overview tab summarizes the last seven days: builds, the remote cache hit rate, actions that ran on Limrun, and the targets you build most.

## Limits and behavior

- **Each region keeps its own cache.** A build in a region it has not run in before starts with an empty cache there.
- **Bazel 9 shares external repositories too.** On Bazel 9 and later, the configuration also stores downloaded external repositories in the remote cache, so machines after the first fetch them from Limrun instead of the internet.
- **Setup finds the workspace root itself.** Run it from any directory inside the workspace; it walks up to the directory with `MODULE.bazel` and writes `.limrun/` there.

## Next steps

<Columns cols={2}>
  <Card title="Build with Bazel (legacy)" icon="zap" href="/docs/ios/build-with-bazel">
    The legacy `lim xcode rbe` path: a private Xcode sandbox per workspace, with simulator installs and asset uploads.
  </Card>
  <Card title="CLI reference" icon="terminal" href="/docs/reference/cli">
    Every `lim` command and its flags.
  </Card>
</Columns>