leo agent¶
Spawn and control ephemeral Claude agents on a leo server. The leo binary is dual-purpose: on a server it supervises processes and runs scheduled tasks, and on a laptop it becomes a thin remote client that talks to a leo host over SSH.
Usage¶
leo agent list # list running agents
leo agent spawn <template> # spawn the template as-is (no repo)
leo agent spawn <template> --repo <owner/repo> # spawn from a template
leo agent spawn <template> --repo <name> --name <n> # spawn with a custom name
leo agent spawn <template> --repo <owner/repo> --worktree <branch> # spawn into a dedicated git worktree
leo agent worktree <agent> <branch> # spawn a worktree agent branched off an existing agent
leo agent attach <name> # attach to the agent's tmux session
leo agent session-name <query> # print the tmux session name
leo agent stop <name> [--prune] # stop a running agent (optionally remove worktree)
leo agent suspend <name> # suspend a running agent (idle-suspend, manual)
leo agent resume <name> # resume a suspended agent, rejoining its prior conversation
leo agent reset <name> # stop, clear stored session id, and respawn fresh
leo agent prune <name> # remove a stopped worktree agent's on-disk state
leo agent logs <name> [-n LINES] [-f] # tail the agent's pane output
<name> for attach, stop, suspend, reset, and logs accepts shorthand — see Shorthand Resolution below. resume and prune take the canonical name only — the shorthand resolver only matches live agents, and both a suspended agent (resume's target) and a stopped worktree agent (prune's target) are not live. session-name is the explicit resolver.
Flags¶
Every agent subcommand accepts --host NAME to select a remote. The name must match an entry in client.hosts in leo.yaml, or the literal string localhost to force local dispatch even when remotes are configured.
Resolution order when --host is omitted:
LEO_HOSTenvironment variableclient.default_hostinleo.yaml- First entry in
client.hosts(sorted by key) - Localhost (only if no hosts are configured)
If any hosts are configured, Leo assumes this machine is a client and will never silently fall back to localhost — pass --host localhost explicitly when you want to target the local daemon on a server.
Host Configuration¶
Add a client section to leo.yaml on the client machine:
client:
default_host: prod
hosts:
prod:
ssh: alice@leo.example.com
ssh_args: ["-p", "2222"]
dev:
ssh: alice@devbox.local
ssh is passed verbatim as the SSH target. ssh_args adds extra flags (port, identity file, jump host) between the target and the remote command. Leo does not parse ~/.ssh/config — anything SSH itself resolves works transparently.
See the Remote CLI guide for a complete walkthrough.
Shorthand Resolution¶
Any subcommand that takes <name> — attach, stop, logs — accepts shorthand in place of the canonical agent name. session-name is the explicit resolver and accepts the same queries. Resolution walks these tiers in order and returns the first unambiguous match against live agents:
- Exact full name (case-insensitive)
- Exact stored repo (e.g.
owner/name) - Repo short — the segment after
/forowner/namerepos, or the full value for slashless repos - Suffix match on the full name (
-<query>)
leo agent stop leo # resolves to leo-coding-blackpaw-studio-leo if unique
leo agent logs my-app -f # matches either a bare-name agent or owner/my-app
Ambiguous queries print the candidates and exit non-zero — re-run with the full name or a more specific query. Only running agents participate; stopped records are never matched, so short names are reusable as soon as an agent stops.
The same resolver is shared by the daemon HTTP API (POST /api/agent/stop, etc.) and the web UI, so shorthand works identically everywhere.
Subcommands¶
leo agent list¶
Show running agents as a table:
NAME TEMPLATE WORKSPACE STATUS RESTARTS
leo-coding-my-app coding ~/agents/my-app running 0
leo-scratch - ~/agents/scratch running 1
--json emits the raw AgentRecord array for scripting.
leo agent spawn <template>¶
Spawn a new agent from the named template. --repo (or the positional [repo] arg) is optional and takes either an owner/repo pair (Leo clones via gh repo clone) or a plain name (Leo reuses the template's configured workspace path under a per-name subdir). Omit it entirely to run the template as-is, directly in its own workspace — the agent is named after the template.
leo agent spawn coding # run the template as-is; agent named "coding"
leo agent spawn coding --repo blackpaw-studio/leo
leo agent spawn coding --repo my-app --name scratch
--name overrides the auto-derived name (the template name for a repo-less spawn, leo-<template>-<repo> otherwise). When the agent already exists, Leo appends a numeric suffix (-2, -3, …) so repeated spawns never collide.
Worktree Spawns¶
Pass --worktree <branch> to isolate the agent in its own git worktree instead of sharing a single clone:
leo agent spawn coding --repo blackpaw-studio/leo --worktree feat/cache
leo agent spawn coding --repo blackpaw-studio/leo --worktree feat/new --base main
--worktreerequires a repo, and specificallyowner/repo(a repo-less or slashless spawn has no canonical clone to branch from).- If the branch exists locally or on
origin, Leo attaches to it. Otherwise Leo creates a new branch off--base, defaulting to origin's default branch. - The worktree lives at
<baseWorkspace>/.worktrees/<repo-short>/<branch-slug>/. See workspace structure for the full layout. - The agent name includes the branch slug:
leo-<template>-<owner>-<repo>-<branch-slug>. leo agent listshows aBRANCHcolumn for worktree agents; stopped worktree agents stay in the list until youprunethem.
Collision Prompt¶
When --repo is a bare name (no slash) that matches the short name of a running agent, Leo prompts for how to proceed:
- a — attach to the existing agent
- b — spawn a fresh agent using that agent's canonical
owner/repo - c — spawn a fresh agent under the template workspace (default)
- q — cancel
When --repo is owner/repo and a running agent already targets the same repo (and branch, if --worktree is set), Leo prompts with the same options minus b (since the user already supplied the canonical repo). Selecting c spawns a new agent with a numeric suffix (e.g. -2).
Non-TTY runs skip the prompt and default to fresh-template. Two flags override the prompt:
--attach-existing— always attach if a collision is found--reuse-owner— always respawn using the existing canonical repo (slashless only)
On success Leo prints the resolved name and workspace, plus the one-liner to attach.
leo agent worktree <agent> <branch>¶
Spawn a worktree agent branched off an existing agent — sugar over spawn --worktree that derives everything from the source agent's record instead of an owner/repo. Works for any agent whose workspace is a git repository, not just ones spawned with --repo owner/repo.
leo agent worktree chronicle a11y
leo agent worktree chronicle hotfix --base v1.2.0 --prompt "fix the crash"
- Template and env are inherited from the source agent's record by default; the source's workspace (or its canonical repo, if the source is itself a worktree agent) becomes the new agent's git canonical.
- Naming:
<agent>-<branch-slug>. The worktree lives at<workspace-base>/.worktrees/<agent>/<branch-slug>/. - Branching off a worktree agent uses that agent's canonical repo, not its own checkout — pass
--base <its-branch>to fork from the branch it's on rather than the canonical's default. - Remoteless repos (no
origin): the fetch step is skipped and new branches are cut fromHEADinstead of origin's default branch. - If the branch exists locally or on
origin, Leo attaches to it; otherwise it creates a new branch off--base(or the remoteless/default-branch fallback above).
Flags:
--name— override the derived agent name--base— base ref for new branches (defaults to origin's default branch, orHEADfor remoteless repos)--template— build the new agent from a different template than the source agent's, keeping the same source repo as the git canonical; the override template must exist in config. Model, harness, and args re-resolve from it. When set, none of the source agent's env is inherited — only the override template's own env plus--env.--prompt— opening prompt delivered as the agent's first interactive turn--env KEY=VALUE— extra env var (repeatable); overrides an inherited value on collision--json— emit the spawnedAgentRecordas JSON
Clean up the same way as any worktree agent: leo agent stop <name> --prune.
# chronicle is a running agent with a git workspace; branch it onto an a11y pass
leo agent worktree chronicle a11y
# spawned chronicle-a11y (branch: a11y, worktree: ~/.leo/workspace/.worktrees/chronicle/a11y)
# attach with: leo agent attach chronicle-a11y
leo agent stop chronicle-a11y --prune # done — tear down the checkout
leo agent attach <name>¶
Attach to the agent's tmux session. Leo keeps all supervised sessions on a dedicated tmux socket — every invocation passes -L leo, so leo-<name> sessions never mix with your personal tmux server.
- From a normal shell: Leo replaces the CLI with
tmux -L leo attach -t leo-<name>viasyscall.Execso the TUI owns the TTY cleanly. - From inside tmux: Leo uses
display-popup -Eon your outer tmux server to open the leo session as an overlay, preserving your original tmux session when the popup is dismissed (no nested tmux). - Remotely: Leo runs
ssh -t <host> tmux -L leo attach -t leo-<name>.
Running leo attach without a name opens a full-screen, fuzzy-filterable picker over every agent — local and every configured remote host — in every state (running, starting, suspended, stopped). Beyond attaching, the picker doubles as a lifecycle surface: Enter attach (a suspended agent is resumed first), s suspend, u resume, x stop (with confirmation), r rename, / filter, q quit. The picker always opens when no name is given — there is no longer a single-candidate auto-attach shortcut.
Pass --cc to open the session in tmux control mode (-CC), which iTerm2 and WezTerm pick up as a native tab. Control mode is refused cleanly from inside tmux or over SSH.
<name> accepts shorthand — see Shorthand Resolution. Detach with the normal tmux prefix + d (default: C-b d). The agent keeps running. See tmux config for deeper detail on the dedicated socket and recommended bindings (tmux 3.2+).
leo agent session-name <query>¶
Resolve a shorthand query to the canonical tmux session name and print it to stdout. Useful in scripts that want the canonical session string without attaching, and the building block for the remote attach round-trip:
leo agent stop <name>¶
Stop a running agent. Kills the tmux session and deregisters from the supervisor. Accepts shorthand.
- Shared-workspace agents: the record is removed; the workspace stays on disk.
- Worktree agents: the record is preserved so you can reattach or inspect the branch. Pass
--pruneto also remove the worktree and record in a single round trip.
Flags (only meaningful with --prune, and only for worktree agents):
--prune— also remove the on-disk worktree and agentstore record--force— with--prune, remove even when the worktree is dirty--delete-branch— with--prune, delete the local branch after the worktree is gone
leo agent suspend <name>¶
Suspend a running agent: kills the process/tmux session but preserves the workspace and stored claude session id. Accepts shorthand. A suspended agent shows as suspended in leo agent list and auto-resumes on the next incoming message. See Config Reference → Idle-suspend.
leo agent resume <name>¶
Resume a suspended agent, rejoining its prior conversation via --resume. Takes the canonical name only — shorthand resolution only matches live agents, and a suspended agent isn't one.
leo agent reset <name>¶
Reset an agent to a brand-new conversation: stops any live process/tmux session, clears the stored claude session id, and respawns fresh from the agent's template. Accepts shorthand. Unlike resume, which rejoins the prior conversation, reset deliberately discards it — use this when an agent's context has gotten stuck or corrupted (a common case: a long-lived agent backing a runtime: persistent task whose conversation has filled up). See Persistent Tasks → leo agent reset.
leo agent prune <name>¶
Remove the on-disk worktree and agentstore record for a worktree agent that has already been stopped. No-op (returns an error) for shared-workspace agents. Takes the canonical agent name — shorthand resolution only matches live agents, so prune requires the full name you saw in the last leo agent list. Use leo agent stop --prune instead when the agent is still running and you want shorthand.
leo agent prune leo-coding-blackpaw-studio-leo-feat-cache
leo agent prune feat-cache --delete-branch
Flags:
--force— remove even when the worktree has uncommitted changes, or the branch is unmerged--delete-branch— delete the local branch after the worktree is gone
Typical flow:
leo agent stop feat-cache # stop, leave worktree for inspection
# … review the branch, push a PR, merge …
leo agent prune feat-cache --delete-branch
Or in one step:
leo agent logs <name>¶
Capture the tmux pane for the named agent. Accepts shorthand.
-n/--lines N— tail length (default 200)-f/--follow— stream viatail -fon a temp log file fed bytmux pipe-pane. Ctrl-C to exit.
See Also¶
- Remote CLI guide — host setup and SSH walkthrough
- Agents guide — templates, lifecycle, and channel/web parity
leo template— manage the templatesagent spawnconsumes