CLI reference¶
A complete, generated reference for every af command and flag, produced from the Cobra command tree. This page is regenerated by scripts/gen-docs.sh and verified in CI, so it never drifts from the binary — do not edit it by hand.
Run af <command> --help for the same information at the terminal. For a narrative, task-oriented tour of the CLI see the CLI guide.
Commands¶
af— Agent Factory - Manage multiple AI agents like Claude Code, Aider, Codex, Gemini, and Amp.af accounts— Manage per-session agent credential directoriesaf accounts add— Register a credential directory for an agent accountaf accounts list— List registered agent accountsaf agent-server— Run a headless single-workspace backend (not the web UI — that is 'af daemon')af api— Show the daemon-hosted HTTP/JSON API catalogaf bug-report— Bundle logs, versions, tasks, and redacted state for a bug reportaf completion— Generate the autocompletion script for the specified shellaf completion bash— Generate the autocompletion script for bashaf completion fish— Generate the autocompletion script for fishaf completion powershell— Generate the autocompletion script for powershellaf completion zsh— Generate the autocompletion script for zshaf config— Read global or project-effective config and write global configaf config get— Print one global or project-effective config valueaf config list— Print global or project-effective config valuesaf config set— Set a single settable global config keyaf config unset— Clear a per-project config overrideaf config validate— Check that the global config parses and validatesaf daemon— Manage the background daemon: serves the web UI and schedules tasksaf daemon adopt— Hand a detached daemon back to the installed autostart unitaf daemon install— Register the daemon to start automatically at loginaf daemon restart— Restart the running daemon without stopping live sessionsaf daemon status— Report daemon liveness, config freshness, and supervisionaf daemon uninstall— Remove the daemon autostart unitaf debug— Print debug information like config pathsaf doctor— Diagnose setup, daemon health, and leaked session resourcesaf keys— Show the effective TUI key bindings (defaults plus [keys] rebinds)af projects— Manage projects and durable registrationsaf projects add— Add a project: register a repo by path with a stable local identityaf projects delete— Delete a project, archiving its restorable sessionsaf projects list— List registered projectsaf projects rebind— Rebind a registered project after its checkout movesaf quota— Show usage-limit status for each agent CLIaf reset— Factory-reset Agent Factory: remove AF sessions, tasks, project registrations, worktrees, and state (keeps repos and config)af sessions— Manage sessionsaf sessions archive— Finish with a session by archiving it for later restoreaf sessions attach— Attach to a session's terminalaf sessions backends— List the runtimes this project can create sessions onaf sessions create— Create a new sessionaf sessions get— Get a session by titleaf sessions handoff— Continue a session under a different agent, in placeaf sessions kill— Permanently destroy a session and prune its worktree branchaf sessions list— List sessions in the current projectaf sessions preview— Preview a session's terminal contentaf sessions restore— Restore an archived, lost, or dead sessionaf sessions retry-limit— Retry a session blocked at a usage limitaf sessions send-prompt— Send a prompt to a session (or broadcast to all with --all)af sessions tab-create— Spawn a shell, process, web, or VS Code tab in a sessionaf sessions tab-delete— Delete a single tab from a sessionaf sessions tab-rename— Rename a tab of a sessionaf sessions tab-reorder— Move a tab within a session's tab orderaf sessions tabs— Manage a session's tabs (create/delete/rename/reorder)af sessions tabs create— Spawn a shell, process, web, or VS Code tab in a sessionaf sessions tabs delete— Delete a single tab from a sessionaf sessions tabs rename— Rename a tab of a sessionaf sessions tabs reorder— Move a tab within a session's tab orderaf sessions watch— Block until a session goes idle, or until any session in the fleet changes stateaf sessions whoami— Identify the current Agent Factory sessionaf tasks— Manage tasksaf tasks add— Add a new task bound to the current projectaf tasks get— Get a task in the current project by IDaf tasks list— List tasks in the current projectaf tasks remove— Remove a task in the current projectaf tasks restart— Restart an enabled watch task without process overlapaf tasks trigger— Trigger a task in the current project to run immediatelyaf tasks update— Update a task in the current projectaf token— Manage the daemon's bearer token for the direct-TCP APIaf token rotate— Replace the bearer token with a fresh one and print itaf token show— Print the bearer token (generating it if absent)af upgrade— Upgrade agent-factory to the latest release on the configured channelaf version— Print the version number of agent-factory
af¶
Agent Factory - Manage multiple AI agents like Claude Code, Aider, Codex, Gemini, and Amp.
Run 'af' with no arguments to open the TUI. The subcommands below drive the
same daemon non-interactively (af sessions, af tasks emit JSON).
The daemon also serves the web UI — the same sessions in a browser — at http://localhost:8443, which needs no token by default. See 'af daemon --help' for the web UI, the listener and its auth, and autostart; to drive a daemon on another machine, start with the remote guide: https://sachiniyer.github.io/agent-factory/remote-http-auth/
Subcommands
af accounts— Manage per-session agent credential directoriesaf agent-server— Run a headless single-workspace backend (not the web UI — that is 'af daemon')af api— Show the daemon-hosted HTTP/JSON API catalogaf bug-report— Bundle logs, versions, tasks, and redacted state for a bug reportaf completion— Generate the autocompletion script for the specified shellaf config— Read global or project-effective config and write global configaf daemon— Manage the background daemon: serves the web UI and schedules tasksaf debug— Print debug information like config pathsaf doctor— Diagnose setup, daemon health, and leaked session resourcesaf keys— Show the effective TUI key bindings (defaults plus [keys] rebinds)af projects— Manage projects and durable registrationsaf quota— Show usage-limit status for each agent CLIaf reset— Factory-reset Agent Factory: remove AF sessions, tasks, project registrations, worktrees, and state (keeps repos and config)af sessions— Manage sessionsaf tasks— Manage tasksaf token— Manage the daemon's bearer token for the direct-TCP APIaf upgrade— Upgrade agent-factory to the latest release on the configured channelaf version— Print the version number of agent-factory
Flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
-p, --program |
string |
Program to run in new sessions (one of: claude, codex, aider, gemini, amp, opencode, devin) |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af accounts¶
Manage per-session agent credential directories
Prepare the credential directories a session can later be scoped to.
An account is one of an agent's logged-in identities, held as a directory the agent CLI treats as its home. af never reads, stores, or forwards the credential itself — it decides which directory a session sees, and the agent's own login flow puts the material there.
add creates that directory and prints its path · list shows what is registered. Register an account, then log in with the agent pointed at that directory:
af accounts add codex work CODEX_HOME=$(af accounts add codex work) codex login
Select an account for a session with:
af sessions create --account work
That both injects the account's directory and removes every other identity-bearing variable for the agent. The removal is what makes the selection real: an ambient ANTHROPIC_API_KEY or OPENAI_API_KEY outranks the config directory, so without it a session would authenticate as whoever that key belongs to while every visible signal reported the selected account.
Account-scoped sessions require the local backend and tmux 3.2 or newer. af refuses rather than falling back, because a fallback would run on the ambient account while reporting the one you asked for.
af never switches accounts on its own — not on a rate limit, not on a failure. A session runs as the account it was started with.
Subcommands
af accounts add— Register a credential directory for an agent accountaf accounts list— List registered agent accounts
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af accounts add¶
Register a credential directory for an agent account
Create the credential directory for an account and print its path.
This makes a place; it does not log in. Run the agent's own login flow against the printed directory to put credentials there.
Registration is idempotent — running it again on an existing account reports the same directory and touches nothing inside it.
Flags
| Flag | Type | Description |
|---|---|---|
--json |
Output the {data,error} JSON envelope |
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af accounts list¶
List registered agent accounts
List the registered accounts, for one agent or for every agent that supports account scoping.
An agent absent from this list is one whose credential relocation af has not verified, not one that is merely unconfigured — af reports unsupported rather than accepting a selection that would silently do nothing.
Flags
| Flag | Type | Description |
|---|---|---|
--json |
Output the {data,error} JSON envelope |
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af agent-server¶
Run a headless single-workspace backend (not the web UI — that is 'af daemon')
Run a headless agent-server for exactly one session's workspace, served over the same REST + WebSocket protocol the daemon speaks, behind a plain-HTTP listener that requires a bearer token on every request.
This does not start the web UI, and serves no frontend at all — opening its port in a browser returns a 404 saying so. If you want the browser app, run the daemon — any 'af' command starts it — and open http://localhost:8443. The web UI is bundled into the daemon and served from its listen_addr; agent-server is only the headless per-workspace backend that a daemon drives, and it exists to be consumed by a daemon rather than opened by a person.
This is the process that runs inside a docker container or on an ssh remote (#1592 Phase 4): a remote daemon dials the authed URL it exposes and drives the workspace exactly as it drives a local in-process session. Run it directly only to host one workspace as a backend for a daemon on another machine.
The listener always requires the token and serves plain HTTP (no TLS) — reach it over a private network or a tunnel (the docker/ssh runtimes forward a loopback port). Its token is mandatory for every peer, whatever the global require_token key says: that key governs only the daemon's own web listener. On startup it prints one JSON line to stdout carrying the bound address and the bearer token. On SIGINT/SIGTERM it tears the workspace down (kills tmux, removes the worktree) — durability of in-progress work is the driving daemon's job (push the branch before shutdown), not this server's.
Flags
| Flag | Type | Description |
|---|---|---|
--listen |
string |
HTTP TCP bind address (host:port); :0 lets the kernel pick a free port (default 127.0.0.1:0) |
--program |
string |
Agent program to run (default: the configured default_program) |
--program-resolved |
Treat --program as an already-resolved runtime command | |
--repo |
string |
Repository path the workspace runs against (default: current directory) |
--session-env |
stringSlice |
Additional exact environment variable name an agent may inherit (repeatable) |
--title |
string |
Session title for the workspace (required) |
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af api¶
Show the daemon-hosted HTTP/JSON API catalog
Print the HTTP/JSON API the daemon exposes over a local Unix socket.
The daemon serves a small JSON API — a 1:1 mirror of the session and task operations the CLI performs — on a 0600 Unix socket (owner-only; there is no TCP port and no token). This command lists the resolved socket path and every endpoint with a ready-to-run curl example.
It is read-only and never contacts or starts the daemon; it just prints the catalog. Use --json for a machine-readable form wrapped in the shared {data,error} envelope. Full reference: docs/http-api.md.
Flags
| Flag | Type | Description |
|---|---|---|
--json |
Emit the catalog as JSON wrapped in the {data,error} envelope |
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af bug-report¶
Bundle logs, versions, tasks, and redacted state for a bug report
Collect a single, shareable diagnostics bundle for triage:
- the daemon log tail (bounded to the last ~2MiB / 5000 lines)
- versions: af, Go, OS/arch, and the daemon's version snapshot
- the configured tasks (redacted)
- the session state from instances.json (redacted)
- the daemon health snapshot (same no-spawn probe as af daemon status)
- the global config file, if any (redacted)
By default the redacted bundle is written to a single text file
(~/af-bug-report-
The draft body carries a bounded, redacted summary of the key diagnostics (versions, daemon status, counts, and the newest log lines) so the report is useful even as filed; the complete bundle is too large for a URL, so it stays on disk for you to attach. The draft is never submitted for you: review it, drag the bundle file onto the issue, and click Submit yourself. If neither gh nor a browser opener is available, the command falls back to just writing the bundle file and printing where it is so you can attach it to an issue by hand.
Use -o/--output
REDACTION IS BEST-EFFORT. Free-text and secret-bearing fields (session titles, session prompts, task prompts, tab commands, remote metadata) are dropped; $HOME and your username are collapsed to ~ / [user]; and known credential shapes are scrubbed wherever they appear. Perfect redaction is impossible — open the file and review it before sharing it publicly.
Use --json to emit the structured manifest (wrapped in the shared {data,error} envelope) to stdout instead of writing a file or opening a draft.
Flags
| Flag | Type | Description |
|---|---|---|
--file |
Only write the bundle file (to ~/af-bug-report- |
|
--json |
Emit the structured manifest to stdout (in the {data,error} envelope) instead of writing a file or opening a draft | |
-o, --output |
string |
Write the bundle to this path and skip opening a GitHub draft (implies --file) |
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af completion¶
Generate the autocompletion script for the specified shell
Generate the autocompletion script for af for the specified shell. See each sub-command's help for details on how to use the generated script.
Subcommands
af completion bash— Generate the autocompletion script for bashaf completion fish— Generate the autocompletion script for fishaf completion powershell— Generate the autocompletion script for powershellaf completion zsh— Generate the autocompletion script for zsh
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af completion bash¶
Generate the autocompletion script for bash
Generate the autocompletion script for the bash shell.
This script depends on the 'bash-completion' package. If it is not installed already, you can install it via your OS's package manager.
To load completions in your current shell session:
source <(af completion bash)
To load completions for every new session, execute once:
Linux:¶
af completion bash > /etc/bash_completion.d/af
macOS:¶
af completion bash > $(brew --prefix)/etc/bash_completion.d/af
You will need to start a new shell for this setup to take effect.
Flags
| Flag | Type | Description |
|---|---|---|
--no-descriptions |
disable completion descriptions |
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af completion fish¶
Generate the autocompletion script for fish
Generate the autocompletion script for the fish shell.
To load completions in your current shell session:
af completion fish | source
To load completions for every new session, execute once:
af completion fish > ~/.config/fish/completions/af.fish
You will need to start a new shell for this setup to take effect.
Flags
| Flag | Type | Description |
|---|---|---|
--no-descriptions |
disable completion descriptions |
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af completion powershell¶
Generate the autocompletion script for powershell
Generate the autocompletion script for powershell.
To load completions in your current shell session:
af completion powershell | Out-String | Invoke-Expression
To load completions for every new session, add the output of the above command to your powershell profile.
Flags
| Flag | Type | Description |
|---|---|---|
--no-descriptions |
disable completion descriptions |
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af completion zsh¶
Generate the autocompletion script for zsh
Generate the autocompletion script for the zsh shell.
If shell completion is not already enabled in your environment you will need to enable it. You can execute the following once:
echo "autoload -U compinit; compinit" >> ~/.zshrc
To load completions in your current shell session:
source <(af completion zsh)
To load completions for every new session, execute once:
Linux:¶
af completion zsh > "${fpath[1]}/_af"
macOS:¶
af completion zsh > $(brew --prefix)/share/zsh/site-functions/_af
You will need to start a new shell for this setup to take effect.
Flags
| Flag | Type | Description |
|---|---|---|
--no-descriptions |
disable completion descriptions |
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af config¶
Read global or project-effective config and write global config
Read and write keys in the global config (~/.agent-factory/config.toml).
"get"/"list" print the effective config for the current repository, including
its checked-in and personal per-project layers. Pass --repo
"set"/"unset" write config. Without --project they edit the global config,
changing a single settable key in place so all comments and ordering are
preserved. With --project
Subcommands
af config get— Print one global or project-effective config valueaf config list— Print global or project-effective config valuesaf config set— Set a single settable global config keyaf config unset— Clear a per-project config overrideaf config validate— Check that the global config parses and validates
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af config get¶
Print one global or project-effective config value
Print the effective value of one config key (e.g. default_program, auto_update, update_channel). By default the current repository's legacy, checked-in, and personal layers participate; outside git, the command falls back to global defaults. Run "af config list" to see every key. Scalar values print bare; composite values (program_overrides, root_agents, limit_patterns, keys) print as JSON.
Use --repo
Flags
| Flag | Type | Description |
|---|---|---|
--explain |
Show every source candidate and why it did or did not supply the value | |
--json |
Emit the value(s) as JSON wrapped in the {data,error} envelope | |
--repo |
string |
Resolve config for this project instead of the current repository |
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af config list¶
Print global or project-effective config values
Print every effective config key. By default the current repository's
legacy, checked-in, and personal layers participate; outside git, the command
falls back to global defaults. Pass --repo
Flags
| Flag | Type | Description |
|---|---|---|
--explain |
Show every source candidate and why it did or did not supply each value | |
--json |
Emit the value(s) as JSON wrapped in the {data,error} envelope | |
--repo |
string |
Resolve config for this project instead of the current repository |
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af config set¶
Set a single settable global config key
Write one key into the global config.toml, editing only that value in place — every comment, blank line, section header, and key ordering is preserved (the file is not regenerated). Only a curated set of scalar keys is settable; the value is validated with the same rules the config loader uses before anything is written, so set can never leave a config that fails to load.
Settable keys:
default_program agent enum (claude, codex, aider, gemini, amp, opencode, devin)
program_overrides.
Structural keys (root_agents, [theme], the [keys] rebind table) and the session_env_passthrough list have no single-scalar shape, so they are not settable here. Ask the config assistant to change them (it edits the file and validates), or edit config.toml directly and run "af config validate". A settable key applies to a running daemon in place (#2480); only the structural keys above take effect on the next daemon start.
With --project
Examples: af config set default_program codex af config set auto_update false af config set program_overrides.claude "/usr/local/bin/claude --verbose" af config set default_program codex --project ~/work/myrepo af config unset default_program --project ~/work/myrepo
Flags
| Flag | Type | Description |
|---|---|---|
--json |
Emit the value(s) as JSON wrapped in the {data,error} envelope | |
--project |
string |
Write to this project's machine-local config instead of the global config (a prj_ id or a repository path) |
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af config unset¶
Clear a per-project config override
Remove one key's personal override for a project so the value falls back to the lower layers again (built-in < global < in-repo). Clearing an override is deliberately different from setting a value equal to the lower layer, which is still a present, winning override.
--project
Flags
| Flag | Type | Description |
|---|---|---|
--json |
Emit the value(s) as JSON wrapped in the {data,error} envelope | |
--project |
string |
The project whose override to clear (a prj_ id or a repository path) |
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af config validate¶
Check that the global config parses and validates
Read the global config (~/.agent-factory/config.toml) exactly as af and the daemon do at startup and report whether it loads. It writes nothing and materializes nothing — a read-only check.
This is the companion to a hand-edit. Most keys go through "af config set", which validates before it writes and so can never leave a broken file; but the structured settings (theme, the [keys] rebinds, root_agents, and the session_env_passthrough list) are edited in the file directly, and a broken edit there is a hard startup failure with no fallback to defaults. Run this after such an edit: exit 0 means the next start will load it, a non-zero exit names what is wrong so it can be fixed before restarting.
Flags
| Flag | Type | Description |
|---|---|---|
--json |
Emit the value(s) as JSON wrapped in the {data,error} envelope |
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af daemon¶
Manage the background daemon: serves the web UI and schedules tasks
The agent-factory daemon runs task cron schedules in-process, supervises watch-task scripts, monitors sessions, and serves the bundled web UI.
The web UI is part of the daemon — there is no separate web command — so it is served whenever the daemon is running. Running af starts one: the TUI reads session state through the daemon and spawns it if none is up, so simply opening af serves the web UI. Any enabled task starts one too. Only standalone commands that never talk to the daemon (such as 'af config list') leave it down.
With af running, open:
http://localhost:8443
It needs no token by default, so the page connects as soon as it loads. Set listen_addr to change the address (or to "" to turn the web server off). require_token = true demands a bearer token ('af token show') from network peers; on the default loopback listener same-host callers stay exempt, so the UI keeps opening with no login on this machine. Add require_loopback_token = true to require the token from localhost as well. Note that 'af agent-server' does not serve the web UI: it is the headless per-workspace backend a daemon drives on a remote machine.
Clients reach the daemon over a local Unix socket by default. To drive one from another machine, either ssh to that host and run 'af' there, or give listen_addr a routable address and point a client at it with the persistent --daemon-url and --token flags. A routable listener is allowed with the token off, but af warns once at daemon start: with require_token = false anyone who can reach the address drives your agents, so set require_token = true unless you trust the network. That listener speaks plain HTTP either way, so put it behind a reverse proxy or a private network (Tailscale/VPN) if you need TLS. Full guide: https://sachiniyer.github.io/agent-factory/remote-http-auth/
Install the daemon as a user-level autostart unit (systemd user service on Linux, launchd agent on macOS) so tasks keep firing and the web UI stays up after reboots, even when af is never opened:
af daemon install
Subcommands
af daemon adopt— Hand a detached daemon back to the installed autostart unitaf daemon install— Register the daemon to start automatically at loginaf daemon restart— Restart the running daemon without stopping live sessionsaf daemon status— Report daemon liveness, config freshness, and supervisionaf daemon uninstall— Remove the daemon autostart unit
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af daemon adopt¶
Hand a detached daemon back to the installed autostart unit
Reclaim supervision of the background daemon for the installed autostart unit.
When a daemon is running detached from its unit — an ad-hoc child a live af spawned, which the service manager can no longer restart — adopt stops that daemon and starts the installed unit in its place, then verifies the unit now owns the process answering the control socket. Live sessions keep running in tmux; the new supervised daemon re-adopts persisted session state on startup, exactly as 'af daemon restart' does.
It needs an installed unit that serves this home ('af daemon install'); with no such unit there is nothing to adopt the daemon into. If the installed unit already owns the running daemon, adopt reports that and changes nothing.
Flags
| Flag | Type | Description |
|---|---|---|
--force |
displace the running daemon even if af cannot confirm it is unsupervised (you assert it is yours to replace) |
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af daemon install¶
Register the daemon to start automatically at login
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af daemon restart¶
Restart the running daemon without stopping live sessions
Restart the background daemon if one is running. Live sessions keep running in tmux; the new daemon re-adopts persisted session state on startup. If no daemon is running, this command exits successfully without starting one.
Flags
| Flag | Type | Description |
|---|---|---|
--quiet |
Suppress output when no daemon is running |
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af daemon status¶
Report daemon liveness, config freshness, and supervision
Print a read-only snapshot of the background daemon: whether it is responding on the control socket, the control and HTTP socket paths (and whether their files are present), the recorded and responding pids, whether the installed autostart unit owns that responding process, whether the config on disk matches what the daemon booted with, and whether the running binary was replaced.
It never contacts a paused daemon in a way that spawns one and never starts the daemon. Service-manager inspection is bounded and read-only. Use --json for a machine-readable form wrapped in the shared {data,error} envelope.
Flags
| Flag | Type | Description |
|---|---|---|
--json |
Emit the status as JSON wrapped in the {data,error} envelope |
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af daemon uninstall¶
Remove the daemon autostart unit
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af debug¶
Print debug information like config paths
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af doctor¶
Diagnose setup, daemon health, and leaked session resources
Diagnose the local agent-factory environment.
For first-run setup checks, use:
af doctor --setup
The setup profile checks the prerequisites needed to create the first local session: AF home writability, config materialization and parsing, git and the current repo, git identity, tmux, configured agent commands, state/log storage, daemon health, and remote-hook setup when this repo configures it.
Without --setup, doctor runs the full maintenance sweep for problems that accumulate silently on a machine running agent-factory:
- orphaned processes spawned by sessions that no longer exist
- processes that escaped a live session's pane, or peg a CPU core for hours
- af_ tmux sessions with no backing session record
- abandoned agent-factory homes under the temp dir (leaked by tests/debug runs)
- daemon health: control socket, autostart unit, pid file, binary freshness
- client/daemon version skew, and the ways a stale daemon survives an upgrade: a second daemon on this home, an autostart unit launching a different af binary than yours, several af installs at different versions, sockets left behind with no daemon answering, and an autostart unit that is installed but not actually supervising anything
- remote-hook setup for the current repo: config completeness and launch_cmd/delete_cmd script presence/executability (skipped cleanly when no remote backend is configured)
The version-skew check exists because a skewed daemon fails quietly: it keeps
answering while rejecting fields a newer client sends, which surfaces as
"unknown field
Use --json to emit each check as {name, section, status, detail, remedy, actionable} in the shared {data,error} envelope for scripting. Branch on "actionable", not on the status or whether --fix supports the row. Actionable means doctor established a specific unhealthy condition and named a correction that must happen before the run is healthy. Some exact corrections are manual and remain actionable even though --fix does not perform them.
UNKNOWN observations stay visible as advisory warnings with inspection guidance, but they are not actionable: "inspect it and decide" is not a finding that the run is unhealthy. A CI step or health probe should fail on the command exit code (equivalently, JSON summary.unresolved > 0), which includes only actionable rows.
High-volume process findings are summarized by default so the actionable problem is visible first. Use --verbose to show each process behind those summaries.
Read-only by default. With --fix, applies the safe remediations — killing orphans whose ancestry markers prove they came from a dead af session, and removing stale temp homes — logging each action. Ambiguous cases are always reported rather than acted on, and remain advisory unless another check establishes a specific unhealthy condition.
Exits 1 when unresolved actionable issues remain, 0 when doctor established no unhealthy condition (advisory warnings may still be present).
Flags
| Flag | Type | Description |
|---|---|---|
--fix |
apply safe remediations (kill verified orphans, remove stale temp homes) | |
--json |
emit each check as JSON in the {data,error} envelope | |
--setup |
run the first-run setup profile (prerequisites, config, agent commands) | |
--verbose |
show per-process doctor findings instead of collapsed summaries |
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af keys¶
Show the effective TUI key bindings (defaults plus [keys] rebinds)
Show every TUI action with its effective key binding: the built-in default, or the rebind from the [keys] table in config.toml (#1026). Fixed bindings — structural keys config cannot touch — are listed last. Contextual pane actions such as pane_prev/pane_next are included; their default arrow keys apply only while a workspace pane has focus.
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af projects¶
Manage projects and durable registrations
Subcommands
af projects add— Add a project: register a repo by path with a stable local identityaf projects delete— Delete a project, archiving its restorable sessionsaf projects list— List registered projectsaf projects rebind— Rebind a registered project after its checkout moves
Flags
| Flag | Type | Description |
|---|---|---|
--json |
Wrap output in the {data,error} JSON envelope (default: bare payload) |
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af projects add¶
Add a project: register a repo by path with a stable local identity
Add a project by registering a git checkout with a stable, machine-local identity, so it appears as an (initially sessionless) project you can create sessions into.
The path may be relative (including '.'), absolute, or start with ~. A relative path or '~' is resolved against YOUR shell's working directory before the request is sent — so 'af projects add .' registers the repo you are standing in. The daemon then walks to the checkout's canonical main-repo root and validates it is a git repository (an actionable error otherwise). Any directory inside a checkout resolves to that root. Registration is idempotent: adding a known checkout is a no-op success that returns its existing identity.
The returned project id survives an explicit rebind after the checkout moves.
Two clones remain separate projects. Identity is anchored in an AF-home-scoped
agent-factory/checkout-id-
'register' is a deprecated alias for 'add'.
Aliases: register
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--json |
Wrap output in the {data,error} JSON envelope (default: bare payload) | |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af projects delete¶
Delete a project, archiving its restorable sessions
Delete a project for a git repository and remove its live sessions.
Every regular worktree session is archived (its tmux is torn down and its worktree moved to the archive dir, but its branch and uncommitted changes are preserved). The always-on root agent (if any) is stopped and its root-agent opt-in removed. In-place sessions (the root agent, 'af sessions create --here') are torn down instead of archived — their cleanup never touches your working tree or branch.
The durable project registration, if any, is removed so the project leaves the project list. Restoring an archived session makes its repository active again, but does not restore the durable registration or root-agent opt-in.
Your real git repository is never touched. To undo a mis-click, restore any archived session with 'af sessions restore
[repo] is a path inside the repository to delete (default: the current repo). Deleting an unknown project is a clean no-op; deleting a registered project with no live sessions still removes its registration. Prints how many sessions were archived.
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--json |
Wrap output in the {data,error} JSON envelope (default: bare payload) | |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af projects list¶
List registered projects
List durable machine-local project bindings.
path_exists reports only whether the last-known path is present. It does not claim that a new checkout at a reused path has the registered identity.
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--json |
Wrap output in the {data,error} JSON envelope (default: bare payload) | |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af projects rebind¶
Rebind a registered project after its checkout moves
Rebind a stable project id to a new checkout path.
The project id is preserved. Rebinding refuses to take a path already owned by another registered project.
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--json |
Wrap output in the {data,error} JSON envelope (default: bare payload) | |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af quota¶
Show usage-limit status for each agent CLI
Show what af knows about each agent CLI's usage limits.
Two different things, kept apart on purpose:
QUOTA what the provider reports about the account's ceiling. af has no quota API for any supported agent today, so every row reads "not reported". That is af declining to guess, not a ceiling of zero.
OBSERVED what af has seen in its OWN sessions — a session parked at a usage wall, and the reset time recorded with it. Real signal even where the provider exposes nothing.
Read-only: it reads local session records and starts nothing.
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af reset¶
Factory-reset Agent Factory: remove AF sessions, tasks, project registrations, worktrees, and state (keeps repos and config)
Factory-reset Agent Factory.
Removes every AF-created resource — all sessions (live and archived), all scheduled cron/watch tasks, registered-project bindings and their reachable checkout identity markers for this AF home, all AF worktrees, the AF session branches AF created, and all stored state — returning AF to a clean slate.
Stops every af daemon running for this AF home — the managed one and any orphan left behind by an upgrade or a source build — and removes the daemon sockets, so a stale daemon or socket cannot serve the next af you start. Only daemons owned by you AND using this AGENT_FACTORY_HOME are stopped, and the autostart unit is only paused when it serves this AGENT_FACTORY_HOME; a daemon or unit for a different AF home is never touched.
KEEPS your real git repositories (working tree, .git, and your own branches), and KEEPS the daemon configuration (config.toml: listen_addr, defaults, root_agents, update_channel, and per-repo config). After the wipe the supervised daemon restarts with empty session/task state and the same config; root_agents in config re-register, which is intended.
This is IRREVERSIBLE. You will be asked to type WIPE to confirm. Pass --yes (or --force) to skip the prompt for scripted use; when stdin is not a terminal the prompt is skipped automatically so existing scripted callers do not hang.
Flags
| Flag | Type | Description |
|---|---|---|
--force |
Alias for --yes: skip the typed WIPE confirmation | |
-y, --yes |
Skip the typed WIPE confirmation (for non-interactive/scripted use) |
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af sessions¶
Manage sessions
Subcommands
af sessions archive— Finish with a session by archiving it for later restoreaf sessions attach— Attach to a session's terminalaf sessions backends— List the runtimes this project can create sessions onaf sessions create— Create a new sessionaf sessions get— Get a session by titleaf sessions handoff— Continue a session under a different agent, in placeaf sessions kill— Permanently destroy a session and prune its worktree branchaf sessions list— List sessions in the current projectaf sessions preview— Preview a session's terminal contentaf sessions restore— Restore an archived, lost, or dead sessionaf sessions retry-limit— Retry a session blocked at a usage limitaf sessions send-prompt— Send a prompt to a session (or broadcast to all with --all)af sessions tab-create— Spawn a shell, process, web, or VS Code tab in a sessionaf sessions tab-delete— Delete a single tab from a sessionaf sessions tab-rename— Rename a tab of a sessionaf sessions tab-reorder— Move a tab within a session's tab orderaf sessions tabs— Manage a session's tabs (create/delete/rename/reorder)af sessions watch— Block until a session goes idle, or until any session in the fleet changes stateaf sessions whoami— Identify the current Agent Factory session
Flags
| Flag | Type | Description |
|---|---|---|
--json |
Wrap output in the {data,error} JSON envelope (default: bare payload) | |
--repo |
string |
Path to the project's git repository (default: the current directory's project) |
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af sessions archive¶
Finish with a session by archiving it for later restore
Archive is the default way to finish with a session: tear down its tmux
and move its git worktree out to the global archive directory
(
Archive is refused while any enabled task targets the session. The error names every blocking task; disable or retarget them, then archive again. Agent Factory never silently restores the target or disables its automation as a side effect. While a session is archiving or archived, task writes that would newly enable it as a target are likewise refused until the session is restored.
With --self, archive the current session (resolved via whoami) instead of a named one — use it from inside a session when your work is done. --self and a
Not available for remote or in-place (--here) sessions: archive relocates the worktree, which those don't own. The relocated worktree path is printed on success.
Flags
| Flag | Type | Description |
|---|---|---|
--self |
Archive the current session (resolved via whoami); use from inside a session when your work is done |
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--json |
Wrap output in the {data,error} JSON envelope (default: bare payload) | |
--repo |
string |
Path to the project's git repository (default: the current directory's project) |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af sessions attach¶
Attach to a session's terminal
Attach to a running session's tmux terminal. Detach with the configured detach key (default: Ctrl-w).
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--json |
Wrap output in the {data,error} JSON envelope (default: bare payload) | |
--repo |
string |
Path to the project's git repository (default: the current directory's project) |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af sessions backends¶
List the runtimes this project can create sessions on
Report which backends 'af sessions create --backend' accepts for this project, whether each one is usable as the project is configured right now, and which backend a create with no --backend resolves to.
--backend names the enum, but knowing that "docker" is spelled correctly is not the same as knowing this project can use it. The daemon checks each backend's preconditions against the project's config and answers one of three things:
available every precondition that can be checked was checked and passed unavailable a precondition FAILED — a create would fail; "reason" says what to fix unknown the preconditions could NOT be evaluated (e.g. the project's config would not parse) — neither yes nor no is honest, so "reason" says what stopped the check
"unknown" is deliberately not folded into either of the other two: reporting an unchecked backend as available is a promise nobody verified.
"default" is the backend a create with no --backend resolves to here. It is EMPTY when the project's 'backend' config key names something unrecognized — such a create fails rather than quietly running local, and "default_reason" names the offending value.
The reasons are the same text a create prints when it refuses, because both come from the same precondition checks.
Example: af sessions backends af sessions backends --repo ~/src/myproject
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--json |
Wrap output in the {data,error} JSON envelope (default: bare payload) | |
--repo |
string |
Path to the project's git repository (default: the current directory's project) |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af sessions create¶
Create a new session
Create a new session running an agent in its own git worktree.
With --here (alias --in-place) the session instead attaches to the repo's existing working tree at its current branch: no worktree or branch is created, the agent runs in the repo root, and killing the session never removes the working tree or branch. Requires running inside a git repository (or --repo pointing at one).
Flags
| Flag | Type | Description |
|---|---|---|
--account |
string |
Credential account name to run the agent as (register it with af accounts add; defaults to the ambient identity) |
--backend |
string |
Runtime to run the session on (one of: local, docker, ssh, sandbox, hook; defaults to the repo's backend config, or local). docker runs the session in a container (set docker.image in the repo config); ssh runs it on a remote host (set ssh.host in the repo config). Run "af sessions backends" for which of these this project can actually use, and why not |
--here |
Run in the repo's existing working tree at its current branch (no new worktree/branch; kill preserves both) | |
--in-place |
Alias for --here | |
--name |
string |
Session title (alternative to positional |
--program |
string |
Program to run (one of: claude, codex, aider, gemini, amp, opencode, devin; defaults to config default) |
--prompt |
string |
Initial prompt to send |
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--json |
Wrap output in the {data,error} JSON envelope (default: bare payload) | |
--repo |
string |
Path to the project's git repository (default: the current directory's project) |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af sessions get¶
Get a session by title
Titles are unique within a project, not across projects, so the same name can exist in several repos. The title resolves inside the repo given by --repo, or the current directory's repo when --repo is omitted.
With no repo context, a title held by exactly one session still resolves; one held by sessions in several projects is ambiguous and reports an error naming those projects instead of guessing between them.
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--json |
Wrap output in the {data,error} JSON envelope (default: bare payload) | |
--repo |
string |
Path to the project's git repository (default: the current directory's project) |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af sessions handoff¶
Continue a session under a different agent, in place
Hand a session's work over to a different agent without losing it.
The session keeps its identity, its git worktree, and its branch — only the agent process changes. The incoming agent starts a fresh conversation and is given a mission brief: the session's goal, and what is already on the branch.
This is the answer to an agent that has stopped and cannot continue — most often one blocked at its provider's usage limit, where the alternative is waiting for the window to reset (see 'af sessions list' for a [limit] badge, and docs/usage-limits.md for the waiting path).
Agent conversations are not portable between providers: the incoming agent cannot read what its predecessor was thinking, only the working tree and the git history. The brief points it at both. Because of that, a handoff is recorded — the swap and the branch tip at the moment it happened — so a reviewer reading the resulting diff can tell which agent wrote which part.
Local-worktree sessions only: swapping the agent inside a remote/docker/ssh sandbox is a different lifecycle and is not supported yet.
Examples: af sessions handoff fix-auth --to claude af sessions handoff fix-auth --to gemini --brief "finish the retry test, skip the docs"
Flags
| Flag | Type | Description |
|---|---|---|
--brief |
string |
Mission for the incoming agent, replacing the session's stored prompt |
--to |
string |
Agent to hand the session off to (one of claude, codex, aider, gemini, amp, opencode, devin) |
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--json |
Wrap output in the {data,error} JSON envelope (default: bare payload) | |
--repo |
string |
Path to the project's git repository (default: the current directory's project) |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af sessions kill¶
Permanently destroy a session and prune its worktree branch
Permanently destroy a session: tear down tmux, remove the worktree, delete the stored session record, and prune the session branch when Agent Factory owns it.
For normal "done with this session" cleanup, prefer: af sessions archive
Kill always destroys the session, including any uncommitted or unmerged work on its branch — there is no undo. To keep a session restorable instead, archive it. --force is accepted but has no effect (kept for backward compatibility).
Flags
| Flag | Type | Description |
|---|---|---|
--force |
Deprecated no-op, accepted for compatibility: kill always destroys the session (use 'af sessions archive' to keep it restorable) |
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--json |
Wrap output in the {data,error} JSON envelope (default: bare payload) | |
--repo |
string |
Path to the project's git repository (default: the current directory's project) |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af sessions list¶
List sessions in the current project
List sessions in the current project.
Scope follows the shared project-context contract: --repo names a project, otherwise the current directory's project is used, and --all spans every project. Run from outside a git repository with no --repo, there is no project context and every project's sessions are listed.
Flags
| Flag | Type | Description |
|---|---|---|
--all |
List sessions across every project instead of only the current one |
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--json |
Wrap output in the {data,error} JSON envelope (default: bare payload) | |
--repo |
string |
Path to the project's git repository (default: the current directory's project) |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af sessions preview¶
Preview a session's terminal content
Titles are unique within a project, not across projects, so the same name can exist in several repos. The title resolves inside the repo given by --repo, or the current directory's repo when --repo is omitted.
With no repo context, a title held by exactly one session still resolves; one held by sessions in several projects is ambiguous and reports an error naming those projects instead of guessing between them.
By default this captures the session's AGENT tab (slot 0), visible screen only. Address another tab with --tab-name (the tab name "af sessions tab-create" printed, as reported by "af sessions get" — not the TUI's "Agent"/"Terminal" label), --tab-id (the stable id, for scripts that must not follow a reused name), or --tab (the 0-based slot). They resolve in that precedence — id, then name, then slot — the same order every tab verb uses. An id or name that does not resolve is an error, never a silent fall back to a slot: that would capture whatever tab had shifted into it.
--full returns the entire scrollback instead of the visible screen.
Flags
| Flag | Type | Description |
|---|---|---|
--full |
Capture the entire scrollback instead of the visible screen | |
--tab |
int |
Tab slot to capture, 0-based as the tab bar reads left to right (slot 0 is the agent tab) (default 0) |
--tab-id |
string |
Stable id of the tab to capture (#1738); wins over --tab-name and --tab |
--tab-name |
string |
Name of the tab to capture, as reported by "af sessions get" (not the TUI's "Agent"/"Terminal" label); wins over --tab |
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--json |
Wrap output in the {data,error} JSON envelope (default: bare payload) | |
--repo |
string |
Path to the project's git repository (default: the current directory's project) |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af sessions restore¶
Restore an archived, lost, or dead session
Restore a session that is currently archived, lost, or dead.
Archived sessions are moved back next to the repository, re-registered, re-spawned, and marked running. Lost/dead sessions are recovered in place, rebuilding a missing worktree when possible and resuming the recorded agent conversation when required.
Fails if the session is not restorable, or if its origin repository is gone. The restored worktree path is printed on success.
For a sandbox session (docker/ssh/hook) whose sandbox still ANSWERS but whose agent is gone, restore first pushes the sandbox's work to origin, because recovery re-clones from there and anything unpushed would be destroyed. If that push fails, or if af cannot tell whether the sandbox is gone or merely unreachable, the restore REFUSES and the session stays recoverable.
--force-reap replaces the sandbox anyway, without the push. It discards whatever that sandbox has not pushed, so it is for a sandbox you know is expendable. It applies to this one session and this one command; there is no global equivalent.
Flags
| Flag | Type | Description |
|---|---|---|
--force-reap |
replace a reachable sandbox WITHOUT pushing its work first (discards anything it has not pushed) |
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--json |
Wrap output in the {data,error} JSON envelope (default: bare payload) | |
--repo |
string |
Path to the project's git repository (default: the current directory's project) |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af sessions retry-limit¶
Retry a session blocked at a usage limit
Retry a session that is parked at a provider usage-limit wall.
The daemon runs the same recovery action as the TUI's c key and the web's Retry button: it re-spawns an exited agent when necessary, re-delivers the pending prompt (or "continue" for an interactive session with no stored prompt), and clears the limit state after delivery succeeds.
The command fails if the session is not currently blocked on a usage limit. Use 'af sessions list' to find sessions carrying the [limit] badge.
Example: af sessions retry-limit fix-auth
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--json |
Wrap output in the {data,error} JSON envelope (default: bare payload) | |
--repo |
string |
Path to the project's git repository (default: the current directory's project) |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af sessions send-prompt¶
Send a prompt to a session (or broadcast to all with --all)
Send a prompt to an existing session. The session must already exist unless --create is used.
If the session does not exist, use --create to automatically create it first, or use 'af sessions create --name
With --all, broadcast a single prompt to every live session in scope:
af sessions send-prompt --all "<prompt>"
Broadcast scope defaults to the current repo (honoring --repo). Pass --all-repos to broadcast across every repo. The reserved root session is excluded unless --include-root is given. Delivery is best-effort per session: unreachable (Lost, Dead) and Archived sessions are skipped and reported, and one failure never aborts the rest. The command prints a JSON summary (delivered / failed / skipped) and exits 0 even when some sessions fail, so scripts can inspect per-session results.
Flags
| Flag | Type | Description |
|---|---|---|
--all |
Broadcast the prompt to every live session in scope (current repo by default; excludes the reserved root session) | |
--all-repos |
With --all, broadcast across every repo instead of only the current/--repo one | |
--create |
Auto-create the session if it doesn't exist | |
--include-root |
With --all, also deliver to the reserved root session (excluded by default) | |
--program |
string |
Program to run when creating a new session (one of: claude, codex, aider, gemini, amp, opencode, devin; defaults to config default) |
--prompt |
string |
The prompt to send (alias for the positional |
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--json |
Wrap output in the {data,error} JSON envelope (default: bare payload) | |
--repo |
string |
Path to the project's git repository (default: the current directory's project) |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af sessions tab-create¶
Spawn a shell, process, web, or VS Code tab in a session
Create a new tab in an existing session.
Shell tab (--kind shell): starts the user's $SHELL in the session's git worktree. This is the same Terminal tab the TUI and web UI open; "shell" is its canonical kind and name, while "Terminal" is only the label those UIs display.
Process tab (default): runs --command in the session's git worktree (e.g. a data explorer TUI or a test watcher). If --name is omitted, a name is derived from the command's basename.
Web tab (--kind web): a URL/iframe tab with NO process — an agent injects a live
browser view into the user's screen. Point it at a local dev server with --port
The tab persists and reconnects across a daemon/af restart like every other tab.
--name sets a process, web, or VS Code tab's name — the handle every other tab verb addresses it by. A shell tab does not accept --name: its canonical name is "shell" (auto-suffixed on collision), while the TUI renders the presentation-only label "Terminal". Other names are sanitized before use: characters outside [A-Za-z0-9_-] become "-". The name is then made unique within the session (auto-suffixed -2, -3, …). So the name you pass is not always the name you get — the resolved tab name is printed on success, and that is the one the other tab verbs address.
Not available for remote sessions: they have no local worktree.
Flags
| Flag | Type | Description |
|---|---|---|
--command |
string |
Command to run in a process tab (required when --kind is empty) |
--kind |
string |
Tab kind: "shell" for a $SHELL terminal, empty for a process command, "web" for a URL/iframe, or "vscode" for VS Code |
--name |
string |
Tab name — sanitized to [A-Za-z0-9_-] and auto-suffixed on collision (not valid with --kind shell) |
--port |
int |
Web tab convenience for --url http://localhost:0) |
--url |
string |
Web tab target URL (with --kind web): a localhost dev-server address or an external https URL |
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--json |
Wrap output in the {data,error} JSON envelope (default: bare payload) | |
--repo |
string |
Path to the project's git repository (default: the current directory's project) |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af sessions tab-delete¶
Delete a single tab from a session
Delete the named tab from an existing session — the counterpart of tab-create.
The tab is removed from the daemon's session state and its tmux window is killed. The removal is persistent: the daemon will not respawn the tab, and it does not return on a daemon/af restart. The name to pass is the tab name tab-create printed, as reported by "af sessions get" — not the label the TUI tab bar shows, which is a fixed "Agent"/"Terminal" for agent and shell tabs. A miss lists the tabs that exist, with those labels, so a wrong name is a next step rather than a dead end.
The agent tab can't be deleted — use "af sessions kill" to tear down the whole session. Deleting a tab or session that doesn't exist is an error, not a silent success. Not available for remote sessions: their tabs are fixed by remote_hooks config.
Flags
| Flag | Type | Description |
|---|---|---|
--name |
string |
Name of the tab to delete (required; the tab's name, not the TUI's "Agent"/"Terminal" label) |
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--json |
Wrap output in the {data,error} JSON envelope (default: bare payload) | |
--repo |
string |
Path to the project's git repository (default: the current directory's project) |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af sessions tab-rename¶
Rename a tab of a session
Rename an existing tab — the fix for a name you have to live with all day, typically one an agent picked when it created the tab.
Only web, process and VS Code tabs can be renamed: those are the tabs that display their name. The agent tab always shows "Agent" and shell tabs always show "Terminal" on every surface, so renaming one would change the handle you address it by without changing anything you can see — confusing rather than useful, so it is refused.
--new-name follows the same rules as tab-create's --name: characters outside [A-Za-z0-9_-] become "-", and the name is made unique within the session (auto-suffixed -2, -3, …). A name that sanitizes away to nothing is an error rather than a silent fall back to a default. The resolved name is printed on success — that is what the tab is actually called, and what the other tab verbs now address it by.
The rename persists across a daemon/af restart and does not disturb the tab's running process. Not available for remote sessions (their tabs are fixed by remote_hooks config) or archived sessions (restore them first).
Flags
| Flag | Type | Description |
|---|---|---|
--name |
string |
Name of the tab to rename (required; the tab's name, not the TUI's "Agent"/"Terminal" label) |
--new-name |
string |
New name for the tab (required; sanitized and auto-suffixed on collision) |
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--json |
Wrap output in the {data,error} JSON envelope (default: bare payload) | |
--repo |
string |
Path to the project's git repository (default: the current directory's project) |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af sessions tab-reorder¶
Move a tab within a session's tab order
Move a tab to a different slot, so the tab order is yours rather than whatever order the tabs happened to be created in.
--index is the destination slot, 0-based, counting the tab bar left to right, and read as the tab's FINAL position: moving a tab to --index 3 of a 4-tab session puts it last.
Slot 0 is reserved for the agent tab: the agent tab can't be moved, and no tab can be moved in front of it. That is structural, not cosmetic — the agent tab is identified by its position throughout a session's lifecycle.
The new order persists across a daemon/af restart and does not disturb any tab's running process. Not available for remote sessions (their tabs are fixed by remote_hooks config) or archived sessions (restore them first).
Flags
| Flag | Type | Description |
|---|---|---|
--index |
int |
Destination slot, 0-based, as the tab bar reads left to right (required; slot 0 is the agent tab and can't be targeted) (default 0) |
--name |
string |
Name of the tab to move (required; the tab's name, not the TUI's "Agent"/"Terminal" label) |
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--json |
Wrap output in the {data,error} JSON envelope (default: bare payload) | |
--repo |
string |
Path to the project's git repository (default: the current directory's project) |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af sessions tabs¶
Manage a session's tabs (create/delete/rename/reorder)
Noun-subcommand aliases for the tab-create/tab-delete/tab-rename/tab-reorder verbs.
"sessions tabs create" is identical to "sessions tab-create", and the same holds for delete, rename and reorder; the hyphen verbs remain supported for existing scripts. To list a session's tabs, use "sessions get
Subcommands
af sessions tabs create— Spawn a shell, process, web, or VS Code tab in a sessionaf sessions tabs delete— Delete a single tab from a sessionaf sessions tabs rename— Rename a tab of a sessionaf sessions tabs reorder— Move a tab within a session's tab order
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--json |
Wrap output in the {data,error} JSON envelope (default: bare payload) | |
--repo |
string |
Path to the project's git repository (default: the current directory's project) |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af sessions tabs create¶
Spawn a shell, process, web, or VS Code tab in a session
Alias for "sessions tab-create". See "af sessions tab-create --help" for details.
Flags
| Flag | Type | Description |
|---|---|---|
--command |
string |
Command to run in a process tab (required when --kind is empty) |
--kind |
string |
Tab kind: "shell" for a $SHELL terminal, empty for a process command, "web" for a URL/iframe, or "vscode" for VS Code |
--name |
string |
Tab name — sanitized to [A-Za-z0-9_-] and auto-suffixed on collision (not valid with --kind shell) |
--port |
int |
Web tab convenience for --url http://localhost:0) |
--url |
string |
Web tab target URL (with --kind web): a localhost dev-server address or an external https URL |
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--json |
Wrap output in the {data,error} JSON envelope (default: bare payload) | |
--repo |
string |
Path to the project's git repository (default: the current directory's project) |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af sessions tabs delete¶
Delete a single tab from a session
Alias for "sessions tab-delete". See "af sessions tab-delete --help" for details.
Flags
| Flag | Type | Description |
|---|---|---|
--name |
string |
Name of the tab to delete (required; the tab's name, not the TUI's "Agent"/"Terminal" label) |
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--json |
Wrap output in the {data,error} JSON envelope (default: bare payload) | |
--repo |
string |
Path to the project's git repository (default: the current directory's project) |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af sessions tabs rename¶
Rename a tab of a session
Alias for "sessions tab-rename". See "af sessions tab-rename --help" for details.
Flags
| Flag | Type | Description |
|---|---|---|
--name |
string |
Name of the tab to rename (required; the tab's name, not the TUI's "Agent"/"Terminal" label) |
--new-name |
string |
New name for the tab (required; sanitized and auto-suffixed on collision) |
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--json |
Wrap output in the {data,error} JSON envelope (default: bare payload) | |
--repo |
string |
Path to the project's git repository (default: the current directory's project) |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af sessions tabs reorder¶
Move a tab within a session's tab order
Alias for "sessions tab-reorder". See "af sessions tab-reorder --help" for details.
Flags
| Flag | Type | Description |
|---|---|---|
--index |
int |
Destination slot, 0-based, as the tab bar reads left to right (required; slot 0 is the agent tab and can't be targeted) (default 0) |
--name |
string |
Name of the tab to move (required; the tab's name, not the TUI's "Agent"/"Terminal" label) |
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--json |
Wrap output in the {data,error} JSON envelope (default: bare payload) | |
--repo |
string |
Path to the project's git repository (default: the current directory's project) |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af sessions watch¶
Block until a session goes idle, or until any session in the fleet changes state
Watch a session and return when its agent finishes working: exit 0 the moment the session goes IDLE (the agent stopped working and is awaiting input), so an operator or root agent can dispatch a session and be notified on completion instead of polling 'af sessions preview'.
Polls the daemon's snapshot (the same read path as 'af sessions get') every --interval (default 2s). Exits non-zero if the session reaches a terminal state it can't leave on its own (lost, dead, or archived), if it disappears (killed), or if --timeout elapses first (default 30m). A session that is still working, a usage-limit block that auto-resumes, or a create/archive/restore in progress all keep the watch waiting.
By default prints a concise line on transition; with --json emits the final session record. Honors --repo to scope the title lookup to one repository.
With NO title (or --all) it watches every session in scope and returns when the first one CHANGES STATE, printing which and why. That form is edge-triggered: the first poll establishes a baseline and reports nothing, so a session that was already idle before you called does not fire. Pass --include-current to report those too, for a driver that wants a starting snapshot; that snapshot omits archived sessions, which are inert by construction and cannot change on their own (a session archived WHILE you watch is still reported).
Each reported session carries a reason a driver can act on: idle, usage-limited (af resumes it automatically — do not prompt it), lost, dead, archived, killed, gone, or unknown. "idle" covers both "finished its work" and "waiting on input": af records both as the same state and does not distinguish them, so neither does this. A session af cannot classify reports "unknown" and is never reported as idle, because an idle report tells a driver to act.
Flags
| Flag | Type | Description |
|---|---|---|
--all |
Watch every session in scope and return when the first one changes state (the default when no title is given) | |
--include-current |
Fleet form: also report sessions that are already stopped at the first poll, instead of only transitions | |
--interval |
duration |
How often to poll the session's status (default 2s) |
--timeout |
duration |
Give up and exit non-zero if the session is not idle within this window (0 = wait forever) (default 30m0s) |
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--json |
Wrap output in the {data,error} JSON envelope (default: bare payload) | |
--repo |
string |
Path to the project's git repository (default: the current directory's project) |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af sessions whoami¶
Identify the current Agent Factory session
Returns the session info for the current tmux session by matching the tmux session name against stored sessions.
Identity is not scoped: you are the session you are, in whatever project it belongs to. --repo therefore acts as an assertion — it checks that the resolved session really is in that project, and errors if it is not.
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--json |
Wrap output in the {data,error} JSON envelope (default: bare payload) | |
--repo |
string |
Path to the project's git repository (default: the current directory's project) |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af tasks¶
Manage tasks
Subcommands
af tasks add— Add a new task bound to the current projectaf tasks get— Get a task in the current project by IDaf tasks list— List tasks in the current projectaf tasks remove— Remove a task in the current projectaf tasks restart— Restart an enabled watch task without process overlapaf tasks trigger— Trigger a task in the current project to run immediatelyaf tasks update— Update a task in the current project
Flags
| Flag | Type | Description |
|---|---|---|
--json |
Wrap output in the {data,error} JSON envelope (default: bare payload) | |
--repo |
string |
Path to the project's git repository (default: the current directory's project) |
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af tasks add¶
Add a new task bound to the current project
Add a new task bound to the current project.
A task is bound to exactly one project, and every run's worktree is created inside it. The binding comes from --repo when given, otherwise from the current directory's git repository (a linked worktree resolves to its main repository). The resolved project is echoed back as project_path so the binding is visible at creation rather than inferred later.
Outside a git repository, --repo is required — the binding is never guessed. A current directory that resolves to a clone inside af's own home is refused as a stray checkout (#1891); pass --repo to name the intended project.
Flags
| Flag | Type | Description |
|---|---|---|
--cron |
string |
Cron expression (exactly one of --cron / --watch-cmd) |
--max-concurrent-runs |
int |
Cap how many sessions this watch task may have in flight at once; excess events are queued in order instead of spawning runs, subject to the durable queue's retention limits (0 = unlimited; --watch-cmd tasks without --target-session only) (default 0) |
--name |
string |
Task name (required) |
--on-complete |
string |
What happens to the session a run spawns once it finishes: keep (default, leaves it in place), archive (restorable, but retains its whole worktree), or kill (reclaims the worktree and prunes the session's branch). Not for --target-session tasks, whose session is meant to be reused |
--program |
string |
Program to run (one of: claude, codex, aider, gemini, amp, opencode, devin; defaults to config default) |
--prompt |
string |
Prompt to send (required for --cron tasks; --watch-cmd tasks default to the emitted line, with {{line}} substituted when present) |
--target-session |
string |
Deliver the prompt into this session (auto-created if missing); empty creates a new session per run |
--watch-cmd |
string |
Long-running watch command; each stdout line triggers the task (exactly one of --cron / --watch-cmd) |
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--json |
Wrap output in the {data,error} JSON envelope (default: bare payload) | |
--repo |
string |
Path to the project's git repository (default: the current directory's project) |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af tasks get¶
Get a task in the current project by ID
Get a task in the current project by ID.
The task must belong to the resolved project: --repo when given, otherwise the current directory's project. Inspecting another project's task requires naming it with --repo. Outside a git repository there is no project context and the id resolves globally.
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--json |
Wrap output in the {data,error} JSON envelope (default: bare payload) | |
--repo |
string |
Path to the project's git repository (default: the current directory's project) |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af tasks list¶
List tasks in the current project
List tasks in the current project.
Scope follows the shared project-context contract: --repo names a project, otherwise the current directory's project is used, and --all spans every project. Run from outside a git repository with no --repo, there is no project context and every project's tasks are listed.
This default changed in #1893: af tasks list inside a repository used to list every project's tasks. Pass --all for the old behavior.
Flags
| Flag | Type | Description |
|---|---|---|
--all |
List tasks across every project instead of only the current one |
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--json |
Wrap output in the {data,error} JSON envelope (default: bare payload) | |
--repo |
string |
Path to the project's git repository (default: the current directory's project) |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af tasks remove¶
Remove a task in the current project
Remove a task in the current project.
The task must belong to the resolved project: --repo when given, otherwise the current directory's project. Removing another project's task requires naming it with --repo. Outside a git repository there is no project context and the id resolves globally.
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--json |
Wrap output in the {data,error} JSON envelope (default: bare payload) | |
--repo |
string |
Path to the project's git repository (default: the current directory's project) |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af tasks restart¶
Restart an enabled watch task without process overlap
Restart an enabled watch task in the current project. The command waits for the old process tree to exit before starting one replacement, so an edited script is re-read without double-emitting events.
The task must belong to the resolved project: --repo when given, otherwise the current directory's project. Outside a git repository there is no project context and the id resolves globally.
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--json |
Wrap output in the {data,error} JSON envelope (default: bare payload) | |
--repo |
string |
Path to the project's git repository (default: the current directory's project) |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af tasks trigger¶
Trigger a task in the current project to run immediately
Trigger a task in the current project to run immediately.
The task must belong to the resolved project: --repo when given, otherwise the current directory's project. Triggering another project's task requires naming it with --repo. Outside a git repository there is no project context and the id resolves globally.
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--json |
Wrap output in the {data,error} JSON envelope (default: bare payload) | |
--repo |
string |
Path to the project's git repository (default: the current directory's project) |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af tasks update¶
Update a task in the current project
Update a task in the current project.
The task must belong to the resolved project: --repo when given, otherwise the current directory's project. Updating another project's task requires naming it with --repo. Outside a git repository there is no project context and the id resolves globally.
--repo scopes which task may be updated; it never re-binds one. Pass --project-path to move that task to another existing git repository. The new path becomes the task's working directory and project binding.
Flags
| Flag | Type | Description |
|---|---|---|
--cron |
string |
New cron expression (clears watch-cmd) |
--enabled |
string |
Enable or disable the task (true/false) |
--max-concurrent-runs |
int |
New in-flight session cap for this watch task; pass 0 to revert to unlimited (default 0) |
--name |
string |
New task name |
--on-complete |
string |
New spawned-session lifecycle: keep, archive, or kill; pass keep to revert to leaving sessions in place |
--program |
string |
New program to run (one of: claude, codex, aider, gemini, amp, opencode, devin; leave unset to keep the current one) |
--project-path |
string |
Move the task to this git repository (distinct from --repo, which scopes its current project) |
--prompt |
string |
New prompt |
--target-session |
string |
New target session; pass an empty value to revert to a new session per run |
--watch-cmd |
string |
New watch command (clears cron) |
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--json |
Wrap output in the {data,error} JSON envelope (default: bare payload) | |
--repo |
string |
Path to the project's git repository (default: the current directory's project) |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af token¶
Manage the daemon's bearer token for the direct-TCP API
Manage the bearer token that authenticates the daemon's direct-TCP HTTP API.
The token grants full access under the single-owner auth model. It is only used by the TCP listener (enabled with the listen_addr config key); the local unix socket stays unauthenticated (its 0600 filesystem perms are the local auth). The token is stored in the af home (~/.agent-factory) with 0600 permissions.
The listener serves plain HTTP — af terminates no TLS of its own. The token travels over the connection, so expose the listener only behind a reverse proxy (nginx/caddy) or on a private network (Tailscale/VPN/SSH tunnel).
Subcommands
af token rotate— Replace the bearer token with a fresh one and print itaf token show— Print the bearer token (generating it if absent)
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af token rotate¶
Replace the bearer token with a fresh one and print it
Generate a new bearer token, persist it (overwriting the old one), and print it.
Rotation takes effect for new connections immediately — the auth gate re-reads the token file per request — while any in-flight streams keep running until they reconnect.
Flags
| Flag | Type | Description |
|---|---|---|
--json |
Emit the result as JSON wrapped in the {data,error} envelope |
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af token show¶
Print the bearer token (generating it if absent)
Print the daemon's bearer token.
It is generated on first access if it does not yet exist, so this is safe to run before the TCP listener is ever enabled. Present it to a remote daemon with the --token flag (or the AF_DAEMON_TOKEN env var).
Flags
| Flag | Type | Description |
|---|---|---|
--json |
Emit the result as JSON wrapped in the {data,error} envelope |
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af upgrade¶
Upgrade agent-factory to the latest release on the configured channel
Upgrade agent-factory to the newest release on the configured update channel (stable by default, or preview via the update_channel config key).
You rarely need this: af auto-updates on launch by default, at most once every 6 hours, and re-launches you into the new version. Disable that with auto_update = false in your config to pin the installed version — af upgrade keeps working either way.
A manual upgrade never downgrades: if the channel's latest release is older than the running binary — which happens when you switch from the preview channel back to stable — the upgrade is a no-op with an explanation. Pass --allow-downgrade to install the older release anyway.
af upgrade restarts the running daemon after the swap, and always has: the daemon keeps executing the old code until something restarts it, so a fix that does not reach it is not really installed. Live sessions survive — they run in tmux and the new daemon re-adopts them. Pass --no-restart to leave the daemon on the old binary until you restart it yourself with 'af daemon restart'.
Flags
| Flag | Type | Description |
|---|---|---|
--allow-downgrade |
Install the channel's latest release even if it is older than the current binary (e.g. switching from preview back to stable) | |
--allow-rejected |
Install even if this exact build was rolled back on this machine (it failed validation here before) | |
--ignore-active-upgrade |
Install even while a daemon upgrade transaction is in progress (this can leave that upgrade unable to roll back) | |
--no-restart |
Leave the running daemon alone (af upgrade restarts it by default so the new binary takes effect) |
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |
af version¶
Print the version number of agent-factory
Global flags
| Flag | Type | Description |
|---|---|---|
--daemon-url |
string |
Target a REMOTE daemon at this http:// or ws:// URL instead of the local unix socket (env: AF_DAEMON_URL). The daemon is HTTP-only; terminate TLS at your own proxy if needed. |
--token |
string |
Bearer token for a remote daemon set with --daemon-url (env: AF_DAEMON_TOKEN). Get it with 'af token show' on the daemon host. |