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

# Run and synchronise workspaces

> Run an exact local checkout remotely and synchronise Git and explicit extra-file layers.

# Run and synchronise workspaces

Workspace transfer and repository authority are separate:

* **Workspace source** is the exact local checkout or linked worktree transferred into the sandbox.
* **Repository authority** is the server-verified GitHub repository against which brokered provider credentials and repository-scoped policy may be used.

You can upload and test a workspace without GitHub authorisation. Pushing a branch, creating a pull request, or using repository-scoped capabilities requires a verified repository binding.

## `aient sandbox run`

Create a sandbox, optionally transfer a workspace or upload, run one command, and delete the sandbox:

```sh theme={"theme":{"light":"github-light","dark":"github-dark"}}
aient sandbox run --environment development -- pnpm test
```

With `--environment`, `--workspace` defaults to the current directory. With `--workspace`, the remote directory defaults to `/workspace/repo`, and the command runs there unless `--workdir` overrides it.

Use exact argv after `--`:

```sh theme={"theme":{"light":"github-light","dark":"github-dark"}}
aient sandbox run --environment development -- go test ./...
```

Use an explicit shell only when shell syntax is required:

```sh theme={"theme":{"light":"github-light","dark":"github-dark"}}
aient sandbox run --environment development \
  --shell 'pnpm lint && pnpm test'
```

Or read the shell body from standard input:

```sh theme={"theme":{"light":"github-light","dark":"github-dark"}}
printf '%s\n' 'pnpm lint && pnpm test' |
  aient sandbox run --environment development --stdin
```

### Workspace and authority flags

| Flag                         | Meaning                                                                                                                             |
| ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| `--environment SLUG_OR_ID`   | Select an authorised customer development environment.                                                                              |
| `--workspace PATH`           | Synchronise a local Git checkout or linked worktree.                                                                                |
| `--repository OWNER/NAME`    | Explicit repository selector for disambiguation and provider access.                                                                |
| `--include GLOB`             | Add an untracked or ignored repository-relative file layer. Repeatable.                                                             |
| `--exclude GLOB`             | Narrow the explicit non-Git layer selected by at least one `--include`. Repeatable.                                                 |
| `--remote-dir ABSOLUTE_PATH` | Select a replaceable remote child directory for Git activation, such as `/workspace/repo`; never use the mounted `/workspace` root. |

Repository candidates are inferred from sanitised `origin` and `upstream` remotes when possible. Embedded remote credentials are not transmitted or displayed. If exactly one authorised repository matches, Aient binds it automatically. If none match, ordinary offload may continue without GitHub access. Use `--repository` when candidates are ambiguous.

Changing a local remote cannot grant repository access. Every provider operation is re-authorised against the authenticated organisation, active GitHub App installation, and current repository permissions.

### Command and lifecycle flags

| Flag                      | Meaning                                                 |
| ------------------------- | ------------------------------------------------------- |
| `--workdir ABSOLUTE_PATH` | Remote working directory.                               |
| `--env KEY=VALUE`         | Non-secret environment value. Repeatable.               |
| `--shell COMMAND`         | Run an explicit remote shell command instead of argv.   |
| `--stdin`                 | Read the explicit shell command from standard input.    |
| `--keep`                  | Retain the created sandbox after completion or failure. |
| `--lease-seconds N`       | Requested sandbox lease. Default `7200`.                |
| `--name NAME`             | Requested sandbox name.                                 |
| `--metadata KEY=VALUE`    | Non-secret control-plane metadata entry. Repeatable.    |
| `--download REMOTE=LOCAL` | Download an explicit file before cleanup. Repeatable.   |

`--upload PATH` uploads a non-Git file or directory instead of synchronising Git state. It excludes `.git` and `node_modules` by default. Do not combine `--upload` and `--workspace`.

`--env` and `--metadata` are non-secret inputs. Metadata is ordinary control-plane state: never put tokens, credentials, or sensitive values in it. It cannot override server-owned organisation, actor, environment, or repository identity.

Environment and GitHub credentials are injected only into an authorised sandbox process. Raw credentials are not returned as OAuth, profile, operation-result, metadata, or workspace-revision fields, and generic file APIs do not project mounted secrets. The CLI does not retain normal command output. An authorised child can nevertheless deliberately print or copy a mounted secret; stdout and stderr are returned verbatim to the connected caller, child-created files can contain those bytes, and either may be captured by its terminal or agent transcript. Avoid `env`, `printenv`, shell tracing, or echoing `GH_TOKEN`.

<Note>
  `sandbox run` is buffered. It is convenient for bounded commands, but it does not provide durable detach or output replay. For long commands whose live progress matters, retain a sandbox and use `sandbox exec`.
</Note>

## `aient sandbox sync`

Synchronise exact local Git state into an existing sandbox without an environment binding:

```sh theme={"theme":{"light":"github-light","dark":"github-dark"}}
aient sandbox sync laptop-offload .
```

The default remote workspace is `/workspace/repo`. In 0.7.0, `sync` cannot carry the environment and repository selectors needed to reopen an environment-bound customer sandbox created by `run --keep`. Start a fresh `run --keep` to transfer changed customer workspace state.

```sh theme={"theme":{"light":"github-light","dark":"github-dark"}}
aient sandbox sync laptop-offload . \
  --include 'fixtures/local-only/**' \
  --exclude '**/*.generated' \
  --remote-dir /workspace/repo
```

The synchronised state includes the selected worktree's exact HEAD, index, tracked changes, and selected explicit extra files. Include and exclude globs use repository-relative `/` separators and support `*`, `**`, and `?`.

Excludes filter only the explicit non-Git layer and are valid only when the same command has at least one `--include`. They cannot remove tracked Git state. This dependency applies to Git workspace synchronisation; raw `--upload` and `files put --exclude` have their own file-transfer filters.

Git activation atomically replaces the destination directory. `--remote-dir` must therefore name a replaceable child on the workspace filesystem, such as `/workspace/repo` or `/workspace/alternate-repo`, never the mounted `/workspace` root itself. Raw upload may target `/workspace` because it does not use Git-directory activation.

### Atomic activation and the workspace fence

Aient constructs and verifies a candidate before activating it as `/workspace/repo`. Activation replaces the live child on the same filesystem while holding the exclusive workspace fence; the `/workspace` mount point itself is not replaced.

`sandbox exec`, `sandbox shell`, and workspace reads hold the shared fence. A sync waits before activation rather than replacing the live tree under an admitted command. Direct file operations currently fail with a busy response instead of waiting.

Do not start a second workspace mutation while a sync is active. Wait for the real terminal prefix:

```text theme={"theme":{"light":"github-light","dark":"github-dark"}}
Synchronized Git HEAD 0123456789ab to sandbox-name:/workspace/repo
```

When an explicit non-Git layer is present, the CLI prints a second `Synchronized N explicit path(s) ...` line.

Partial transfer progress is not completion. If another program invokes the CLI, it must preserve the child process's complete lifecycle result—including a running session handle, final exit status, and terminal output. Completion of an outer wrapper is not evidence that the CLI child has exited.

For a large snapshot, increase the request budget:

```sh theme={"theme":{"light":"github-light","dark":"github-dark"}}
aient --timeout 20m --verbose sandbox sync laptop-offload .
```

`--verbose` prints safe request correlation and detailed progress; it does not print credentials.
