简体中文 · 日本語 · Documentation
Run amira in the directory you want it to work in. A positional prompt becomes the first message; --cwd selects a different working directory. See Getting started for provider setup.
To run the agent and tools on a Linux SSH host with the fullscreen UI on your computer, use amira remote add and amira remote attach. Remote workspaces covers setup, configuration ownership, local model proxying and its limits. The remote commands have their own options (amira remote --help); ordinary startup flags and the print/RPC modes below apply to local runs. In remote mode, quitting detaches rather than stopping remote work.
Use amira --thinking high in interactive mode or amira -p --thinking xhigh "Explain this repository" in print mode. Accepted levels are low, medium, high, xhigh and max.
During a session, /thinking opens a picker with those five levels and default (no effort sent). Set one directly with /thinking high, or use /thinking default to keep the server default. These changes last until Amira exits and do not write settings; like the current model, they carry over to the conversation /clear, /resume, a rewind or a fork switches to. The precedence is the session's runtime choice > --thinking > providers.<id>.models[].thinking > top-level thinking in Settings. Choosing default explicitly suppresses all three lower-priority sources; it does not restore the flag or settings. With no choice or configured effort, requests also omit effort.
After you pick a thinking-capable model in the interactive /model picker, a second step offers the same effort choices. Esc at that step keeps the selected model and leaves the effort choice unchanged. Only models with caps.thinking receive effort; the status bar shows it beside the model name, and /status shows it only for those models. Switching to a non-thinking model hides the effort without discarding the choice. Sub-agents inherit the parent's selected effort, while title generation and compaction keep their defaults.
Responses and Anthropic adaptive mode send the level unchanged. Anthropic budget mode maps xhigh to 32,768 tokens, below max at 64,000, capped to leave room for the answer. Gemini maps xhigh like high, keeping its larger max budget for Gemini 2.5 Pro. Chat Completions currently does not send reasoning parameters.
/fast toggles the requested fast-mode preference. /fast on and /fast off set it explicitly; /fast status reports the request, whether it applies to the current model/provider, and the last reply's actual service tier or Claude speed (for example, priority, default, fast or standard). Status does not change the preference. Unsupported models keep the request for a supported one and show the reason it is not applied. The status bar shows fast while fast mode applies, and a muted fast n/a while it is requested but the current model does not support it.
Fast mode requests faster serving, not a different model or thinking effort. Presets depend on the endpoint and model:
| Provider | Preset and limits |
|---|---|
| First-party Claude API | Supported Claude Opus models use Anthropic speed: "fast" (research preview). Fast mode has separate rate limits. This does not automatically enable compatible gateways, Bedrock, Vertex, Foundry or Claude Platform on AWS. |
| OpenAI | Chat Completions and Responses request service_tier: "priority"; availability depends on the model and your account. Priority shares the standard model's rate limits. The response reports the actual tier, which can be standard after a downgrade. |
| xAI | Requests priority for text-only requests. Requests containing images do not apply the tier; priority capacity can fall back to default. |
| Google Gemini | Requests priority on supported models. The x-gemini-service-tier response header reports the tier actually served; capacity overflow can downgrade to standard without an error. |
| OpenRouter | Only selected supported models: OpenAI, Anthropic fast mode, Google Vertex/AI Studio and xAI categories. Availability and pricing depend on the selected model and upstream endpoint; a catalog match alone does not guarantee support. |
| DeepInfra | Priority is available only on models tagged for it. Configure the model's fast service-tier override when supported; unsupported tiers may silently run at standard speed. |
| First-party DeepSeek and Moonshot/Kimi | DeepSeek has no fast request flag. For Kimi, switch to a separate *-highspeed model; /fast does not switch models. |
Pricing and capacity limits depend on the provider. A request can fall back to standard without turning off your preference; changing the preference may invalidate the prompt cache. /cost groups each model's actual reported usage into fast and standard rows, never inferring fast billing from the request. When premium rates are unknown, /fast status warns and /cost marks affected amounts and totals as standard-rate estimates, with a premium pricing unknown note. These are not exact premium charges; verify your provider's current rates before setting optional cost.fast prices.
The default is off. Set "fastMode": true in Settings to request it at startup; that section also shows endpoint/model overrides. Interactive /fast changes save the preference to your user settings and, when allowed, the project's settings.local.json; status and unchanged choices do not save. Print mode, RPC and extension changes do not save it. Sub-agents inherit the preference but apply it only where supported.
amira
amira --cwd /path/to/project "Explain this repository"Amira always uses a full-screen interface. It keeps the transcript on the alternate screen, scrolls and searches it itself, and prints the displayed session to the normal terminal on exit. For plain output without the interface, use amira -p "your prompt". TERM=dumb cannot run the interactive interface; use -p instead.
The setting tui.mode is deprecated and ignored. For one release, tui.mode: "inline" and --inline emit this notice and run fullscreen: inline mode was removed; running fullscreen. Use -p for plain output. The --fullscreen flag remains accepted as a no-op.
The transcript contains your messages, streamed replies, thinking where the model supplies it, tool activity, questions and notices. In full-screen mode, PgUp/PgDn scroll; End returns to the newest output when the input is empty. Ctrl+F searches the transcript. Ctrl+Up selects a block; ↑/↓ move between blocks, Enter folds or unfolds, and y copies. Some terminals need the alternate bindings listed in Keybindings.
Ctrl+O toggles summary and full tool output; from collapsed it returns to summary. /verbose collapsed selects collapsed, and /verbose without an argument still cycles all three levels. Alt+C copies the last reply as Markdown. In full-screen mode dragging selects and copies text; Shift+drag uses the terminal's own selection. Type ? with an empty input to see the keys currently bound.
Enter sends a message while idle. While a turn runs, Enter normally steers it: the message reaches the agent before its next model request, without interrupting a tool already running. Alt+Enter queues a message for after the current turn. Windows Terminal may reserve Alt+Enter; Ctrl+Q is another queue binding. Setting tui.submitWhileWorking to "queue" swaps the two actions.
Shift+Enter inserts a newline where the terminal supports it; Ctrl+Enter is the fallback. Type / for commands, $ for skills and @ followed by part of a path for file completion. See Keybindings for editor, completion and history controls.
Esc stops the current turn; while a slash command such as /ext install is still running, it cancels that command first and keeps your draft. If steering or queued messages are waiting, they are combined in the order you typed them and sent together. Background sub-agents keep running; Sub-agents explains how to stop them. Ctrl+C likewise cancels a running command first, otherwise stops a turn, otherwise clears a nonempty input, otherwise quits. /quit also exits.
The main agent allows up to 500 model calls per turn by default. Set agent.maxSteps in Settings to a nonnegative integer; 0 removes the step limit. --max-steps <n> overrides the setting for one run in both interactive and print modes, without saving it.
This limit applies only to the main agent; sub-agents do not inherit it. Removing the step limit does not change how aborts, budget limits or context errors stop a turn.
Messages can carry PNG, JPEG, GIF and WebP images:
- Paste or drop paths. A paste made only of paths to existing image files (absolute or relative to the working directory, quoted when they contain spaces, or with backslash-escaped spaces as macOS and Linux terminals write dropped paths, or
file://URIs) attaches them. Anything else, such as prose or other files, is pasted as text, and so is an image that cannot be attached, with a notice saying why. - Pick one in the
@file list. An image attaches; other files keep their@pathreference. - Paste from the clipboard with Alt+V (
paste.image; see Keybindings for the other keys). The clipboard's text wins when it has any. This uses PowerShell on Windows,osascript(orpngpastewhen installed) on macOS, andwl-pasteorxclipon Linux; without them a notice says what is missing, and paths still work.
An attachment shows as one placeholder, such as [image 1: screen.png 120 KB], in the input and in the sent message. Backspace or Delete removes it whole; undo, cut and yank keep it. Remove attachments before editing the message in an external editor (Ctrl+G). A message with images is never run as a slash command or skill.
The images in one message are limited to 5 MB in total. Sending them needs a model that accepts images; otherwise a warning appears and the message stays in the input. Images are stored inline (base64) in the session file, so resuming does not need the original files. Image prompts are recalled with ↑ during the run but are not written to the project's prompt history file.
The bundled tools can read, search, write and edit files, run shell commands, search the web and delegate work. Availability depends on the platform, model and loaded extensions. /tools lists the current tools; /tools disable <name> and /tools enable <name> change availability for this session. --disable-tools supplies a comma-separated list at startup. See Settings and Extensions for persistent configuration.
Files are changed with one of two editing tools. edit replaces exact text in one file. apply_patch takes a patch in the Codex format (*** Begin Patch … *** End Patch) that can add, delete, update and move several files at once; it checks every hunk before writing anything and rolls back what it wrote if a write fails. Each model gets edit unless its provider settings choose otherwise; see Editing tools. write is always available. /tools lists the tool the current model does not use as disabled, with the reason, and /tools enable cannot turn it on; change the setting instead.
grep and glob skip what git would: .git, node_modules, files excluded by .gitignore files, .git/info/exclude or the global excludes file, and directories that hold another repository or a linked worktree (such as .claude/worktrees/* inside a checkout). Submodules of the searched repository are searched. A path you pass explicitly is searched even if it is ignored itself. Results outside the working directory are shown as absolute paths marked [outside working directory].
Approval requests come from the permission policy and from extensions, which can block a tool call or require approval before it runs. A request shows the tool, the reason (with the mode or rule that caused it) and a preview or arguments. Select an option with the arrows, then Enter; confirmations begin with no option selected. Esc denies the call and stops the turn.
When offered, Don't ask again allows that tool for the same stated reason, for the rest of the session; it does not save a persistent permission. A sub-agent's permission questions go to you, not to its parent; questions an extension raises for a sub-agent are still decided by the parent agent's model. Print mode cannot answer dialogs, so requested approvals are denied and questions are cancelled. RPC clients must answer UI requests explicitly; once an RPC client closes stdin, approvals are denied.
The permission mode decides what the model may do without asking. It applies to the whole session, including sub-agents.
| Mode | What it does |
|---|---|
auto (default) |
Runs everything without asking, except where your rules or protected files say otherwise |
edits |
Changes files without asking; asks before shell commands your allow rules do not cover |
plan |
Read-only: no file changes and no shell commands; asks before tools it does not know to be read-only, such as MCP tools |
Press Shift+Tab in the UI to cycle auto, edits and plan; a mode other than auto shows next to the model in the input box's border. --permission-mode <mode> or "permissions": {"mode": "edits"} in settings chooses the mode at startup. Plan mode blocks every shell command for now, because Amira cannot yet prove that a command only reads.
Command rules allow, ask about or deny shell commands by their words:
{
"permissions": {
"mode": "edits",
"rules": [
{ "command": ["git", "status"], "decision": "allow" },
{ "command": ["git", "push"], "decision": "ask", "reason": "Review what goes out" },
{ "command": ["rm", "-rf"], "decision": "deny" }
]
}
}A rule matches the words of a command (its argv), not the text: git status --short matches ["git", "status"], git statusx does not. For ask and deny rules the command name also matches as a path or with a Windows extension (/usr/bin/git, git.exe), and in PowerShell under its built-in aliases (rm, del and Remove-Item are one command); they also match when other words come between theirs (git -C repo push matches ["git", "push"]) and ignore case. allow rules must match the start of the command exactly, and only a command named without a path (x/git status is not git status) unless the rule itself names that path. When several rules match, deny wins over ask and ask over allow. allow only means "do not ask": it never lifts plan mode or a protected file.
Commands joined with &&, ||, ;, | or newlines are split and each part is checked. Commands Amira cannot check word by word ask instead: substitutions such as $(...) and backticks, variables, redirections into files, here-documents and here-strings, grouping, file name patterns (*, ?, [...]), wrappers that run other commands (eval, sudo, xargs, bash -c, Invoke-Expression, Start-Process, interpreters), commands that define aliases (alias, Set-Alias, git -c, git config alias.*) and scripts. In auto mode they still run without asking unless you have ask or deny rules. Commands are read the way the shell that runs them reads them: bash or PowerShell, including the bash tool falling back to PowerShell on Windows.
Shell commands already start in the working directory; use cd only when a command needs another directory. Bash runs foreground and background commands with pipefail, so a failed pipeline component keeps a non-zero status: bun test | tail fails when the tests fail. A pipeline whose last command succeeds and whose earlier commands only succeeded or were killed by SIGPIPE (141), such as git log | head, is treated as successful; other non-zero pipeline statuses still fail. Only the command's final status changes: inside the command such a pipeline still fails, so a following && does not run (git log | head && echo done prints no done). Limit output with the command's own options, such as git log -n 5, when more commands follow. PowerShell has no pipefail option, but its wrapper preserves a failing native command's $LASTEXITCODE through a native pipeline; cmdlet pipelines follow PowerShell's $? rules.
Rules make Amira ask or refuse; they are not a sandbox. A command can still reach a denied program another way, for example through a copy or link of it, or through a script the model wrote earlier. Use deny for mistakes worth stopping, not as a security boundary.
The user file's rules always apply. A project's .amira/settings.json or .amira/settings.local.json can only tighten: its mode counts when it is stricter than yours, its ask and deny rules apply, and its allow rules apply only after you trust the project (amira ext trust, the same trust its extension packages need). What a project file is not allowed to change is reported at startup. --permission-mode wins over every file. /permissions lists the mode, every rule with the file it comes from and what was left out; /status shows the mode and the number of rules.
Some files normally require protected-write approval before write, edit or apply_patch (or an extension tool that declares the paths it writes) changes them: .amira directories (settings, packages and lock files) and Amira's user directory, .git (hooks, config and the rest of Git's metadata, including a linked worktree's Git directory), .gitmodules, the directory core.hooksPath names and your global Git config. Other names for the same file count too (a different case, ../, absolute or MSYS paths, links). Shell commands can still change these files: commands do not run in a sandbox yet.
A narrow exception lets an extension tool maintain its own state in its host-assigned api.dataDir. The tool must explicitly declare traits.writesFiles: "paths" and provide getWrittenPaths; every path in the combined write reports must be securely contained in that extension's directory. Mixed inside/outside reports get no partial exemption; outside paths keep the normal protected-path checks. Unknown or unsafe resolution asks for approval. This only removes protected-write approval: plan mode still denies writes, shell rules and extension interceptor approval requests are unchanged, and sub-agents follow the same policy. Path reports are trusted declarations, not a sandbox or a race-free guarantee of exclusive access to the files.
A refused call tells the model why and that asking you is the way forward. In print mode, and in RPC once no client can answer, anything that would ask is refused with the reason. Print mode also hides ask_user and other tools that need a UI from the model (sub-agents included), and its system prompt says the run is non-interactive, so the model decides for itself. Use auto mode or rules for unattended runs.
Conversations are stored automatically and listed by working directory. On exit, Amira prints a command for continuing a nonempty session.
| Action | Command |
|---|---|
| Continue the newest session in this directory | amira -c or amira --continue |
| Pick a stored session | amira -r or amira --resume |
| Resume a known session | amira -r <session-id> |
| List sessions without the UI | amira -p -r |
| Pick or switch within the UI | /resume or /resume <session-id> |
| Start an empty conversation | /clear |
| Name or clear the current session name | /rename [title] |
| Continue in a copy of this session | /fork |
| Rewind to an earlier user message | /rewind, or /rewind <n> [--yes] |
| Delete a stored session without the UI | amira sessions rm <session-id> (-C <dir> for another directory) |
| Compact older context now | /compact or /compact <instructions> |
Do not combine -c and -r. Session IDs begin with s_; use the actual ID shown in the list. /clear starts a new stored session, keeping the previous one available to resume. /resume keeps the current model selected; when no model is selected, the stored model can be used. Top-level background jobs survive /clear, /resume and /fork, and the new session can list, read and stop them; jobs owned by a sub-agent still stop when that sub-agent ends. All background jobs stop when Amira exits.
After a session's first successful turn, Amira asks the model for a short title (at most six words and 60 characters, in the conversation's language) in the background; it uses compact.model when set, otherwise the current model, and never holds up the conversation. Print mode and sub-agents do not request titles. The request's cost appears in /cost and /status. A /rename name always wins over the automatic one; /rename without an argument clears that manual name and shows the latest automatic title again. Set "sessions": { "autoTitle": false } in user or project settings to turn it off. Titles show in /status, /resume, amira -r and the terminal title, alongside the directory name.
Typing in the /resume picker searches titles and the user and assistant text of whole conversations, compacted history included; matching is a case-insensitive substring, so Chinese or Japanese needs no spaces, and the matching text shows under the row. Ctrl+D deletes the selected session after a confirmation; the current session is never listed. Deleting removes the session file, its captured file history and saved artifacts, and the sub-agent sessions it started (with theirs), except ones a fork still uses. If another running Amira process has the session open, deletion refuses with a message. A crashed process's owner-record lease is recovered only when its owner is provably dead in the same host and PID domain. Legacy leases from older builds have the limited heartbeat-based recovery described below; other unverifiable leases require offline cleanup.
Session writes also use a short-lived stale-write guard at <session-file>.lock.lease-gate. Both this guard and the persistent <session-file>.lock lease carry a versioned owner record with a PID, unique nonce, creation time and host/PID-domain identity. If a process crashes while creating, recovering or releasing either, the next attempt to resume or delete the session automatically recovers it only when the owner is provably dead in the same host and PID domain. Age alone never permits takeover. For upgrade compatibility, a legacy bare-PID lease (or an empty/unparseable single-line lease) is recoverable only when both its PID is provably dead on this host (or no valid PID is present) and its mtime is older than SESSION_LOCK_STALE_MS (30 seconds). Older builds refresh it every SESSION_LOCK_HEARTBEAT_MS (10 seconds), so a holder on another host keeps the lease fresh. A live local PID blocks recovery even if the file is old. Legacy recovery uses the same gate, rechecks the file's identity, contents and mtime both before retirement and on the moved file, restores changed leases without overwriting another holder, and publishes an owner-record lease with exactly one winner. The moved legacy lease uses the fixed <session-file>.lock.legacy-stale path: every later acquisition must restore it exclusively before proceeding. Failed restoration or a recovery-process crash therefore cannot silently discard a possible live holder's authority. Invalid or foreign owner records never fall back to this legacy rule. Session locking uses only filesystem operations: no native loader, libc, flock or FFI support is required. Each participating writer initializes a nonempty private guard directory before atomically publishing it; only successful publication grants the guard. A recoverer proves death, rechecks the same owner identity at the authoritative path, then renames the dead guard to <session-file>.lock.lease-gate.dead-<owner-nonce>. This nonempty crash tombstone is retained: a delayed recoverer cannot rename a newer guard over it, even after the replacement writer releases. Recovery does not block unrelated session paths. Normal release moves its own nonce-validated guard to a private cleanup path before deleting it, so a crash never leaves an empty authoritative guard. Ordinary claim/release cycles leave no auxiliary files; only interrupted operations and recovery leave debris. These guarantees require all participants to use this protocol and a filesystem with atomic directory rename and exclusive file publication. External edits to guard paths are not part of the protocol. Unknown empty guard directories fail closed rather than being overwritten.
A blocked legacy lease instead says an older Amira build appears to hold the session: close it before resuming or deleting, then retry; after a crash, wait for the lease to become stale. A busy or unverifiable guard, or another unverifiable persistent lease, reports a stale-write guard error when resuming or deleting a session, rather than claiming another process has it open. The error identifies the guard directory or lease file that blocked the attempt. Retry first; if contention happens before a guard is published, the error explicitly says no guard exists yet and gives no removal instruction. A live owner, a reused PID that cannot be distinguished from the original owner, a foreign host/PID domain, missing proof or an old/invalid owner record blocks automatic recovery. Host proof combines hostname and platform with the machine ID on Linux, or network-interface identities when no machine ID is available. Windows uses only sorted, unique universally administered unicast MACs, excluding locally administered virtual/VPN addresses, loopback, tunnel and zero MACs. Adding or removing those excluded adapters does not change the host hash. For compatibility, an older Windows hash is also accepted when it matches the current full MAC set; otherwise the lease stays protected. Boot identity and PID namespace must match; a different boot never proves death, because a concurrently running clone can have a different boot. Windows records boot:null, as before, and recovery still requires a provably dead PID. The error identifies host mismatch, unverifiable boot/PID domain, or a live or unprobeable PID. Verify the originating hostname and hardware MACs against trusted records, and check the recorded PID and Amira command lines in each sharing host's OS process list before considering manual cleanup. Missing proof or changes to host identity may require manual recovery. Only after confirming no Amira process is running on any host using these session files, remove the exact existing .lease-gate directory or .lock / .lock.legacy-stale lease file named in the error, then retry the original command (for example, amira -r <session-id>). A foreign or legacy lease may have no guard directory: removing a nonexistent guard will not recover that lease. Do not remove the session's .jsonl file or remove a guard, lease or retained crash tombstone while a writer may still run. Never delete .lease-gate.dead-<owner-nonce> tombstones online: they fence delayed recoverers, not just crashed writers. Crash-left .lease-gate.pending-*, .lease-gate.retired-*, .lock.pending-* and .lock.stale-* paths are private staging/cleanup leftovers, not write authority. Both those leftovers and retained crash tombstones can be removed only under the same offline-only condition. No separate cleanup command is needed.
/fork copies the current branch of the conversation into a new session that records where it came from, named <title> (fork), and switches to it; messages abandoned by an earlier rewind are not copied, and the original stays as it was.
Automatic compaction normally starts at 80% of the model's context window. It reduces older context while keeping recent conversation. Compatible providers can use native compaction; otherwise Amira writes a text summary. Instructions passed to /compact force a text summary. See Providers and Settings for the conditions and options. /context shows what occupies the context window.
Press Esc twice in succession, or run /rewind, to open the rewind picker. Select a previous user message, then choose Restore files too or Conversation only. File restoration is selected by default when there are captured changes after that message; the picker previews how many files will be restored or removed and lists conflicts. That message and everything after it leave the active conversation, and the prompt returns to the editor for changes and resubmission. In the picker, F forks instead: a new session ends before the selected message on the current branch, so messages abandoned by earlier rewinds are not copied; the current one stays whole, and no files are restored. Only messages still present after compaction can be selected; a stored session is required. A popup, text selection or dialog can consume Esc first, so follow the current hint line.
/rewind <n> goes directly to before the n-th most recent user message and asks for confirmation showing that message, the number of messages it will cut, file restore/remove counts and conflicts. Like the picker's default, it restores captured files when there are any; a conflict refuses the whole rewind. In print mode, and when an RPC client cannot answer the confirmation, it refuses without changing the session; use /rewind <n> --yes only after checking the preview you intend to apply. /rewind without a number is available in the terminal UI because it needs the picker.
A turn starts with a user prompt. Rewinding to before it restores each affected file to its bytes before the first captured mutation after that prompt, and removes files that did not exist then. Capture covers only Amira's write, edit and apply_patch tools and extension tools that declare the paths they write, including file-tool writes by sub-agents in the same directory or a subdirectory of it. Shell commands, formatters run by hooks, other processes, user edits and sub-agents in separate worktrees are not captured. Before restoring anything, Amira compares all affected files with the journal's expected last contents. Any mismatch, including an external change between captured writes, refuses the entire restore and leaves the conversation unchanged. Resolve the listed conflicts or choose conversation-only rewind. Stop active sub-agents before rewinding.
File bytes, including binary pre-images, are kept by hash in <session-id>.assets/files/ beside the session's JSONL recording. The journal records paths, pre/post hashes, prompt, turn and tool call. Settings fileRewind.maxFileBytes (default 10485760, 10 MiB) and fileRewind.quotaBytes (default 268435456, 256 MiB of unique images per session) bound storage. Both pre-images and post-images must fit the size cap: refusing oversized new contents also keeps future restores bounded. Failure to store an image or journal entry refuses the tool write. Paths are recorded as real paths, with symbolic links, junctions, letter case and short names resolved, so a file reached two ways is one file; if a recorded path later leads elsewhere (a directory on it replaced by a link, say), it counts as a conflict. A file with other hard links is restored in place, so every link sees the restored bytes; a hard-linked file that was deleted comes back as a separate file. Set "fileRewind": { "enabled": false } to opt out; the picker then says files will not be restored.
Captured history lasts as long as the session, across conversation branches and restarts. /rewind-prune explicitly discards all captured file history for the current session and frees its quota; earlier changes can no longer be restored, but later writes start a new history. There is no automatic eviction. Deleting a session (Ctrl+D in /resume, or amira sessions rm <id>) also deletes its captured file history; when deleting recordings by hand, remove the matching <session-id>.assets directory too. /fork gives the new session its own copy of the history, so either can be deleted. A restore records its plan and progress before checking out the conversation. Resuming the session finishes an interrupted restore after rechecking all files, including ones already restored; conflicts stop recovery without further writes, and Amira says so when the session opens. Until the restore finishes, file tools cannot write and the session cannot be forked. An interrupted core restore that can still finish must finish before choosing conversation-only rewind or an extension owner, even if capture is subsequently disabled; one that conflicts, or an error in this run such as a locked file, keep from finishing is abandoned by choosing conversation-only rewind, leaving the files as they are. File restoration concerns bytes, not empty directories or shell side effects.
The checkpoints extension can take exclusive ownership with api.registerFileRestoration({ label, restore: async (index) => { /* restore bytes */ } }). The picker shows its label; the host calls it before rewinding the conversation and does not run the core restore. The callback must restore files only (do not call session.rewind recursively), and throw on conflicts. Conversation-only rewind skips it. Unloading the extension releases ownership; only one extension can own restoration at a time.
The session file always keeps every message and tool result whole. What each model request carries is a projection of that history: large outputs are previewed, repeated reads are shortened and, when the context gets full, old tool results can be cleared. Previews, /context, compaction summaries, sub-agent forks and parent consultations all use the same projection. Once a result has been sent in a shortened form, later requests repeat exactly the same text, so the provider's prompt cache keeps its prefix.
Large outputs. Tool output longer than 16,000 characters is saved whole as an artifact next to the session file, in <session id>.assets/outputs/ (sessions without a file use the system temp directory). The model gets a preview of about 8,000 characters instead: a first line with the artifact ID (a_…), its size and how to read more, then the start and end of the output with a note where lines were left out. Sizes are counted in characters, with a Chinese, Japanese or Korean character counting as four, since each takes about a token: such output is saved sooner and gets a shorter preview, and read stops sooner. This applies to bash and powershell, to grep and glob (which save all results, before their own result limits) and to the results of MCP servers and other tools. read does not save artifacts: a long range stops at a whole line under the limit and says which offset to continue from. In the terminal UI a saved output shows its preview, with the header as a short muted line.
The model reads artifacts with output_read: offset and limit select lines, grep returns matching lines (ignore_case for case-insensitive), and column pages through very long lines. read also works on the artifact's file path. An artifact holds what the tool returned at that time; reading the source file shows it as it is now.
Repeated reads. When a read returns exactly the same text as the latest read of the same file and line range that is still in the context, only the new result is sent as a short note pointing to the earlier one. Earlier results are never rewritten. A changed range, a different range or an earlier read that was compacted or cleared is sent in full. The model can pass force: true to get the text anyway.
Aging. When the next request is expected to pass 70% of the context window, Amira clears old tool results in one batch until about 60% is left. Each cleared result is sent from then on as a short stub saying what it was and how to get it back: its artifact ID for output_read, or for a read the file to read again. The most recent two user turns are kept, or in a long turn its last two model steps, along with results that later calls are still working on. A round that would free fewer than 8,000 tokens (or, in a small window, less than the space between 70% and 60%) is skipped. Aging only rewrites history where the provider allows it: nothing before signed or encrypted reasoning that the request would send back is changed, so with such models compaction does the work. When a request is rejected as too long, one aging round is tried before compacting. The experimental afterTurns option also clears results older than that many user turns regardless of pressure; it is off by default.
Keeping and pruning artifacts. Artifacts live as long as their session; nothing deletes them automatically. A session keeps at most 256 MB of them; past the quota, outputs are only previewed and the preview says they could not be saved. /prune shows how many artifacts are active (mentioned in the context the model sees), inactive (mentioned only in compacted or rewound history, or a sub-agent's) and unused, grouped by the parent and each stored sub-agent session. /prune unused, /prune inactive and /prune all apply the same rules to every group; while a sub-agent is running, queued or idle (a persistent one waiting for its next message), pruning refuses until it finishes or is stopped, so nothing it may read is removed. Reading a pruned artifact says it was pruned.
| Action | Command |
|---|---|
| Show artifact usage | /prune |
| Delete unreferenced artifacts | /prune unused |
| Also delete ones only old history mentions | /prune inactive |
| Delete every artifact of this session | /prune all |
The defaults can be changed under context in settings:
{
"context": {
"outputs": { "saveAbove": 16000, "previewChars": 8000, "quotaMB": 256 },
"dedupeReads": true,
"aging": {
"enabled": true,
"start": 0.7,
"target": 0.6,
"minSavedTokens": 8000,
"keepTurns": 2,
"keepSteps": 2,
"afterTurns": 0
}
}
}saveAbove is at least 4000 and previewChars at least 500 (it is never larger than saveAbove); start and target are shares of the context window between 0 and 1. Set dedupeReads or aging.enabled to false to turn those off.
Use monitor when the model needs to watch a command's output and react to matching lines without polling. Unlike a normal background shell job, a monitor can wake the model with new output.
monitor parameter |
Meaning |
|---|---|
command |
Shell command to run and watch |
filter |
Regular expression matched against each output line, case-insensitively; an invalid regular expression is treated as literal text, also case-insensitively |
timeout_ms |
Lifetime in milliseconds: defaults to 1,800,000 (30 minutes), with a maximum of 7,200,000 (2 hours) |
description |
Optional short description of what the monitor watches |
The tool returns a job ID immediately; the job has kind: "monitor". Matching is per line, not across lines. Matching lines are delivered as automatic notices that wake the model, batched over roughly one second and sent at most once every two seconds. Each notice is capped at about 4 KB; +N more lines reports lines omitted from the batch.
Line framing is independent of the retained job-output buffer, including during startup. A line longer than 65,536 characters is omitted in full before filtering, with an explicit warning; a truncated prefix or suffix is never treated as a complete line.
After 200 notification events, a throttle notice says notifications paused. The command keeps running, but further matching output no longer wakes the model. Stop it and start a new monitor with a narrower filter if you need more notifications. Command exit or timeout still produces a final notice; a timeout also stops the command. The model can stop a monitor with job_stop using its job ID, just like a shell job, and inspect it with job_list and job_output.
Natural monitor exits and timeouts finishing close together are combined per owner over roughly 100 ms, so a burst starts one follow-up turn. Outstanding notice reservations remain held until delivery, including in print mode and across handovers. Watched or requested-stop final notices do not wake an idle model.
Monitors follow the same ownership and cleanup rules as other background jobs: the main session can see jobs in its tree, while a sub-agent sees only its own. A sub-agent's monitors stop when that sub-agent ends; top-level monitors survive /clear, /resume and /fork and follow the replacement session. Amira stops all remaining monitors on exit. Notices belong to the owning conversation, not an unrelated session.
/tasks is the unified entry point for sub-agents, background shell jobs and monitors. Use the IDs shown in its list:
| Command | Purpose |
|---|---|
/tasks or /tasks list |
List all task kinds |
/tasks view <id> |
Open a task's live transcript or output |
/tasks stop <id> |
Stop the specified task |
/tasks stop all |
Stop all live tasks, including queued, idle and paused sub-agents |
The existing /jobs and /agents commands remain available for their respective jobs and sub-agents. The task panel includes all three kinds, rather than only shell jobs. It shows each sub-agent's state and separates running, queued, idle and paused counts; idle and paused sub-agents remain available to view or stop by ID. When a live view is unavailable, /tasks view <id> prints the sub-agent's transcript, including tool calls and result previews. Status counts distinguish agents, shell jobs and monitors, label queued, idle and paused agents separately, use an ASCII running indicator only when work is running, and hide zero counts.
amira -p "Summarize the changes in this repository"
amira -p -c "Continue the review"
amira -p --json "Explain the failing test"
amira -p --json --json-coalesce "Explain the failing test"
amira -p --json-out events.json "Explain the failing test"
amira -p -- "-v means verbose?"-p / --print runs without the interactive UI and needs a prompt, except when listing sessions with bare -r. Plain mode streams reply text to stdout and tool activity, warnings and errors to stderr. --json requires print mode and writes each event as one ASCII-only JSON line to stdout; non-ASCII string characters are escaped as \uXXXX, so a Windows parent can decode the stream without a code-page mismatch. --json-out <path> implies --json and writes the same JSONL event stream to the file instead of stdout; a relative path is resolved from where Amira was invoked. These lines include session, turn, message, tool and sub-agent events, rather than one final JSON answer.
JSON print output omits empty ui.render events and includes a tool-call name only on its first delta unless the provider changes it. --json-coalesce merges consecutive text, thinking and same-tool-call argument deltas into larger JSONL chunks, each written once it reaches 4,096 characters or 100 ms; without it, each remaining event stays a separate line. When --json-out ends with an error, the event file still contains the stream and a short failure summary is printed to stderr.
A quoted slash command such as amira -p "/status" runs the command instead of sending a model prompt. Skills can also run this way when available. Commands requiring a picker cannot obtain interactive answers; supply explicit arguments where supported.
Print mode waits for top-level background shell jobs started during the run, up to backgroundJobs.printWaitMs (30 seconds by default), and delivers their end notices to the model for a follow-up turn. It also waits for background sub-agents and the follow-up turns their results start. If the job wait expires, Amira prints a note and stops those jobs on exit. Configured budgets still apply. Failed result-delivery turns can be retried up to three times after 10, 30 and 90 seconds. Ctrl+C aborts and stops waiting; a second Ctrl+C forces exit. The exit codes are 0 for completion, 1 for errors and 130 for an aborted turn.
In -p mode, an active monitor holds an expectNotice reservation: the run stays alive to receive matching-line notices and their follow-up turns until the monitor is stopped, exits or times out. It is not cut short by the ordinary shell-job backgroundJobs.printWaitMs wait. Stop a monitor when it is no longer needed; the configured budgets and Ctrl+C behavior still apply.
amira --rpc
amira --rpc-schemaRPC uses JSON Lines on stdin and stdout. It cannot be combined with -p or a positional prompt. --rpc-schema prints the full protocol schema and exits without starting a model turn. For an initial resume, pass --resume <session-id> or -c; bare -r is not supported in RPC mode.
Send one object per line, with id, cmd and command parameters at the top level. For example, on a connection with a model configured:
{"id":1,"cmd":"prompt","text":"Explain the test layout"}The immediate response contains the request ID, ok: true and a turnId; it acknowledges the start, not completion. Events interleave with responses. Wait for the matching turn.end to know the outcome. Failed commands respond with ok: false and an error containing code and message.
| Command | Purpose |
|---|---|
prompt |
Start a turn; fails with busy while work runs |
steer |
Add instructions before the next model call; start a turn if idle |
abort |
Stop a turn or compaction |
state |
Get status, model, session and pending UI requests |
session.read |
Read messages or lastTurn using the what parameter |
session.resume |
Switch to a stored session using sessionId |
session.rename |
Name the current session using title; a session.title event follows, as it does for an automatic title |
session.fork |
Fork into a new session, before the user message at the optional index; a session.start with reason fork follows |
model.set |
Switch model using model as provider/model |
thinking.set |
Set level to low, medium, high, xhigh, max or default; fails with busy while work runs |
command.list, command.complete, command.run |
Discover and run slash commands |
skill.list, skill.run |
Discover and run skills |
ui.respond |
Answer a UI request using requestId and value |
ui.action, ui.configure, ui.focus |
Support form actions, form presentation and client focus |
Read the generated schema for parameter shapes and UI answer types. For example, a confirmation uses a boolean value; explicit null cancels, while omitting value is invalid. Requests can remain open while later input lines answer them. If a slow client receives events.lost, use state and session.read to resynchronize. Keep reading stdout while work runs.
thinking.set requires an explicit level; missing or invalid values return invalid_params. default sends no reasoning effort, overriding flags and settings rather than restoring them. Its response and state include supportsThinking, the effective thinkingLevel even for unsupported models, and thinking only when an effort is sent to the current model. Both effort fields are omitted for the server default. default does not turn thinking off: Claude 5.x models think by default, and Amira has no off choice. Anthropic rejects disabled thinking on Opus 5.5, Fable and Mythos; Sonnet 5.5 requires between_tools to skip up-front thinking (it can still think between tool calls).
Closing stdin waits for active work, including background results and their follow-up turns; dialogs that nobody can answer are cancelled. For dialog-driven commands, keep stdin open until they finish.
/status reports the model and provider, session, context use, output tokens, cache hit rate, costs, permissions and workspace. Speed occupies up to three short lines: total output speed and TTFT for the last provider request, an optional thinking/reply split, and effective TPS for the last completed turn.
All durations use our event timestamps, in seconds. Let O be reported usage.output, R reported usage.reasoning (already included in O), T the interval from the first content block start or delta to the last provider event, and H the sum of thinking-block start/end durations:
- Output speed:
O / T. This is the primary metric, including thinking and tool-call output. - TTFT: first content event minus request sent. An empty thinking block or delta counts; this is not time to first visible answer text. Retries start a new request clock.
- Split: thinking
R / H; reply(O − R) / (T − H). These require reported reasoning counts, complete block timing, and omitted thinking display or raw streamed reasoning. Requested summaries suppress the split: server buffering makes its timings meaningless. Summary mode comes from the request metadata, never from summary length. - Turn effective TPS: sum of reported output over the turn’s provider requests divided by prompt-sent-to-turn-end wall time, including tools, retry waits and compaction. It excludes sub-agents and background title requests.
Missing output counts use marked text estimates (~); a reported total output count remains exact even when reasoning counts are missing. Missing reasoning counts retain marked split estimates. When display mode is unknown, hidden reasoning keeps the legacy reply ~N tok/s (hidden reasoning) estimate; reported reply token counts are still used when available, but the phase timing is approximate. Requested summaries never show a split, and known raw/omitted displays with incomplete thinking-block timing never invent an exact split.
The TUI activity line shows elapsed turn time and output tokens, not tok/s; its streaming estimate is replaced by reported output as each reply ends. The footer has no speed display. Omitted thinking has no reasoning row in the TUI, like live redacted thinking; its signed block is still saved and replayed unchanged. Resumed sessions include earlier usage, but speed is measured only from events in this run. The status bar reports tree usage since the current run started; /status can include stored session and sub-agent costs.
/cost reports this session's replies by model, and compaction and session-title requests separately; it does not aggregate child-agent costs. Use /status and /agents for those. Costs depend on known model pricing and reported usage; unknown prices are identified, and totals with unpriced rows are partial estimates. Provider billing remains the source for actual charges.
Related: Getting started · Providers · Sub-agents · Extensions · Settings · Keybindings.