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¶
# 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 to supervised processes¶
Configured processes (the ones managed by leo service on the server) expose the same attach and logs commands:
leo process attach primary # ssh -t <host> tmux attach -t leo-primary
leo process logs primary -n 100
leo process logs primary --follow
And leo attach <name> resolves against both processes and agents — handy when you don't want to remember which namespace a name lives in:
When a name exists in both namespaces, Leo errors rather than guessing and points you at the explicit leo process attach / leo agent attach forms. For remote hosts the resolution is deferred to the server so the client never needs to know the remote's process list.
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