# Architecture overview Source: https://docs.amika.dev/architecture/overview Core Amika concepts and system layout. Amika lets you create VMs and sandboxes on (a) machines you already own, (b) in your existing cloud accounts, or (c) in compute you rent from Amika. We call these VMs and sandboxes "rigs": isolated devboxes for developers or agents. You drive rigs and their agents from the web UI, the open-source `amika` CLI, the TypeScript SDK, or the HTTP API. ## Core concepts * **Rigs**: Isolated VMs with your repos, agent credentials, and services in place. Agents work in `/home/amika/workspace`. A rig can be temporary or persistent. * **Hosts**: Machines you own that run rigs. The `amika-hostd` daemon registers a machine with Amika and runs each rig on it as a local VM with [smolvm](https://smolmachines.com). See [Bring your own compute](/guides/byoc). * **Amika Cloud compute**: When you don't pick a host, Amika runs the rig on Amika's own cloud compute. * **Control plane**: The hosted API and web UI at `app.amika.dev`. It authenticates requests, stores configuration and secrets, provisions rigs, and forwards requests to your hosts. * **Preset environments**: Bundled images (`coder`, `coder-plus-docker`) with common tooling and agent CLIs. See [Presets](/reference/presets). * **Services**: Named network-facing ports with URL schemes, declared in `.amika/config.toml`. See [Services](/reference/services). * **Snapshots**: Captured rig state you can create new rigs from. See [Create a snapshot](/guides/create-a-snapshot). * **Credential discovery**: `amika secret extract` finds local coding-agent credentials so you can push them as Amika secrets. Rigs receive credentials from the control plane, not from your machine. ## Components | Component | Purpose | | - | - | | `amika` | CLI for rigs, hosts, snapshots, services, secrets, and agent messages | | `amika-hostd` | Daemon that turns a machine you own into a host | | `amikad` | Daemon inside each rig that serves SSH connections and tracks injected credentials so snapshots can scrub them | | `@amika/sdk` | TypeScript SDK for the hosted API | ## Package layout The open-source code lives in [gofixpoint/amika](https://github.com/gofixpoint/amika). ```text theme={null} go/cmd/amika # CLI entrypoint go/cmd/amikad # In-rig daemon js/amika-hostd # Host daemon for your own machines sdk/typescript # TypeScript SDK ``` ## State storage The CLI stores local state files in XDG paths by default. See [Storage paths](/reference/storage) for exact locations. # Architecture roadmap Source: https://docs.amika.dev/architecture/roadmap Current capabilities and planned system evolution. Amika is open-sourcing the parts of its codebase that let developers control individual sandboxed agents — the messaging and filesystem layer between the agent and the rig it lives on. You can spin up a rig, put any agent on it, and then use the open-source components to: 1. Message the agent over SSE or WebSockets. 2. Manage the files synced to and from the rig. Beyond that, we're working on: 1. A network proxy for agent security and request/response authorization. 2. A secrets vault so a sandboxed agent can use APIs without directly seeing secrets. The open source runs on any sandbox provider, or you can pair it with the hosted product, which handles the tricky parts of scaling and provisioning rigs and provides extra features for managing fleets of agents, their filesystems, and security. ## Architecture diagrams Amika OSS diagrams: [https://link.excalidraw.com/l/7iUc0S5ODSX/8Eeboz1Tg38](https://link.excalidraw.com/l/7iUc0S5ODSX/8Eeboz1Tg38) ![single rig with direct rig control](https://mintcdn.com/fixpoint/LxvlpE-cz8J2mAls/images/single-sbox-arch.svg?fit=max\&auto=format\&n=LxvlpE-cz8J2mAls\&q=85\&s=a742e7cedafc154ffaaa3a86429c891b) ![multiple rigs with control plane](https://mintcdn.com/fixpoint/LxvlpE-cz8J2mAls/images/multi-sbox-arch.svg?fit=max\&auto=format\&n=LxvlpE-cz8J2mAls\&q=85\&s=7ec578daab707e1df8c473a7dcc619b5) ## Invariants Two properties stay fixed as the system evolves: 1. POSIX remains the primary interface for agents. 2. Filesystem and network access control remain the safety boundary. ## Components ### Open source * **`amika`** — client-side CLI to interact with sandboxed agents. * In **direct mode**, it talks to `amikad` on a rig directly. * In **scalable mode**, it talks to the closed-source Amika Control Plane. * **`amikad`** — daemon that runs on a rig and: * Provisions and controls the rig lifecycle. * Messages agents on the rig. * Copies files in and out of the rig. * Proxies network requests for agent security and authorization. * Keeps secrets in a vault, away from the agents. * **`amikactl`** — CLI that lives on the rig and lets the agent talk to `amikad` to self-control its rig (access secrets, pull remote files, spawn new rigs). ### Closed source * **Amika Control Plane** — API to provision hundreds to thousands of rigs, manage agents across them, enable multiplayer and team-shared rigs, index and store agent sessions, centralize configuration of agent skills/tools/MCP servers, and host a centralized file repo that can be mounted onto rigs. * **Amika Web UI** — the web interface to the Control Plane and sandboxed cloud agents. ## Daemon capabilities The `amikad` daemon is evolving toward four capabilities. ### Agent Messaging Layer *Open source.* HTTP APIs to message any agent on a rig. Supports Claude Code, Codex, OpenCode, Pi, and custom agents via the [Agent Communication Protocol](https://agentcommunicationprotocol.dev/introduction/welcome). * **Current:** request/response messaging, SSE streaming back to the client, session management. * **Planned:** hooks for piping agent chat sessions to your own datastore or to the Amika Control Plane. ### Sandbox Filesystem Layer *Open source: sync from host to rig, and copy data out of a rig to a destination. Closed source (for now): the Filesystem Volume backend and live sync tech.* Mount persistent file volumes onto rigs and version and control the files. Mount parts of a Filesystem Volume to a rig; when the rig terminates, the files persist. * **Current:** * Mount modes: `ro` (read-only), `rw` (read-write, syncs back), `rwcopy` (read-write over a snapshot; writes land in a separate tree, preserving originals). * Batch file materialization — spin up a rig, inject files, run scripts to pull or mutate data, output the resulting filesystem to a persistent volume or another rig. Useful for pulling data out of enterprise systems-of-record, transforming it to be "agent-ready," and handing it to a sandboxed agent. * S3-compatible storage sync that avoids the POSIX gaps typical of FUSE filesystems (for instance, preserving symlinks so `git clone` works). * **In progress:** bidirectional syncing — materialization processes that update a Filesystem Volume stream their changes down into running rigs, and vice versa. Live sync engine and git-like transparent versioning with agent-authored commit messages. * **Planned:** network-mountable filesystem for remote sandbox providers, per-agent mount policies with isolated data views, lazy-loading strategies for faster rig startup. ### Network Proxy *Early design. Open-source status TBD.* Goals for agent control: 1. Run arbitrary scripts to process inbound and outbound network requests and responses, airgapped from the agent's control. 2. Set authorization rules at the network layer for total control over how the agent interacts with external systems. 3. Mutate inbound and outbound traffic to constrain what requests the agent can make, strip sensitive data, and so on. 4. Fully airgap sandboxed agents from sensitive data or secrets, injecting them and stripping them at the network layer. Goals for service exposure: 1. Control which ports and services are exposed from a rig. 2. Control whether services are exposed publicly or behind team auth. The direction is a filter pipeline: inbound redaction and tokenization → constrained-mount file access → outbound validation and approval before write-back. ### Secrets Vault *Early design. Open-source status TBD.* Stores secrets for a rig. Two usage modes: 1. **Fully isolated** — the agent only sees tokenized versions of secrets; the network-proxy layer swaps tokens for real values on outbound requests. Similar to how credit-card payments avoid exposing card numbers to merchants. 2. **Agent-accessible** — optionally gated behind hooks that pause for human approval. Safer than putting credentials in environment variables or directly on the filesystem. # Agent quickstart Source: https://docs.amika.dev/guides/agent-quickstart Instructions for a coding agent to set up and operate Amika. ## Start here Send this prompt to your coding agent: ```markdown theme={null} Follow the instructions in https://docs.amika.dev/guides/agent-quickstart to set up and use Amika. ``` The rest of this page is written for the agent. You do not need to perform its steps yourself. ## Instructions for the agent To set up Amika, first make sure you either: 1. have an Amika API key 2. have installed and logged into the `amika` CLI (use `amika auth status` to check) If you don't have either of the above, Your human can sign up at [https://app.amika.dev/signup](https://app.amika.dev/signup). Have them go through onboarding, and then report back. ### Offer to install the amika-cli skill Do this once the `amika` CLI is installed and `amika auth status` shows you are logged in. If you are working only with an API key and the CLI is not installed, skip this step. The amika-cli skill teaches coding agents the CLI's commands, which commands block on interactive prompts, and how to get JSON output. `amika skill install` installs the copy of the skill embedded in the CLI binary, so the skill matches the installed CLI version. 1. Ask your human these two questions, then stop and wait for their answers: 1. Install the amika-cli skill locally (this repo or project only), globally (every project on this machine), or not at all? 2. Which agents should get it: Claude Code, Codex, Cursor, or several of them? Suggest the agent you are as the default. If you are none of these, ask without a default. 2. If they chose not at all, skip the rest of this step. 3. Otherwise, run `amika skill install` with the flags that match their answers: * `--local` for this repo or project only, or `--global` for every project. Pass exactly one. * `--agents` with a comma-separated list of `claude`, `codex`, and `cursor`. For example, to install the skill for Claude Code and Codex in every project: ```bash theme={null} amika skill install --global --agents claude,codex ``` 4. Tell your human which agents got the skill and whether it was installed locally or globally, including any paths the command reports. ### Learn how to operate Amika Read these docs first: * [https://docs.amika.dev/](https://docs.amika.dev/) * [https://docs.amika.dev/quickstart](https://docs.amika.dev/quickstart) * [https://docs.amika.dev/install](https://docs.amika.dev/install) To operate Amika, you can use either: 1. the `amika` CLI 1. docs: [https://docs.amika.dev/reference/cli](https://docs.amika.dev/reference/cli) 2. implementation: [https://github.com/gofixpoint/amika/tree/main/go/cmd/amika](https://github.com/gofixpoint/amika/tree/main/go/cmd/amika) 2. the TypeScript SDK 1. docs: [https://docs.amika.dev/sdks/typescript/quickstart](https://docs.amika.dev/sdks/typescript/quickstart) 2. OSS implementation: [https://github.com/gofixpoint/amika/tree/main/sdk/typescript](https://github.com/gofixpoint/amika/tree/main/sdk/typescript) 3. the raw HTTP API: [https://app.amika.dev/api/docs](https://app.amika.dev/api/docs) and [https://app.amika.dev/api/openapi.json](https://app.amika.dev/api/openapi.json) 4. if you are a human, the UI at [https://app.amika.dev/](https://app.amika.dev/) The full docs are at [https://docs.amika.dev/](https://docs.amika.dev/). In the docs, there are "Guides for agents" which are agent specific. But you can read any docs pages that are useful. All OSS code is at [https://github.com/gofixpoint/amika](https://github.com/gofixpoint/amika) If you are trying to connect your own machine as a sandbox host: [https://docs.amika.dev/guides/byoc](https://docs.amika.dev/guides/byoc) # Bring your own compute Source: https://docs.amika.dev/guides/byoc Run rigs on your own machines instead of Amika Cloud. Bring your own compute (BYOC) runs rigs on hardware you control. You install the `amika-hostd` daemon on a machine, it registers that machine with Amika as a **host**, and each rig you create on that host runs there as a local VM. By default (`transport = "tunnel"`), the daemon dials out to Amika's gateway, so the machine needs no open port and works behind a home router or firewall. If you'd rather expose a port yourself, the daemon can [listen on one](#listen-on-a-port-instead) instead. ## Requirements > [!NOTE] > > * Linux x86\_64 or arm64 with glibc 2.34+ and KVM, or macOS on Apple silicon. > * `e2fsprogs`, which smolvm needs for disks under 20 GiB. The installer adds > it if it is missing. > * Outbound HTTPS from the machine to Amika. > * A user-scoped Amika API key, owned by you rather than your organization. > Create one under **Settings → API Keys** at > [app.amika.dev](https://app.amika.dev/settings/api-keys), or with the CLI > during [setup](#set-up-a-host). A > [listening host](#listen-on-a-port-instead) also accepts an organization key. Node.js and [smolvm](https://smolmachines.com), which the daemon needs, are installed for you when the machine doesn't already have them. ## Set up a host **1. Install the daemon** On the machine you want to run rigs: ```bash theme={null} curl -fsSL https://raw.githubusercontent.com/gofixpoint/amika/main/install-amika-hostd.sh | sh ``` See [Installer options](#installer-options) to pin a version, skip smolvm, or preview the install with `--dry-run`. If `resize2fs` is missing, the installer installs `e2fsprogs`. On macOS it runs `brew install e2fsprogs`. On Linux it uses `apt-get`, `dnf`, or `yum` as root or with `sudo`, and asks first. With `--install-deps` it installs without asking, but only as root or when `sudo` needs no password. When it can't install, it prints a warning with the reason and the exact command to run, and the install still succeeds. The installer creates a config file at `$XDG_CONFIG_HOME/amika-hostd/config.toml` (`~/.config/amika-hostd/config.toml` by default). **2. Store your credentials** ```bash theme={null} amika-hostd setup ``` It asks for this host's name and your Amika API key, and generates the secret key Amika uses to reach the daemon. Secrets go in the system keychain. On a server with no keychain, set `secret_store = "file"` in the config file before running setup. To set up a host without prompts, for a script or an AI agent, pipe the API key into `setup --non-interactive`. `amika auth api-key create` writes a new key straight to a file without printing it: ```bash theme={null} dir=$(mktemp -d) amika auth api-key create --name my-host-hostd --scope user --out "$dir/api-key" amika-hostd setup --non-interactive --hostname my-host < "$dir/api-key" rm -rf "$dir" ``` `--non-interactive` asks nothing. It keeps any secret key the host already has, and it stops without changing anything if the hostname is invalid or no key arrives on stdin. > [!NOTE] > > `amika auth api-key create` needs amika CLI v0.24.0 or later. Run it while > signed in as yourself (`amika auth login`): an organization key can't create a > user key. Otherwise, create the key in the web UI and save it to a file. > [!TIP] > > `amika-hostd setup --skill` prints step-by-step instructions an AI agent can > follow to set up the host, including whether to use the gateway or listen on a > port, and how to get the API key without seeing it. **3. Start the daemon** To [listen on a port](#listen-on-a-port-instead) instead, set `transport = "listen"` in the config first. ```bash theme={null} amika-hostd up ``` This registers the host with Amika, connects the daemon to Amika's gateway, and starts smolvm alongside it. Amika assigns the host's address, so there is no URL to set up. Pass `--fg` to stay in the foreground. ### Listen on a port instead The daemon can instead listen on a port that you expose to the internet over HTTPS, with [ngrok](https://ngrok.com) or [Cloudflare Tunnel](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/), for example. Set this in the config file, above its first `[` line (the installer's config has it commented out): ```toml theme={null} transport = "listen" ``` The daemon listens on `127.0.0.1:3020` by default. To use another address or port, set `host` and `port` in the config, or pass `--host` and `--port` to `up`. Expose the port, then start the daemon: ```bash theme={null} ngrok http 3020 # in another terminal; note the https URL it prints amika-hostd up # paste that URL when asked ``` To set the URL later, or when it changes (a free ngrok URL changes on every restart), run `amika-hostd register-url https://`. > [!WARNING] > > Register a bare HTTPS hostname, such as `https://hostd.example.com`, with no > path or port. Browsers can only open > [previews](#previews-and-service-access) on such a host. Other URLs still work > for creating and managing rigs. > > Browser previews and `amika rig ssh` reach the daemon directly at that URL, so > don't limit it to Amika's IP addresses or put it behind an access gate. > [!NOTE] > > A host set up before the gateway was the default has no `transport` line in > its config. Its next `amika-hostd up` moves it to the gateway and drops its > registered URL. Add `transport = "listen"` first to keep it listening. ## Create a rig on your host **CLI** ```bash theme={null} # Confirm the host registered, and see the sizes it offers amika host list # Create a rig on it amika rig create --name dev-box --host my-host --size small ``` `--size` takes one of that host's own sizes, not the cloud size names. Omit `--host` and the rig runs on Amika Cloud. To boot from a snapshot, add `--snapshot `. It must be a snapshot taken on that same host (see [Snapshots on your host](#snapshots-on-your-host)). The first `amika-hostd up` downloads the preset images in the background, and a rig created before that finishes can time out. The daemon logs the progress. **Web UI** 1. Open **Create a rig** at [app.amika.dev](https://app.amika.dev). 2. Under **Runs on**, switch from **Amika Cloud** to **Your hosts**. 3. Pick your host and one of its sizes, then click **Create rig**. Hosts that can't take a rig stay in the list but can't be picked. Each shows why: **Not responding**, **No URL yet**, or **Checking…**. When a host isn't answering, the form explains the problem under the picker, with links to **Manage hosts** and to **check again**. Your registered hosts are also listed under **Hosts** in the sidebar. **TypeScript** Pass the host's ID as `hostId`. `amika host get ` prints it, along with the sizes the host offers. ```ts theme={null} const hostId = "host_123"; // From `amika host get my-host` const rig = await client.rigs.create({ name: "dev-box", hostId, size: "small" }); await rig.wait(); ``` With `hostId`, `size` names one of that host's own sizes. `rig.hostId` and `rig.hostname` report where a rig runs. **HTTP API** Send the host's ID as `host_id`. `size` then names one of the host's sizes. ```bash theme={null} curl -X POST https://app.amika.dev/api/v0beta1/rigs \ -H "Authorization: Bearer $AMIKA_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name":"dev-box","host_id":"host_123","size":"small"}' ``` ## Configure sizes and images The config file you set up above sets the rig sizes this host offers and the preset image each rig boots. Every `amika-hostd up` publishes the sizes to Amika, so the file is the source of truth for them. Preset images stay local: the host pins the version it boots. Edit the file and restart the daemon either way. ```toml theme={null} [sizes.small] vcpus = 2 memory_gib = 4 disk_gib = 20 [preset_images] amika-coder = "ghcr.io/gofixpoint/amika-coder:latest" ``` > [!TIP] > > Keep `disk_gib` at 20 or more. Below that, smolvm doesn't cache the rig's > image, so every create downloads it again. ## Snapshots on your host You can [snapshot](/guides/create-a-snapshot) a rig that runs on your host. The snapshot is a `.smolmachine` file that stays on that host's disk, and it can only boot new rigs on the same host. * **Snapshot and delete is the only mode.** The daemon stops the rig to pack its disks, so **Snapshot everything**, which keeps the source rig running, isn't offered. * **Repository and organization default snapshots don't apply.** A host rig boots its preset image unless you pick one of that host's snapshots when you create it. * **Snapshots are large.** Each one is several gigabytes. Point `snapshot_dir` in the config (or `AMIKA_HOSTD_SNAPSHOT_DIR`) at a disk with room for them. By default they go under `~/.local/state/amika-hostd/snapshots`. ```toml theme={null} snapshot_dir = "/var/lib/amika-hostd/snapshots" ``` `amika snapshot list --long` shows a `HOST` column, so you can tell which snapshots belong to which host. ## Previews and service access Each [service](/reference/services) on a host rig gets a preview link. Opening it asks you to sign in to Amika, and only members of your organization get through. The link carries no credential, so sharing it gives no one access. Where it points depends on the host's transport: | Transport | Preview URL | | - | - | | `tunnel` (the default) | Its own subdomain, `https://--.r..o.amika.run/` | | [`listen`](#listen-on-a-port-instead) | A path on the URL you registered, `/v0beta1/rigs//previews//` | On a listening host, all previews share one origin and one sign-in: * A page in one preview can act on any other preview you've opened there, so don't run untrusted code on that host. * Open one preview at a time. Root-relative assets, such as a Vite or Next.js dev server's, follow the preview you opened last. For scripts and tools like `curl`, mint a short-lived service token with the HTTP API. It works only for rigs on your own hosts, never for `amikad`. ```bash theme={null} curl -X POST \ "https://app.amika.dev/api/v0beta1/rigs/dev-box/services/web/tokens?ttl_seconds=900" \ -H "Authorization: Bearer $AMIKA_API_KEY" ``` The response gives the service's `url`, the `header` to send the token in (`X-Amika-Authorization`), the `token`, and `expires_at`. Tokens last an hour by default and at most a day. ```bash theme={null} curl -H "X-Amika-Authorization: Bearer $TOKEN" "$URL" ``` ## Manage hosts | Command | What it does | | - | - | | `amika host list` | List your organization's hosts and their sizes | | `amika host get ` | Show one host, its ID, and the sizes it offers | | `amika host delete ` | Delete a host and its stored secret | Hosts register themselves, so there is no command to add one. A host that still has rigs on it can't be deleted: delete the rigs first. You can also delete a host from **Hosts** in the sidebar. To take a host offline, run `amika-hostd down` on the machine. That stops the daemon and the VMs it is running, keeping their disks. The next `up` brings the daemon back, but not the rigs: start those with `amika rig start`. Deleting the host record alone leaves the machine untouched, so it registers itself again on the next `amika-hostd up`. ### Rigs on a host that's gone Deleting a rig needs its host to answer. When the host is offline, the delete fails and the web UI offers **Remove from Amika only**. That deletes Amika's record of the rig but leaves anything still running on the machine, which you then clean up yourself. The HTTP API does the same with `DELETE /api/v0beta1/rigs/{id}?forget=true`. ## Uninstall the daemon Run the installer with `--uninstall` on the host: ```bash theme={null} curl -fsSL https://raw.githubusercontent.com/gofixpoint/amika/main/install-amika-hostd.sh | sh -s -- --uninstall ``` It shows what it found and asks you to confirm, stops the daemon, and deletes the launcher and its files. It then asks separately whether to remove the config and state directory, the keychain secrets, and smolvm. | Flag | What it does | | - | - | | `--purge` | Also remove the config, state directory, and keychain secrets without asking. Keeps smolvm | | `--yes`, `-y` | Answer yes to every question except smolvm's. Needed without a terminal | | `--dry-run` | Show what would be removed | smolvm is removed only if you type `remove smolvm` at its prompt. Uninstalling doesn't remove the host from Amika: delete it with `amika host delete`. ## Installer options | Flag | What it does | | - | - | | `--install-version ` | Install a specific `amika-hostd` version | | `--dry-run` | Show what would be done without downloading or installing | | `--smolvm-version ` | Install this smolvm version if smolvm is missing | | `--skip-smolvm` | Don't install smolvm | | `--install-deps` | Install missing system packages (`e2fsprogs`) without asking, only as root or when `sudo` needs no password. Use it for scripts and AI agents | | `--uninstall` | Remove `amika-hostd`. See [Uninstall the daemon](#uninstall-the-daemon) | Pass flags after `sh -s --`, for example `curl -fsSL .../install-amika-hostd.sh | sh -s -- --dry-run`. `AMIKA_INSTALL_DIR` sets where the launcher goes (default `/usr/local/bin`), and `AMIKA_HOSTD_HOME` where the daemon's files go. ## Next steps > **[amika host reference](/reference/cli#amika-host)** > > Every flag for the `amika host` commands. > **[Create a rig](/guides/create-a-rig)** > > The full rig creation flow, on cloud or your own host. # Capture agent sessions Source: https://docs.amika.dev/guides/capture-agent-sessions Capture every Claude Code and Codex session as append-only event files on disk with amikalog. > [!NOTE] > > **Research preview.** Interfaces, config formats, and CLI commands described > here may change before general availability. Reach out on > [Discord](https://discord.gg/xDXk4KjGWg) or email > [help@amika.dev](mailto:help@amika.dev) to join the early access program. [amikalog](https://github.com/gofixpoint/amika#amikalog) is an open-source CLI that captures every Claude Code and Codex session as plain, append-only files on disk. Your past agent work becomes data that future agents, scripts, and pipelines can read, search, and build on. It ships from the `amika` repo but is a standalone tool — you can use it on its own. ## Install amikalog is versioned and installed independently of the `amika` CLI. Pass `--component amikalog` to the [install script](/install): ```bash theme={null} curl -fsSL https://raw.githubusercontent.com/gofixpoint/amika/main/install.sh | sh -s -- --component amikalog ``` Pin a version with `--install-version` (amikalog releases under tags of the form `amikalog@v*`), or build from source with `make build-amikalog`. ## Turn on capture Enable capture once, globally: ```bash theme={null} amikalog start ``` That's it. Use Claude Code and Codex exactly as before — every session is now recorded. amikalog rides the agents' own hook systems, so there is no daemon, no proxy, and no change to how you invoke the agent. `amikalog start` idempotently installs hook entries into: * `~/.claude/settings.json` — one entry per Claude Code agent-activity hook event (tool use, prompts, permissions, subagents, tasks, turns, context compaction, and session lifecycle). * `~/.codex/hooks.json` — one entry per Codex lifecycle event (honors `$CODEX_HOME`). The hooks are global: they fire in every repository. Capture is best-effort — a failure to record is reported on stderr but never blocks the agent or alters its behavior. > [!NOTE] > > **Codex requires trusting the hooks before they run.** On first run Codex marks > newly added hooks for review and skips them until trusted, printing a warning > that points you to its `/hooks` command — review and trust the amikalog hook > there, and Codex sessions start producing events. Claude Code needs no such > step. > [!WARNING] > > Sessions started before `amikalog start` are not captured. Only sessions that > begin after capture is on produce a record. To turn capture off, run: ```bash theme={null} amikalog stop ``` `stop` removes only the hooks amikalog installed; unrelated hooks and already-captured events are left alone. ## What gets captured amikalog records every session as append-only JSON events under a predictable directory tree on your own disk. Each event carries the raw hook payload plus the git state it fired in — repository, commit, branch, and whether the tree was dirty. Events are written under the amika state directory, resolved in order: `AMIKA_STATE_DIRECTORY` if set, otherwise `$XDG_STATE_HOME/amika`, otherwise `~/.local/state/amika`. `amikalog start` prints the resolved paths. Events land at: ``` /events/{claude,codex}/sessions/_.jsonl ``` Each session is a single append-only [JSONL](https://jsonlines.org/) file — one JSON event per line, and earlier lines are never modified. The files are ordinary text you can `grep`, `jq`, sync, or load into a database. Each line records: | Field | Description | | - | - | | `source` | The agent that fired the hook (`claude` or `codex`) | | `hook_event` | The hook's event name (e.g. `PostToolUse`) | | `session_id` | The agent session the event belongs to | | `timestamp` | Capture time (RFC3339 with nanoseconds, UTC) | | `seq` | The event's position within its session, starting at 0 | | `cwd` | The working directory the hook reported | | `git` | Git state of `cwd` (`repo_root`, `commit`, `branch`, `dirty`), or `null` | | `payload` | The raw hook payload exactly as the agent provided it | For example, pull every `PostToolUse` event a session recorded: ```bash theme={null} jq 'select(.hook_event == "PostToolUse")' \ ~/.local/state/amika/events/claude/sessions/*_3f2a....jsonl ``` ## Why capture Local capture is just JSON on disk, so you can close the loop with whatever you already have — `jq`, a script, a cron job, or your agent's own file tools. Past sessions feed forward into future runs: * **Memory** — have a new session read past sessions' event logs in the same repo, so agents stop rediscovering the same context. * **Guardrails** — mine past sessions for the rules your team keeps learning the hard way and write them into the instruction files (`CLAUDE.md`, `AGENTS.md`) that future runs load. * **Evals** — each session is the full sequence of what an agent actually did, pinned to the exact commit it ran on. Real sessions make the best test cases. Claude Code and Codex events share one schema, so anything you build on top works across agents. ## Share sessions with your org > [!NOTE] > > Org sync is in beta. Local capture works entirely offline. To pool your org's sessions in one place, two beta commands sync the event log with a storage bucket that the hosted Amika platform manages for your organization. Both authenticate with an org API key set in `AMIKA_API_KEY`: ```bash theme={null} amikalog beta:push # upload not-yet-pushed events amikalog beta:fetch # download the org bucket into ``` `beta:push` uploads your not-yet-pushed events to the org bucket. Pushed files are tracked by size, so repeated runs re-upload only sessions that grew new events, and re-pushing is idempotent. `beta:fetch` downloads the org bucket into a local directory — your whole org's sessions as ordinary files. > [!WARNING] > > `beta:push` uploads message contents, tool arguments, file paths, and commit > messages to Amika's servers. Treat captured transcripts the same way you treat > the source code your agents read. ## Command reference | Command | Description | | - | - | | `amikalog start` | Register the amikalog hooks with Claude Code and Codex | | `amikalog stop` | Remove the hooks (already-captured events are kept) | | `amikalog beta:push` | Upload not-yet-pushed events to your org's storage bucket | | `amikalog beta:fetch ` | Download the entire org storage bucket into a local directory | | `amikalog version` | Print version information | ## Environment variables | Variable | Purpose | | - | - | | `AMIKA_STATE_DIRECTORY` | Override the state directory (else `$XDG_STATE_HOME/amika`, then `~/.local/state/amika`) | | `AMIKA_API_KEY` | Org API key for `beta:push` / `beta:fetch` | | `AMIKA_API_URL` | Override the API base URL (default `https://app.amika.dev`) | | `CODEX_HOME` | Override the Codex config directory (default `~/.codex`) | ## Next steps > **[Send a message to an agent](/guides/send-a-message-to-an-agent)** > **[amikalog on GitHub](https://github.com/gofixpoint/amika#amikalog)** # Codex app Source: https://docs.amika.dev/guides/codex-app Connect the Codex mobile or desktop app to an Amika rig. Connect to a rig VM from Codex in two ways: * **Desktop app:** add the rig as an SSH host and open its remote project. * **Mobile app:** pair with the rig's remote-control daemon. The rig must remain active while you use either connection. See [Create a rig](/guides/create-a-rig). ## Connect the desktop app You need the Codex desktop app, the [authenticated Amika CLI](/quickstart#step-2-set-up-the-cli), and an SSH identity. Create an identity with `amika secret ssh-keygen` if you do not already have one. **1. Add the rig as an SSH host** Run this on the computer where you use the Codex desktop app. Replace `dev-box` with your rig name. ```bash theme={null} amika rig open dev-box --app codex ``` On CLI v0.23.0 and earlier, run `amika rig code dev-box --editor codex`. The command adds a concrete host to your SSH configuration, enables Codex remote connections, and opens the Codex app. It prints the SSH host name and remote project folder to use in the next step. **2. Enable the SSH host in Codex** In the Codex desktop app, open **Settings > Connections**. Add or enable the SSH host printed by the CLI, then choose the printed remote project folder. The desktop app starts and manages the remote Codex app-server over SSH. You do not need to start `codex remote-control` or generate a pairing code for this connection. ## Connect the mobile app You need Codex remote control access for your ChatGPT account and workspace. Sign in to the Codex mobile app with the same account and workspace you use on Amika rigs. **1. Open a shell in the rig** Replace `dev-box` with your rig name. ```bash theme={null} amika rig ssh dev-box ``` **2. Sign in to Codex** Check whether the rig already has a Codex login: ```bash theme={null} codex login status ``` If you are not logged in, use device authentication and follow the printed instructions: ```bash theme={null} codex login --device-auth ``` **3. Start remote control** Start the app-server daemon in the rig: ```bash theme={null} codex remote-control start ``` **4. Generate a pairing code** Generate a short-lived code: ```bash theme={null} codex remote-control pair ``` Open remote control in the mobile app and enter the code. Generate another code if it expires before you finish pairing. ### Stop mobile remote control Stop the rig's app-server daemon when you no longer want it available for remote control: ```bash theme={null} codex remote-control stop ``` Stopping or deleting the rig also makes it unavailable. # config.toml reference Source: https://docs.amika.dev/guides/config-toml Every table and key you can set in .amika/config.toml, with examples. This is the full field-by-field guide to `.amika/config.toml`, the file that declares rig defaults for a repository. For how these settings reach a rig — resolution precedence, multi-repo, and repo-less behavior — read [How configuration works](/guides/configuration) first. The file lives at the root of a Git repository: ``` / .amika/ config.toml ``` ## Quick start A minimal config that sets up a Node project with a secret and a web server: ```toml theme={null} [lifecycle] setup_script = ".amika/setup.sh" [env] NODE_ENV = "development" API_KEY = { secret = "my-api-key" } [services.web] port = 3000 url_scheme = "http" [sandbox] preset = "coder" size = "m" ``` ## Sections * [`[lifecycle]`](#lifecycle) — setup and start scripts * [`[env]`](#env) — environment variables and secret references * [`[services.]`](#services) — named services with port bindings and URL schemes * [`[sandbox]`](#sandbox) — default rig preset, size, and snapshot * [`[filesystem]`](#filesystem) — additional repos to clone alongside the primary repo * [`[agent_credentials]`](#agent_credentials) — per-agent credential defaults *** ## `[lifecycle]` Controls rig initialization. Both keys are optional; a repository can define only setup, only start, or both. ```toml theme={null} [lifecycle] setup_script = "scripts/setup.sh" start_script = "scripts/start.sh" ``` ### `setup_script` | | | | - | - | | **Type** | String (file path) | | **Required** | No | | **Default** | Built-in no-op script (`exit 0`) | Path to a repository script whose contents Amika installs as the setup hook. It runs once during initial rig creation. Use a path relative to the repository root. **Requirements:** * Include a shebang and exit with status code `0` on success. * The executable bit in Git is not required for hosted rigs. * A nonzero exit records a setup failure, but the hosted rig remains accessible. * The script runs with the working directory set to `$AMIKA_AGENT_CWD`. **CLI override:** `--setup-script` on `amika rig create` takes priority over this value. ### `start_script` | | | | - | - | | **Type** | String (file path) | | **Required** | No | | **Default** | Built-in no-op script (`exit 0`) | Path to a repository script that Amika installs as the start hook. Unlike `setup_script`, it does **not** run on the initial create. It runs each time a stopped rig is started again. It is re-read on each start, so edits take effect without recreating the rig. Use it for steps that must repeat whenever a rig resumes, such as starting a long-running dev server or re-opening a tunnel. Put one-time provisioning in `setup_script`. Relative paths resolve from the repository root. The same exit-code behavior as `setup_script` applies. This key is applied by the hosted platform. The open-source Go config parser does not support a start script. *** ## `[env]` Declares environment variables that are set inside the rig. Each key is a variable name and each value is either a plain string or a reference table. See [Environment variables vs. secrets](/guides/env-vars-and-secrets) for how to choose between a plain value and a secret reference. ### Plain string ```toml theme={null} [env] DATABASE_HOST = "localhost" NODE_ENV = "production" PORT = "3000" ``` The value is set as-is in the rig environment. ### Secret reference ```toml theme={null} [env] ANTHROPIC_API_KEY = { secret = "my-anthropic-key" } AWS_SECRET_KEY = { secret = "My AWS Secret" } ``` The `secret` field references a secret by name in the Amika secrets store. The secret is resolved at rig creation time and its value is injected as the environment variable. Secrets must be pushed before rig creation via `amika secret push` or the web UI. ### Service reference ```toml theme={null} [env] WEB_URL = { service = "web", field = "url" } WEB_HOST = { service = "web", field = "host" } WEB_PORT = { service = "web", field = "port" } ``` The `service` field references a service declared in the same file's `[services.]` section. The `field` selects which attribute to inject: * `"url"` — the public URL of the service (e.g. `https://.preview.amika.dev`). Requires the service to have a `url_scheme`. * `"host"` — the hostname of that public URL (e.g. `.preview.amika.dev`), with no scheme, port, or path. Like `"url"`, requires the service to have a `url_scheme`. * `"port"` — the host-side port (inside the rig) the service is exposed on. Service references are resolved during rig initialization and written to the rig environment. They're useful when one service needs to reach another by URL. ### Validation rules | Rule | Detail | | - | - | | **Name format** | Must match `^[A-Z_][A-Z0-9_]*$` (UPPER\_SNAKE\_CASE) | | **Value type** | String, `{ secret = "..." }` table, or `{ service = "...", field = "..." }` table | | **Secret name** | Must be a non-empty string | | **Service name** | Must match a service declared in `[services.]` | | **Service field** | Must be `"url"`, `"host"`, or `"port"` | If validation fails, the `[env]` section is skipped and a warning is logged. Other sections are still applied. ### Merge semantics Environment variables are merged per-key across sources. Database entries (saved via the web UI) override TOML entries with the same name, but TOML-only entries are preserved. *** ## `[services.]` Declares named services with port bindings and optional URL schemes. Each `[services.]` section defines one service. See [Services](/reference/services) for usage examples and runtime behavior. > [!NOTE] > > The singular `[service.]` is accepted as an alias for > `[services.]`. Use one form or the other consistently within a file. ### Fields | Field | Type | Required | Description | | - | - | - | - | | `port` | integer or `"port/protocol"` string | No | Single port declaration | | `ports` | array of integer or `"port/protocol"` string | No | Multiple port declarations | | `url_scheme` | string or array of `{ port, scheme }` tables | No | URL generation scheme | `port` and `ports` are mutually exclusive. A service may omit both to act as a metadata-only entry with no port bindings. ### Port format Each port value is either: * **Integer** — interpreted as `containerPort/tcp` (TCP is the default protocol). * **String** `"containerPort/protocol"` — sets the protocol explicitly. ```toml theme={null} # These are equivalent port = 4838 port = "4838/tcp" ``` ### `url_scheme` Controls URL generation for service ports. Allowed values: `"http"`, `"https"`. **Single-port services** accept a string or a single-element array: ```toml theme={null} [services.api] port = 4838 url_scheme = "http" ``` **Multi-port services** must use the array form. Only listed ports get URLs: ```toml theme={null} [services.web] ports = [4211, "9872/tcp", "4982/udp"] url_scheme = [ { port = 4211, scheme = "http" }, { port = 9872, scheme = "https" }, ] # 4982/udp gets no URL ``` ### Validation rules | Rule | Detail | | - | - | | **Port range** | 1–65535 | | **Reserved range** | Ports 60899–60999 are reserved for Amika internal services and are rejected | | **Protocol** | `tcp` or `udp` | | **Mutual exclusivity** | Cannot specify both `port` and `ports` on the same service | | **Uniqueness** | No duplicate `(port, protocol)` pair across all services in the file | | **url\_scheme ports** | Must reference a port declared in the same service | | **url\_scheme uniqueness** | No duplicate port entries within `url_scheme` | If a service definition fails validation, rig creation fails with a 400 `invalid_repo_config` error whose message names the problem. Fix `.amika/config.toml` and create the rig again. ### Merge semantics Service definitions use DB-wins-all semantics: if any service definitions are saved via the web UI, those are used exclusively and TOML definitions are ignored. ### Examples **Simple web server:** ```toml theme={null} [services.web] port = 3000 url_scheme = "http" ``` **API with multiple ports:** ```toml theme={null} [services.api] ports = [8000, "8001/udp"] url_scheme = [ { port = 8000, scheme = "http" }, ] ``` **Metadata-only service (no ports):** ```toml theme={null} [services.worker] # No port or ports — acts as a named reference only ``` *** ## `[sandbox]` Sets default rig settings for the repository. ### `preset` | | | | - | - | | **Type** | String | | **Required** | No | | **Default** | `"coder"` | | **Values** | `"coder"`, `"coder-plus-docker"` | The base image preset for rigs created from this repository. * `coder`: Ubuntu 24.04 with Git, Node.js, Python, and the Claude Code, Codex, OpenCode, and Pi agent CLIs. * `coder-plus-docker`: Same as `coder`, with Docker support inside the rig. See [Presets](/reference/presets) for full details on what each preset includes. ### `size` | | | | - | - | | **Type** | String | | **Required** | No | | **Default** | The provider's `m` tier: `a0.m`, or `a1.medium` on E2B | | **Values** | A versioned size offered by the provider, or a friendly alias | The resource allocation size for rigs created from this repository. Each provider serves one size generation. E2B serves `a1`, and the other hosted providers serve `a0`: | Generation | Sizes | | - | - | | `a0` | `a0.xs`, `a0.m`, `a0.l`, `a0.xl` | | `a1` | `a1.tiny`, `a1.small`, `a1.medium`, `a1.large`, `a1.xlarge` | The friendly aliases are `xs` (or `extra-small`), `m` (or `medium`), `l` (or `large`), and `xl` (or `extra-large`). Aliases and sizes are case-insensitive. ```toml theme={null} [sandbox] preset = "coder-plus-docker" size = "m" ``` Friendly aliases normalize to the legacy `a0` generation, so they are not portable across providers. For example, `l` resolves to `a0.l`, which E2B does not offer. Use `a1.large` for a large E2B rig. The API accepts versioned sizes when the selected provider offers them. The `coder-plus-docker` preset does not support the `xs` tier. Amika ignores a `size` value it doesn't recognize, and falls back to the default. An unrecognized `preset` makes it ignore the whole `[sandbox]` table, including `size` and `snapshot`. ### `snapshot` | | | | - | - | | **Type** | String | | **Required** | No | | **Default** | None | The friendly label of a snapshot captured for this repository (for example `custom-snapshot`), **not** the org-qualified Daytona name. Amika maps the label to the full snapshot for your org at creation time, keeping the config portable across orgs. ```toml theme={null} [sandbox] snapshot = "custom-snapshot" ``` When a rig is created, the snapshot layer order is: an explicit `snapshot` in the API request, then this repository default, then a repository custom image, then the preset/size default. If the named snapshot is missing or no longer owned by your org, Amika logs a warning and falls through to the preset/size path rather than failing the create. ### Merge semantics Preset, size, and snapshot are resolved independently. Database values (saved via the web UI) override TOML values. When neither sets a value, the platform defaults apply: the `coder` preset, the provider's `m` size (`a0.m`, or `a1.medium` on E2B), and no snapshot. *** ## `[filesystem]` Declares extra repositories to clone into the rig alongside the primary repo. See [Multi-repo rigs](/guides/configuration#multi-repo-rigs) for the key rule: only the primary repo's `.amika/config.toml` is applied. ### `repos` | | | | - | - | | **Type** | Array of strings (GitHub repo URLs) | | **Required** | No | | **Default** | Empty (only the primary repo is cloned) | ```toml theme={null} [filesystem] repos = [ "https://github.com/gofixpoint/amika", "https://github.com/gofixpoint/amika-mono", ] ``` Each repo is cloned at its default branch into `~/workspace/`. The primary repo (the one this config lives in) is inferred automatically and need not be listed; if listed, it is deduped. ### Validation and resolution | Rule | Detail | | - | - | | **URL form** | Must be a GitHub `owner/repo` URL. Non-GitHub URLs and page URLs (`/tree/main`, query strings) are dropped. | | **Name collisions** | Two repos with the same basename would share `~/workspace/`; the first seen wins and the rest are dropped. | | **Access** | Each repo passes the same per-user GitHub access check as the primary. An inaccessible repo fails the create with `github_repo_not_accessible`. | **Merge semantics:** DB-wins-all. If additional repos are saved via the Edit Repository UI, that list is used exclusively and the TOML list is ignored. > [!NOTE] > > Additional repos are cloned during the hosted-platform initialization phase. > Providers without that phase (for example local Docker) clone only the primary > repo and log that the extras were skipped. *** ## `[agent_credentials]` Pins which credential each agent uses by default for rigs created from this repository. This dimension lives only in TOML — there is no database layer. ```toml theme={null} [agent_credentials] claude = { type = "api_key" } codex = { type = "oauth", name = "work-codex" } ``` Each key is an agent kind. Each value is an inline table: | Field | Type | Required | Description | | - | - | - | - | | `type` | `"api_key"` or `"oauth"` | No | The credential type to use. | | `name` | string | No | The name of the credential to select. | | Rule | Detail | | - | - | | **Agent kinds** | `claude`, `codex`. Entries for unknown kinds are ignored, so a repo may declare a default for an agent the server doesn't support yet. | | **Non-empty entry** | An entry must set `type`, `name`, or both. Entries with neither are dropped. | | **Unknown fields** | An entry with keys other than `type` and `name` is ignored. | See [Inject credentials](/guides/inject-credentials) for how these defaults interact with per-rig credential selection. *** ## Full example ```toml theme={null} [lifecycle] setup_script = ".amika/setup.sh" start_script = ".amika/start.sh" [env] NODE_ENV = "development" DATABASE_URL = "postgresql://localhost:5432/mydb" ANTHROPIC_API_KEY = { secret = "my-anthropic-key" } AWS_ACCESS_KEY_ID = { secret = "aws-access-key" } [services.web] port = 3000 url_scheme = "https" [services.api] port = 8080 url_scheme = "http" [services.db] port = 5432 [services.worker] ports = [9000, "9001/udp"] url_scheme = [ { port = 9000, scheme = "http" }, ] [sandbox] preset = "coder" size = "m" snapshot = "custom-snapshot" [filesystem] repos = [ "https://github.com/gofixpoint/amika", ] [agent_credentials] claude = { type = "api_key" } ``` ## Related docs * [How configuration works](/guides/configuration) — resolution precedence, multi-repo, repo-less * [config.toml key lookup](/reference/config-toml) — every key at a glance * [Environment variables vs. secrets](/guides/env-vars-and-secrets) — choosing plain values vs. secrets * [Services](/reference/services) — service runtime behavior, port resolution, and listing # How configuration works Source: https://docs.amika.dev/guides/configuration How a repository configures its rigs and agents, and how Amika resolves settings across sources. A rig needs to know what image to boot, what to install, what services to expose, and which secrets to inject. Amika reads that from **repository configuration** — a `.amika/config.toml` file committed at the root of your repo. When a rig is created from the repo, Amika reads the file and applies the settings automatically, so every collaborator gets the same environment without passing extra flags. ``` / .amika/ config.toml ``` This guide explains how configuration reaches a rig: where it can come from, how Amika resolves conflicts, and how it behaves for multi-repo and repo-less rigs. For the full field-by-field spec, see [config.toml reference](/guides/config-toml). ## What a repo config controls `.amika/config.toml` is a template for the rigs created from a repository. Each section maps to one dimension of the rig: * **`[lifecycle]`** — setup and start scripts that provision the environment. * **`[env]`** — environment variables and secret references. * **`[services.]`** — named services with port bindings and public URLs. * **`[sandbox]`** — the default preset, size, and boot snapshot. * **`[filesystem]`** — additional repos to clone alongside the primary one. * **`[agent_credentials]`** — which stored credential each agent uses by default. * **`[workflow]`**: a hosted multi-step agent workflow. Because the file lives in the repo, it is versioned with your code and easy for a coding agent to read and edit. That makes it the **recommended** place to declare rig settings. ## How configuration is applied The same setting can be declared in more than one place. Amika resolves each setting independently, taking the first non-empty value in this order: | Priority | Source | Where it comes from | | - | - | - | | 1 (highest) | **API request / CLI flags** | Values passed at rig creation time | | 2 | **Database** | Values saved through the web UI | | 3 | **`.amika/config.toml`** | Committed in the repository | | 4 (lowest) | **Built-in default** | Fallback when nothing else is set | Resolution is per-dimension: a preset from a CLI flag, env vars from the TOML, and a size from a UI setting can all apply to the same rig at once. A value saved through the web UI becomes the "Database" layer and overrides the corresponding `.amika/config.toml` value for all future rigs; the UI shows a notice when a value originates from the TOML file. > [!TIP] > > Prefer `.amika/config.toml` as your source of truth. It is versioned with your > code, reviewable in pull requests, and easy for coding agents to edit — unlike > UI or per-request settings, which live outside the repo. Reserve CLI flags and > the UI for one-off overrides. ### Setting a value across surfaces Setting the rig preset is a good example — you can declare it once in the repo, override it per rig from the CLI, or set a repository default in the UI. All three feed the resolution table above. **.amika/config.toml** Commit the default with your code. It applies to every rig created from the repo. ```toml theme={null} [sandbox] preset = "coder-plus-docker" ``` **CLI** Override the preset for a single rig at create time. ```bash theme={null} amika rig create --preset coder-plus-docker ``` **Web UI** On [app.amika.dev](https://app.amika.dev), open **Repos** and select your repo. In the **Rig Image** section, pick a **Preset**, then click **Save**. This becomes the "Database" layer and wins over the `[sandbox]` value in `.amika/config.toml`. ## Multi-repo rigs A rig can clone more than one repository. List the extra repos under [`[filesystem].repos`](/guides/config-toml#filesystem) in the primary repo's config. Each is cloned into `~/workspace/` alongside the primary. > [!WARNING] > > Only the **primary repo's** `.amika/config.toml` is applied. The primary repo is > the one the rig is created from — the repo that carries the `[filesystem]` > list. Any `.amika/config.toml` in an additional repo is **ignored**: its > `[env]`, `[services]`, `[lifecycle]`, and other sections have no effect. Declare > everything the rig needs in the primary repo's config. ```toml theme={null} # In the primary repo's .amika/config.toml [filesystem] repos = [ "https://github.com/gofixpoint/amika", "https://github.com/gofixpoint/amika-mono", ] ``` ## Repo-less rigs A repository is optional. A rig can boot with **no repo** — and therefore no `.amika/config.toml`. This is useful for scratch environments, or when you clone repos yourself after connecting. With no config file, every setting falls through to the API request / CLI flags layer or the built-in default. Pass the preset, size, env vars, and credentials you need at create time. ```bash theme={null} # Create a repo-less rig and configure it inline amika rig create --name scratch --no-git --preset coder --size m ``` See [Create a rig](/guides/create-a-rig) for how the CLI picks (or skips) a repo. ## Related docs * [config.toml reference](/guides/config-toml) — full field-by-field spec * [Create a rig](/guides/create-a-rig) — repo detection and `--no-git` * [Repository configuration](/reference/repository-configuration) — reference-tab summary * [Manage secrets](/guides/manage-secrets) — pushing secrets referenced from `[env]` # Create a rig Source: https://docs.amika.dev/guides/create-a-rig Spin up a rig pre-loaded with your repo and agent credentials. This guide walks through creating a rig, waiting for it to become ready, and tearing it down. By default everything runs on the hosted platform at [app.amika.dev](https://app.amika.dev). ## Prerequisites > [!NOTE] > > * An Amika account. The CLI uses `amika auth login`. The SDK needs an API > key, which you pass as `apiKey`. > * (For the `--git` flow) Git installed and a repo to mount. > * For the SDK: `npm install @amika/sdk`. ## Step 1 — Create the rig The simplest rig uses the `coder` preset (Ubuntu 24.04 with Node, Python, and the Claude Code / Codex / OpenCode CLIs pre-installed). ```bash CLI theme={null} amika rig create --name dev-box --preset coder ``` ```ts TypeScript theme={null} import { AmikaClient } from "@amika/sdk"; const client = new AmikaClient({ apiKey: process.env.AMIKA_API_KEY! }); const rig = await client.rigs.create({ name: "dev-box", preset: "coder", }); ``` ```bash HTTP API theme={null} curl -X POST https://app.amika.dev/api/v0beta1/rigs \ -H "Authorization: Bearer $AMIKA_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name": "dev-box", "preset": "coder"}' ``` To clone a repo into the rig, run the CLI from inside that repository or pass `--git `. The SDK accepts a URL through `repoUrl`. ```bash CLI theme={null} # Clone the repo in the current directory amika rig create --name dev-box --preset coder # Or clone a remote URL amika rig create --name dev-box --preset coder \ --git https://github.com/gofixpoint/example-repo.git ``` ```ts TypeScript theme={null} const rig = await client.rigs.create({ name: "dev-box", preset: "coder", repoUrl: "https://github.com/gofixpoint/example-repo.git", branch: "main", }); ``` ```bash HTTP API theme={null} curl -X POST https://app.amika.dev/api/v0beta1/rigs \ -H "Authorization: Bearer $AMIKA_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "dev-box", "preset": "coder", "repo_url": "https://github.com/gofixpoint/example-repo.git", "branch": "main" }' ``` ### How the CLI picks a repo * Run `amika rig create` **from inside a git repo** and that repo is used automatically — no flag needed. * **Outside a repo** (or to target a different one), pass `--git `. The value accepts a local path or a git URL (HTTPS or SSH). * Pass `--no-git` to skip auto-detection and create a **repo-less rig** — a rig with no repository mounted. This is useful for scratch environments or when you clone repos yourself after connecting. > [!NOTE] > > A repo-less rig still boots a full environment; it just starts without a > checked-out repository. Configuration for multi-repo and repo-less rigs is > covered in the [Repository configuration](/reference/repository-configuration) > guide. ## Step 2 — Wait until it's ready A new rig starts out initializing and becomes `running` once it's reachable and its setup has finished. ```bash CLI theme={null} # `rig create` blocks until the rig is ready — no extra step needed. ``` ```ts TypeScript theme={null} // `rigs.create` returns before setup finishes. // `wait` polls every 3 seconds until the rig is running and setup // succeeded, for up to 15 minutes. await rig.wait(); ``` ```bash HTTP API theme={null} # Create returns 202 before setup finishes. Poll until `status` is # `running` and `setup_status` is `ok`. curl https://app.amika.dev/api/v0beta1/rigs/dev-box \ -H "Authorization: Bearer $AMIKA_API_KEY" ``` > [!NOTE] > > `rig.wait()` throws an `AmikaWaitError` if provisioning fails, the setup > script fails, or the deadline passes. Its `reason` field says which. Pass > `{ maxWaitMs }` to change the deadline. ## Step 3 — Tear it down When you're done, delete the rig to free its resources. ```bash CLI theme={null} amika rig delete dev-box --force ``` ```ts TypeScript theme={null} await rig.delete(); // Or, without a fetched rig: await client.rigs.handle("dev-box").delete(); ``` ```bash HTTP API theme={null} curl -X DELETE https://app.amika.dev/api/v0beta1/rigs/dev-box \ -H "Authorization: Bearer $AMIKA_API_KEY" ``` ## Next steps > **[Send a message to an agent](/guides/send-a-message-to-an-agent)** > **[Inject credentials](/guides/inject-credentials)** > **[Rig lifecycle](/guides/rig-lifecycle)** > **[Rig configuration reference](/reference/rig-configuration)** # Create a snapshot Source: https://docs.amika.dev/guides/create-a-snapshot Capture a configured rig as a reusable base image so new rigs boot fast. A snapshot captures a configured rig's filesystem as a reusable base image. New rigs that boot from it start with your dependencies, tools, and environment already in place, with no waiting on a fresh install each time. > [!NOTE] > > You can create snapshots from the CLI, the web UI, the TypeScript SDK, or the > HTTP API, for rigs on Amika Cloud and for rigs on > [your own hosts](#snapshots-on-your-own-hosts). For a walkthrough of the whole flow, watch the demo: [Create a snapshot in Amika](https://www.youtube.com/embed/WIdizBsWXYE) The flow is: 1. Create a base rig with the setup script skipped. 2. Configure it the way you want the base to look. 3. Take a snapshot. 4. Launch new rigs from the snapshot, and optionally set it as the repository default. ## Step 1: Create a base rig, skipping setup When you build a base rig for a snapshot, skip the repository's setup script. The setup script runs automatically every time a rig is created. If it runs while you build the snapshot *and* again when someone boots from that snapshot, it executes twice. Skip it now, and let it run once at boot time later. **1. Open the create form** Open **Create a rig** at [app.amika.dev](https://app.amika.dev) and select your repository. **2. Check Skip setup script** On the **Setup script** row, check **Skip setup script**. Click **Show script** first if you want to see what you're skipping. Then create the rig. From the CLI, pass `--no-setup` to provision the rig with a no-op setup script: ```bash theme={null} amika rig create --name base-box --preset coder --no-setup ``` ## Step 2: Configure the environment Connect to the rig and set it up the way you want the base image to look: install dependencies, build caches, configure tools. ```bash theme={null} amika rig ssh base-box # inside the rig pnpm install ``` See [SSH and connect](/guides/ssh-and-connect) for the connection options. ## Step 3: Take the snapshot The source rig must be running. Choose a capture mode: | Mode | Value | What it does | | - | - | - | | **Snapshot and delete** (recommended) | `scrub_and_delete` | Removes Amika-injected secrets (credential files and injected environment variables), then captures the snapshot and deletes the source rig. | | **Snapshot everything** | `full` | Captures everything as-is, including any secrets, and leaves the source rig running. | > [!WARNING] > > **Snapshot everything** captures the filesystem as-is, so any secrets present > in the rig are baked into the image. Prefer **Snapshot and delete** for > shared base images. Not every rig offers both modes. Rigs on your own hosts, for example, only support **Snapshot and delete**. Capture the snapshot from any of these surfaces: **CLI** `amika snapshot create` is interactive by default: it prompts for the capture mode and name, and for `scrub_and_delete` it previews the injected secrets that will be removed and asks you to confirm. ```bash theme={null} # Interactive: prompts for mode and name amika snapshot create --rig base-box # Non-interactive: requires --mode and --name amika snapshot create --rig base-box \ --name example-repo-base --mode scrub_and_delete --no-interactive ``` Capture runs in the background. Check progress with `amika snapshot list`. **Web UI** Open the rig's detail page and click **Take Snapshot**. Pick a capture mode, give the snapshot a name you'll recognize, and confirm. **TypeScript** `client.snapshots.create` starts the capture and returns right away. `snapshot.wait()` polls until the snapshot is `active`. ```ts theme={null} const snapshot = await client.snapshots.create({ rigRef: "base-box", name: "example-repo-base", mode: "scrub_and_delete", }); await snapshot.wait(); ``` `client.snapshots.previewScrub("base-box")` lists the paths and environment variable names a scrub would remove, without their values. **HTTP API** `POST /sandbox-snapshots` returns `202` immediately and captures in the background. Reference the source rig by `sandbox_name`, `sandbox_id`, or `sandbox_ref` (an ID or a name). ```bash theme={null} curl -X POST https://app.amika.dev/api/v0beta1/sandbox-snapshots \ -H "Authorization: Bearer $AMIKA_API_KEY" \ -H "Content-Type: application/json" \ -d '{"sandbox_name":"base-box","name":"example-repo-base","mode":"scrub_and_delete"}' ``` The snapshot moves through `capturing`, then `finalizing`, then `active`. Once it's `active` it's ready to launch from. ## Step 4: Launch from a snapshot When you create a new rig, pick your snapshot from **Start from snapshot** in the **Rig Snapshot** section. On the **Rigs** page's create panel, that section is under **Advanced**. The new rig boots from the captured image instead of the preset. From the CLI, pass `--snapshot`: ```bash theme={null} amika rig create --name dev-box --snapshot example-repo-base ``` ### Set a repository default Make every new rig for a repository boot from a snapshot by default, either from the web UI or in your `.amika/config.toml`. **.amika/config.toml** Commit the default to your [repository configuration](/reference/repository-configuration) so every collaborator shares it. Add a `[sandbox]` section to `.amika/config.toml`: ```toml theme={null} [sandbox] snapshot = "example-repo-base" ``` **Web UI** 1. Go to **Repos** in the sidebar: [https://app.amika.dev/repositories](https://app.amika.dev/repositories) 2. Click the repo you're configuring. 3. Under **Default Snapshot**, choose your snapshot. The repository's **Rig Snapshots** table on the same page lists every snapshot captured for the repo. > [!NOTE] > > A default set in the web UI (stored in the database) takes precedence over > the `[sandbox]` value in `.amika/config.toml`. See the > [`[sandbox]` reference](/reference/config-toml#sandbox) for the full > resolution order. ## Snapshots on your own hosts Rigs on your [own hosts](/guides/byoc) can be snapshotted too, with a few differences: * **The snapshot stays on the host.** It is stored on that host's disk and can only boot new rigs on the same host. Pick it when you create a rig there, or pass `--snapshot` along with `--host`. * **Only Snapshot and delete.** The host stops the rig to capture its disks, so **Snapshot everything** isn't offered. * **No defaults.** Repository and organization default snapshots never apply to a rig on your own host. The create form offers each host only its own snapshots. `amika snapshot list --long` shows a `HOST` column for snapshots taken on your hosts. See [Snapshots on your host](/guides/byoc#snapshots-on-your-host) for where the host keeps them. ## Next steps > **[Rig lifecycle](/guides/rig-lifecycle)** > **[Create a rig](/guides/create-a-rig)** > **[SSH and connect](/guides/ssh-and-connect)** > **[Manage secrets](/guides/manage-secrets)** # Environment variables vs. secrets Source: https://docs.amika.dev/guides/env-vars-and-secrets When to use a plain environment variable and when to use a vault-backed secret. Every value you inject into a rig is one of two things: a **plain environment variable** or a **vault-backed secret**. This page explains the decision so you can pick the right one, then points you to the guides that cover each in depth. ## The decision You declare both in the `[env]` table of `.amika/config.toml`. The difference is whether the value itself lives in the repo or in the Amika vault. ```toml theme={null} [env] # Plain environment variable — the literal value is committed in the repo NODE_ENV = "production" DATABASE_HOST = "db.internal" # Secret — a reference by name; the value lives in the Amika vault ANTHROPIC_API_KEY = { secret = "my-anthropic-key" } ``` | | Plain environment variable | Secret | | - | - | - | | **Syntax** | `KEY = "value"` | `KEY = { secret = "name" }` | | **Where the value lives** | In `.amika/config.toml`, committed to the repo | In the Amika vault, referenced by name | | **Use for** | Non-sensitive config: hostnames, ports, feature flags, `NODE_ENV` | Anything sensitive: API keys, tokens, passwords | | **Set up before create** | Nothing — the value is in the file | Push the secret with `amika secret push` or the web UI | The rule of thumb: if you would be uncomfortable seeing the value in your Git history, make it a secret. Otherwise a plain value is simpler and versioned with your code. ## Security model today > [!WARNING] > > Secrets are resolved at rig creation time and **copied into the rig VM**, > where they are readable as environment variables from inside the rig. The > vault protects secrets at rest and keeps them out of your repository — it does > not currently isolate them from code running in the rig. A future design (tokenized secrets swapped in by a network proxy on outbound requests, so the agent never sees real values) is described under [Secrets Vault](/architecture/roadmap#secrets-vault) in the roadmap. Until that ships, treat any secret injected into a rig as visible to the agent and any code it runs. ## Where to go next * [Manage secrets](/guides/manage-secrets) — push, list, and update vault secrets, including Claude and Codex credentials. * [Inject credentials](/guides/inject-credentials) — wire stored secrets and agent credentials into a rig at create time. * [config.toml reference](/guides/config-toml#env) — the full `[env]` syntax, including service references. # GitHub authentication Source: https://docs.amika.dev/guides/github-authentication How Amika authenticates to GitHub: the GitHub App, personal access tokens, and the runtime credential a rig uses for git. Amika touches GitHub in two distinct ways, and it helps to keep them separate: * **Repository discovery**: letting Amika see and select which repositories you can create rigs from. This is the GitHub App. * **Runtime git credential**: the credential a rig uses to clone, push, and open pull requests. This is either a per-user GitHub App token (the default) or a shared personal access token (PAT). ## Connect the GitHub App The GitHub App controls which repositories Amika can see and select for rigs. Connect it on [app.amika.dev/settings/github](https://app.amika.dev/settings/github), in the **GitHub App** panel: 1. Click **Connect GitHub**. 2. Approve the authorization on github.com, then pick which repositories Amika can access. The settings page updates once you return. Connecting the app is per user: each teammate connects it for their own account. Once connected, the panel shows **Manage repositories**, which opens github.com so you can add or remove repositories at any time, and **Disconnect account**, which removes your GitHub authorization. Disconnecting leaves the GitHub App installed until you remove it on GitHub. ## Set the git author On the same page, **Git Author** sets the name and email used for git commits made inside rigs. Amika pre-fills this from your profile and saves it automatically, so most users never need to change it. ## Runtime git credential: GitHub App token vs. PAT When a rig runs git commands, it needs a credential. Amika supports two modes. Pick the default for your organization in the **GitHub Access** panel of [settings/github](https://app.amika.dev/settings/github), under **Default auth mode**, then click **Save**. The setting applies to every new rig in your organization. ### GitHub App token **App Token (recommended)** is the default. Instead of a shared static token, each rig authenticates as the creating user's GitHub App connection. In this mode: * There is no shared secret to manage. It uses the per-user GitHub App connection you set up above. * Tokens are minted at runtime through a git credential helper, so no long-lived credential is ever written to disk inside the rig. * The creating user must have the GitHub App connected. Without it, rig creation fails with a message asking you to connect GitHub in settings first. ### Personal access token (PAT) A single organization-wide token, shared across your org. Every teammate can use, replace, or delete it. The **PAT** option under **Default auth mode** stays disabled until a token is saved. Set it up in the **GitHub PAT (optional)** section of the same panel: 1. Click **Create GitHub PAT Token** to open GitHub's fine-grained token page. 2. Grant the permissions below. 3. Paste the token (it starts with `github_pat_`) into **Organization Access Token** and click **Save**. Required permission: * **Contents** → Read and Write: clone, pull, push branches, and create commits. Recommended permissions: * **Pull requests** → Read and Write: create and update PRs from the rig. * **Issues** → Read and Write: read and create issues from the rig. * **Actions** → Read: monitor GitHub Actions so agents can auto-fix CI. The token is stored once and reused by every rig in the org until it is replaced or deleted. ## Which mode should you use? | | GitHub App token | PAT | | - | - | - | | Scope | Per user, tied to each user's GitHub connection | One shared token for the whole org | | Setup | Connect the GitHub App | Create and paste a fine-grained PAT | | Secret on disk | Short-lived tokens minted at runtime; none persisted | Static token, stored and reused | | Attribution | The creating user's identity | Shared identity | Keep the **GitHub App token** default when you want per-user attribution and no shared long-lived secret. Use a **PAT** when you want one credential to administer centrally. Either mode requires its credential to be present. The organization default applies unless a rig overrides it. When your organization has a PAT saved, the create form offers a **GitHub Authentication** section under **Advanced**, where you can pick a different mode for that one rig. > [!NOTE] > > Regardless of runtime mode, the GitHub App still governs which repositories are > selectable in the UI. Connect it before creating rigs. ## Next steps > **[Create a rig](/guides/create-a-rig)** > **[Inject credentials](/guides/inject-credentials)** > **[Authentication reference](/reference/auth)** # Inject credentials Source: https://docs.amika.dev/guides/inject-credentials Wire stored secrets and agent credentials into a rig at create time. Once you've pushed secrets and provider credentials to the vault (see [Manage secrets](/guides/manage-secrets)), you decide which ones get injected into each new rig. Amika supports three patterns: 1. **Env-var secrets** — generic secrets exposed as environment variables. 2. **Pinned agent credentials** — pick a specific Claude / Codex credential. 3. **Skip an agent kind** — opt out entirely for one kind. ## Step 1 — Inject env-var secrets Map a rig env var to a secret stored in the vault. ```bash CLI theme={null} # Map a specific env var to a secret by name amika rig create --name dev-box \ --secret env:ANTHROPIC_API_KEY=my-claude-key # Shorthand: env var name matches the secret name amika rig create --name dev-box --secret env:DATABASE_URL ``` ```ts TypeScript theme={null} await client.rigs.create({ name: "dev-box", secretEnvVars: { ANTHROPIC_API_KEY: "my-claude-key", DATABASE_URL: "database-url", }, }); ``` ## Step 2 — Pin a specific agent credential If you have multiple credentials for the same agent (e.g. both an OAuth and an API-key credential for Claude), pin which one to inject. Pin by name or by type. ```bash CLI theme={null} # Pin by stored credential name amika rig create --name dev-box \ --agent-credential claude=personal-oauth # Pin by type — let the server pick a matching credential amika rig create --name dev-box \ --agent-credential-type claude=api-key ``` ```ts TypeScript theme={null} await client.rigs.create({ name: "dev-box", agentCredentials: [ { kind: "claude", name: "personal-oauth" }, // Or pin by type: // { kind: "claude", type: "api_key" }, ], }); ``` ## Step 3 — Skip an agent kind entirely Opt out of credential injection for one agent kind. ```bash CLI theme={null} amika rig create --name dev-box \ --no-agent-credential codex ``` ```ts TypeScript theme={null} await client.rigs.create({ name: "dev-box", agentCredentials: [{ kind: "codex", none: true }], }); ``` ## Inspect what actually got injected The rig response includes a `resolvedAgentCredentials` field that shows, per kind, the outcome (`resolved` or `skipped`), the source, and a reason. Use it to confirm the right credential made it into the rig. ```ts theme={null} const rig = await client.rigs.get("dev-box"); for (const c of rig.resolvedAgentCredentials ?? []) { console.log(c.kind, c.outcome, c.name, c.source, c.reason); } ``` Example: ``` claude resolved personal-oauth user_default "" codex skipped "" no-credential "no-agent-credential flag" ``` ## Picking from the web UI When you create a rig on [app.amika.dev](https://app.amika.dev), the **Agent Credentials** section lets you pick the credential per kind from a dropdown. On the **Create a rig** page, it is under **Advanced**. The CLI flags and SDK options above are the scriptable equivalent of that picker. ## Combining flags * `--agent-credential` and `--agent-credential-type` may both appear for the same kind — they narrow by both name and type. * `--no-agent-credential` is mutually exclusive with the other two flags for the same kind. * Each flag may appear at most once per kind. Supported kinds today: `claude`, `codex`. Type values: `oauth` and `api_key` (the CLI also accepts the hyphenated `api-key`). ## Next steps > **[Manage secrets](/guides/manage-secrets)** > **[Send a message to an agent](/guides/send-a-message-to-an-agent)** > **[Rig configuration reference](/reference/rig-configuration)** # Manage secrets and agent credentials Source: https://docs.amika.dev/guides/manage-secrets Store API keys, OAuth credentials, and agent secrets in the Amika vault. Amika has two kinds of secrets: * **Generic secrets** — arbitrary `KEY=VALUE` pairs you can reference from `.amika/config.toml` or inject as rig env vars. * **Provider secrets** — Claude Code / Codex credentials that get auto-injected into rigs so the agent runs without re-authenticating. This guide covers both. ## Prerequisites > [!NOTE] > > * The CLI logged in (`amika auth login`), or an Amika API key for the SDK. > * For Claude / Codex pushes: the relevant credentials available on your local > machine (config files, keychain, or in your environment). ## Push a generic secret Generic secrets are scoped to your user (`user`) or your org (`org`). ```bash CLI theme={null} # Inline KEY=VALUE amika secret push DATABASE_URL=postgres://... # From specific env vars on your shell amika secret push --from-env DATABASE_URL,REDIS_URL # From a .env file amika secret push --from-file .env # Org-scoped (visible to your whole org) amika secret push API_KEY=sk-... --scope org ``` ```ts TypeScript theme={null} await client.secrets.create({ name: "DATABASE_URL", value: "postgres://...", scope: "user", // or "org" }); ``` ```bash HTTP API theme={null} curl -X POST https://app.amika.dev/api/v0beta1/secrets \ -H "Authorization: Bearer $AMIKA_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name": "DATABASE_URL", "value": "postgres://...", "scope": "user"}' ``` For `--from-env`, each environment-variable name becomes the Amika secret name. For `--from-file`, each `KEY` in the file becomes the secret name. Use that exact name in `.amika/config.toml`: ```toml theme={null} [env] OP_SERVICE_ACCOUNT_TOKEN = { secret = "OP_SERVICE_ACCOUNT_TOKEN" } ``` > [!NOTE] > > The CLI and the SDK can create, list, and update generic secrets, but not > delete them. Delete a generic secret in the web UI, or call > `DELETE /api/v0beta1/secrets/{id}` on the HTTP API. Provider secrets > (Claude / Codex) can be deleted from the CLI and the SDK too. ## Push a Claude credential Pushed Claude credentials are auto-injected into new rigs — no in-rig login required. ```bash CLI theme={null} # Auto-detect and push an OAuth credential (preferred) amika secret claude push --type oauth # Push an API key amika secret claude push --type api_key # From a specific credentials file amika secret claude push --from-file ~/.claude/.credentials.json # Or pass the value inline amika secret claude push --type api_key --value sk-ant-... ``` ```ts TypeScript theme={null} const claudeSecret = await client.agentCredentials.create("claude", { name: "personal-oauth", value: '{"claudeAiOauth":{...}}', type: "oauth", // or "api_key" }); ``` ```bash HTTP API theme={null} curl -X POST https://app.amika.dev/api/v0beta1/secrets/claude \ -H "Authorization: Bearer $AMIKA_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name": "personal-api-key", "value": "sk-ant-...", "type": "api_key"}' ``` ## Push a Codex credential Same shape as Claude — only the provider segment changes. ```bash CLI theme={null} amika secret codex push --type oauth # API key amika secret codex push --type api_key --value sk-... ``` ```ts TypeScript theme={null} await client.agentCredentials.create("codex", { name: "personal-codex", value: "sk-...", type: "api_key", }); ``` ```bash HTTP API theme={null} curl -X POST https://app.amika.dev/api/v0beta1/secrets/codex \ -H "Authorization: Bearer $AMIKA_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name": "personal-codex", "value": "sk-...", "type": "api_key"}' ``` ## Extract local credentials (CLI only) The CLI ships an extractor that scans your filesystem for Claude, Codex, OpenCode, and Amp credentials and either prints them or pushes them straight to the vault. ```bash theme={null} # Print what was discovered amika secret extract # Push everything that was discovered, after confirmation amika secret extract --push # Push only specific keys amika secret extract --push --only ANTHROPIC_API_KEY,OPENAI_API_KEY # Skip OAuth sources amika secret extract --no-oauth ``` See [Reference — Secrets](/reference/secrets) for the full source-priority table. ## List and delete ```bash CLI theme={null} # Generic secrets — list only (no delete in CLI today) # Use the web UI to inspect generic secrets. # Provider secrets amika secret claude list amika secret claude delete amika secret codex list amika secret codex delete ``` ```ts TypeScript theme={null} // Generic secrets const all = await client.secrets.list(); await client.secrets.update(all[0].id, { value: "new-value" }); // No delete in the SDK. See the note above. // Provider secrets const claudeSecrets = await client.agentCredentials.list("claude"); await client.agentCredentials.delete("claude", claudeSecrets[0].id); ``` ```bash HTTP API theme={null} # Generic secrets curl https://app.amika.dev/api/v0beta1/secrets \ -H "Authorization: Bearer $AMIKA_API_KEY" curl -X DELETE https://app.amika.dev/api/v0beta1/secrets/ \ -H "Authorization: Bearer $AMIKA_API_KEY" # Provider secrets (use /secrets/codex for Codex) curl https://app.amika.dev/api/v0beta1/secrets/claude \ -H "Authorization: Bearer $AMIKA_API_KEY" curl -X DELETE https://app.amika.dev/api/v0beta1/secrets/claude/ \ -H "Authorization: Bearer $AMIKA_API_KEY" ``` ## Next steps > **[Inject credentials into a rig](/guides/inject-credentials)** > **[Secrets reference](/reference/secrets)** > **[Repository configuration](/reference/repository-configuration)** # Manage sessions Source: https://docs.amika.dev/guides/manage-sessions List, read, and continue agent sessions on a rig. An agent session is a durable chat with a coding agent on a rig. Its transcript is stored on the server and can outlive the rig. You pick a session each time you send a prompt. The CLI can list and read sessions with `amika sessions`, and the SDK can list sessions and read their transcripts. ## Prerequisites > [!NOTE] > > A rig in the `active` / `running` / `started` state. See > [Create a rig](/guides/create-a-rig). ## CLI: pick or start a session at agent-send time To control which session a prompt runs in, use the flags on `agent-send`. ```bash theme={null} # Start a fresh session amika rig agent-send dev-box "Plan the migration" --new-session # Resume a specific session amika rig agent-send dev-box "Continue from earlier" \ --session-id 3f2a... ``` See [CLI reference: agent-send](/reference/cli#agent-send) for the full flag table. ## CLI: list and read sessions `amika sessions list` lists your organization's agent chats. `amika sessions show` prints one chat and every message in it. ```bash theme={null} # List chats (the server's page size is 50) amika sessions list amika sessions list --limit 100 # Read one chat amika sessions show 3f2a... ``` The list shows each chat's session ID, agent, status, rig, and last update. Add `-o json` to either command for machine-readable output. See [`amika sessions`](/reference/cli#amika-sessions) for details. ## SDK: list, read, and continue sessions Sessions are created when you send a prompt. There is no separate create or update call. ### List sessions ```ts TypeScript theme={null} const { sessions, total } = await client.agentSessions.list({ rigRef: "dev-box", limit: 20, }); for (const s of sessions) { console.log(s.sessionId, s.agent, s.status, s.preview); } ``` Sessions come back newest first. Omit `rigRef` to list sessions across all your rigs. `limit` defaults to 50 on the server. `total` can be larger than `sessions.length`, so keep it when showing a partial list. ### Read a transcript ```ts TypeScript theme={null} const chat = await client.agentSessions.get(sessions[0].sessionId); for (const m of chat.messages) { console.log(m.role, m.content); } ``` ### Continue a session A fetched session has `send`, `sendStream`, and `refresh` methods bound to it. ```ts TypeScript theme={null} const turn = await chat.send({ message: "Continue from where you left off" }); await chat.refresh(); // Reload the transcript. ``` You can also continue a session from its rig by passing `sessionId`: ```ts theme={null} await client.rigs.handle("dev-box").send({ message: "Continue from where you left off", sessionId: chat.sessionId, }); ``` ## End-to-end example ```ts theme={null} const rig = client.rigs.handle("dev-box"); // Start a new session for this task const first = await rig.send({ message: "Add unit tests for the auth module", newSession: true, }); // Continue the same session const second = await rig.send({ message: "Now run them and fix any failures", sessionId: first.sessionId, }); if (second.isError) throw new Error(second.response); // Read the whole conversation const chat = await client.agentSessions.get(first.sessionId); console.log(chat.messages.length, "messages"); ``` ## Session shape ```ts theme={null} interface AgentSessionSummary { sessionId: string; sandboxId: string; // the rig the session runs on sandboxName: string | null; // null if the session outlived its rig agent: string; status: string; preview: string | null; model: string | null; effort: string | null; startedAt: string; endedAt: string | null; // null while still running createdAt: string; updatedAt: string; } ``` `agentSessions.get()` adds `messages`, the full transcript. See [Types](/sdks/typescript/types#agent-sessions). > [!NOTE] > > Earlier SDK versions had `createSession`, `listSessions`, > `getLatestSession`, `getSession`, and `updateSession`. Those methods have > been removed. Use `client.agentSessions` instead. ## Next steps > **[Send a message to an agent](/guides/send-a-message-to-an-agent)** > **[TypeScript SDK reference](/sdks/typescript/client)** # MCP integrations Source: https://docs.amika.dev/guides/mcp-integrations Give sandboxed agents pre-authenticated access to external tools via MCP servers. MCP (Model Context Protocol) integrations let a sandboxed coding agent call out to external services — error trackers, project management tools, internal systems — without running an interactive OAuth flow inside the rig. You connect your account to a provider once on the host. Amika stores the OAuth token in the secrets vault, attaches it to each rig created from repositories that use the integration, and writes the MCP server configuration into the rig's `~/.claude/.config.json` so Claude Code picks it up on startup. ## Supported providers | Provider | MCP server URL | Transport | | - | - | - | | Sentry | `https://mcp.sentry.dev/mcp` | HTTP + OAuth 2.1 | | Linear | `https://mcp.linear.app/mcp` | HTTP + OAuth 2.1 | | Pylon | `https://mcp.usepylon.com` | HTTP + OAuth 2.1 | Each provider uses OAuth 2.1 with PKCE and dynamic client registration. ## Connect your account 1. Go to [app.amika.dev/integrations](https://app.amika.dev/integrations). 2. Click **Connect** next to the provider you want. 3. Complete the provider's OAuth flow in your browser. You'll be redirected back to `/integrations` with a success banner. Credentials are per-user: every teammate connects their own account to each provider. You only need to connect once per provider — the same token is reused across every repository that uses the integration. To disconnect, click **Disconnect** on the same page. This removes your token from the vault and detaches you from any repositories that had the integration enabled under your account. ## Enable integrations on a repository Integrations attach to repositories, so rigs inherit the right tools automatically. 1. Open the repository's settings in the web UI. 2. Under **MCP integrations**, add any connected providers you want agents in this repo to use. 3. Save. Configuration is org-visible — any teammate can see which integrations a repo uses — but each teammate's token is personal. > [!NOTE] > > If a repo has an integration enabled but you haven't connected your account for that provider, rig creation skips the integration silently. Your rig is created successfully; the missing provider just won't be available to the agent. ## Override at rig creation The **Create rig** dialog pre-checks every integration attached to the repo. Uncheck any you don't want for that rig, and Amika skips them at provisioning time. The final list of integrations is recorded on the rig so you can audit which tools the agent had access to. ## What the agent sees During rig initialization, Amika writes the MCP servers into `~/.claude/.config.json` under the project's entry: ```json theme={null} { "projects": { "/home/amika/workspace/": { "mcpServers": { "sentry": { "type": "http", "url": "https://mcp.sentry.dev/mcp", "headers": { "Authorization": "Bearer " } } } } } } ``` This is the same location `claude mcp add` writes to, so Claude Code trusts the servers implicitly — no in-rig approval prompt. Injection runs after the setup script finishes, so a setup script that installs Claude Code or rewrites `.config.json` won't clobber the MCP entries. ## Limitations * **Token refresh is manual.** If a provider's access token expires while a rig is running, MCP requests start returning 401. Reconnect the provider on `/integrations` and recreate the rig. * **One token per user per provider.** If a provider supports multiple organizations (e.g. multiple Sentry orgs), you authorize one at a time. Switching orgs requires disconnecting and reconnecting. * **No `.amika/config.toml` support yet.** Integrations are currently repo-only (database). They will eventually be readable from config.toml with DB values taking precedence. # Open a rig in your editor Source: https://docs.amika.dev/guides/open-in-editor Open a running rig in Cursor, VS Code, Claude Desktop, Codex, Paseo, or Herdr over SSH. `amika rig open` opens a remote rig in Cursor, VS Code, Claude Desktop, Codex, Paseo, or Herdr over SSH. Cursor is the default. `amika rig code` and `--editor` still work as aliases for `amika rig open` and `--app`. > [!NOTE] > > `rig open`, `--app`, and the `herdr` app ship in the next CLI release. In > v0.23.0 and earlier, run `amika rig code --editor ` instead. It > supports every app except `herdr`. ## Prerequisites > [!NOTE] > > * An SSH identity. Create one with `amika secret ssh-keygen`. > * For Cursor or VS Code, its CLI (`cursor` or `code`) on your `PATH` and the > **Remote - SSH** extension installed. > * For Herdr, the `herdr` CLI on your `PATH`. ## Open the rig ```bash theme={null} amika rig open dev-box # Cursor is the default amika rig open dev-box --app cursor amika rig open dev-box --app vscode amika rig open dev-box --app claude amika rig open dev-box --app codex amika rig open dev-box --app paseo amika rig open dev-box --app herdr ``` Use `cursor` or `vscode` to open the repository in that editor. Use `claude` to register the rig as a Claude Desktop SSH environment, then select `Amika: ` from its environment dropdown. Use `codex` to add the rig as a Codex remote connection, then enable the host in **Settings > Connections**. See [Codex app](/guides/codex-app). Use `paseo` to print the SSH host to add in Paseo. See [Paseo](/guides/paseo). For Cursor and VS Code, the command opens the repository directory. If the file explorer is not visible, press `Cmd+Shift+E`. To open a different directory, pass `--path` with an absolute path or a path relative to the rig workspace: ```bash theme={null} amika rig open dev-box --path /home/amika/workspace/other-repo ``` `--path` has no effect with `paseo` or `herdr`. ## Add the rig to Herdr `--app herdr` runs `herdr machine add` with the rig's SSH host and labels the machine with the rig name. Herdr connects to the rig over SSH to prepare its remote server, and may prompt during setup. ```bash theme={null} amika rig open dev-box --app herdr ``` If Herdr already has the rig, the command says so and does nothing. If another machine already uses the rig's name as its label, the command names that machine so you can remove it with `herdr machine remove` and retry. ## Use another Remote-SSH editor Any editor that reads your `~/.ssh/config` and supports remote SSH can use the Amika-managed host alias. 1. Run `amika rig open dev-box` once to write the rig alias to `~/.ssh/amika.conf` and include it from your SSH config. 2. Open your editor's remote-SSH host picker and select `...amika`. 3. Open the repository directory in the rig, typically under `/home/amika/workspace`. ## Use a browser To work with an agent without a local editor, open the rig in the web UI and choose **OpenCode** or **Pi Web** from **Open with ...** while the rig is running. The agent's web console opens in a new tab through a signed, short-lived URL, so there is no password to set. ## What it does Under the hood, `amika rig open`: 1. Creates a direct SSH session and pins the rig's Ed25519 host key. 2. Builds an alias in the format `...amika`. 3. Ensures `~/.ssh/config` includes the Amika-managed `~/.ssh/amika.conf`. 4. Adds a concrete host entry so editors can discover the rig. An environment-scoped wildcard entry supplies the shared connection settings: ```ssh-config theme={null} # dev-box Host dev-box..app-amika-dev.amika Host *.app-amika-dev.amika User amika IdentityFile ~/.ssh/amika_id_ed25519 IdentitiesOnly yes IdentityAgent ~/.ssh/amika_agent.sock ForwardAgent yes StrictHostKeyChecking yes UserKnownHostsFile ~/.ssh/amika_known_hosts ProxyCommand amika plumbing ssh-stdio-proxy %h ServerAliveInterval 15 ServerAliveCountMax 3 ``` 5. Opens or configures the selected editor or coding agent with the alias. The concrete entry intentionally has no connection options. OpenSSH gets those from the wildcard entry for the current Amika environment. This lets one config support rigs from multiple control planes without sending an alias through the wrong proxy. ## Troubleshooting * **`cursor` or `code` CLI is not installed or not in `PATH`**: install the editor's shell command from its command palette. * **`unsupported app`**: pass one of `cursor`, `vscode`, `claude`, `codex`, `paseo`, or `herdr`. * **Cursor or VS Code opens but cannot connect**: make sure its **Remote - SSH** extension is installed. ## Next steps > **[SSH and connect](/guides/ssh-and-connect)** > **[Rig lifecycle](/guides/rig-lifecycle)** # Guides overview Source: https://docs.amika.dev/guides/overview Amika gives you three main ways to drive rigs and agents: 1. the web UI at [https://app.amika.dev/](https://app.amika.dev/) 2. the `amika` CLI 3. the `@amika/sdk` TypeScript SDK ## Where to start > **[Create a rig](/guides/create-a-rig)** > > Spin up a rig loaded with your repo and agent credentials. > **[Send a message to an agent](/guides/send-a-message-to-an-agent)** > > Run Claude, Codex, or another agent inside a rig synchronously. > **[Rig and repository configuration](/guides/configuration)** > > Each rig boots from a repository, whose `.amika/config.toml` configures the rig and agents. > **[Remote control agents and rigs](/guides/remote-control)** > > Remote-control agents and rigs from Slack, Linear, the Codex app, or SSH. ## What you need * An Amika account on the hosted platform at [app.amika.dev](https://app.amika.dev). * For the CLI: install it (see [Install](/install)) and run `amika auth login`. * For the SDK: an Amika API key from [app.amika.dev/settings](https://app.amika.dev/settings) and `npm install @amika/sdk`. > [!NOTE] > > The SDK does not read `AMIKA_API_KEY` from your environment or disk. The > caller is responsible for sourcing the token. The CLI handles credential > storage for you. ## See also > **[CLI reference](/reference/cli)** > > Full flag listing for every `amika` command. > **[TypeScript SDK](/sdks/typescript/quickstart)** > > Method-by-method reference, types, and errors. > **[HTTP API](/reference/api-reference)** > > Interactive docs and OpenAPI spec for the hosted API. # Paseo Source: https://docs.amika.dev/guides/paseo Install the Paseo daemon in a rig snapshot and connect from Paseo Desktop. [Paseo](https://paseo.sh) connects to a daemon running on your rig over SSH. Install the daemon in a reusable Amika snapshot so every rig created from that snapshot is ready for Paseo Desktop. This example installs Paseo `0.9.2` on an Ubuntu AMD64 rig. It runs the daemon as the rig user with a systemd user service and keeps that service running when the user is not signed in. ## Add the snapshot files At the root of your repository, create `amika-scripts/paseo-daemon.service`: ```ini amika-scripts/paseo-daemon.service theme={null} [Unit] Description=Paseo daemon Documentation=https://paseo.sh/docs/connectivity [Service] Type=simple WorkingDirectory=%h Environment="PATH=%h/.local/bin:%h/.local/share/pnpm:%h/.npm-global/bin:%h/.bun/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" ExecStart=/opt/Paseo/resources/bin/paseo daemon run --home %h/.paseo Restart=always RestartSec=5s TimeoutStopSec=30s [Install] WantedBy=default.target ``` Then create `amika-scripts/snapshot-init.sh`: ```bash amika-scripts/snapshot-init.sh theme={null} #!/usr/bin/env bash set -euo pipefail PASEO_VERSION="0.9.2" PASEO_SHA256="848a86d424d98e40b3157cfb93804fad93a599b0fdfec1dfffe78cd9e7feeac3" PASEO_DEB="Paseo-${PASEO_VERSION}-amd64.deb" PASEO_URL="https://github.com/getpaseo/paseo/releases/download/v${PASEO_VERSION}/${PASEO_DEB}" SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" RIG_USER="$(id --user --name)" RIG_UID="$(id --user)" if [[ "$RIG_UID" == "0" ]]; then echo "Run this script as the rig user, not as root." >&2 exit 1 fi if [[ "$(dpkg --print-architecture)" != "amd64" ]]; then echo "This example supports AMD64 Ubuntu rigs only." >&2 exit 1 fi if [[ -e "$HOME/.paseo" ]]; then echo "Paseo already has local state. Use a fresh snapshot base rig." >&2 exit 1 fi if [[ "$(dpkg-query -W -f='${Version}' paseo 2>/dev/null || true)" != "$PASEO_VERSION" ]]; then sudo apt-get update sudo env DEBIAN_FRONTEND=noninteractive apt-get install -y \ ca-certificates curl libasound2t64 download_dir="$(mktemp -d)" trap 'rm -rf "$download_dir"' EXIT curl --fail --location --silent --show-error \ "$PASEO_URL" --output "$download_dir/$PASEO_DEB" echo "$PASEO_SHA256 $download_dir/$PASEO_DEB" | sha256sum --check --status sudo env DEBIAN_FRONTEND=noninteractive apt-get install -y \ "$download_dir/$PASEO_DEB" fi install -D -m 0644 "$SCRIPT_DIR/paseo-daemon.service" \ "$HOME/.config/systemd/user/paseo-daemon.service" # Start the user service at boot, even when this user has no login session. sudo loginctl enable-linger "$RIG_USER" sudo systemctl start "user@${RIG_UID}.service" export XDG_RUNTIME_DIR="/run/user/${RIG_UID}" systemctl --user daemon-reload systemctl --user enable paseo-daemon.service systemctl --user is-enabled --quiet paseo-daemon.service ``` Make the script executable and commit both files: ```bash theme={null} chmod +x amika-scripts/snapshot-init.sh git add amika-scripts/snapshot-init.sh amika-scripts/paseo-daemon.service git commit -m "Configure Paseo in rig snapshots" ``` > [!NOTE] > > The pinned version and checksum make snapshot builds reproducible. Update both > values together when you upgrade Paseo. Find releases on the > [Paseo releases page](https://github.com/getpaseo/paseo/releases). ## Build the snapshot Follow [Create a snapshot](/guides/create-a-snapshot) to create a base rig with repository setup skipped. Connect to the base rig, then run the initialization script from the repository root: ```bash theme={null} ./amika-scripts/snapshot-init.sh ``` Verify that the service is enabled: ```bash theme={null} systemctl --user is-enabled paseo-daemon ``` Do not start the daemon in the base rig. Paseo stores a stable host identity in `~/.paseo/server-id`. Starting it before capture would copy the same identity into every rig created from the snapshot. Take the snapshot after the service is enabled. Each new rig starts the Paseo daemon automatically on `127.0.0.1:6767` and creates its own host identity on first boot. ## Connect Paseo Desktop Install [Paseo Desktop](https://paseo.sh/docs) on your computer. Then print the rig's SSH host: ```bash theme={null} amika rig open dev-box --app paseo ``` On CLI v0.23.0 and earlier, run `amika rig code dev-box --editor paseo`. In Paseo Desktop, click **Hosts > Add host > Remote SSH**. Paste the `ssh://` host printed by the command. Paseo reaches the daemon through SSH, so port `6767` does not need to be exposed publicly. See [Paseo connectivity](https://paseo.sh/docs/connectivity) for details about remote SSH connections. # Programmatic usage Source: https://docs.amika.dev/guides/programmatic-usage Script the Amika CLI to spin up a rig, drive an agent non-interactively, and ship the result. The Amika CLI is shell-friendly, so you can wire it into bash scripts, CI jobs, and code-gen pipelines. This guide walks through a complete automated flow: push a credential, create a remote rig cloned from a git repo, drive Claude Code non-interactively to make a change and open a PR, then tear the rig down. ## Prerequisites * The CLI installed and logged in. See [Install](/install) and [Authentication](/reference/auth). * A Claude API key on disk. See [Manage secrets](/guides/manage-secrets) for how to push it to the Amika secrets store. * Run from inside a git repository whose remote you want the agent to work against. > [!NOTE] > > The pattern below uses `amika rig ssh` with heredocs to control the agent. > Pair it with `--agent-credential-type` so the right credential is injected > without an interactive picker. See > [Inject credentials](/guides/inject-credentials). ## Walkthrough **1. Push your Claude API key to the Amika vault** ```bash theme={null} amika secret claude push \ --type api_key \ --from-file /path/to/your/CLAUDE_API_KEY ``` `--from-file` reads the key without prompting, which keeps the script non-interactive. **2. Create a remote rig cloned from the repo** ```bash theme={null} amika rig create \ --agent-credential-type claude=api-key \ --name testing-claude-api ``` Running the command inside a Git repository selects that repository. `--agent-credential-type claude=api-key` tells Amika to inject your stored API-key credential, which avoids the OAuth picker. **3. Configure agent permissions inside the rig** Use a heredoc with `amika rig ssh` to write a Claude `settings.local.json`. The `$AMIKA_AGENT_CWD` env var resolves to the cloned repo root inside the rig. ```bash theme={null} export CLAUDE_SETTINGS=' { "permissions": { "allow": [ "Bash(git:*)", "Bash(gh:*)" ] } }' amika rig ssh testing-claude-api << EOF mkdir -p \$AMIKA_AGENT_CWD/.claude echo 'settings.local.json' > \$AMIKA_AGENT_CWD/.claude/.gitignore echo '$CLAUDE_SETTINGS' > \$AMIKA_AGENT_CWD/.claude/settings.local.json EOF ``` The unquoted `<< EOF` lets the host shell expand `$CLAUDE_SETTINGS` before ssh transmits the body. Guest-side variables like `$AMIKA_AGENT_CWD` are escaped with `\$` so they survive to the rig shell and resolve there. These permissions let the agent run `git` and `gh` commands. Adjust the allowlist to match what your script needs. **4. Generate a session id so you can resume the agent run** ```bash theme={null} export CLAUDE_UUID=$(uuidgen) ``` Holding the session id lets you continue the same conversation across multiple agent invocations. This is useful when you want to break the work into phases. **5. Run Claude non-interactively to make code changes** ```bash theme={null} export CLAUDE_PROMPT="Change the heading text to also include, 'Dylan was here!' Do not stop, do not ask me for clarification or questions. " amika rig ssh -t testing-claude-api << EOF cd \$AMIKA_AGENT_CWD && claude \ --dangerously-skip-permissions \ --session-id '$CLAUDE_UUID' \ -p '$CLAUDE_PROMPT' < /dev/null EOF ``` A few details that matter for scripting: * `-t` allocates a TTY so Claude renders correctly. * `--dangerously-skip-permissions` is safe here because the allowlist in `settings.local.json` already constrains what the agent can do. * `< /dev/null` closes stdin so Claude exits when the prompt is done instead of waiting for input. **6. Resume the same session to commit and open a PR** ```bash theme={null} amika rig ssh -t testing-claude-api << EOF cd \$AMIKA_AGENT_CWD && claude \ --dangerously-skip-permissions \ --resume '$CLAUDE_UUID' \ -p 'Make a git branch and commit the changes. Then make a Github PR' < /dev/null EOF ``` Splitting the code change and the git/PR work into two prompts is more reliable than asking the agent to do both at once. **7. Tear down the rig** ```bash theme={null} amika rig rm --force testing-claude-api ``` `--force` skips the confirmation prompt, which is what you want in a script. ## Full script Drop this into a file and run it end-to-end. Make sure `/path/to/your/CLAUDE_API_KEY` exists and that GitHub access is set up in [GitHub settings](https://app.amika.dev/settings/github) so the agent can push the branch and open the PR. See [GitHub authentication](/guides/github-authentication). ```bash theme={null} #!/bin/bash set -euo pipefail errcho() { echo "$@" >&2; } amika secret claude push \ --type api_key \ --from-file /path/to/your/CLAUDE_API_KEY errcho "Creating rig..." amika rig create \ --agent-credential-type claude=api-key \ --name testing-claude-api export CLAUDE_SETTINGS=' { "permissions": { "allow": [ "Bash(git:*)", "Bash(gh:*)" ] } }' errcho "Configuring Claude settings in rig..." amika rig ssh testing-claude-api << EOF mkdir -p \$AMIKA_AGENT_CWD/.claude echo "settings.local.json" > \$AMIKA_AGENT_CWD/.claude/.gitignore echo '$CLAUDE_SETTINGS' > \$AMIKA_AGENT_CWD/.claude/settings.local.json EOF export CLAUDE_UUID=$(uuidgen) export CLAUDE_PROMPT="Change the heading text to also include, 'Dylan was here!' Do not stop, do not ask me for clarification or questions. " errcho "Running Claude to make code changes..." amika rig ssh -t testing-claude-api << EOF cd \$AMIKA_AGENT_CWD && claude --dangerously-skip-permissions --session-id '$CLAUDE_UUID' -p '$CLAUDE_PROMPT' < /dev/null EOF errcho "Resuming Claude to create git branch and PR..." amika rig ssh -t testing-claude-api << EOF cd \$AMIKA_AGENT_CWD && claude --dangerously-skip-permissions --resume '$CLAUDE_UUID' -p 'Make a git branch and commit the changes. Then make a Github PR' < /dev/null EOF errcho "Removing rig..." amika rig rm --force testing-claude-api ``` > [!TIP] > > For long agent runs, drop `set -e` around the agent invocations or wrap them > so a single failed run does not leak a rig. `amika rig rm --force` > should always run, even on failure. ## Next steps > **[Inject credentials](/guides/inject-credentials)** > > Push and pin Claude or Codex credentials for rigs. > **[CLI reference](/reference/cli)** > > Full flag listings for rig, secret, and ssh commands. # Remote control agents and rigs Source: https://docs.amika.dev/guides/remote-control Connect to Amika rigs and interact with their coding agents. Use Amika from the surface that fits the task. There are many ways to interact with a rig and its agents: * Use the [web UI](https://app.amika.dev/) * Use the [CLI](/reference/cli) to send messages to agents or run commands in rigs * Do the same with the [TypeScript SDK](/sdks/typescript/quickstart) or [HTTP API](/reference/api-reference) * Message agents from Slack and Linear * Connect to the rig with your favorite editor or ADE, such as the Codex app, Cursor, OpenCode Web, and other apps ## Work with agents Send a prompt to an agent when you want Amika to provision a rig and run the task for you. You can also review and continue the resulting session. > **[Send a message to an agent](/guides/send-a-message-to-an-agent)** > > Start an agent session from the CLI, web UI, SDK, or HTTP API. > **[Manage sessions](/guides/manage-sessions)** > > List, inspect, and continue agent sessions. > **[Use Slack](/guides/slack)** > > Send and receive agent messages in Slack. > **[Use OpenCode or Pi in a browser](/guides/open-in-editor#use-a-browser)** > > Open an agent's web console on a running rig. ## Connect to a rig Connect directly when you need to inspect the environment, run commands, or use a local development tool against the rig. > **[SSH and connect](/guides/ssh-and-connect)** > > Open a shell in a rig from the CLI or SSH. > **[Open in an editor or ADE](/guides/open-in-editor)** > > Open a rig in Cursor, VS Code, Claude Desktop, Codex, or another Remote-SSH editor. # Rig lifecycle Source: https://docs.amika.dev/guides/rig-lifecycle List, start, stop, and delete rigs. A rig progresses through a small set of states. This guide covers each transition. ## State values | State | Meaning | | - | - | | `initializing` | Provisioning; not yet reachable | | `active`, `running`, `started` | Reachable | | `stopped` | Paused. Can be resumed with `start` | | `failed` | Provisioning or runtime failure. `rig.wait()` throws on this | > [!NOTE] > > The server may introduce new `state` values over time. The SDK's > `rig.wait()` checks the rig's lifecycle `status` and its setup status, and > only treats `failed` as a failure, so unknown values won't break your code. ## List rigs ```bash CLI theme={null} amika rig list ``` ```ts TypeScript theme={null} const rigs = await client.rigs.list(); for (const rig of rigs) { console.log(rig.name, rig.status, rig.createdAt); } ``` ```bash HTTP API theme={null} curl https://app.amika.dev/api/v0beta1/rigs \ -H "Authorization: Bearer $AMIKA_API_KEY" ``` ## Stop a running rig ```bash CLI theme={null} amika rig stop dev-box ``` ```ts TypeScript theme={null} const rig = client.rigs.handle("dev-box"); await rig.stop(); await rig.wait({ status: "stopped" }); ``` ```bash HTTP API theme={null} curl -X POST https://app.amika.dev/api/v0beta1/rigs/dev-box/stop \ -H "Authorization: Bearer $AMIKA_API_KEY" ``` `wait({ status: "stopped" })` polls every 3 seconds until the rig is `stopped` (or `suspended`), for up to 15 minutes. It throws an `AmikaWaitError` if the rig fails or the deadline passes. ## Start a stopped rig ```bash CLI theme={null} amika rig start dev-box ``` ```ts TypeScript theme={null} const rig = client.rigs.handle("dev-box"); await rig.start(); await rig.wait(); ``` ```bash HTTP API theme={null} curl -X POST https://app.amika.dev/api/v0beta1/rigs/dev-box/start \ -H "Authorization: Bearer $AMIKA_API_KEY" ``` `wait()` polls every 3 seconds until the rig is `running` and its setup succeeded, for up to 15 minutes. Over HTTP, start and stop return `202` with `{"ok": true}` and finish in the background. Poll `GET /api/v0beta1/rigs/{id}` until `status` and `setup_status` reach the values you need. Every rig path takes the rig's ID or its name. See the [HTTP API overview](/reference/http-api-overview). ## Delete a rig ```bash CLI theme={null} # Prompts for confirmation amika rig delete dev-box # Skip the prompt amika rig delete dev-box --force # Multiple at once amika rig delete dev-box-1 dev-box-2 --force ``` ```ts TypeScript theme={null} await client.rigs.handle("dev-box").delete(); ``` ```bash HTTP API theme={null} curl -X DELETE https://app.amika.dev/api/v0beta1/rigs/dev-box \ -H "Authorization: Bearer $AMIKA_API_KEY" ``` ## End-to-end example ```ts theme={null} // Create const rig = await client.rigs.create({ name: "dev-box", preset: "coder" }); await rig.wait(); // Use it… await rig.send({ message: "Run the test suite" }); // Stop to pause cost await rig.stop(); await rig.wait({ status: "stopped" }); // Later: resume await rig.start(); await rig.wait(); // When done await rig.delete(); ``` ## Next steps > **[Create a rig](/guides/create-a-rig)** > **[SSH and connect](/guides/ssh-and-connect)** > **[Rig configuration reference](/reference/rig-configuration)** # Send a message to an agent Source: https://docs.amika.dev/guides/send-a-message-to-an-agent Run Claude, Codex, or another agent inside a rig and read its response. Once you have a running rig, you can drive its coding agent (Claude Code, Codex, OpenCode, etc.) by sending a single prompt synchronously. The call blocks until the agent finishes and returns the result. ## Prerequisites > [!NOTE] > > * A rig in the `active` / `running` / `started` state. See > [Create a rig](/guides/create-a-rig). > * Agent credentials injected at rig-create time. See > [Inject credentials](/guides/inject-credentials). ## Step 1 — Send a prompt By default the call uses Claude. Pass `--agent` / `agent` to switch agents. ```bash CLI theme={null} amika rig agent-send dev-box "Add unit tests for the auth module" ``` ```ts TypeScript theme={null} const rig = client.rigs.handle("dev-box"); const turn = await rig.send({ message: "Add unit tests for the auth module", }); if (turn.isError) throw new Error(turn.response); console.log(turn.response); ``` ```bash HTTP API theme={null} curl -X POST https://app.amika.dev/api/v0beta1/agent-sessions \ -H "Authorization: Bearer $AMIKA_API_KEY" \ -H "Content-Type: application/json" \ -d '{"sandbox_id": "dev-box", "message": "Add unit tests for the auth module"}' ``` ## Step 2 — Continue or start a fresh session By default, both the CLI and SDK resume the most recent session for the rig. Force a new session with `--new-session` / `newSession`, or pick a specific one with `--session-id` / `sessionId`. ```bash CLI theme={null} # Start fresh amika rig agent-send dev-box "Refactor the API layer" --new-session # Resume a specific session amika rig agent-send dev-box "Now write the tests" \ --session-id 3f2a... ``` ```ts TypeScript theme={null} const rig = client.rigs.handle("dev-box"); // Start fresh await rig.send({ message: "Refactor the API layer", newSession: true, }); // Resume a specific session await rig.send({ message: "Now write the tests", sessionId: "3f2a...", }); ``` ```bash HTTP API theme={null} # Start fresh curl -X POST https://app.amika.dev/api/v0beta1/agent-sessions \ -H "Authorization: Bearer $AMIKA_API_KEY" \ -H "Content-Type: application/json" \ -d '{"sandbox_id": "dev-box", "message": "Refactor the API layer", "new_session": true}' # Resume a specific session curl -X POST https://app.amika.dev/api/v0beta1/agent-sessions \ -H "Authorization: Bearer $AMIKA_API_KEY" \ -H "Content-Type: application/json" \ -d '{"message": "Now write the tests", "session_id": "3f2a..."}' ``` ## Stream the reply `sendStream` takes the same request and calls your handlers as the turn runs. `onDelta` receives reply text in order, and `onStatus` reports milestones. It resolves with the completed turn, like `send`. Over HTTP, `POST /agent-sessions/stream` takes the same body and answers with a `text/event-stream`. Each frame's SSE `event:` field names it: `status` for milestones, `delta` for reply text, `done` for the completed turn (the same object `POST /agent-sessions` returns), or `error`. ```ts TypeScript theme={null} const turn = await client.rigs.handle("dev-box").sendStream( { message: "Explain the test setup" }, { onDelta: (text) => process.stdout.write(text) }, ); ``` ```bash HTTP API theme={null} curl -N -X POST https://app.amika.dev/api/v0beta1/agent-sessions/stream \ -H "Authorization: Bearer $AMIKA_API_KEY" \ -H "Content-Type: application/json" \ -d '{"sandbox_id": "dev-box", "message": "Explain the test setup"}' ``` ## Response shape `send` and `sendStream` return the agent's reply, the session ID it ran in, and whether the agent reported an error. ```ts theme={null} interface AgentSessionSendResponse { sessionId: string; // pass back as sessionId to continue sandboxId: string; // the rig the turn ran on agent: string; response: string; // the reply, or failure details when isError isError: boolean; isNewSession: boolean; createdSandbox: boolean; usage?: AgentSessionUsage; } ``` See [Types](/sdks/typescript/types#agent-sessions) for `AgentSessionUsage`. The HTTP API returns the same fields in snake case (`session_id`, `sandbox_id`, `is_error`, `is_new_session`, `created_sandbox`, `usage`). ## Things to know * **Sends block.** The call waits for the agent to finish before returning. The SDK uses a **10-minute HTTP timeout** for sends (the default elsewhere is 30 seconds). Anything that wraps the SDK (Lambda, Cloudflare Worker, etc.) needs at least that much runtime budget. * **Check `isError`.** An agent failure, such as a rejected agent credential, returns `isError: true` with details in `response`, even though the HTTP request succeeded. To fix a credential problem, see [Inject credentials](/guides/inject-credentials). * **Default is resume.** Without `--new-session` / `newSession` or `--session-id` / `sessionId`, both the CLI and the SDK continue the rig's current session. ## Next steps > **[Manage sessions](/guides/manage-sessions)** > **[SSH into the rig](/guides/ssh-and-connect)** > **[Programmatic walkthrough](/guides/programmatic-usage)** # Set up repo config for VM rigs Source: https://docs.amika.dev/guides/set-up-vm-repo-config Instructions for a coding agent to inspect a local development environment and configure an Amika VM rig for the repository. ## Start here From the local development environment for your chosen repository, send this prompt to your coding agent: ```markdown theme={null} Follow the instructions in https://docs.amika.dev/guides/set-up-vm-repo-config to set your chosen Git repo in Amika VM rigs. ``` The rest of this page is written for the agent. You do not need to perform its steps yourself. ## Instructions for the agent You are helping a user configure their chosen Git repository for Amika VM rigs. Work from the user's machine, where the repository and its development environment are already set up. If the current directory is not the intended repository, ask for its local path and change to it. Your goal is to configure `.amika/config.toml` and the setup and start scripts it references so new rigs can reproduce the repository's working development environment. Complete the work yourself when it is safe to do so. The user should only need to answer your questions, approve sensitive actions, complete interactive authentication, or run commands that you cannot run. ## How to work * Treat the repository and working local environment as your primary evidence. Run safe, read-only repository commands yourself. * Ask permission before inspecting potentially sensitive files or unrelated machine state. Explain what you need and why. * Never read, print, or request secret values. Only inspect `.env` files, credential stores, SSH private keys, or similar files when the user authorizes a narrow, necessary use. * Ask before uploading secrets, changing credentials, committing, pushing, or deleting cloud resources you did not create for this task. Clean up temporary rigs you create unless the user asks you to keep them. * Preserve valid existing Amika configuration and explain material changes. * Keep the user informed with short findings and targeted questions. Do not send them away to read documentation. Use judgment throughout this process. The examples below are starting points, not a requirement to add every file or setting. ## 1. Establish the local context Confirm that you are in the intended repository and inspect its current state: ```bash theme={null} git rev-parse --show-toplevel git status --short git branch --show-current amika auth status ``` If Amika authentication is missing, run: ```bash theme={null} amika auth login ``` Tell the user how to complete the browser flow and show any verification code. Check whether the user has an SSH key registered with Amika: ```bash theme={null} amika secret ssh-key list ``` If no key is registered, ask permission before creating one: ```bash theme={null} amika secret ssh-keygen ``` Only public key material is uploaded. The private key remains on the user's machine. ## 2. Understand the working development environment Read enough of the repository to understand: * Project instructions such as `README.md`, `CONTRIBUTING.md`, `AGENTS.md`, `CLAUDE.md`, and `Makefile`, plus any existing `.amika/` files. * Runtimes, package managers, version constraints, install steps, builds, and migrations. * Services, startup commands, ports, and health checks. * Required environment-variable names and which are secret. Ask permission to inspect relevant local tools and configuration outside the repository. Avoid broad commands that dump the full environment, process arguments, or credential-bearing configuration. Use local state to discover requirements, not as something to copy blindly. Prefer reproducible project setup over machine-specific files and manually installed state. ## 3. Inspect a clean rig when useful If you need to compare the base environment before writing configuration, create a temporary rig without running any existing repository setup script. Choose a unique name derived from the repository: ```bash theme={null} setup_rig="my-project-setup" amika rig create --name "$setup_rig" --no-setup amika rig ssh "$setup_rig" ``` Compare only the tools and behavior relevant to the project. Record any needed changes in repository configuration or lifecycle scripts, not as manual changes to this temporary rig. Skip this step when the repository and preset reference already provide enough evidence. Use [`amika scp`](/guides/ssh-and-connect#copy-files) when you need to move a temporary, non-secret file between the user's machine and a rig: ```bash theme={null} amika scp ./local.txt "$setup_rig":local.txt amika scp -r "$setup_rig":/srv/output ./output ``` Do not use file transfer instead of committing reproducible setup files to the repository. ## 4. Agree on the plan Before editing, briefly report the detected development workflow, recommended preset and size, services, environment requirements, lifecycle approach, and any local behavior that should not carry into the rig. Ask only questions that block a sound implementation. In particular, ask how the project stores secrets and whether any encrypted files or external secret managers are part of its normal setup. Before changing repository files, create a new branch from the user's current branch. Choose a unique name and keep unrelated working-tree changes intact: ```bash theme={null} git switch -c amika/rig-config ``` ## 5. Create the repository configuration Create or update `.amika/config.toml` and its setup and start scripts. Add only settings supported by what you found. Use the [config reference](/guides/config-toml) for field syntax. * Use `coder` unless the project needs Docker inside the rig. Use `coder-plus-docker` when it does. Prefer a provider-supported versioned size. Friendly aliases are not portable: for example, `l` resolves to `a0.l`, which E2B does not offer. Use `a1.large` for a large E2B rig. * Put one-time work in `setup_script`. `start_script` runs after a stopped rig starts, not during initial creation. Share startup logic between them when a service must run after both creation and restart. * Use `$AMIKA_AGENT_CWD` for the primary repository. Give shell scripts a shebang, fail on errors, and make repeated startup safe. Set the executable bit on setup and start scripts with `chmod +x`, even though hosted lifecycle hooks do not require it. * Use the project's existing process manager when practical. For systemd, keep unit files in the repository, install them from the setup script, and run `systemctl daemon-reload` and `systemctl enable --now`. Make this idempotent. * Declaring `[services.]` publishes ports and URLs. It does not start the process. Ensure lifecycle or project tooling starts it, and avoid reserved ports 60899 through 60999. * Use plain `[env]` strings only for non-secret values. Use secret references for secrets. * Use a [service reference](/guides/config-toml#service-reference) when an environment variable needs a service's public URL, host, or port. Use optional sections such as `[filesystem]`, `[agent_credentials]`, and `[workflow]` only when the repository needs them. ### Handle secrets without exposing them Never put plaintext secrets in `.amika/config.toml`, lifecycle scripts, Git, or your responses. If the required values are already exported in the local environment, ask permission to upload only the named variables without printing them: ```bash theme={null} amika secret push --from-env=API_KEY,DATABASE_URL ``` The environment-variable name becomes the Amika secret name. Reference that exact name in `.amika/config.toml`: ```toml theme={null} [env] OP_SERVICE_ACCOUNT_TOKEN = { secret = "OP_SERVICE_ACCOUNT_TOKEN" } ``` For example, `--from-env=OP_SERVICE_ACCOUNT_TOKEN` does not create a secret named `op-service-account-token`. If the project uses a 1Password service account, consult the [1Password service account reference](https://www.1password.dev/cli/reference/management-commands/service-account). If the values are not exported and no suitable secret file exists, create a temporary directory and permission-restricted file: ```bash theme={null} secret_dir="$(mktemp -d)" secret_file="$secret_dir/amika-secrets.env" touch "$secret_file" chmod 600 "$secret_file" ``` Give the user the exact file path and variable names, then ask them to add one `KEY=VALUE` per line. Do not read or print the populated file. After the user confirms it is ready, ask permission and upload it: ```bash theme={null} amika secret push --from-file="$secret_file" ``` Each key in the file becomes the Amika secret name. After a successful upload, or if the user cancels, delete the file and temporary directory. Preserve an existing encrypted-file workflow when it is suitable for rigs. Never add a secret file to the repository. ## 6. Validate the files Run the relevant checks yourself: ```bash theme={null} python3 -c 'import pathlib, tomllib; tomllib.loads(pathlib.Path(".amika/config.toml").read_text())' find .amika/scripts -type f -name '*.sh' -exec bash -n {} + git diff --check ``` Confirm that referenced scripts exist, service ports match their processes, setup and start scripts are executable, secrets use exact-name references, reserved ports are unused, and setup does not depend on unexplained local state. ## 7. Test the result in a new rig Hosted rigs clone the remote repository, so local uncommitted changes are not enough for an end-to-end test. Show the user the diff and ask permission to commit and push it. If approved, run: ```bash theme={null} config_branch="$(git branch --show-current)" git add .amika git diff --cached git commit -m "Add Amika rig configuration" git push -u origin "$config_branch" ``` After the configuration and required secrets are available remotely, create a new test rig: ```bash theme={null} config_branch="$(git branch --show-current)" test_rig="my-project-config-test" amika rig create --name "$test_rig" --branch "$config_branch" amika rig ssh "$test_rig" ``` Always pass the pushed configuration branch to `amika rig create`. Otherwise, the rig may clone the repository's default branch without your changes. Verify the actual development workflow, not only that the rig booted. Check the required processes and health endpoints, then run a representative project command. Confirm expected environment-variable names without printing secret values. Inspect published service bindings from the local machine: ```bash theme={null} amika service list --rig-name "$test_rig" ``` If the test fails, diagnose it, update the repository files, and repeat the smallest useful part of the test. Do not hide unresolved failures. When finished, delete every temporary rig you created. Use the actual names you chose, and do not delete pre-existing rigs: ```bash theme={null} amika rig delete my-project-setup --force amika rig delete my-project-config-test --force ``` ## Report back Tell the user what changed, the branch you pushed, which local behavior you carried into the rig, what you tested, which secret names or actions remain, and whether temporary rigs are still running. Do not send the user back to this page for next steps. Give them the exact command or question in your response. ## Reference material * [How configuration works](/guides/configuration) * [config.toml reference](/guides/config-toml) * [Services](/reference/services) * [SSH and file transfer](/guides/ssh-and-connect) * [Rig environment presets](/reference/presets) * [Manage secrets](/guides/manage-secrets) * [Amika CLI skill](https://github.com/gofixpoint/amika/tree/main/.agents/skills/amika-cli) # Slack Source: https://docs.amika.dev/guides/slack Drive sandboxed agents from Slack: install the app, set channel and workspace defaults, and start a conversation. The Slack integration lets your team talk to Amika's coding agents from a Slack channel or DM. Mention the bot with a request and Amika spins up a rig for that thread, runs the agent, and replies in-thread. Follow-up messages in the same thread continue the same rig and session. ## Prerequisites > [!NOTE] > > * A connected [GitHub App](/guides/github-authentication). > * An org [GitHub personal access token](/guides/github-authentication#personal-access-token-pat), > saved in [GitHub settings](https://app.amika.dev/settings/github). > Slack-triggered agents use it to reach GitHub. > * [Agent credentials](/guides/inject-credentials) for the agent the bot runs. > * The Slack app enabled for your organization. Until it is, the connect button > is disabled. Contact Amika to enable it. ## Install the Slack app 1. Go to [app.amika.dev/integrations](https://app.amika.dev/integrations). 2. In the **Slack** section, click **Connect Slack workspace**. 3. Approve the requested permissions in Slack, then choose the workspace to install into. After the OAuth flow completes, the workspace appears under **Connected Slack workspaces**. Click a workspace to open its settings. The app requests the scopes it needs to read mentions and channel history, post replies, add and remove reactions (the "eyes" acknowledgement the bot shows while an agent is thinking), and read your workspace name and icon. ## Set workspace defaults Open a connected workspace and expand **Workspace defaults**. These are the org-wide fallback the bot uses in any channel that has no defaults of its own: * **Repository** — the repo agents work in. * **Agent** — the agent CLI used to process messages. Configure that agent's credentials in the matching settings page. * **System prompt** — optional extra instructions passed to the agent on every turn. Leave a field blank to pass no default for it. ## Set channel defaults Expand **Channel defaults** on the same page to pin a repository, agent, and system prompt per channel. A channel appears in this list once the bot has been mentioned in it. Until then, mention `@amika` in the channel to populate its name. A channel that defines its own defaults uses them instead of showing the picker card when a new thread starts. Any field left as **Inherit (org default)** falls back to the workspace defaults above. ## Start a conversation from Slack 1. Invite the bot to a channel, or open a DM with it. 2. Mention `@amika` with your request (in a channel), or just message the bot directly (in a DM). 3. The bot adds an "eyes" reaction to acknowledge the message, runs the agent, and posts the result back in the thread. The reaction is removed once the reply lands. How Amika picks the repository and agent for a new thread: 1. **Channel defaults**, if the channel has any. 2. **Workspace defaults**, otherwise. 3. **The picker card** — if neither is set, the bot prompts you to choose the repository and agent for the thread. Each Slack thread maps to its own rig. Continuing the thread continues that rig's session, so the agent keeps its context across follow-up messages. > [!TIP] > > Set channel or workspace defaults for the channels your team uses most so > threads start working immediately without the picker card. ## Next steps > **[GitHub authentication](/guides/github-authentication)** > **[Inject credentials](/guides/inject-credentials)** > **[Manage sessions](/guides/manage-sessions)** # SSH and connect Source: https://docs.amika.dev/guides/ssh-and-connect Open a shell on a rig over SSH, or open it in your editor. Once a rig is running, you have a few ways to get inside it: * **`rig ssh`**: interactive shells, one-off commands, and port forwarding. * **`rig connect`** (CLI-only): a plain interactive shell over the same transport. * **`scp`** (CLI-only): copy files to and from a rig. * **`rig open`** (CLI-only): opens the rig in an editor or app, such as Cursor, VS Code, or Codex, over SSH. ## Prerequisites > [!NOTE] > > * A rig in the `active` / `running` / `started` state. See > [Create a rig](/guides/create-a-rig). > * An SSH key. Create one with `amika secret ssh-keygen`, or upload an existing > public key with `amika secret ssh-keygen --import ~/.ssh/id_ed25519.pub`. ## Open an interactive SSH session ```bash theme={null} amika rig ssh dev-box ``` The TypeScript SDK has no SSH methods. Use the CLI to open a shell. ## Run a one-off command `amika rig ssh` works like `ssh`: options go before the rig name, and the command goes after it. Use `-t` to allocate a TTY when the remote command needs one. ```bash theme={null} # Non-interactive command amika rig ssh dev-box ls -la # Interactive program (force TTY) amika rig ssh -t dev-box top ``` ## Forward a port Every `ssh` option works, including port forwarding. Forward a local port to a port in the rig with `-L`, and add `-N` to skip the remote shell: ```bash theme={null} # Reach the rig's port 3000 at http://localhost:3000 amika rig ssh -N -L 3000:localhost:3000 dev-box # SOCKS proxy on local port 1080 amika rig ssh -N -D 1080 dev-box ``` Local (`-L`) and dynamic (`-D`) forwarding are supported. Remote (`-R`) and X11 forwarding are not. Agent forwarding is on by default and uses a dedicated agent that holds only your Amika SSH key, so your other keys never reach the rig. ## Copy files Use `amika scp` to copy files between your machine and a rig. It uses the same SSH identity as `amika rig ssh` and accepts standard `scp` options such as `-r`, `-p`, and `-C`. ```bash theme={null} # Upload a file into the rig user's home directory amika scp ./local.txt dev-box:local.txt # Download a directory amika scp -r dev-box:/srv/output ./output ``` A relative rig path starts under `/home/amika`. Use an absolute path when the file lives elsewhere in the rig. To see the `scp` command Amika would run without running it, add `--print`: ```bash theme={null} amika scp --print ./local.txt dev-box:local.txt ``` See [`amika scp`](/reference/cli#amika-scp) for copying between rigs and other SSH hosts. ## Open a plain shell (CLI only) `amika rig connect` opens an interactive shell in the rig over the same transport as `rig ssh`. Use it when you don't need SSH options or a remote command. ```bash theme={null} amika rig connect dev-box ``` ## Open in an editor (CLI only) `amika rig open` opens the rig in Cursor, VS Code, Claude Desktop, Codex, Paseo, or Herdr over SSH. See [Open a rig in your editor](/guides/open-in-editor) for the full command and instructions for other Remote-SSH editors. ```bash theme={null} amika rig open dev-box amika rig open dev-box --app vscode ``` On CLI v0.23.0 and earlier, the command is `amika rig code` and the flag is `--editor`. ## Next steps > **[Programmatic walkthrough](/guides/programmatic-usage)** > **[Rig lifecycle](/guides/rig-lifecycle)** > **[CLI reference](/reference/cli)** # What is a rig? Source: https://docs.amika.dev/guides/what-is-a-rig Learn how an Amika rig gives each coding agent or developer an isolated devbox VM. A rig is an isolated devbox: a sandboxed VM tuned for coding agents. Agents and people can work in the same repository and environment on it, without touching each other's work or your everyday machine. Each rig includes: * One or more agent harnesses, such as Claude Code, Codex, OpenCode, or Pi * Your Git repositories, dependencies, tools, and development services * Agent credentials, environment variables, and secrets your agent can never read * SSH access and URLs for exposed services * VM snapshots to save a rig's filesystem and then boot new VMs from it Amika provisions the VM, prepares it from your repository configuration, and connects it to the control plane. You can then operate the rig and its agents from the web UI, CLI, TypeScript SDK, HTTP API, chat integrations, or your editor. ## Shared by agents and people You can give an agent a rig and let it work in the background, or you can use the rig interactively, just like a normal cloud devbox. You, your teammates, and your agents can connect to a rig at any time to inspect files, run commands, write code, open your repo in an editor, and view dev server URLs. A single rig can run multiple agents at the same time (it's just a VM!). All rigs are on a mesh network, so rigs and your agents can communicate with other rigs when work needs to span environments. ## Persistent or temporary Choose the lifetime that fits the task: * **Temporary rigs** start clean for a branch, pull request, check, or one-off task. Delete them when the work is complete. * **Persistent rigs** keep their filesystem and environment available for an ongoing project or durable automation. Stop them when idle and start them again later. You can capture a configured rig as a snapshot to create more rigs from the same starting point. ## Where rigs run Rigs can run on computers you already own, such as a Mac Mini, a desktop, an EC2 in your VPC, or a sandbox cloud account you already have. Install the Amika host daemon on a machine and it can run several isolated rigs side by side. See [Bring your own compute](/guides/byoc). If you'd rather not run hardware, Amika hosts rigs too. A rig runs on Amika's hosted compute unless you pick one of your hosts when you create it. ## Next steps > **[Create a rig](/guides/create-a-rig)** > > Provision a rig with your repository and agent credentials. > **[Rig lifecycle](/guides/rig-lifecycle)** > > List, stop, start, and delete rigs. > **[Connect to a rig](/guides/ssh-and-connect)** > > Open a shell or connect with an editor. > **[Bring your own compute](/guides/byoc)** > > Run rigs on your own machines instead of Amika Cloud. > **[Configure a repository](/guides/configuration)** > > Define reproducible rig settings alongside your code. # Introduction Source: https://docs.amika.dev/index ## Cloud devboxes for coding agents, on computers you already own Amika **slices computers you already own into isolated devbox VMs for coding agents**, and lets you reach them and their agents from anywhere. Each devbox is an **Amika rig**: a VM tuned for coding agents, with your repos, credentials, and services already in place. * **Run on your own machines.** Add a Mac Mini, a desktop, or EC2 in your VPC, and run several isolated rigs on each one. If you'd rather not run hardware, Amika hosts rigs too. * **Run on your own cloud accounts.** Unify your existing cloud accounts (AWS, GCP, etc.) and sandbox providers (Daytona, E2B, etc.) and manage VMs across all of them. * **Bring any agent.** Use Codex, Claude, OpenCode, Pi, or your own agent with existing subscriptions and API keys. * **Control from anywhere.** Use chat apps, the web UI, API, CLI, SSH, or your editor or ADE. ![Amika rig dashboard showing OpenCode and Pi coding agents, exposed services, and rig controls.](https://mintcdn.com/fixpoint/bkqk3GbCJfRMcAIq/images/amika-sandbox-dashboard.png?fit=max\&auto=format\&n=bkqk3GbCJfRMcAIq\&q=85\&s=12a0ae7c57f98bb6cf200d9825e55419) ## What can an Amika rig do? On a rig, you can * **run 1 or more agents** simultaneously * **expose the HTTPS URLs** of the apps your agent is working on * let rigs and their agents **communicate with each other** * **programmatically control** the rig and its agents * **connect** to the rig from tools like the **Codex app, Cursor, cmux, and Herdr** Each rig can be short-lived or persistent, depending on whether you want it to disappear when your PR is done, or whether you want to keep it around more permanently. Amika **automatically wires your Git repos and agent configs and credentials** into each rig. ## What can you use Amika for? Since Amika runs isolated VMs on your machines or in its cloud, and then gives you networking, agent messaging, and chat UIs, you can use it in many ways. Some examples: * give your agents a cloud machine that keeps running even when you close your own laptop * give engineers **devboxes** that are pre-configured with your tech stack * build **managed agents** that you **control via API** to automate work in the background * **plug into your GitHub CI** to not only run unit tests, but **auto-fix failures** * **talk with agents** from other **tools like Slack and Linear** You can use Amika for anything where you need isolated VMs and control over the VMs, their agents, and their file contents or git repos. ## Start here > **[What is a rig?](/guides/what-is-a-rig)** > > Learn how rigs give each agent its own isolated devbox VM. > **[Quickstart](/quickstart)** > > Install the CLI and create your first rig. > **[Run on your own machines](/guides/byoc)** > > Register a machine you own as a host and run rigs on it. > **[Repository configuration](/reference/repository-configuration)** > > Configure rig defaults with .amika/config.toml, including precedence > rules and multi-repo or repo-less rigs. > **[CLI reference](/reference/cli)** > > Browse command syntax, key flags, and examples. > **[Pricing](https://www.amika.dev/pricing)** > > Free for up to 3 active users. Your own machines are never metered. ## Product links > **[Website](https://www.amika.dev)** > > Read product overview and use cases. > **[Pricing](https://www.amika.dev/pricing)** > > Pay per active user. Hosted compute bills per second. > **[GitHub](https://github.com/gofixpoint/amika)** > > View source code and contribute. # Install Source: https://docs.amika.dev/install Install the Amika CLI and SDKs. ## CLI The Amika CLI is a single binary that runs on macOS and Linux. ### Quick install ```bash theme={null} curl -fsSL https://raw.githubusercontent.com/gofixpoint/amika/main/install.sh | sh ``` This downloads the latest release, verifies its SHA-256 checksum, and installs it to `/usr/local/bin`. ### Verify the installation ```bash theme={null} amika --version ``` ### Options #### Install a specific version ```bash theme={null} curl -fsSL https://raw.githubusercontent.com/gofixpoint/amika/main/install.sh | sh -s -- --install-version 0.23.0 ``` #### Custom install directory Set `AMIKA_INSTALL_DIR` to install somewhere other than `/usr/local/bin`: ```bash theme={null} curl -fsSL https://raw.githubusercontent.com/gofixpoint/amika/main/install.sh | AMIKA_INSTALL_DIR=~/.local/bin sh ``` Make sure the directory is on your `PATH`. #### Install another component The installer also installs Amika's separately versioned binaries. Pass `--component` with `amika` (the default), `amikad` (the daemon that runs inside a rig), or `amikalog` (the agent session capture CLI, see [Capture agent sessions](/guides/capture-agent-sessions)): ```bash theme={null} curl -fsSL https://raw.githubusercontent.com/gofixpoint/amika/main/install.sh | sh -s -- --component amikalog ``` `--install-version` applies to the component you pick. #### Dry run Preview what the installer would do without downloading or installing anything: ```bash theme={null} curl -fsSL https://raw.githubusercontent.com/gofixpoint/amika/main/install.sh | sh -s -- --dry-run ``` ### Shell completion `amika completion ` prints a completion script for `bash`, `zsh`, `fish`, or `powershell`. For example, to load zsh completion in the current shell: ```bash theme={null} source <(amika completion zsh) ``` Run `amika completion --help` for how to install it permanently. ### Supported platforms | OS | Architecture | | - | - | | Linux | x86\_64, arm64 | | macOS | x86\_64 (Intel), arm64 (Apple Silicon) | ### Build from source ```bash theme={null} git clone https://github.com/gofixpoint/amika.git && cd amika make build-cli # Binary is at dist/amika ``` ## SDKs Install the Typescript SDK with: ```bash theme={null} npm install @amika/sdk ``` See the [TypeScript quickstart](/sdks/typescript/quickstart) to get started. SDKs for more languages are on the way — in the meantime you can use the [CLI](/reference/cli) or the [HTTP API](/reference/api-reference) directly. # Quickstart Source: https://docs.amika.dev/quickstart Install the CLI and create your first rig. This quickstart walks you through a minimal Amika flow: 1. Log into Amika. 2. Install the CLI. 3. Create a rig and message a sandboxed agent from the CLI. 1. You can also use the web UI or the TypeScript SDK. ## Prerequisites * macOS or Linux ## Step 1: Sign up Sign up at [https://app.amika.dev/signup](https://app.amika.dev/signup) and follow onboarding. ## Step 2: Set up the CLI 1. Download the CLI ```bash theme={null} curl -fsSL https://raw.githubusercontent.com/gofixpoint/amika/main/install.sh | sh ``` 2. Login, and sync your Claude and/or Codex credentials ```bash theme={null} amika auth login amika secret codex push --type oauth --name "Codex Subscription" amika secret claude push --type oauth --name "Claude Subscription" ``` ## Step 3: Create rigs and message agents Now, you can either (a) create a rig and then connect to it however you choose, or (b) directly start an agent chat session, which will provision its own rig behind the scenes. Both can be done from the [https://app.amika.dev/](https://app.amika.dev/), and also from the CLI. ### Create a rig If you want to create a rig and then chat with it from Codex, Cursor, OpenCode, SSH, etc., you can create a rig without first making an agent session. Assuming you connected GitHub during web onboarding: ```bash theme={null} # make sure you uploaded an SSH key amika secret ssh-keygen cd path/to/git/repo/you/want/to/work/on amika rig create --name my-first-rig amika rig ssh my-first-rig ``` This spins up a rig, pre-loaded with your Git repo and agent credentials. List your rigs with: ```bash theme={null} amika rig list ``` ### Create an agent chat session ```bash theme={null} cd path/to/git/repo/you/want/to/work/on amika send --agent codex "What does this repo do?" ``` This will spin up a rig in the background and send the message to a Codex agent on the rig. You can list agent sessions with: ```bash theme={null} amika session list ``` ## Make an API key To use Amika programmatically, you can generate an API key. Either go to [https://app.amika.dev/settings/api-keys](https://app.amika.dev/settings/api-keys) or after logging into the `amika` CLI, run `amika auth api-key create --help` and then create and store a key. ## Next steps > **[Create a rig](/guides/create-a-rig)** > > Spin up a rig loaded with your repo and agent credentials. > **[Send a message to an agent](/guides/send-a-message-to-an-agent)** > > Run Claude, Codex, or another agent inside a rig synchronously. > **[Rig and repository configuration](/guides/configuration)** > > Each rig boots from a repository, whose `.amika/config.toml` configures the rig and agents. > **[Remote control agents and rigs](/guides/remote-control)** > > Remote-control agents and rigs from Slack, Linear, the Codex app, or SSH. ## See also > **[CLI reference](/reference/cli)** > > Full flag listing for every `amika` command. > **[TypeScript SDK](/sdks/typescript/quickstart)** > > Method-by-method reference, types, and errors. > **[HTTP API](/reference/api-reference)** > > Interactive docs and OpenAPI spec for the hosted API. # API reference Source: https://docs.amika.dev/reference/api-reference Interactive docs, OpenAPI spec, and LLM context for the hosted Amika API. The hosted Amika platform at [app.amika.dev](https://app.amika.dev) exposes a versioned REST API. Use the resources below to explore and integrate with it. > **[Interactive docs](https://app.amika.dev/api/docs)** > > Browse endpoints, try requests, and view response schemas in the browser. > **[OpenAPI spec](https://app.amika.dev/api/v0beta1/openapi.json)** > > Machine-readable OpenAPI 3 specification for code generation and tooling. > **[llms.txt](https://app.amika.dev/api/v0beta1/llms.txt)** > > LLM-friendly plain-text reference for AI-assisted development. # Authentication Source: https://docs.amika.dev/reference/auth CLI login flows, credential precedence, and session storage. This page is the reference for how the `amika` CLI authenticates to the hosted platform. For a task-oriented walkthrough, see the [Manage secrets](/guides/manage-secrets) guide. > [!NOTE] > > The TypeScript SDK does **not** use any of the stored credentials below. It > requires you to pass an `apiKey`, an `accessToken`, or a `tokenSource`. See > [Token sources](/sdks/typescript/token-sources). The HTTP API takes an API key > as a bearer token. See the [HTTP API overview](/reference/http-api-overview). ## Login modes `amika auth login` has two modes: * **Browser login**: interactive device authorization flow. Best for local development. * **API key login**: non-interactive, for CI and automation. ## Browser login The default `amika auth login` authenticates with Amika using a device authorization flow. ```bash theme={null} # Log in (opens browser) amika auth login # Check login status amika auth status # Log out amika auth logout ``` ### How it works 1. The CLI requests a device code from Amika. 2. A user code is displayed and the browser opens for you to authorize. 3. The CLI polls Amika until you complete authorization. 4. The session (access token, refresh token, email, org) is saved to `${XDG_STATE_HOME}/amika/workos-session.json`. 5. Access tokens are automatically refreshed when within 60 seconds of expiry. ## API key login Use an Amika API key when you need to authenticate without a browser, for example from CI jobs or automated scripts. ### Create a key Generate API keys in the web UI at [app.amika.dev/settings/api-keys](https://app.amika.dev/settings/api-keys) in the **API Keys** section. Or create one from the CLI with [`amika auth api-key create`](/reference/cli#amika-auth-api-key-create). It writes the key to a file and never prints it. This command ships in the next CLI release, so use the web UI until then. ```bash theme={null} amika auth api-key create --name ci --out ./amika-key amika auth login --api-key-file ./amika-key ``` Keys are scoped to your organization by default. Pass `--scope user` for a key that acts as you. ### Use the key **Environment variable** (highest priority): ```bash theme={null} export AMIKA_API_KEY= amika auth status ``` When `AMIKA_API_KEY` is set, it overrides any stored API key or browser session. Good for ephemeral CI runs. **Store on disk** with `amika auth login --api-key-file`: ```bash theme={null} # From a file amika auth login --api-key-file ./key.txt # From stdin, which pairs well with secret managers vault kv get -field=key secret/amika | amika auth login --api-key-file - ``` The key is written to `${XDG_STATE_HOME}/amika/api-key.json` with `0600` permissions. ## Credential precedence When multiple credentials are present, `amika` picks the first one that is set, in this order: 1. `AMIKA_API_KEY` environment variable 2. Stored API key file (`${XDG_STATE_HOME}/amika/api-key.json`) 3. Browser login session (`${XDG_STATE_HOME}/amika/workos-session.json`) `amika auth status` prints the active source and warns if a lower-priority credential is being shadowed. `amika auth logout` clears both the stored API key and the browser session. ## Local credential discovery `amika secret extract` discovers API credentials that coding agent tools store on your machine, shows them masked, and with `--push` uploads them to the Amika secrets store. See [Manage secrets](/guides/manage-secrets). ```bash theme={null} # Show detected credentials amika secret extract # Push them to the secrets store after confirmation amika secret extract --push # Skip OAuth sources amika secret extract --no-oauth ``` ### Supported sources Amika reads sources in priority order. Higher-priority sources win when multiple files provide the same provider key. | Priority | Source | Files | Providers | | - | - | - | - | | 500 | Claude API key | `~/.claude.json.api`, `~/.claude.json` | Anthropic | | 400 | Claude OAuth | `~/.claude/.credentials.json`, `~/.claude-oauth-credentials.json` | Anthropic | | 300 | Codex | `~/.codex/auth.json` | OpenAI | | 290 | Amika env cache | `${XDG_CACHE_HOME}/amika/env-cache.json` | Any | | 280 | Amika keychain | `${XDG_DATA_HOME}/amika/keychain.json` | Any | | 270 | Amika OAuth | `${XDG_STATE_HOME}/amika/oauth.json` | Any | | 200 | OpenCode | `~/.local/share/opencode/auth.json` | Any | | 100 | Amp | `~/.amp/config.json` | Anthropic | ### Secret names Amika normalizes provider names and uses common aliases as secret names: * Anthropic keys become both `ANTHROPIC_API_KEY` and `CLAUDE_API_KEY`. * OpenAI keys become both `OPENAI_API_KEY` and `CODEX_API_KEY`. Provider names are canonicalized before deduplication: `claude` and `anthropic` become `anthropic`, `codex` and `openai` become `openai`, and other providers are lowercased with separators normalized to hyphens. OAuth tokens with an `expiresAt` or `expires` timestamp are skipped if expired. ### `secret extract` flags | Flag | Default | Description | | - | - | - | | `--push` | `false` | Push discovered secrets to the remote store after confirmation | | `--only ` | | Comma-separated list of secret names to include | | `--scope ` | `user` | Secret scope for pushed secrets: `user` or `org` | | `--homedir ` | `$HOME` | Override home directory for discovery | | `--no-oauth` | `false` | Skip OAuth credential sources | ## Environment variables | Variable | Default | Description | | - | - | - | | `AMIKA_API_KEY` | | Amika API key used to authenticate CLI requests. Overrides any stored API key or browser session when set | | `AMIKA_API_URL` | `https://app.amika.dev` | Override the remote API base URL. | | `AMIKA_WORKOS_CLIENT_ID` | | Override the default WorkOS client ID. If you change `AMIKA_API_URL`, you likely need to update this too | ## Related docs * [Manage secrets](/guides/manage-secrets): push and inject credentials * [Secrets reference](/reference/secrets): scope model and provider secrets * [Storage paths](/reference/storage): where sessions and caches live # CLI reference Source: https://docs.amika.dev/reference/cli Commands, flags, and examples for the Amika CLI. Use this page as the command index for the `amika` CLI. ## Global flags Most commands accept `-o`/`--output` to choose how they print their result, so you can read output at a terminal and pipe the same command into a script or `jq`. | Value | Description | | - | - | | `text` | Human-readable text (the default) | | `json` | Compact, single-line JSON, for piping | | `json-pretty` | Indented, multi-line JSON, for reading | ```bash theme={null} # Capture a new rig's name in a script name=$(amika rig create --no-git -o json | jq -r .name) # Delete several rigs and inspect per-item results amika rig delete a b c --force -o json | jq '.[] | select(.status=="error")' ``` Most list commands emit a JSON array. `snapshot list` is the exception and emits a `{ "items": [...] }` object. In JSON mode the CLI never prompts, so destructive commands need their confirmation flag (`--force` for deletes, `--no-interactive` for `snapshot create`). Progress messages go to stderr, so stdout carries only the JSON value. Commands that open a shell or an editor (`rig connect`, `rig open`, `rig create --connect`) and commands that show a masked credential table and ask for confirmation (`secret extract`, `secret push`) reject `-o json`. `rig ssh` and `scp` hand their arguments to the system `ssh` and `scp`, so they don't take `--output` at all. ### Naming the current rig Inside a rig, any argument or flag that names a rig also accepts `_self`, which resolves to the current rig from the `AMIKA_RIG_NAME` environment variable: ```bash theme={null} amika service list --rig-name _self amika service create --rig _self --name web --port 3000 --url-scheme https ``` ## `amika rig` Manage rigs. > [!NOTE] > > `amika sandbox` remains available as a compatibility alias. Use `amika rig` in > new commands and scripts. ### Global rig flags Rigs always run remotely, on Amika Cloud or on one of your organization's own hosts. `--remote` remains an accepted no-op for compatibility. The retired `--local` flag is hidden and returns an error. ### Create ```bash theme={null} # Use the current Git repository and generate a rig name amika rig create # Use the repository containing a specific path amika rig create --name dev-rig --git ./src # Use a remote Git repository amika rig create --name dev-rig \ --git https://github.com/gofixpoint/example-repo.git # Use the preset that includes Docker amika rig create --name dind-box --preset coder-plus-docker # Set environment variables amika rig create --name dev-rig --env MY_KEY=my_value # Create and immediately connect amika rig create --name dev-rig --connect # Override the setup script amika rig create --name dev-rig --setup-script ./install-deps.sh # Clone a specific git branch amika rig create --name dev-rig --branch develop # Create a new branch from your current branch amika rig create --new-branch feature-x # Create a new branch starting from a specific existing branch amika rig create --branch main --new-branch bugfix-1 # Inject a stored secret amika rig create --name dev-rig \ --secret env:ANTHROPIC_API_KEY=my-claude-key # Pin which agent credential gets injected at create time amika rig create --name dev-rig \ --agent-credential-type claude=api-key \ --no-agent-credential codex # Fork from a captured snapshot amika rig create --name dev-rig --snapshot example-repo-base # Run on one of your organization's own hosts, at one of that host's sizes amika rig create --name dev-rig --host alpha.lan --size small # Create a rig without a repository amika rig create --name scratch --no-git ``` ### Create flags | Flag | Default | Description | | - | - | - | | `--name ` | auto-generated | Name for the rig. If omitted, a random `{color}-{city}` name is generated | | `--preset ` | repository or platform default | Use `coder` or `coder-plus-docker` | | `--size ` | repository or platform default | Rig size, such as `m` or `a1.medium`. With `--host`, one of that host's own sizes instead, defaulting to 4 vCPU, 8 GiB memory, and a 20 GiB disk | | `--host ` | | Run the rig on one of your organization's own hosts rather than on Amika Cloud. See [`amika host`](#amika-host). With `--snapshot`, the snapshot must have been taken on that same host; any other snapshot is refused | | `--snapshot ` | | Fork from a captured snapshot | | `--git ` | auto-detected | Use a local repository path or a Git URL. If omitted, the CLI detects a repository from the current directory | | `--no-git` | `false` | Skip git repo auto-detection; create a repo-less rig with no repo mounted | | `--env ` | | Set environment variable. Repeatable | | `--secret ` | | Inject a stored secret (`env:FOO=SECRET_NAME` or `env:SECRET_NAME`). Repeatable | | `--connect` | `false` | Connect to the rig shell immediately after creation | | `--setup-script ` | | Upload a local setup script | | `--no-setup` | `false` | Replace the configured setup script with a no-op script | | `--branch ` | | Check out this branch, or create it if the remote has none | | `--new-branch ` | | Create a new branch from `--branch` or the inferred base branch | | `--github-auth-mode ` | platform default | GitHub authentication mode: `pat`, `app_token`, or `app-token` | | `--agent-credential ` | | Pin an agent credential by stored name (e.g. `claude=personal-oauth`). Repeatable per kind | | `--agent-credential-type ` | | Pin an agent credential by type, where `TYPE` is `oauth` or `api-key` (e.g. `claude=oauth`). Repeatable per kind | | `--no-agent-credential ` | | Skip injecting any credential of this kind (e.g. `codex`). Repeatable per kind | > [!NOTE] > > `--no-setup` and `--setup-script` are mutually exclusive. > [!NOTE] > > Supported agent kinds for `--agent-credential`, `--agent-credential-type`, and `--no-agent-credential` are `claude` and `codex`. Each flag may appear at most once per kind. `--no-agent-credential` is mutually exclusive with the other two for the same kind. See [Inject credentials](/guides/inject-credentials) for usage. > [!NOTE] > > Rigs clone from the repository remote. Push local commits before creation. The > CLI rejects an inferred branch that is not present and up to date on `origin`. ### List Aliases: `ls` ```bash theme={null} amika rig list amika rig ls --long ``` Output columns: `NAME`, `STATE`, `REPO`, `BRANCH`, `CREATOR`. `--long` adds `ID`, `BASE_SNAPSHOT`, `PORTS`, and `CREATED`. `CREATOR` shows `-` when the creator is unknown, for example for a rig an API key created. | Flag | Default | Description | | - | - | - | | `-l`, `--long` | `false` | Show additional columns | Column selection only applies to text output. `-o json` always includes every field. ### Get Show one rig by name or ID. ```bash theme={null} amika rig get dev-rig amika rig get dev-rig -o json ``` Text output prints one `key: value` per line, with dotted keys for nested fields. `ssh_host` is the rig's SSH alias from `~/.ssh/amika.conf`, which you can use with `ssh`, `scp`, or an editor's Remote-SSH. ### Connect Open an interactive shell in a rig. `connect` is the shell-only form of [`rig ssh`](#ssh) and uses the same transport. It takes no flags. ```bash theme={null} amika rig connect dev-rig ``` The shell starts in `/home/amika`. Like `rig ssh`, it needs an SSH key from [`amika secret ssh-keygen`](#amika-secret-ssh-keygen). ### Delete Aliases: `rm`, `remove` ```bash theme={null} amika rig delete dev-rig amika rig rm dev-rig amika rig delete rig-1 rig-2 amika rig delete dev-rig --force ``` | Flag | Default | Description | | - | - | - | | `--force` | `false` | Skip confirmation prompt | ### Stop Stop one or more running rigs without removing them. ```bash theme={null} amika rig stop dev-rig amika rig stop rig-1 rig-2 ``` ### Start Start (resume) one or more stopped rigs. ```bash theme={null} amika rig start dev-rig amika rig start rig-1 rig-2 ``` ### SSH Aliases: `sshv2` SSH into a rig. Use it like `ssh`: options go before the rig name, and an optional command goes after it. Every `ssh` option works, including port forwarding. Requires an SSH key from [`amika secret ssh-keygen`](#amika-secret-ssh-keygen). ```bash theme={null} amika rig ssh [ssh-options] [command...] ``` ```bash theme={null} # Interactive shell amika rig ssh my-rig # Run a command instead of opening a shell amika rig ssh my-rig uptime # Force pseudo-terminal allocation for an interactive program amika rig ssh -t my-rig top # Forward local port 6789 to port 3010 in the rig, without a shell amika rig ssh -N -L 6789:localhost:3010 my-rig # SOCKS proxy on local port 1080 amika rig ssh -N -D 1080 my-rig ``` `rig ssh` has no flags of its own: everything after `ssh` goes to `ssh`. Write Amika's own flags before `ssh`, as in `amika rig --remote ssh my-rig`. Local (`-L`), dynamic (`-D`), and agent forwarding are supported. Agent forwarding uses a dedicated agent that holds only your Amika SSH key, so your other keys never reach the rig. Remote (`-R`) and X11 forwarding are not supported. ### Open Aliases: `code`, `codev2` Open a rig in an editor or app over SSH. The command adds a named SSH host to Amika's managed SSH config, then starts or configures the app you pick. Requires an SSH key from [`amika secret ssh-keygen`](#amika-secret-ssh-keygen). > [!NOTE] > > `rig open`, `--app`, and the `herdr` app ship in the next CLI release. In > v0.23.0 and earlier, run `amika rig code --editor ` instead. It > supports every app except `herdr`. ```bash theme={null} amika rig open my-rig amika rig open my-rig --app vscode amika rig open my-rig --app codex amika rig open my-rig --app herdr amika rig open my-rig --path /home/amika/workspace/other-repo ``` | Flag | Default | Description | | - | - | - | | `--app ` | `cursor` | App to open: `cursor`, `vscode`, `claude`, `codex`, `paseo`, or `herdr` | | `--editor ` | | Alias for `--app` | | `--path ` | | Remote path to open, absolute or relative to the rig workspace. Ignored by `paseo` and `herdr` | What each app does: | App | Behavior | | - | - | | `cursor` | Launches Cursor connected to the rig | | `vscode` | Launches VS Code connected to the rig | | `claude` | Registers the rig as a Claude Desktop SSH environment, then opens Claude Desktop | | `codex` | Turns on Codex remote connections, then opens Codex. See [Codex app](/guides/codex-app) | | `paseo` | Prints the SSH host to add in Paseo. See [Paseo](/guides/paseo) | | `herdr` | Runs `herdr machine add` to save the rig as a Herdr machine labeled with the rig name. Requires the `herdr` CLI on your `PATH` | See [Open in your editor](/guides/open-in-editor) for setup details. ### Agent Send Send a message to a coding agent in an existing rig. This is the rig-scoped form of [`amika send --rig `](#amika-send), with the same session handling, streaming, and JSON output. The message can be a positional argument or piped through stdin. The command waits for the agent to finish. Without `--session-id` or `--new-session`, the message continues the latest API chat on the rig, or starts one if there is none. The session ID is printed to stderr as `session_id: `. ```bash theme={null} # Send a message to the default agent amika rig agent-send my-rig "Add unit tests for the auth module" # Pipe a message through stdin echo "Fix the failing tests" | amika rig agent-send my-rig # Continue a specific chat amika rig agent-send my-rig "Continue the review" --session-id # Use a different agent and get JSON back amika rig agent-send my-rig "Review this code" --agent codex -o json ``` | Flag | Default | Description | | - | - | - | | `--agent ` | existing chat or organization setting, else `claude` | Coding agent: `claude` or `codex` | | `--session-id ` | | Continue a chat returned by an earlier send | | `--new-session` | `false` | Start a new chat | | `--stream[=false]` | on for a terminal | Stream the reply as the agent writes it. JSON output is always buffered | ## `amika send` Send a message to a coding agent and keep the conversation as a chat. Name an existing rig with `--rig`, continue a chat with `--session-id`, or omit both to create a new rig for the chat. ```bash theme={null} # Create a rig from the current repository and start a chat amika send "What does this repo do?" # Use a specific agent amika send --agent codex "Summarize the open TODOs" # Send into an existing rig amika send "Fix the tests" --rig my-rig # Continue a chat amika send "Now update the README" --session-id ``` When `send` creates a rig, repository and branch selection work like [`rig create`](#create): the current Git repository and branch are used unless `--git`, `--no-git`, `--branch`, or `--new-branch` say otherwise. These flags can't be combined with `--rig` or `--session-id`. | Flag | Default | Description | | - | - | - | | `--agent ` | existing chat or organization setting, else `claude` | Coding agent: `claude` or `codex` | | `--rig ` | | Send into an existing rig | | `--session-id ` | | Continue an existing chat | | `--new-session` | `false` | Start a new chat | | `--git ` | auto-detected | Repository to clone into the new rig | | `--no-git` | `false` | Create the new rig without a repository | | `--branch ` | current branch | Branch to check out in the new rig | | `--new-branch ` | | Create a new branch in the new rig | | `--stream[=false]` | on for a terminal | Stream the reply as the agent writes it. JSON output is always buffered | In text output, the reply goes to stdout and metadata such as `session_id` goes to stderr. With `-o json`, the command prints one object with `session_id`, `sandbox_id`, `agent`, `response`, `is_error`, `is_new_session`, `created_sandbox`, and optional `usage`. If the agent fails, the command still prints its response, then exits with an error. `--repo` is a deprecated alias for `--git`. ## `amika sessions` Aliases: `session` List and read the agent chats created by `amika send` and `amika rig agent-send`. ### List ```bash theme={null} amika sessions list amika sessions list --limit 100 ``` Output columns: `SESSION ID`, `AGENT`, `STATUS`, `SANDBOX`, `UPDATED`. | Flag | Default | Description | | - | - | - | | `--limit ` | server page size (50) | Maximum number of chats to list | ### Show Print a chat's details and every message in it. ```bash theme={null} amika sessions show ``` ## `amika scp` Aliases: `scpv2` Copy files between your machine, rigs, and other SSH hosts. `amika scp` wraps the system `scp`: every argument is passed through, so the usual `scp` flags (`-r`, `-p`, `-C`, `-v`) work. Requires an SSH key from [`amika secret ssh-keygen`](#amika-secret-ssh-keygen). ```bash theme={null} amika scp ... ``` | Form | Meaning | | - | - | | `PATH` | A local path | | `NAME:PATH` | A path in rig `NAME`. A relative path is under `/home/amika` | | `sbox://NAME/PATH` | A path in rig `NAME`, in URI form. `~` is the home directory | | `scp://[user@]host[:port]/path` | A path on any other SSH host | A bare `host:path` always names a rig. Use an `scp://` URI to reach another SSH host. ```bash theme={null} # Upload a file into the rig's home directory amika scp ./local.txt my-rig:local.txt # Download a directory recursively amika scp -r my-rig:/srv/out ./out # Copy from a rig to another SSH host amika scp my-rig:/data.csv scp://user@host:22/tmp/data.csv # Print the resolved scp command instead of running it amika scp --print ./a.txt my-rig:a.txt ``` | Flag | Default | Description | | - | - | - | | `--print` | `false` | Print the resolved `scp` command instead of running it | ## `amika snapshot` Manage snapshots captured from running rigs. See [Create a snapshot](/guides/create-a-snapshot) for the end-to-end flow. ### Create Capture a snapshot from a running rig. Interactive by default: it prompts for the capture mode and name, and for `scrub_and_delete` it previews the injected secrets that will be removed and asks for confirmation. Pass `--no-interactive` for a non-prompting run, which then requires `--mode` and `--name`. ```bash theme={null} # Interactive amika snapshot create --rig base-box # Non-interactive amika snapshot create --rig base-box \ --name example-repo-base --mode scrub_and_delete --no-interactive ``` | Flag | Default | Description | | - | - | - | | `--rig ` | **(required)** | Source rig to snapshot | | `--name ` | | Name for the snapshot (prompted if omitted in interactive mode) | | `--mode ` | | Capture mode: `scrub_and_delete` or `full` (required with `--no-interactive`) | | `--description ` | | Optional description shown in the snapshot list | | `--no-interactive` | `false` | Do not prompt; requires `--mode` and `--name` | Capture modes: | Mode | Behavior | | - | - | | `scrub_and_delete` (default) | Remove Amika-injected secrets, capture the snapshot, then delete the source rig | | `full` | Capture everything as-is (keeps secrets and the source rig; unsafe for shared images) | Capture runs in the background; check progress with `amika snapshot list`. A snapshot of a rig on one of your own hosts stays on that host and can only boot rigs there. See [Bring your own compute](/guides/byoc). ### List Aliases: `ls` ```bash theme={null} amika snapshot list amika snapshot ls --long amika snapshot list --rig base-box amika snapshot list --repo example-repo ``` Output columns: `NAME`, `STATE`, `PROVIDER`, `SOURCE`, `CREATED`. `--long` adds `HOST`, `SIZE`, `BASE`, `DESCRIPTION`, and `ERROR`. `HOST` names the host a snapshot was taken on, if it came from one of your own hosts. | Flag | Default | Description | | - | - | - | | `-l`, `--long` | `false` | Show additional columns | | `--rig ` | | Only show snapshots captured from this rig | | `--repo ` | | Only show snapshots for this repository | ### Delete Aliases: `rm`, `remove` ```bash theme={null} amika snapshot delete example-repo-base amika snapshot rm snap-1 snap-2 amika snapshot delete example-repo-base --force ``` | Flag | Default | Description | | - | - | - | | `-f`, `--force` | `false` | Skip confirmation prompt | ## `amika service` Aliases: `services` Manage the services on your rigs. See [Services](/reference/services) for how to declare services in `.amika/config.toml`. ### List Aliases: `ls` ```bash theme={null} amika service list amika service ls amika service list --rig-name dev-rig ``` Output columns: `SERVICE`, `SANDBOX`, `PORTS`, `URL`. | Flag | Default | Description | | - | - | - | | `--rig-name ` | (none) | Filter services to a specific rig | ### Create Add a service to a running rig, for a port you start listening on after the rig is created. ```bash theme={null} amika service create --rig dev-rig --name web --port 3000 --url-scheme https ``` | Flag | Default | Description | | - | - | - | | `--rig ` | **(required)** | Rig to add the service to | | `--name ` | **(required)** | Service name, a single DNS label (lowercase letters, digits, and hyphens) | | `--port ` | **(required)** | Port the service listens on in the rig | | `--url-scheme ` | **(required)** | Scheme for the generated URL: `http` or `https` | ### Delete Aliases: `rm`, `remove` ```bash theme={null} amika service delete --rig dev-rig --name web amika service delete --rig dev-rig --name web --force ``` | Flag | Default | Description | | - | - | - | | `--rig ` | **(required)** | Rig the service belongs to | | `--name ` | **(required)** | Service to delete | | `-f`, `--force` | `false` | Skip confirmation prompt | ## `amika host` Aliases: `hosts` Inspect and retire your organization's own hosts (bring your own compute). See [Bring your own compute](/guides/byoc) for the setup flow. A host registers itself when `amika-hostd up` runs on the machine, so there is no command to add one. A rig runs on Amika Cloud unless `amika rig create --host` names one of these hosts. ```bash theme={null} # List the organization's hosts amika host list # Show one host and the sizes it offers amika host get alpha.lan # Delete a host and its stored secret amika host delete alpha.lan ``` ### List Aliases: `ls` Output columns: `HOSTNAME`, `TRANSPORT`, `URL`, `SIZES`. `TRANSPORT` is `tunnel` (connected to Amika's gateway) or `listen` (serves a URL it registered). A `tunnel` host always shows `-` for `URL`. A `listen` host shows `-` until it registers a URL, and can't take rigs until then. ### Get ```bash theme={null} amika host get ``` Shows one host's details and the sizes it offers. Those size names, not the cloud size vocabulary, are what `rig create --host ... --size ...` accepts. ### Delete Aliases: `rm`, `remove` ```bash theme={null} amika host delete [...] ``` | Flag | Default | Description | | - | - | - | | `-f`, `--force` | `false` | Skip confirmation prompt | A host that still has rigs on it is refused: delete those rigs first. The machine itself is untouched, so stop its daemon with `amika-hostd down` or it registers itself again on the next `amika-hostd up`. ## `amika auth` Authentication commands. ### `amika auth login` Log in to Amika via the WorkOS Device Authorization Flow. Opens a browser for you to authorize the CLI. ```bash theme={null} amika auth login ``` To skip the browser flow and log in with an Amika API key, for example in CI, pass `--api-key-file`. Use `-` to read from stdin so the key never lands on disk: ```bash theme={null} amika auth login --api-key-file /path/to/key vault kv get -field=key secret/amika | amika auth login --api-key-file - ``` | Flag | Default | Description | | - | - | - | | `--api-key-file ` | | Read an Amika API key from this path (or `-` for stdin) instead of running the device flow | A successful login also writes Amika's managed SSH config (`~/.ssh/amika.conf`, included from `~/.ssh/config`) and prints the files it touched. See [Authentication](/reference/auth) for details on the login flow and session storage. ### `amika auth status` Show current authentication status. ```bash theme={null} amika auth status ``` Prints the logged-in email and organization, or "Not logged in" if no session exists. ### `amika auth logout` Log out of Amika and remove the saved session. ```bash theme={null} amika auth logout ``` ### `amika auth api-key create` Create an Amika API key and write it to a file. Use API keys for CI jobs, scripts, another machine's CLI, or an `amika-hostd` host daemon. The key's value is shown only once, so the command writes it to `--out` and never prints it, including with `-o json`. > [!NOTE] > > `amika auth api-key create` needs amika CLI v0.24.0 or later. With an older > CLI, create API keys in the web UI at > [app.amika.dev/settings/api-keys](https://app.amika.dev/settings/api-keys). ```bash theme={null} # Create a key owned by you for a host daemon, hand it to setup, remove the file dir=$(mktemp -d) amika auth api-key create --name build-01-hostd --scope user --out "$dir/api-key" amika-hostd setup --non-interactive --hostname build-01 < "$dir/api-key" rm -rf "$dir" # Create a key owned by you and log another machine's CLI in with it amika auth api-key create --name laptop --scope user --out ./amika-key amika auth login --api-key-file ./amika-key ``` | Flag | Default | Description | | - | - | - | | `--name ` | **(required)** | Name for the key, shown in the web app's settings | | `--out ` | **(required)** | File to write the key to. A new file is created with mode `0600` | | `--scope ` | `organization` | `organization` (owned by your organization) or `user` (owned by you) | | `-f`, `--force` | `false` | Replace `--out` if it already exists | The file holds the bare key and a newline, so it works as-is with `amika auth login --api-key-file` and `amika-hostd setup --non-interactive`. The command checks that it can write `--out` before it creates the key. If the write still fails afterward, the error names the key's ID so you can delete it in the web app. A user-scoped key acts as you. Organization-scoped keys have no user behind them, so you can't use one to create a user-scoped key. ## `amika secret` Aliases: `secrets` Manage secrets in the remote Amika secrets store. ### `amika secret extract` Discover locally stored credentials and optionally push them to the remote store. ```bash theme={null} amika secret extract amika secret extract --push amika secret extract --push --only=ANTHROPIC_API_KEY,OPENAI_API_KEY ``` | Flag | Default | Description | | - | - | - | | `--push` | `false` | Push discovered secrets to the remote store after confirmation | | `--only ` | | Comma-separated list of secret names to include (e.g. `ANTHROPIC_API_KEY,OPENAI_API_KEY`) | | `--scope ` | `user` | Secret scope: `user` (private) or `org` (visible to org members) | | `--homedir ` | | Override home directory used for credential discovery | | `--no-oauth` | `false` | Skip OAuth credential sources | See [Local credential discovery](/reference/auth#local-credential-discovery) for the sources it checks. ### `amika secret push` Push secrets to the remote store from inline arguments, environment variables, or a `.env` file. ```bash theme={null} amika secret push ANTHROPIC_API_KEY=sk-ant-xxx amika secret push --from-env=ANTHROPIC_API_KEY,OPENAI_API_KEY amika secret push --from-file=.env amika secret push --from-file=.env CUSTOM_KEY=val --from-env=ANTHROPIC_API_KEY ``` | Flag | Default | Description | | - | - | - | | `--from-env ` | | Comma-separated list of environment variable names to read and push | | `--from-file ` | | Path to a `.env` file containing `KEY=VALUE` secrets | | `--scope ` | `user` | Secret scope: `user` (private) or `org` (visible to org members) | When multiple sources are used, positional arguments override `--from-file` values, and `--from-env` overrides both. ### `amika secret claude` Manage Claude Code credentials for rig authentication. Credentials pushed here can be injected into rigs at creation time. #### `amika secret claude push` Push Claude Code credentials (API key or OAuth token) to the remote Amika secrets store. Scans your system for Claude credentials and lets you choose which one to push. On macOS, the keychain is also checked. ```bash theme={null} # Interactive: discover and select credentials amika secret claude push # Push with a custom label amika secret claude push --name claude-oauth-work-laptop # Push from a credentials file amika secret claude push --from-file ~/.claude/.credentials.json # Push a credential value directly amika secret claude push --value '{"claudeAiOauth":{...}}' # Auto-resolve by type (reads ANTHROPIC_API_KEY env var for api_key) amika secret claude push --type api_key # Share the credential with your organization amika secret claude push --scope org ``` | Flag | Default | Description | | - | - | - | | `--name