@candledottv/cli 0.13.16 → 0.13.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +28 -13
  2. package/dist/index.js +543 -173
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -53,6 +53,12 @@ or with Homebrew:
53
53
  Then: candle setup
54
54
  ```
55
55
 
56
+ The installer checks the download's SHA-256 and its Sigstore signature before it writes anything,
57
+ and needs nothing beyond `curl` and `sha256sum` or `shasum`. It checks the signature with `cosign` or
58
+ a signed-in `gh` when one is installed, and otherwise with Candle's own `candle verify`, offline, from
59
+ a CLI release whose SHA-256 the script carries (it downloads that `candle` and checks it against the
60
+ SHA-256 before running it). If no check can run, it installs nothing.
61
+
56
62
  `candle setup` authorizes this device from your browser, shows the agent wallets as funding
57
63
  destinations, prints the skill and MCP install lines, and runs a full health check. `candle auth
58
64
  login` on its own does just the authorization step.
@@ -85,6 +91,10 @@ vault key with `candle tee sweep` or `candle vault demote`. Promoting, moving fu
85
91
  emergency procedure, rebinding, trusted wallets and API key access levels are all in
86
92
  [Custody tiers: the vault and TEE wallets](https://docs.candle.tv/developers/cli-custody).
87
93
 
94
+ The recovery phrase ceremony (`vault init`'s offer or `vault phrase show`) waits for you to save
95
+ all 24 words offline and press Enter, then clears the screen before asking for three randomly
96
+ chosen words from your saved copy. Clear your terminal's scrollback too: the CLI cannot erase it.
97
+
88
98
  ## Commands
89
99
 
90
100
  | Command | What it does |
@@ -94,8 +104,9 @@ emergency procedure, rebinding, trusted wallets and API key access levels are al
94
104
  | `candle auth status` | Shows which storage backend is in use, both credential prefixes, the config file path, and a live validity check for each credential. |
95
105
  | `candle auth logout [--keep-key]` | Revokes the stored API key (skipped with `--keep-key`), clears local credentials and config, and prints the portal URL for revoking the device itself. |
96
106
  | `candle keys list [--scopes]` | Lists this account's API keys: prefix, name, Read, Write or Withdraw access, environment, timestamps, and which device minted each one. `--scopes` adds the raw scopes, sorted. |
97
- | `candle keys create [--access read\|write\|withdraw \| --scopes <a,b,c>] [--label <name>] [--expires-in <days>] [--tx-limit <usd> [--reset daily\|weekly\|monthly\|never]] [--embedded-wallet deny\|allow]` | Creates a new API key and prints the plaintext exactly once, with the same optional name, expiration, and USD transaction limit the portal's create form takes. `--access` mints one of the portal's three levels (`write` trades and launches and cannot move funds; `withdraw` is Write plus `transfer:write` and `transfer:bound`: the key can move funds between your own wallets and to addresses you approved, and out of the wallet it runs to wallets you linked while signed in or marked trusted and to that wallet's vault); `--scopes` names raw scopes instead, never both. `--embedded-wallet` defaults to `deny`; `allow` lets the key spend the account's embedded wallet and is confirmed at a terminal. Stored locally only if the CLI does not already hold a working key. An account holds at most 25 active keys. |
107
+ | `candle keys create [--access read\|write\|withdraw \| --scopes <a,b,c>] [--label <name>] [--expires-in <days>] [--tx-limit <usd> [--reset daily\|weekly\|monthly\|never]] [--embedded-wallet deny\|allow] [--no-store]` | Creates a new API key and prints the plaintext exactly once, with the same optional name, expiration, and USD transaction limit the portal's create form takes. `--access` mints one of the portal's three levels (`write` trades and launches and cannot move funds; `withdraw` is Write plus `transfer:write` and `transfer:bound`: the key can move funds between your own wallets and to addresses you approved, and out of the wallet it runs to wallets you linked while signed in or marked trusted and to that wallet's vault); `--scopes` names raw scopes instead, never both. `--embedded-wallet` defaults to `deny`; `allow` lets the key spend the account's embedded wallet and is confirmed at a terminal. Stored locally only if the CLI does not already hold a working key. `--no-store` prints the new key without saving it or changing the profile's working key or metadata; `--json` reports `stored: false`. An account holds at most 25 active keys. |
98
108
  | `candle keys access <prefix\|label\|self> (--access read\|write\|withdraw [--yes] \| --history)` | Changes an existing key's level in place (same key, wallets and caps). Widening needs the device token and the prefix typed back at a terminal; `--yes` skips the prompt when narrowing; `self` narrows the profile's own key and can never widen it. `--history` lists the key's changes and who made them. |
109
+ | `candle keys limits <prefix> <asset>=<raw> [<asset>=<raw> ...]` | Sets a key's per-asset caps (`sol`, `usdc`, `cndl`, `eth`, `usdg`, in base units per transaction) with the profile's own API key. It can only tighten; raising or removing a cap is `LOOSEN_REQUIRES_SESSION`, and the owner does that in the web key manager. A device token cannot set these caps. |
99
110
  | `candle keys update <prefix\|label> --embedded-wallet allow\|deny [--yes]`, `candle keys self embedded-wallet deny` | Allow or deny a key the account's embedded wallet, with the device token (allowing needs the prefix typed back at a terminal). `self embedded-wallet deny` lets the profile's own key give it up with no prompt; a key can never allow itself. |
100
111
  | `candle keys signer approve <code> --key <prefix\|label> [--reject]`, `candle keys signer move <prefix\|label> [--to-key <prefix\|label>]` | Key signers for bots on a different machine from the vault. `approve` accepts (or rejects) a key's signer request with the device token, after you type the full fingerprint the trading machine printed. `move`, on the machine holding a wallet's current signer, moves every wallet on the key onto its active signer; `--to-key` moves a revoked key's wallets to a live key. |
101
112
  | `candle keys stop <prefix>` | Pause one key using the device token. Its requests are refused with `PROFILE_PAUSED` until resumed; the key and its local credential are kept. Repeating the command succeeds. |
@@ -105,13 +116,14 @@ emergency procedure, rebinding, trusted wallets and API key access levels are al
105
116
  | `candle keys wallets <prefix>`, `keys wallets set <prefix> --wallets <id,id>`, `keys wallets scope <prefix> --scope all\|selected` | Each key is an agent profile with its own wallet set: list it, replace it, or limit the profile to its assigned wallets. |
106
117
  | `candle wallets` (alias `candle wallet`) | Shows the account's embedded (launch) wallets and any linked wallets, using the API key, with a `Signer` column saying whether this machine holds each linked wallet's signing key and a `Trusted` column saying whether it is yours (linked while signed in, or marked with `trust`). It links and revokes; it never generates or prints a key, which the vault now derives. |
107
118
  | `candle wallets import --chain solana\|evm`, `wallets revoke <wallet-id>` | Link a wallet you own (key from `--key-file` or a hidden prompt, sealed to Privy before it leaves the machine), or unlink one. |
119
+ | `candle wallets allowlist [--all]` | Print the account's withdrawal allowlist: each approved address's id, chain, address and label, the same rows `candle transfer --to <allowlist label>` resolves by. `--all` adds removed rows. Approving an address is the owner's, in the agent console's Wallets tab; an API key cannot approve. An acting key can revoke an address; a read-only key cannot. |
108
120
  | `candle wallets authorize` | Gives agents access to the account's embedded wallets. The grant is yours to make in a browser (each wallet's owner is you, so neither the CLI nor the API can attach Candle's signer): this opens the Agents page's grant-only step, creates no key, and with an API key waits until the wallets show as delegated. On a new account, run it before `candle auth login`. |
109
121
  | `candle wallets trust\|untrust <label\|address\|id\|prefix*>...` | Mark linked wallets as yours so an agent's Withdraw key can move funds into them, or clear the mark. Owner only, over the device token, with a typed confirm; a trailing `*`, as in `'tr-*'`, selects by prefix. |
110
122
  | `candle wallets allow-launch\|disallow-launch <label\|address\|id\|prefix*>...` | Deprecated. Where the server has `TEE_LAUNCH_BY_SCOPE_ENABLED` on, a key's `launch:write` decides TEE launches: `allow-launch` saves the value and exits 0, and `disallow-launch` saves it, prints the server's `ALLOW_LAUNCH_NOT_ENFORCED` message and exits 1, because no launch is stopped. A server with the switch off still lets TEE wallets pay for a launch (`candle launch`) only after `allow-launch`. Owner only, over the device token; the screen shows each wallet's label, address and bound key before a typed confirm. `disallow-launch --yes` skips the confirm. |
111
123
  | `candle wallets close-empty [--wallet embedded\|<tee address\|label>] [--keep <mint>]... [--client-trade-id <id>] [--preview] [--yes]` | Closes a wallet's empty token accounts and returns their rent to it, after a preview: the embedded wallet (`transfer:write`), or a Solana TEE wallet bound to the key (`swap:write`), whose close transactions Candle builds, this machine checks and the key signer approves. `--preview` prints what would close — the whole preview as one JSON document on stdout under `--json` — and closes, signs and prompts nothing; headless without `--yes`, the `CONFIRMATION_REQUIRED` refusal carries that same preview under `details`. |
112
- | `candle vault init\|status\|list\|new-key\|rename\|phrase show\|restore\|reconcile-exposure` | The encrypted local vault, `vault.enc` (Tier 1). `init` creates it with a passphrase factor and a 24-word recovery phrase (and no key), `new-key` derives a key inside it (`--count`, `--labels-from <file>` for many under one unlock), `list [filter] [--balances]` shows one line per key, `rename` changes a label only, `phrase show` displays the phrase on a terminal (never in `--json`, a log or a pipe), and `restore --phrase` rebuilds the derived keys on another machine with a new passphrase (`--count`, `--tee-count`, `--external-count`, `--evm-count` and `--evm-tee-count` for EVM keys and Hood TEE wallets, or a Solana gap scan with `--rpc-url`); a restored vault never allocates new keys. `reconcile-exposure` re-reads the account and adds exposure records, clearing nothing. No key ever leaves the vault to reach Candle. See [CLI custody](https://docs.candle.tv/developers/cli-custody). |
124
+ | `candle vault init\|status\|list\|new-key\|rename\|phrase show\|restore\|reconcile-exposure` | The encrypted local vault, `vault.enc` (Tier 1). `init` creates it with a passphrase factor and a 24-word recovery phrase (and no key), labels its read-back derivation as verification, and leaves security-key enrollment to the separate optional `candle vault enroll security-key` command; `new-key` derives a key inside it (`--count`, `--labels-from <file>` for many under one unlock), `list [filter] [--balances]` shows one line per key, `rename` changes a label only, `phrase show` displays the phrase on a terminal (never in `--json`, a log or a pipe), and `restore --phrase` rebuilds the derived keys on another machine with a new passphrase (`--count`, `--tee-count`, `--external-count`, `--evm-count` and `--evm-tee-count` for EVM keys and Hood TEE wallets, or a Solana gap scan with `--rpc-url`); a restored vault never allocates new keys. `reconcile-exposure` re-reads the account and adds exposure records, clearing nothing. No key ever leaves the vault to reach Candle. See [CLI custody](https://docs.candle.tv/developers/cli-custody). |
113
125
  | `candle vault factor list\|add passphrase\|add security-key\|add touch-id\|add passkey\|remove` (or `vault enroll <kind>`), `vault backup --to <path>\|icloud`, `vault verify-backup <path>` | What can open the vault, and proving a copy of it works: `backup` verifies the copy in full before reporting (a copy is sealed, keeping only the passphrase and security-key envelopes, unless it goes to a recognised local disk or removable drive, so a cloud folder and any path the CLI cannot place are both sealed unless `--accept-shared-domain` is passed), and `verify-backup` re-checks an existing one against this vault's key and address set. `add security-key` enrolls a FIDO2 security key (CTAP2 `hmac-secret`, user-verified with the key's PIN or biometric) through the bundled `candle-fido2` helper (`--install-helper` fetches and verifies this release's helper first); one key is not a recoverable factor, two keys are a pair, an enrolled key can authorize adding another, and the passphrase stays the recovery floor. `add touch-id` and `add passkey` are refused with `VAULT_FACTOR_UNSUPPORTED_ON_PLATFORM` until the Apple-signed helper ships. Every vault command then takes `--factor <id\|passphrase\|security-key>` to say which envelope opens it and `--device <id>` to name the key when several are attached. |
114
- | `candle vault transfer\|promote\|promote-batch\|fund\|demote\|export-key` | Moving value and authority. `transfer` and `fund` sign locally after showing the decoded transaction (`transfer` from a vault key or a promoted TEE wallet, which warns when an agent may be trading it and reports the finalized transfer to Candle's history; `fund` reaches a TEE wallet from its pinned vault key, or an external wallet, with no `--yes`; both verify once, at the unlock, which names the send, then show the destination grouped in fours and take a typed `confirm`); `promote --from <cold label>` derives a fresh TEE wallet pinned to that key (an EVM vault key becomes a Hood TEE wallet), `promote --in-place <label> --sweep-to <cold label>` promotes a key at its own address after a typed warning, `promote-batch --pairs-from <file>` does many in place under one unlock, `--to-key` binds the result to another of your keys, and `demote` (disable then sweep; `--emergency` sweeps even when the stop request fails) sends it back to its pinned vault; `export-key` is the one ceremony that writes a single private key to a file you name. `demote` takes several addresses, or `--all --empty` for every Solana TEE wallet with nothing left to sweep, under one unlock and one typed `confirm` (`--yes` skips it), with a result line per wallet and one `--json` document. |
126
+ | `candle vault transfer\|promote\|promote-batch\|fund\|demote\|export-key` | Moving value and authority. `transfer` and `fund` sign locally after showing the decoded transaction (`transfer` from a vault key or a promoted TEE wallet, which warns when an agent may be trading it and reports the finalized transfer to Candle's history; `fund` reaches a TEE wallet from its pinned vault key, or an external wallet, with no `--yes`; both verify once, at the unlock, which names the send, then show the destination grouped in fours and take a typed `confirm`); `promote --from <cold label>` derives a fresh TEE wallet pinned to that key (an EVM vault key becomes a Hood TEE wallet), shows the pinned vault address and asks you to type `confirm` to promote the new wallet (promotion moves no funds), `promote --in-place <label> --sweep-to <cold label>` promotes a key at its own address after a typed warning, `promote-batch --pairs-from <file>` does many in place under one unlock, `--to-key` binds the result to another of your keys, and `demote` (disable then sweep; `--emergency` sweeps even when the stop request fails) sends it back to its pinned vault; `export-key` is the one ceremony that writes a single private key to a file you name. `demote` takes several addresses, or `--all --empty` for every Solana TEE wallet with nothing left to sweep, under one unlock and one typed `confirm` (`--yes` skips it), with a result line per wallet and one `--json` document. |
115
127
  | `candle external new\|list\|sweep` | External wallets for outside tools: keys on the vault's third branch (`m/44'/501'/n'/2'`), never delegated to Privy and never registered with Candle. `new` allocates one (and moves the vault to format version 3; refused in a restored vault), `list` shows them, and `sweep <external> --to <vault>` sends everything back to a named vault key, signed locally, confirmed by a typed `confirm` after the vault key's address is shown. See [Bring your own services](https://docs.candle.tv/developers/cli#bring-your-own-services). |
116
128
  | `candle sign [--file <path>] --wallet <external>... [--broadcast] [--yes]`, `candle sign message --wallet <external> [--file <path>] [--yes]` | The generic signer: a base64 transaction any tool built, legacy or v0, decoded (lookup tables resolved) and simulated over your own RPC before it is displayed and signed with an external wallet only. A vault key, a TEE wallet or an unnamed signer is refused; a failing simulation is refused with no override; `--yes` skips the confirmation prompt and nothing else. `sign message` signs the exact bytes of a file or of stdin. |
117
129
  | `candle secrets set\|list\|remove <name>` | Your own third-party API keys, in a keychain namespace separate from Candle's credentials (`tv.candle.cli.secrets`, or `secrets.enc` on the encrypted-file fallback). Typed on a hidden prompt, never sent to Candle, never printed after `set`; `list` shows names only. A plug-in receives one as `CANDLE_SECRET_<NAME>` only when named with `--secret`. |
@@ -121,7 +133,7 @@ emergency procedure, rebinding, trusted wallets and API key access levels are al
121
133
  | `candle tee signer new --key <prefix\|label> [--out <pem>] [--force] [--no-wait]` | On the trading machine, with that key's API key: generates the key's signer here and waits for the owner to approve it with `keys signer approve`. The key's wallets then trade from this machine. `--out` also writes a plaintext P-256 authorization key for Privy wallet RPC; it cannot sign Solana transactions (the TEE signs them). `--no-wait` exits 0 once the request exists. With `--json`, stdout is newline-delimited JSON: a pending event (`state`, `userCode`, `verificationUriComplete`, `expiresAt`, `fingerprint`) immediately, then an active result or error when waiting. A retry re-attaches to the same live request without changing its code or deadline. |
122
134
  | `candle tee signer status --key <prefix\|label> [--json]` | Read the current server signer state without generating a key, requesting a code or waiting. On the requesting machine, also shows the cached approval URL and code while the same request is live. |
123
135
  | `candle tee signer remove --key <prefix\|label>` | Removes this machine's key signer once it owns no wallets, and tells the server the signer is gone. Refuses while a wallet is still owned by it. Uses the device token, or the key's own API key. |
124
- | `candle tee rebind <wallet...> --to-key <prefix\|label>`, `candle tee rebinds [wallet]` | Move TEE wallets to another key on the same account (owner only, preview then `confirm`; funds and the relay signer do not move), and list the rebind history. |
136
+ | `candle tee rebind <wallet...> --to-key <prefix\|label>`, `candle tee rebinds [wallet]` | Move TEE wallets to another key on the same account (owner only, preview then `confirm`; funds and the relay signer do not move), and list the rebind history, filtered to one wallet by its id, address or exact label. |
125
137
  | `candle tee rename <label\|address\|id> <new-label>`, `candle tee rename --pairs-from <file> [--dry-run]` | Rename one TEE wallet, or 1–256 from a pairs file: the label Candle holds and the vault entry when there is one (owner only; one server call, all or nothing, then one vault commit). |
126
138
  | `candle tee new\|enable` | `new` adds a key to an existing `tee-wallets.enc` and refuses when that store is absent (`vault new-key --chain solana`, then `vault promote --from <label> --to-key <prefix>`). `--factor` does not apply. `enable <address> --vault <address>` delegates an existing key with a pinned sweep vault. `vault import-legacy --tee` migrates an existing store. |
127
139
  | `candle swap <from> <to> --amount <n>\|--percent <n> --wallet <tee> [--to <tee>] [--wait]` | Quote, confirm and swap through the TEE wallet's bound key; the first buy after a launch is this command, unless `candle launch --buy` made it. The assets decide the chain (ETH, USDG or a 0x token is Hood; SOL, USDC, CNDL or a mint is Solana). SOL or USDC to ETH or USDG, or back, is a bridge through Relay into this key's own TEE wallet on the other chain (`--to` names it when there are several); `--wait` follows it for up to ten minutes. With `--json`, stdout is exactly one JSON value for swaps, token trades, replays and `swap status`: `kind`, `status`, `clientTradeId`, `signature` (the primary transaction, or `null`), `signatures` (a list) and `raw` (the original response). Every human line is on stderr. The keys older versions printed stay beside them. |
@@ -131,7 +143,7 @@ emergency procedure, rebinding, trusted wallets and API key access levels are al
131
143
  | `candle launch status <mint-or-client-launch-id> [--wait]` | One launch state, `build`, `signed`, `confirmed`, `trading`, `bonded` or `migrated`, for a mint or a `clientLaunchId`. Reads `GET /api/v1/launch/status/{id}` (`launch:read`) and reports the market's own `lifecycle` and `migration` fields. `--wait` follows it until the token is trading, the launch has failed, or ten minutes pass. Nothing is sent. |
132
144
  | `candle image upload <path>` | Uploads a PNG, JPEG, GIF or WebP file, at most 10MB, and prints the `https://` URL Candle hosts it at, ready to be a launch's `imageUrl`. The type is read from the file's first bytes. The file becomes public and permanent. Needs `launch:write`; spends nothing and does not count against the launch cap. `--json` adds the content type and the size. |
133
145
  | `candle pnl [--profile <name>]` | P&L: realized net, fees, unrealized and total, then open positions, the same figures the console shows. Without `--profile`, the account's books (every profile, the web app and the CLI, one ledger; needs the Read scope), with a By agent table (each key, then Manual, then the account total). With `--profile <name>`, that profile's key's share of the same P&L: realized on its sales and the open positions that belong to it, with a row per wallet that sums to the total. Each wallet is its own average-cost pool, and a recorded move between the account's wallets carries its cost. Both show a Solana block, a Hood block, then the combined figure, the closed positions as money made, minus money lost, plus partial sells, and a `CHAIN` column (and `WALLET`, where the API names it) on positions. Unpriced positions are never valued at zero; dust (worth under one cent) is marked and still counted. A bridge between Solana and Hood is not a trade, and bridge and Relay costs are not netted. DAMM v2 LP positions are included: realized (withdrawals against the cost basis at the add, plus claimed fees), unrealized (open positions at their share of the pool plus unclaimed fees, against that basis) and vs holding (what the deposited tokens would be worth held); `Total` stays the console's token figure and `Total with LP` covers tokens and LP. |
134
- | `candle portfolio [<filter>] [--chain solana\|hood] [--rpc-url <url>] [--evm-rpc-url <url>] [--no-perps]` | Vault, TEE and embedded wallets on Solana and Hood in one table with chain, amount, price and value, subtotals per group and per chain, and a total. Solana vault and external balances are read over your own Solana RPC; Candle is sent only the mints, for prices. EVM vault keys are read over your own Hood RPC (`--evm-rpc-url`, else `CANDLE_EVM_RPC_URL`, else the built-in Hood RPC) for ETH and USDG only, priced by asset, never by address; an RPC on another chain is refused. An unpriced Hood token shows why (`no-market-row`, `stale-mark`, ...). `--chain` shows one chain. Each TEE wallet's DAMM v2 LP positions follow the tokens, valued by Candle at the same marks, and count in the total; one whose pool could not be read is shown as not read and the total says it is partial. A Hyperliquid section follows (each EVM TEE wallet's account, read from Hyperliquid directly, never in the total); `--no-perps` skips it. |
146
+ | `candle portfolio [<filter>] [--chain solana\|hood] [--rpc-url <url>] [--evm-rpc-url <url>] [--no-perps] [--no-vault]` | Vault, TEE and embedded wallets on Solana and Hood in one table with chain, amount, price and value, subtotals per group and per chain, and a total. Solana vault and external balances are read over your own Solana RPC; Candle is sent only the mints, for prices. EVM vault keys are read over your own Hood RPC (`--evm-rpc-url`, else `CANDLE_EVM_RPC_URL`, else the built-in Hood RPC) for ETH and USDG only, priced by asset, never by address; an RPC on another chain is refused. An unpriced Hood token shows why (`no-market-row`, `stale-mark`, ...). `--chain` shows one chain. Each TEE wallet's DAMM v2 LP positions follow the tokens, valued by Candle at the same marks, and count in the total; one whose pool could not be read is shown as not read and the total says it is partial. A Hyperliquid section follows (each EVM TEE wallet's account, read from Hyperliquid directly, never in the total); `--no-perps` skips it. It needs no terminal: without one, `--factor touch-id` or `passkey` still unlocks the vault, and otherwise the vault row says not read and the rest is shown, but the total is partial (exit 3); `--no-vault` leaves the vault out on purpose and may exit 0. |
135
147
  | `candle scan <contract address> [--chain solana\|hood]` | The token card for one contract, as a Quant group gets it: market, all-time high since launch, bundles, snipers, insiders, fresh wallets, wallet age, tracked wallets in the last hour, the same-name leader, forensics coverage and the Candle page, with the source of each figure. Facts only; a field with no source prints a dash. The chain is read from the address unless `--chain` names it. No key needed and none sent. Served only where `TOKEN_CARD_ENABLED` is on, and `TOKEN_CARD_DISABLED` elsewhere. |
136
148
  | `candle token clusters <mint> [--chain solana\|hood]` | Optional third-party Solana cluster estimates, with fetched time and a linked-wallet caveat. Unavailable analysis prints a reason and exits 0; `--json` emits the availability union. No key. |
137
149
  | `candle token edit <mint> [--chain solana\|hood] [--description <text>] [--website <url>] [--x <url>] [--telegram <url>] [--discord <url>] [--clear <field>]...` | As the token's creator, set Candle's copy of its description and links; `--clear` removes one. Name, symbol and image cannot be changed, and nothing is written on chain. Needs a `launch:write` key from the launching account. Served only where `TOKEN_METADATA_EDIT_ENABLED` is on, and `METADATA_EDIT_DISABLED` elsewhere. |
@@ -213,7 +225,7 @@ which `candle verify` cannot read.
213
225
 
214
226
  No cosign or gh installed? `candle verify <file> --bundle <path>` (this CLI's own command, see the
215
227
  table above) runs the same check against the trusted root compiled into the binary, no network
216
- call required. Full walkthrough, including the installer script's own signature and the
228
+ call required. It is also what `install.sh` uses on a machine with neither. Full walkthrough, including the installer script's own signature and the
217
229
  transparency log: [Verify a Candle release](https://docs.candle.tv/developers/verify-a-candle-release).
218
230
 
219
231
  ## The `--json` contract
@@ -349,9 +361,11 @@ address is shortened (`FfU8…8pPD`; `--full` prints it whole) and an `https://`
349
361
  `auth login` and `doctor`, which carry `profile` and `account`; `auth status` and `doctor` also
350
362
  carry `cachedAccount`, the account the profile recorded, whenever a profile is resolved; scripts
351
363
  get identity from `auth status --json`. The account is cached
352
- at login from the API. Where the line is printed from that cache and `CANDLE_API_KEY` or
353
- `CANDLE_DEVICE_TOKEN` is overriding the stored credential, it reads
354
- `Account unknown (CANDLE_API_KEY override)` rather than naming an account that credential was
364
+ at login from the API. Where the line is printed and `CANDLE_API_KEY` or `CANDLE_DEVICE_TOKEN` is
365
+ overriding the stored credential, it reads `Account <address> (CANDLE_API_KEY override)` when the
366
+ overriding key could be asked which account it belongs to, and
367
+ `Account unknown (CANDLE_API_KEY override)` when it could not (offline, revoked, or a
368
+ device-token-only override), rather than naming an account that credential was
355
369
  never checked against; `auth status` and `setup` look the account up live and print what they
356
370
  get, and `auth status` and `doctor` name the account the profile recorded beside it when the two
357
371
  differ (not under an env credential override, where the live answer is not the profile's key's).
@@ -411,10 +425,11 @@ key; Candle builds the transaction and Privy signs it through the relay. See TEE
411
425
  below. Limit orders are a REST surface only (`/api/v1/trade/agent/orders`), not in this CLI, the
412
426
  SDK or the MCP server.
413
427
 
414
- **`keys limits`.** There is no command for setting per-key spend limits, because the API route
415
- that sets them (`PUT /keys/:prefix/limits`) structurally rejects a device token. It only accepts
416
- an agent key or a live session, since a spend limit is fund-movement authority, and this CLI's
417
- device token is scoped narrowly to key management. Manage limits from the portal.
428
+ **`keys limits`.** The API route that sets per-key spend limits (`PUT /keys/:prefix/limits`)
429
+ structurally rejects a device token: a spend limit is fund-movement authority, and this CLI's
430
+ device token is scoped narrowly to key management. So `candle keys limits` sends the profile's own
431
+ API key, and an agent key may only tighten (lower a cap, or add one where none was set). Raising
432
+ or removing a cap is refused with `LOOSEN_REQUIRES_SESSION`; the owner does that from the portal.
418
433
 
419
434
  **`devices list` / `devices revoke`.** The device-token endpoints (`GET`/`DELETE
420
435
  /device/tokens`) are session-only by design: this is the self-renewal guard that keeps a stolen