---
name: cachely-remote-cache
description: Connect an Nx, Lerna, Turborepo, Gradle, or Bazel build to the Cachely remote build cache so tasks are cached once and reused across machines and CI. Use when setting up remote caching, speeding up CI, or sharing a build cache between developers for any of these tools.
---

# Cachely remote cache

Cachely is a hosted remote build cache. Point your build tool at it with a
workspace token and cacheable tasks are stored once and replayed everywhere.

## Inspect the repository

Identify the build tool and pinned version, cacheable tasks, declared outputs,
and CI workflow before editing. Preserve the existing package manager and
workflow. Do not introduce a new build tool to configure caching. Read the
current guide for the detected tool:

- Nx: https://cachely.dev/docs/nx (native integration requires Nx 20.8 or later)
- Lerna: https://cachely.dev/docs/lerna (check its resolved Nx version)
- Turborepo: https://cachely.dev/docs/turborepo
- Gradle: https://cachely.dev/docs/gradle
- Bazel: https://cachely.dev/docs/bazel

Explain each change. Do not send repository content, paths, or findings to
Cachely. Normal builds upload task outputs to the remote cache; inspect the
chosen task's outputs for secrets before enabling uploads.

## Provision access with MCP when available

Prefer the Cachely MCP tools when connected. If the agent supports remote MCP
with OAuth, help the user add `https://app.cachely.dev/mcp` and complete the
browser sign-in. Connection guide: https://cachely.dev/docs/mcp.

Explain that `create_token` returns the raw credential to the coding agent,
where the agent provider may process it under its own terms. Offer manual
credential entry even when MCP is connected. If the user chooses it, skip
`create_token`, prepare placeholders, and have the user enter the token
directly into the ignored file or CI secret store. Do not read that file or
echo its contents into tool output; verification can run the build command
without displaying credentials.

1. Call `list_workspaces` and reuse the appropriate workspace. Ask the user to
   choose when the intended account or workspace is ambiguous. Otherwise call
   `create_workspace`, named after the repository.
2. Call `create_token` for the selected workspace. Trusted CI uses permissions
   `read,write` and usage `ci`; developer machines use permissions `read` and
   usage `developer`. Use a separate read-only token or no credentials for
   untrusted builds. Prefer an expiry and one token per consumer; do not retry
   a successful creation and produce duplicate credentials.
3. Call `setup_instructions` for the detected tool and desired format (`dotenv`,
   `shell`, or `github`). It returns placeholder-token config and the paths to
   gitignore; inject the real token only into the named secret destination.

If MCP is unavailable, guide the user through creating a workspace and token
in https://app.cachely.dev, then use the tool-specific docs. Do not ask the user
to paste a raw token into chat: have them enter it directly into a gitignored
local file or CI secret store. Continue configuration with placeholders until
credentials are available, and clearly report any blocked steps.

Keep every raw token secret: never commit it, print it, or repeat it in chat.
Verify the secret file is gitignored before writing it. Committed config must
read credentials from the environment or a secret file. Ensure the existing
command actually loads those variables; a `.env.local` file alone is not proof.

## Persist local setup and plan the first upload

Reuse the repository's existing environment loader or native user config.
Wire credentials into the normal build command across sessions; shell exports
alone are temporary. Do not add a dependency or change global shell config
without asking. Start a fresh terminal with the session's cache variables
unset and run the normal command to verify that the saved configuration loads.

An empty workspace needs a trusted writer before a read-only developer can
restore anything. Identify the existing trusted CI job that will populate it.
Ask before changing CI configuration or its secret store; explain the proposed
change and keep the developer token read-only. If no trusted writer is
available, finish the local configuration and report remote verification as
blocked with the exact next step. Never quietly give the laptop write access
or claim a successful local build proves remote caching.

The cache host is `https://remote.cachely.dev`. Each tool speaks its own native
remote-cache protocol - you do not install a Cachely plugin.

## Nx and Lerna (`/v1/cache`)

Set these environment variables (Nx self-hosted remote cache):

```sh
export NX_SELF_HOSTED_REMOTE_CACHE_SERVER=https://remote.cachely.dev
export NX_SELF_HOSTED_REMOTE_CACHE_ACCESS_TOKEN=<token>
```

Run tasks as usual (`nx build`, `nx affected -t build`). Cache hits are restored
instead of re-executing.

## Turborepo (`/v8/artifacts`)

```sh
export TURBO_API=https://remote.cachely.dev
export TURBO_TOKEN=<token>
export TURBO_TEAM=<any-slug>   # required by turbo; the token identifies the workspace
```

Then `turbo run build`. `TURBO_TEAM` can be any string; Cachely resolves the
workspace from the token, not the slug.

- turbo does not read `.env` files for its own settings. If the variables live in
  a gitignored `.env.local`, load them per run:
  `npx dotenv-cli -e .env.local -- turbo run build`.
- turbo reads the token only from `TURBO_TOKEN`; there is no `TURBO_TOKEN_READ`.
  For read-only access, mint a read-only token and put it in `TURBO_TOKEN`.
- If turbo warns that an artifact "was too large to upload within the timeout",
  raise `remoteCache.uploadTimeout` (seconds, default 60) in `turbo.json` and
  check the task's `outputs` exclude caches such as `.next/cache`.

## Gradle (`/v1/gradle`)

In `settings.gradle(.kts)`:

```kotlin
buildCache {
    remote<HttpBuildCache> {
        url = uri("https://remote.cachely.dev")
        isEnabled = !System.getenv("GRADLE_CACHE_TOKEN").isNullOrBlank()
        isPush = System.getenv("GRADLE_CACHE_PUSH") == "true"
        credentials {
            username = ""          // ignored; any value works
            password = System.getenv("GRADLE_CACHE_TOKEN")
        }
    }
}
```

Gradle's HTTP build cache uses HTTP Basic; Cachely takes the token from the
Basic password. Gradle appends the cache key to the URL itself.
Enable caching with `org.gradle.caching=true` or `--build-cache`, and set
`GRADLE_CACHE_PUSH=true` only for trusted writers.

## Bazel (`/v1/bazel`)

In the committed `.bazelrc` (the token goes in a gitignored `user.bazelrc`):

```
build --remote_cache=https://remote.cachely.dev

# Read the cache everywhere, upload from trusted CI only.
build --remote_upload_local_results=false
build:cachely-ci --remote_upload_local_results=true

try-import %workspace%/user.bazelrc
```

```
# user.bazelrc (gitignored - carries the raw token)
build --remote_header="Authorization=Bearer <token>"
```

Bazel uploads locally produced action results by default. Cachely recommends
turning that off until builds are demonstrably hermetic: a non-reproducible
machine that uploads can poison an action result that every other machine then
replays. Trusted CI opts back in per invocation with
`bazel build //... --config=cachely-ci`.

`.bazelrc` options apply in order and the command line overrides them, so the
flag is guidance. The enforcement is the token: give trusted CI a read/write
token (one per pipeline) and give developer machines, pull requests, and forks a
read-only token. Cachely rejects writes from a read-only token with `403` on
both `/ac/` and `/cas/`.

## Verify a real remote cache hit

Do not declare setup complete from a successful build or a faster second run.
Choose a cacheable task with observable generated outputs and unchanged inputs.

1. Populate the remote cache from trusted CI with its read-write token, or use
   an existing trusted cache entry. Keep developer credentials read-only.
2. Before replay, exclude the tool's local task cache and remove only that
   task's confirmed generated outputs. Preserve source files and user work;
   never blindly delete a directory inferred from its name.
3. Rerun the same task with the same source, dependencies, tool version, and
   environment, with remote caching enabled. Do not use force, skip-cache, or
   rerun flags that bypass cache reads.
4. Confirm both a remote hit and restored output files without task execution.
   Use the tool-specific evidence below. Restore temporary verification config.

| Tool       | Exclude local reuse and collect evidence                                                                                                                                                                                                                                                                                              |
| ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Nx / Lerna | Use `nx reset --only-cache` with the repository's resolved Nx CLI before replay, remove declared task outputs, and confirm `[remote cache]` plus restored outputs. Lerna uses the same Nx task cache.                                                                                                                                 |
| Turborepo  | Exclude the configured local cache (including a custom `cacheDir`), remove declared outputs, and run with `--summarize`. Inspect the task's summary for a remote hit, not a local hit, and verify restored outputs.                                                                                                                   |
| Gradle     | Temporarily disable the local build cache with `local { isEnabled = false }` (Kotlin DSL) or `local { enabled = false }` (Groovy DSL). Remove the task outputs and replay with `--build-cache --info`; require `FROM-CACHE` plus output restoration with the local cache excluded. `clean` alone does not clear Gradle's build cache. |
| Bazel      | Replay from a fresh output base with the same build inputs and read-only credentials. Check Bazel's reported `remote cache hit` actions and restored outputs; an up-to-date action or local disk-cache hit is insufficient. Exclude any configured disk cache as well.                                                                |

A warm local cache, `UP-TO-DATE`, `FROM-CACHE` without excluding local reuse,
or aggregate dashboard counters alone do not prove this task restored remotely.
If a trusted writer, credentials, or a safe replay environment is unavailable,
report setup as **unverified**, explain the blocker, and provide the exact
remaining verification steps. Finish with the changes and observed evidence;
do not include raw tokens, private paths, or task output bodies in the summary.

## Notes

- Tokens are scoped to one workspace and subject to that workspace's plan quota.
  When a workspace is over quota, writes are silently skipped and reads miss, so
  builds still succeed - they just re-run the task.
- To authenticate an autonomous agent (rather than a build tool), see the
  `cachely-authentication` skill and https://cachely.dev/auth.md.
