Skip to main content

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).
--foregroundServe in this process instead of backgrounding — what an installed service runs under the hood, and useful for debugging.
--allow-stagingRoute to operator nodes flagged staging on-chain. Off by default.
--timesLog per-request encrypt/decrypt durations — a debugging aid.
--debug-bodiesLocal 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).

info

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.

info

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
FlagWhat it does
[tool]opencode, openclaw, pi, hermes, aider, continue, codex, or generic.
--allConfigure every detected tool, non-interactively.
--listList detected tools and config paths; writes nothing.
--print / --dry-runRender the result to stdout; writes nothing.
-y, --yesSkip 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.yaml keys these flags and env vars override.
  • Running as a serviceinstall-service in full, including the per-OS specifics.