Proxy CLI reference
The proxy ships as a single binary, zs-proxy. Its commands fall into five
groups: the daemon lifecycle (proxy start/stop/...), the wallet,
funding, connecting tools, and a handful of inspection commands.
Each command's own -h/--help is the final word on its flags.
Lifecycle — proxy
zs-proxy proxy start # background daemon, returns to the shell
zs-proxy proxy start --port 9376 # listen-port override
zs-proxy proxy start --allow-staging # also route to operator nodes flagged staging
zs-proxy proxy start --foreground # serve in this process (supervisors / debugging)
zs-proxy proxy stop # graceful drain of in-flight streams
zs-proxy proxy status # pid, uptime, listen, network, /healthz probe
zs-proxy proxy restart # shares start's flags
zs-proxy proxy logs -f # tail the daemon log (metadata only)
zs-proxy proxy install-service # register as an OS service — see below
zs-proxy proxy uninstall-service
Flag (on start/restart) | What it does |
|---|---|
--config <path> | Path to config.yaml. Optional — embedded defaults are used when absent. |
--network <net> | mainnet | testnet | localnet. Defaults to the config value, else mainnet. |
--port <n> | Listen-port override (0 = use config). |
--foreground | Serve in this process instead of backgrounding — what an installed service runs under the hood, and useful for debugging. |
--allow-staging | Route to operator nodes flagged staging on-chain. Off by default. |
--times | Log per-request encrypt/decrypt durations — a debugging aid. |
--debug-bodies | Local debugging only. Dumps full plaintext request and response bodies, including streamed frames, to stderr. This bypasses the network's no-content-logging guarantee for your own machine — never enable it against traffic you need kept private. |
logs takes -f/--follow to stream as the log grows, and -n/--lines
(default 200) for how many trailing lines to print first.
Once an OS service is installed (see Running as a
service), these same commands transparently target
the service instead of the self-managed daemon — install-service itself
takes --port, --print (preview without installing), and on Windows
--service-account (default: the installing user).
Bare zs-proxy (no subcommand), or zs-proxy --config config.yaml, is a
legacy entrypoint that starts the proxy in the foreground — the same flags
as proxy start apply.
Wallet — wallet
zs-proxy wallet show # address, network, kind, source
zs-proxy wallet address # bare address only (scriptable)
zs-proxy wallet new [--network ...] [--force]
zs-proxy wallet import [--network ...] [--force] [--file <path>] [--stdin] [--yes]
zs-proxy wallet login [--client-url <url>] [--no-browser] [--network ...] [--force] [--yes]
zs-proxy wallet export # reveal the recovery phrase (guarded — types "reveal" to confirm)
zs-proxy wallet opt-in # opt the account in to USDC
import reads the phrase from a hidden prompt by default — never an argv
flag, so it can't leak into shell history — or from --stdin/--file for
scripting. login opens your default browser to sign in to the chat app
with your passkey; --no-browser prints the URL instead, for SSH/headless
use. Both import and login derive the address and ask you to confirm it
matches before storing anything; --yes skips that confirmation. See
Wallet & funding.
Funding
zs-proxy fund [--wait] # deposit address + QR; --wait blocks until funds land
zs-proxy slots [n] # show or set how many requests can be in flight at once
zs-proxy withdraw <amount-algo> # reclaim unreserved ALGO from the prepaid MBR pool
zs-proxy close-deposit # close the MBR pool, refund the full balance
zs-proxy status # wallet / balance / funding / spend snapshot
zs-proxy doctor # diagnose config → wallet → chain → funding → port
status prints something like:
address: ALGORAND58CHARACTERADDRESS...
network: mainnet
ALGO: 1.250000 ALGO
USDC: 12.500000 USDC
MBR pool: 1.157000 ALGO deposited, 2 of 10 ticket slot(s) in use
free: 18 of 20 free tickets left today (window resets 2026-07-22T09:14:00-04:00, in 6h12m0s)
ready: yes
spend: $0.42 of $10.00 spent today (daily cap)
per-req: $1.00 max per request
The MBR pool denominator is the number of concurrent ticket boxes your
deposit actually backs (deposited ÷ per-ticket MBR) — that's the limit the
contract admits against, so it can sit below your configured
concurrent_slots (an under-funded pool, which adds a … short of 10 slot(s); run zs-proxy fund line) or above it (you deposited extra). A slot is borrowed
while a request is in flight and returned when the ticket settles. See
Concurrency slots to change it.
The free line shows your remaining free-model allowance: the network caps
free (zero-price) tickets per wallet per 24-hour window, and the window is fixed
— it starts with your first free request and resets 24 hours later (the reset
time is shown in your local timezone). Before your first free request it reads 20 of 20 free tickets available today (quota box not yet created) — the one-time min-balance for the on-chain counter hasn't been drawn
from your pool yet. The line is omitted entirely against a contract with no
free-ticket quota.
The spend line is your actual settled spend for the UTC day (not the
price ceilings reserved on-chain); with no daily_cap_usdc set it reads
$0.42 spent today (no cap). per-req echoes per_request_cap_usdc (or no limit).
doctor walks the same chain of checks (config resolves, wallet present,
chain reachable, funded, USDC opted in, port free) and tells you exactly
which one to fix first. Both accept --config/--network to check against a
config you haven't started the proxy with yet. See Wallet &
funding.
Concurrency slots
How many requests you can have in flight at once. Each one holds an escrow ticket, and every ticket needs a slot in your prepaid pool.
zs-proxy slots # show the current picture
zs-proxy slots 25 # raise it — writes the config and funds the pool
zs-proxy slots 5 # lower it — writes the config and reclaims the excess
zs-proxy slots 25 --dry-run # show what would change; write nothing, submit nothing
zs-proxy slots 25 -y # skip the confirmation prompt
With no argument it only reads — it never signs or spends:
configured: 10 slot(s) zs.concurrent_slots
backed: 12 slot(s) 1.386000 ALGO deposited
in use: 2 slot(s)
per slot: 0.115500 ALGO
- configured is your target — what the next top-up aims for.
- backed is what your deposit actually buys, and it is the real limit: the contract admits a new ticket only while the pool can cover it. It can sit below your target (under-funded) or above it (you deposited extra).
- in use is how many are borrowed by requests in flight right now.
zs-proxy slots <n> does both halves — writes concurrent_slots to your config
and moves the pool — because either one alone leaves you with a number that
isn't true. Raising deposits the difference; lowering reclaims it. The ALGO is
fully recoverable either way, and your existing config comments are preserved.
Lowering only reclaims what isn't currently backing a live request, and the
command tells you when in-flight tickets are holding the rest — re-run it once
they settle. If the proxy is running when you lower the number, restart it
(zs-proxy proxy restart), or its next top-up will put the ALGO back.
Your pool is the limit you control. An operator's node may also cap how many requests one wallet can have running against it at a time, so raising your slots well past what you actually run in parallel buys nothing.
Connecting tools — connect
zs-proxy connect # detect → confirm → configure
zs-proxy connect opencode [--model <id>] # configure one tool
zs-proxy connect --all # configure every detected tool
zs-proxy connect --list # show detection + config paths — no writes
zs-proxy connect opencode --print # render the merged config — no writes
| Flag | What it does |
|---|---|
[tool] | opencode, openclaw, pi, hermes, aider, continue, codex, or generic. |
--all | Configure every detected tool, non-interactively. |
--list | List detected tools and config paths; writes nothing. |
--print / --dry-run | Render the result to stdout; writes nothing. |
-y, --yes | Skip confirmation prompts. |
--model <id> | Default model id to set. |
--config-path <path> | Override the target file (single named tool only). |
--url <url> | Advanced: target a different base URL, skipping the running-proxy check. |
The proxy must be running first. See Connecting AI tools for the full tool list and what gets written.
Inspection
zs-proxy config path # the config file path that would be loaded
zs-proxy config print-effective # the merged config: defaults + file + env + flags
zs-proxy version # product version, proto version, embedded escrow app ids
What's next
- Quick start — the install-to-first-request walkthrough these commands fit into.
- Configuration — the
config.yamlkeys these flags and env vars override. - Running as a service —
install-servicein full, including the per-OS specifics.