Skip to content

Candle CLI

The candle CLI manages agent credentials from the terminal: authorize a device, provision and revoke API keys, inspect and import wallets, and diagnose a broken setup. It exists so an agent machine never needs a browser session of its own; the one browser interaction is a device approval on whatever machine you are already signed in on.

Install the Candle CLI (macOS or Linux):
curl -fsSL https://candle.tv/install.sh | bash
or with Homebrew:
brew install candledottv/tap/candle
Then: candle setup

candle setup authorizes this device from your browser, shows the agent wallets as funding destinations, prints the skill and MCP install lines, and runs a full health check; candle auth login on its own does just the authorization step, e.g. candle auth login --api-url https://staging.api.candle.tv.

The npm package @candledottv/cli stays published for CI, programmatic use, and Windows until install.ps1 ships; npx -y @candledottv/cli@latest <command> runs it once without installing. With no npm and no install.sh, bunx fetches the repo and runs the bin at its root:

Terminal window
bunx github:candledottv/agentic candle auth login --api-url https://staging.api.candle.tv

For repeated use, clone once and run the same bin locally:

Terminal window
git clone https://github.com/candledottv/agentic.git
cd agentic && bun install
bun packages/cli/dist/index.js auth status

Every release is signed; see Verify a Candle release to check a download by hand.

auth login runs an OAuth-style device flow:

  1. The CLI requests a device code and opens your browser to an approval screen (with --no-browser it prints the URL and code for you to open anywhere, including on a different machine).
  2. The screen shows the client name and the exact scopes being requested before anything is granted. A login with no --scopes flag requests all four scopes, swap:write included, and the screen says so; pass --scopes to narrow the grant.
  3. On approval the CLI exchanges the code for a device token and immediately provisions an agent API key with the approved scopes.

The device token is the credential that manages keys from this machine. It can create, list, and revoke API keys, and nothing else: it cannot list or revoke other devices, and it cannot approve another device’s login, so a leaked token cannot quietly widen its own access. Device tokens do not expire; you revoke them from the Authorized devices panel in your Agent access dashboard, and every key a device minted is labeled with that device, so containing a compromise is one action, not an investigation. See device authorization on the access page for the server-side view.

If key provisioning fails (no delegated wallet yet, or the account is at its 5-active-key ceiling), login still succeeds and stores the device token, and the output says exactly why the key was not issued. Fix the cause, then run candle keys create.

CommandWhat it does
auth login [--scopes <a,b,c>] [--label <name>] [--no-browser]Authorize this device and provision a key
auth statusShow which credentials are stored and where
auth logout [--keep-key]Clear local credentials; --keep-key preserves the stored API key
keys listList the account’s API keys, revoked ones included
keys create [--scopes <a,b,c>] [--label <name>]Create an API key over the device token
keys revoke <prefix>Revoke one API key by prefix
walletShow the account’s launch and linked wallets (wallets is an alias)
wallet import --chain <solana|evm> [--address] [--label] [--key-file] [--signer-out]Import a wallet you own; see below
wallet revoke <wallet-id>Revoke a linked wallet and drop its stored signer
profile listProfiles on this machine, with their cached accounts
profile add <name> --api-url <url>Create a profile before authenticating it
profile use <name>Make a profile the active one
profile rename <old> <new>Rename a profile
profile remove <name> --yesDelete a profile and its stored credentials
setup [--no-browser]One wizard: authorize, fund, connect an agent, verify
mcp [--tools <a,b,c>] [--read-only] [--print-config]Run the Candle MCP server, built into the binary; see below
doctorDiagnose CLI setup: credentials, storage backend, API reachability
verify <file> --bundle <path>Verify a release asset against its Sigstore bundle
update [--check] [--to <tag>]Update the CLI to the latest signed release

Global flags: --api-url <url>, --profile <name>, --json for machine-readable output, --help, --version.

The CLI carries the Candle MCP server inside its own binary, so candle mcp starts it with no download and no Node runtime on the host. The key comes from the CLI’s credential store at launch, which is what keeps it out of your MCP client’s config file:

Terminal window
candle mcp --print-config

That prints a ready-to-paste block naming this binary by absolute path. --read-only pins the server to the four tools that authenticate with nothing; --tools <a,b,c> takes an explicit allowlist. The MCP server page documents the tools themselves and the other two ways to run it.

Linked wallets (Pro and Max tiers; see Agent wallets & spend limits) let the rail trade from a wallet you already control. The import is the most security-sensitive command the CLI has, and its shape reflects that:

Terminal window
candle wallets import --chain solana --key-file ~/.config/solana/id.json --label "trading wallet"
  • The private key never appears in the command line. It comes from --key-file (accepts an id.json byte array, base58, or hex) or, with no flag, a hidden terminal prompt. There is no argv or environment form, so the key cannot land in shell history or process listings.
  • A wrong key cannot import silently. For Solana the CLI derives the wallet’s address from the decoded secret; if you pass --address and it doesn’t match, the import refuses before any network call. EVM keys can’t be address-derived without keccak, so --address is required there and the server validates.
  • Only ciphertext leaves your machine. The key is HPKE-sealed locally to Privy’s receiver key (the same RFC 9180 exchange the SDK import documents); Candle never sees plaintext.
  • The signer stays in your keychain. The import generates a P-256 signer keypair; the public half registers with the wallet, and the private half, which every later trade from this wallet signs with, is stored in the same OS keychain as your credentials, keyed by wallet id. --signer-out <path> additionally exports a PEM (written owner-only) for use on another machine; treat that file like the private key it is. On the same machine, no export is needed at all: the SDK’s KeychainSecretStore reads the CLI’s storage directly, so an agent process trades from the imported wallet with zero manual key handling.

candle wallets revoke <wallet-id> unlinks the wallet server-side and removes its stored signer locally. The wallet id is the id printed at import time, also visible via candle wallets.

When you want fresh wallets rather than one you already hold, the CLI can mint them, seal them, and import them in a single pass:

Terminal window
candle wallets generate --chain solana --count 5 --label trading
  • Every key is sealed before anything is imported. The keys are written to an encrypted keystore first, and the command aborts if that write fails. Importing first would mean a crash could leave a wallet on the account whose private key existed only in a dead process. If a later import fails, re-run with --resume: the keys are already safe, and resume imports only what is outstanding.
  • The keystore is a separate file at ~/.config/candle/wallets.enc (override with --keystore), not the credentials store. Your API key is a secret you rotate; these are fund-bearing private keys, and backing them up should not mean copying your credentials too. It is written owner-only, atomically, and its metadata is encrypted along with the keys, so the file does not reveal which addresses you own.
  • The keys are independent, not derived from one seed. That is deliberate: these wallets exist to keep execution compartmentalised, and a shared seed phrase re-couples them. The consequence is that the keystore is the only copy, so back it up. The format is self-describing (AES-256-GCM over a PBKDF2-HMAC-SHA256 key, with the salt, IV and iteration count stored alongside the ciphertext), so it can be decrypted with the passphrase and any standard crypto library, with or without this CLI.
  • --chain hood produces an ordinary EVM wallet. The same key works on Hood and on every other EVM chain, so there is no reason to generate separate sets.
  • These wallets are not a way into your account. Each is owned by its own agent key quorum with the spend policy attached to the wallet, and no user identity is sent to Privy, so a generated wallet’s key cannot be used to sign in.

To recover a key, export one at a time:

Terminal window
candle wallets export --index 2 # names the wallet, prints no key
candle wallets export --index 2 --yes # prints the private key

There is no --all. Moving a whole keystore to another machine is a file copy.

Secrets never land in a plaintext dotfile. The CLI picks the strongest backend the machine has:

PlatformBackend
macOSKeychain, via security (the secret is piped, so it never appears in process arguments)
Linuxlibsecret, via secret-tool
Anywhere elseAn AES-256-GCM encrypted file, unlocked by CANDLE_KEYRING_PASSPHRASE

auth status and doctor both name the backend in use. Non-secret configuration (the stored API URL, the device label) lives in a plain config file; CANDLE_CONFIG_DIR relocates it, which is also how tests and multi-account setups isolate themselves.

Environments without a keychain or a browser skip storage entirely and inject credentials through the environment:

VariableMeaning
CANDLE_API_KEYAn agent API key; takes precedence over any stored key
CANDLE_DEVICE_TOKENA device token, for key-management commands
CANDLE_API_URLAPI base URL
CANDLE_KEYRING_PASSPHRASEUnlocks the encrypted-file backend where no OS keychain exists
CANDLE_CONFIG_DIRRelocates the config directory

Authorize once on a machine with a browser (or use --no-browser and approve from your phone), copy the key into your runner’s secret store, and the runner itself never performs a login.

  • candle doctor first: it checks stored credentials, the storage backend, and API reachability in one pass, and its output is designed to be pasted into a bug report.
  • A 404 on auth login almost always means the command hit production before the device flow reached it; add --api-url https://staging.api.candle.tv.
  • bunx caches the fetched repo per temp directory and can serve a stale build after the repo updates. Clear it with rm -rf "$TMPDIR"/bunx-*agentic* and rerun.