Remote CLI¶
Leo's agent subcommand is designed to be run from a laptop against a persistent leo host. No new daemon, listener, or auth layer — Leo shells out to ssh for every remote call and reuses whatever SSH setup you already have (~/.ssh/config, agent forwarding, MFA, jump hosts).
This guide walks through turning a fresh laptop into a client.
Prerequisites¶
On the server (the machine that runs leo service):
leoalready installed and authenticated with Claude.leo service startrunning (so the daemon and web UI are up).- SSH reachable from the client machine.
On the client (your laptop):
leobinary installed (same version is safest).- Working SSH access to the server —
ssh <host> echo okshould printok.
Leo does not need to be set up or have a daemon running on the client. The client leo.yaml only needs the client section below.
Configure hosts¶
Edit ~/.leo/leo.yaml on the client (create the file if it doesn't exist):
client:
default_host: prod
hosts:
prod:
ssh: alice@leo.example.com
ssh_args: ["-p", "2222"]
dev:
ssh: alice@devbox.local
sshis passed verbatim as the SSH target. Anything SSH itself resolves (Host aliases, ProxyJump, IdentityFile) works.ssh_argsinserts extra flags between the target and the remote command. Handy for non-default ports or explicit identity files.leo_pathoverrides the remote binary path. Defaults to$HOME/.local/bin/leo(matchesinstall.sh). Set this if the remote installed leo elsewhere, or if you seecommand not found: leoover SSH — non-interactive SSH shells don't source.zshrcso PATH additions there don't apply.tmux_pathoverrides the remotetmuxpath used byagent attachandagent logs --follow. Defaults totmux. For macOS arm64 homebrew remotes set to/opt/homebrew/bin/tmux; for intel homebrew,/usr/local/bin/tmux. Same reason asleo_path— homebrew paths live in.zprofile/.zshrcwhich ssh command-mode doesn't load.default_hostis optional — if set, commands without--hostuse it. Otherwise the first host in sorted order wins.
Verify the config parses:
First spawn¶
--repo is optional — leo agent spawn coding alone runs the template as-is on the remote host, with the agent named after the template.
# On the client
leo agent spawn coding --repo blackpaw-studio/leo --name demo
# → spawned leo-demo (workspace: /home/alice/agents/demo)
# attach with: leo agent attach leo-demo
leo agent list
# NAME TEMPLATE WORKSPACE STATUS RESTARTS
# leo-demo coding /home/alice/agents/demo running 0
leo agent attach leo-demo
# (full tmux attach — same Claude TUI as running locally on the server)
# prefix + d to detach
leo agent logs leo-demo -n 50
leo agent stop leo-demo
Every non-attach subcommand runs ssh <host> leo agent <subcommand> under the hood. Attach runs ssh -t <host> tmux attach -t leo-<name> so terminal resizing and scrollback work normally.
Attaching from the top-level shortcut¶
leo attach <name> is a shortcut for leo agent attach <name> — handy when you don't want to type the full subcommand:
For remote hosts the resolution is deferred to the server so the client never needs to know the remote's agent list. The agent backing a persistent task is an agent like any other, so leo agent attach <name> (or the leo attach shortcut) works identically whether the target was spawned directly or ensure-exists'd by a task firing — see Persistent Tasks.
Overriding the target host¶
Precedence when resolving which host to talk to:
--host NAMEflagLEO_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 treats the machine as a client. To bypass and dispatch through the local daemon socket, pass --host localhost explicitly.
leo agent list --host dev # talk to dev
LEO_HOST=dev leo agent list # same thing via env
leo agent list --host localhost # force the local daemon
Web UI and channel-plugin parity¶
The daemon on the server owns agent lifecycle. The CLI, web UI, and any channel plugin that invokes the HTTP API are all clients of the same manager — so an agent spawned from the CLI appears in the web dashboard immediately, and vice versa.
Troubleshooting¶
"no leo.yaml found — run 'leo setup' first" The client's leo.yaml doesn't exist. Create it with just the client section — no other setup needed on a client-only machine.
"host \"prod\" not defined in client.hosts" Typo in --host, LEO_HOST, or default_host. Check leo config show.
Attach hangs or shows "no sessions" The agent name is wrong, or the supervisor already reaped the tmux session. Check leo agent list --host <host>.
Remote leo not on $PATH Leo expects leo to be on the server's default login PATH. Either install it there or add a symlink — SSH non-interactive shells do not load .zshrc by default.
See Also¶
leo agent— subcommand reference- Agents guide — template authoring and channel/web parity