How the vault works
Every container is launched withHTTPS_PROXY pointing at the vault’s gateway. When the agent calls a real API URL — api.anthropic.com, api.github.com, gmail.googleapis.com — the gateway intercepts the request, matches the host against its stored secrets, and rewrites the auth header with the real token before the request leaves for the internet. Clients must use the configured proxy for requests to receive credential injection. Egress lockdown can additionally prevent direct outbound connections that bypass it.
If the target service isn’t connected yet, the gateway returns an error with a connect_url the agent surfaces to you, instead of a silent failure.
NanoClaw talks to the vault through two values in .env: ONECLI_URL (the OneCLI app/API — note that what OneCLI’s own docs call the gateway is a separate proxy listener that agent egress actually flows through; these pages use “gateway” loosely for the whole vault) and ONECLI_API_KEY (the host’s own credential for the vault API).
Credential stubs
Some tools insist on finding a credential locally before they’ll start — MCP servers especially. For these, the container gets stub files whose secret values are the placeholder string"onecli-managed". The flow: the MCP server reads its credential file, finds "access_token": "onecli-managed", happily starts, and sends Authorization: Bearer onecli-managed — which the gateway rewrites to the real token on the request’s way out to the service’s API host. Files containing onecli-managed are managed by OneCLI; agents are instructed never to modify or delete them (the pattern is documented in the onecli-gateway container skill every agent carries).
Setting it up
The setup wizard handles the vault as one of its steps, with three paths:- Fresh install (default) — runs the OneCLI installer (a Docker Compose stack plus the
onecliCLI), points the CLI at the new instance, and writesONECLI_URLto.env. - Reuse existing — if setup finds a
oneclion the host with an api-host already configured, it reuses it without reinstalling (--reuseforces this). Reuse leaves the running gateway untouched (re-running the installer would rebind the listener and break other apps using it) and just records its URL. - Remote vault — set
NANOCLAW_ONECLI_API_HOSTbefore running setup to point at a OneCLI instance on another machine. Setup installs only the CLI, health-checks the remote URL, and writesONECLI_URL. Pass the remote vault’s API token viaNANOCLAW_ONECLI_API_TOKENso setup can authenticate the CLI and writeONECLI_API_KEY.
onecli CLI at the versions pinned in .claude/skills/add-onecli/versions.json (onecli-gateway, onecli-cli; the SDK has its own onecli-sdk pin), never at latest. The versions.json at the project root pins only the agent image. It also probes the gateway’s /v1/health: @onecli-sh/sdk 2.x talks to the gateway’s /v1 API, and a gateway that predates it answers 404 to every vault call — failures that look transient but are permanent. Setup never upgrades the gateway for you. If the gateway’s /v1/health answers with an error status, the OneCLI setup step fails with “OneCLI gateway lacks the /v1 API required by the installed SDK” and points you to the upgrade runbook, docs/onecli-upgrades.md in your NanoClaw folder (source on GitHub). If the gateway does not answer at all, the step fails with “OneCLI gateway /v1 API is unreachable”; check that the gateway is running before you look at the runbook. The gateway pin also moves through /update-nanoclaw — see Upgrading.
On an existing install, run the /add-onecli skill instead of the wizard. Since 2.4.0 it owns the whole OneCLI integration: it copies the provider payload into src/gateway-providers/ and container/skills/onecli-gateway/, installs the pinned SDK, runs the same setup script (reuse, local install, or remote via NANOCLAW_ONECLI_API_HOST and NANOCLAW_ONECLI_API_TOKEN), and records NANOCLAW_GATEWAY_PROVIDER=onecli only after every step succeeds. /update-nanoclaw applies it for you on an install that predates 2.4.0. Channel tokens like TELEGRAM_BOT_TOKEN stay in .env — the host process uses those, not the containers.
Iron Proxy as the gateway
Iron Proxy is the alternative gateway, chosen in Advanced setup or installed later with/add-iron-proxy. It runs one central proxy plus the Iron Control web console (Secrets, Credentials, OAuth Apps, Principals) and PostgreSQL on Docker. Each request passes the front identity and allowlist, then NanoClaw’s approval step, then the stored credential, before it reaches the upstream service; the approval cards below work the same way. Codex runs through Iron, including its WebSocket turns, and OpenCode can store API keys and ChatGPT OAuth credentials in Iron Control. Switching gateways means re-registering your provider credentials in the new one, so do not switch to get through an update. See Credential gateways.
Anthropic credentials
The wizard’s auth step offers three ways to connect Claude, all of which end up as a vault secret rather than an env var:- Claude subscription (Pro/Max)
- API key or existing OAuth token
- Custom endpoint
Setup runs
claude setup-token under a PTY so the browser OAuth flow works, captures the resulting sk-ant-oat… token, and registers it:Adding a credential for a new service
Register a secret with a name and a host pattern — the host the gateway should inject it for:set-secrets replaces the agent’s whole list, so read and merge first:
<agentGroupId> is the agentGroupId field in the group’s container.json. The same model powers .claude/skills/add-onecli/scripts/register-claude-token.sh, which accepts SECRET_NAME and HOST_PATTERN overrides if you want the subscription flow against a different secret name or host.
Accessing the OneCLI dashboard
The vault ships a web dashboard at the same address asONECLI_URL — the “OneCLI web UI”. Open it in a browser to connect OAuth services, browse secrets, and watch gateway activity.
Two gotchas on a headless install:
- The dashboard binds where OneCLI binds. On installs where containers reach the gateway over the Docker bridge, that address isn’t routable from your laptop — reach it through an SSH tunnel or a private network such as a tailnet rather than exposing the port publicly.
- OAuth Connect flows finish by redirecting the browser back into the dashboard at OneCLI’s configured
APP_URL, which defaults tohttp://localhost:10254. Started from a remote browser, the provider consent itself works (that redirect is derived from the request), but the final hop lands on localhost and dies unlessAPP_URLis set to the URL you actually browse from. Theconnect_urllinks the gateway hands to agents are built from the same value, so an unsetAPP_URLmakes those unreachable too.
Approving credential use
Secrets can be configured in OneCLI to require manual approval per request. When the gateway intercepts a request that needs one, it holds the HTTP connection open and asks NanoClaw, which delivers a Credentials Request card to an admin DM with Approve / Reject buttons. The card always names the agent; when the gateway supplies a structured summary, it shows an Action line plus labeled fields describing what the request does. Without one it falls back to the raw shape: theMETHOD host/path line (the query string is dropped).
- Who gets the card: admins of the originating agent group first, then global admins, then owners — the first one with a reachable DM. No eligible approver means auto-deny.
- Approving or rejecting: tap the button on the card. The decision is returned to the gateway, which either injects the credential and lets the request through or fails it.
- Expiry: unanswered cards expire on the gateway’s TTL and the request is denied. The card keeps its full content — title and question stay visible, and the buttons are replaced with a timeout note: “⏱️ Timed out — no response”, or “⏱️ Timed out — host restarted before resolution” for cards swept at startup after a restart.
ncl approvals list --status pending. The CLI is read-only for approvals — decisions happen on the card.
Raw credentials in container environments
The former/use-native-credential-proxy opt-out is retired. Session admission rejects credential values in contributed container environments; NANOCLAW_NATIVE_CREDENTIALS=true is not a supported alternative to the vault. For a custom Anthropic endpoint, use the setup flow above: the container receives the endpoint and a placeholder token, and the gateway injects the real credential on the wire.
NanoClaw registry sign-in
Fetching the Echo hardened runtime image needs a different credential from everything above — a NanoClaw account, not a vault secret. Sign in during setup, or later from your checkout:~/.config/nanoclaw/account.json, mode 0600. For a non-interactive install, NANOCLAW_REGISTRY_TOKEN adopts an existing token and NANOCLAW_REGISTRY_ENROLL_CODE enrolls with an operator-issued code — both skip the browser entirely; NANOCLAW_REGISTRY_API overrides the broker URL (setup/registry-login.ts:65-67).
The token itself never reaches the registry. setup/install-cred-helper.ts installs a docker credential helper (docker-credential-nanoclaw) and wires it into ~/.docker/config.json. Docker execs the helper on every pull, and it exchanges the account token for a short-lived registry password minted for that one pull.
Egress lockdown
For defense in depth,NANOCLAW_EGRESS_LOCKDOWN=true places agents on an internal Docker network where the selected gateway (OneCLI or Iron Proxy) is the only reachable egress hop — agents physically cannot bypass the proxy. See Hardening for the full setup.