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

# Launch a Private Repository

> Check that your workspace can read a private repository, then launch from a pinned commit.

**Before You Begin:** A private GitHub repository and a catalog agent you can launch.

A launch clones a private repository with a token BoxRouter mints for that one checkout. You never
create a personal access token. The repository only has to be linked to your workspace through the
GitHub App.

## Link the Repository

Follow [Connect GitHub](https://boxrouter.ai/docs/github/connect.md) and link the repository to your workspace. A private
repository can be linked to one workspace at a time; to move it, disconnect GitHub from the old
workspace first.

## Check Access Before You Launch

The check reads the repository the way a launch would and creates nothing.

```python Python theme={"theme":"css-variables"}
import json

from boxrouter import BoxRouter
from boxrouter.models import RepositoryAccess

with BoxRouter() as client:
    access = client.api.launches.check_repository_access("OWNER", "REPO", ref="main")
    if not isinstance(access, RepositoryAccess):
        raise RuntimeError("The access check returned no result")
    print(json.dumps(access.to_dict(), indent=2))
```

```typescript TypeScript theme={"theme":"css-variables"}
import { BoxRouter } from '@boxrouter/sdk';

const client = new BoxRouter();
try {
  const access = await client.api.launches.checkRepositoryAccess({
    path: { owner: 'OWNER', repo: 'REPO' },
    query: { ref: 'main' },
  });
  console.log(JSON.stringify(access, null, 2));
} finally {
  await client.close();
}
```

```bash CLI theme={"theme":"css-variables"}
boxrouter api launches check-repository-access OWNER REPO --ref main
```

A repository the workspace can't read is a `200` with `readable: false` and the refusal's `code`,
`message` and `fix`:

Output

```json theme={"theme":"css-variables"}
{
"repo": "boxrouter/nonexistent-repo",
"readable": false,
"visibility": null,
"sha": null,
"files": null,
"recipe": null,
"code": "code_repository_not_found",
"message": "BoxRouter can't read boxrouter/nonexistent-repo: it doesn't exist, or it's private and not linked to this workspace.",
"fix": "Link boxrouter/nonexistent-repo to this workspace under Integrations, then retry. A repository can be linked to only one workspace at a time; if another workspace has it, disconnect GitHub there first."
}
```

A readable repository returns `visibility`, the `sha` the ref points at, its top-level `files` and the
`recipe` a launch would use. Omit `--ref` to check the default branch.

## Launch a Pinned Commit

Replace `OWNER`, `REPO` and `COMMIT_SHA` with the repository and its full commit SHA:

```python Python theme={"theme":"css-variables"}
from boxrouter import BoxRouter

with BoxRouter() as client:
    with client.sandboxes.launch("codex", repo="OWNER/REPO@COMMIT_SHA") as box:
        print("Sandbox:", box.id)
```

```typescript TypeScript theme={"theme":"css-variables"}
import { BoxRouter } from '@boxrouter/sdk';

await using client = new BoxRouter();
await using box = await client.sandboxes.launch('codex', { repo: 'OWNER/REPO@COMMIT_SHA' });
console.log('Sandbox:', box.id);
```

```bash CLI theme={"theme":"css-variables"}
boxrouter launch codex --repo OWNER/REPO@COMMIT_SHA --rm
```

Launch resolves the ref to a commit before it clones and records that `sha` on the launch operation.
You can use a branch or tag instead; a later launch using a moved branch can select a different commit.

`--repo owner/repo@ref` overrides a catalog agent's code selection. The ref is required; use `@HEAD` for the default branch. `--rm` requests sandbox deletion when you exit. In the SDKs, `repo` is an option, and leaving the sandbox's block requests deletion.

The SDK returns the sandbox without attaching your keyboard, so the examples print the sandbox ID
and leave. The [quickstart](https://boxrouter.ai/docs/launch/quickstart.md) shows how to confirm it is gone.

## What the Clone Token Can Do

BoxRouter mints the token per checkout for that repository alone, with read-only `contents` and
`metadata` access, and uses it only for the clone. The agent never receives a reusable GitHub
credential, so it can't push.

## When Access Fails

| Code | HTTP | Meaning |
| - | - | - |
| `code_repository_not_found` | 404 | The repository doesn't exist or isn't linked to this workspace. |
| `code_repository_not_authorized` | 403 | It is linked, but the GitHub App lost access. Give the App access on GitHub, then retry. |
| `code_ref_not_found` | 404 | The branch, tag or commit doesn't exist. |

Each error carries a `fix`. [Launch your own agent](https://boxrouter.ai/docs/launch/your-own-agent.md#repository-errors) lists
the full messages.

## Next Steps

> [card] [Supply an Agent's Secrets](https://boxrouter.ai/docs/launch/secrets.md)
>
> Pass a model key without committing it.

> [card] [Configure a Launch Manifest](https://boxrouter.ai/docs/launch/manifest.md)
>
> Ship setup and the command with your code.

> [card] [Launch Your Own Agent](https://boxrouter.ai/docs/launch/your-own-agent.md)
>
> A repository, a manifest or an image instead of the catalog.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.