CLI & one-command setup
Wiring a project into a new identity system usually means an SDK, a bespoke config file, and an afternoon of docs — whisper collapses all of it into one binary and one line.
whisper init claude, and your project has a real, routable, DNSSEC-anchored identity before you've finished reading this sentence.
The pain this removes
Every coding agent, every automation runner, every CI job that needs a network identity has historically faced the same bad menu: install a Python package with native deps for one stack, an npm package for another, hand-roll a WireGuard config for a third, and hope the proxy environment variables you set actually get inherited by the child process. None of that is hard, exactly — it's just friction, repeated once per tool, per language, per environment. And friction is where identity systems die: an agent that's "supposed to" carry its address ends up talking out from whatever IP the host happened to have, and the whole point of a verifiable identity — that the network layer is the proof — quietly evaporates.
The whisper CLI is the fix: one MIT-licensed, cross-platform Go binary that does registration, connection, and verification without asking you to touch a config file, and a whisper init <tool> family that wires that identity into the specific tool you're already using — Claude Code, Gemini, aider, Zed, browser-use, and eight more — with zero manual setup. It is also, deliberately, not the only way in: everything it does is one HTTP call or one dig away (see the mappings below), so nothing about it is a black box.
Install
curl -fsSL https://get.whisper.online | sh # reads before it runs; one binary, no daemon required
Prefer a package manager? The same signed binary ships on all of them — pick the one your platform already trusts:
brew install whisper-sec/tap/whisper # Homebrew (macOS/Linux)
scoop bucket add whisper https://github.com/whisper-sec/scoop-bucket && scoop install whisper # Windows
go install github.com/whisper-sec/whisper-cli/cmd/whisper@latest # straight from source
mise use -g "github:whisper-sec/whisper-cli[exe=whisper]" # mise
sudo apt install whisper # after adding get.whisper.online/deb — see /docs/integrations
Source, issues, and the release signatures live at github.com/whisper-sec/whisper-cli. Every artifact is signed; whisper --version prints the build's commit and the key fingerprint it was signed with.
Sign in
whisper login # opens the console in a browser, drops a scoped key in your keychain
whisper login --token whisper_live_... # or paste one directly (CI, containers, no browser)
A key is only needed for the control-plane half. Everything under whisper verify works with no login at all — that's the keyless tier, by design (see Verify an agent).
The commands, and what each one actually calls
Nothing the CLI does is proprietary to the CLI. Every command is a thin, honest wrapper over either a public DNS/HTTP check or the one control-plane verb, whisper.agents. Here's the mapping, so you can reimplement any of it yourself or debug it when something looks wrong:
| Command | What it does | Underlying call |
|---|---|---|
whisper login |
store a scoped API key | none — local only |
whisper create --label my-agent |
mint an identity: address, forward name, PTR, DANE pin | CALL whisper.agents({op:'register', args:{label:'my-agent'}}) |
whisper list |
your agents, their addresses and status | CALL whisper.agents({op:'list', args:{}}) |
whisper connect my-agent [--tier socks5\|wireguard] |
bring up egress sourced from the agent's /128 |
CALL whisper.agents({op:'connect', args:{agent:'my-agent', tier:'socks5'}}) |
whisper run -- <cmd> |
connect (if needed), verify egress, exec <cmd> under it |
connect, then the keyless echo check, then execve |
whisper ip my-agent |
prove the current egress source address | curl through the proxy to https://rdap.whisper.online/egress-ip |
whisper verify <addr> |
keyless identity check | GET https://rdap.whisper.online/verify-identity/<addr> |
whisper verify --trustless <addr> |
the same check, re-derived locally from the DNSSEC root — Whisper's own API is never trusted | local DNSSEC chain-of-trust validation, see Trustless verification |
whisper revoke my-agent |
tear down address, DNS, DANE pin, and egress in one step | CALL whisper.agents({op:'revoke', args:{agent:'my-agent'}}) |
Every one of the right-hand-column calls is documented on its own in Control plane and Connect & egress. The CLI adds nothing to the protocol — it only removes the typing.
The same thing, with stock tools only
The table isn't aspirational — every call really is one curl or one dig. Provisioning an agent and proving an identity, with no Whisper software installed anywhere:
# mint an agent — POST the one control-plane verb; the key travels in the header, never the body
curl -s https://graph.whisper.security/api/query \
-H "X-API-Key: whisper_live_..." \
-d '{"query":"CALL whisper.agents({op:'"'"'register'"'"', args:{label:'"'"'my-agent'"'"'}})"}' | jq .
# verify any agent's identity — keyless, no header at all
curl -s https://rdap.whisper.online/verify-identity/2a04:2a01:eb5a:ca74:cef2:2a:323d:40d4 | jq .
The CLI equivalents — whisper create --label my-agent and whisper verify 2a04:2a01:eb5a:ca74:cef2:2a:323d:40d4 — send the same bytes to the same endpoints. Nothing is hidden behind the binary; it only saves the typing. Full request and response shapes: Control plane.
whisper run — what actually changes in the child process
whisper run -- python agent.py does exactly three things, in order, and fails loudly rather than falling back silently if any of them don't hold:
- Connects, if the named (or default) agent isn't already connected —
whisper.agents({op:'connect', tier:'socks5'})by default, since Tier 1.5 needs no root and no kernel interface. - Verifies the egress before handing off control: it fetches
https://rdap.whisper.online/egress-ipthrough the new proxy and checks the answer equals the agent's own/128— the same checkwhisper ipexposes standalone. A mismatch is a hard error, never a quiet fallback to your host's own address. - Execs your command with
ALL_PROXYandHTTPS_PROXYpointed at a local loopback SOCKS5 endpoint the CLI holds open for the life of the command — source-bound to the agent's/128, so no egress credential ever lands in the child's environment (or, for--tier wireguard, nothing at all — the interface itself carries the address, so no env var is needed):
whisper run -- python my_agent.py
# child process env now includes:
# ALL_PROXY=socks5h://127.0.0.1:1080
# HTTPS_PROXY=socks5h://127.0.0.1:1080
Because ALL_PROXY/HTTPS_PROXY are a decades-old Unix convention, this needs no cooperation from your code: curl, git, Python requests/httpx, Node's fetch, and Claude Code's own tool-use network layer all already honor them. There is no SDK to import.
whisper init <tool> — wiring an identity into what you already run
whisper connect and whisper run are generic; whisper init <tool> goes one step further and speaks each target's own configuration surface, so the identity is there before the tool's first network call — no wrapper script, no env var to remember:
whisper init claude # writes the proxy/network entry into ./.claude/settings.local.json
whisper init gemini # same egress, Gemini CLI's own config surface
whisper init aider # aider's local config, same proxy underneath
whisper init zed # Zed's context-server settings
whisper init browser-use # a browser-context proxy config for headless/agentic browsing
Twelve targets ship today — claude, python, zed, gemini, aider, ai-sdk, browser-use, discord, telegram, notebook, compose, k8s — each writing into that tool's native format rather than a Whisper-specific one. Run it with no argument and it detects the project (a .claude/ directory, a pyproject.toml, a docker-compose.yml) and picks the right target itself. Every target is provisioned against the same control-plane register + connect pair above; init only differs in where it writes the result. Before starting the target process, init confirms the local egress endpoint is already listening — so the tool's very first outbound call never races an unready proxy.
whisper init claude && claude # the project now has an identity; Claude Code's traffic carries it
For everything that isn't a first-class init target — n8n, Zapier, Cloudflare Workers, Kubernetes — see the full connector catalog at Integrations; they use the same two calls, just via a platform-native connector instead of a CLI wrapper.
Uninstalling, cleanly
whisper revoke my-agent # first: kill the identity — address, DNS, DANE pin, and status-list entry, provably
rm $(command -v whisper) # then: remove the binary, no other state left behind
whisper keeps no daemon running between invocations and no local database beyond the key in your OS keychain — revoking an agent and deleting the binary leaves nothing behind on either side.
Next
Connect & egress — the three tiers whisper connect and whisper run choose between, and how source-binding actually works · Integrations — every non-CLI way to wire in the same identity, from MCP to Kubernetes.