Skip to main content

Documentation Index

Fetch the complete documentation index at: https://developer.bron.org/llms.txt

Use this file to discover all available pages before exploring further.

The CLI signs every request with a per-key ES256 JWT (P-256 ECDSA). You generate a keypair locally, register the public half with Bron through the UI, and keep the private half on disk. The CLI never sees your password and never round-trips the private key over the network.

Generate a keypair + profile in one step

bron config init --key-file ~/.config/bron/keys/me.jwk
In an interactive terminal, the CLI does the whole bootstrap end-to-end:
  1. Prompts for a profile name (suggesting default if the slot is free; otherwise leaves the default empty so a stray Enter can’t overwrite the active profile).
  2. If --key-file points to a non-existent path → generates a fresh P-256 ECDSA keypair locally (crypto/ecdh), writes the private JWK to that path at mode 0600 (only your user can read it). The file contains kty, crv, x, y, d, kid — the kid is the random key identifier used to look up the matching public key on the server.
  3. If --key-file points to an existing private JWK → leaves it alone, just re-derives the public half.
  4. Prints the public JWK (no d field) and waits — paste it into Bron Settings → API keys.
  5. After you press Enter, calls GET /workspaces with the freshly registered key. That single call validates the registration (you’d 401 if the public JWK wasn’t accepted yet) and returns the workspace the key is bound to. The CLI saves the resolved workspaceId into the profile.
So in the interactive flow you don’t have to type the workspace ID at all — the server tells the CLI which workspace the key belongs to. If you already know it (CI / scripts / non-TTY runs), pass it explicitly and the CLI skips the auto-discovery step:
bron config init --name default --workspace <workspaceId> --key-file ~/.config/bron/keys/me.jwk
In non-interactive runs (no TTY on stdin), --workspace is required — the auto-discovery prompt has no scripted equivalent, and silently saving an unverified profile would be worse than failing fast.
{
  "kty": "EC",
  "crv": "P-256",
  "kid": "f3c2…",
  "x": "qO0e…",
  "y": "8j8x…"
}
Paste that public JWK into Settings → API keys in the Bron UI. Pick a name, role, optional IP whitelist, tick Input public key (JWK) and paste the JSON into the Public key (JWK) field, then Generate key. New API key form in Bron UI, with Input public key (JWK) ticked Bron stores the public key indexed by kid; when the CLI signs a request the server looks up the matching public key and verifies the signature. The private key never leaves your machine. If you lose it, generate a new keypair (point --key-file at a fresh path) and revoke the old kid in the UI.

Re-print the public JWK at any time

If you forgot to copy the public JWK earlier, rerun bron config init with the same --name and --key-file. The CLI re-derives the public half from the existing private JWK on disk (no key regeneration), prints it, and walks you through the same auto-discovery flow as the first run — paste the JWK into Bron Settings → API keys, press Enter, the CLI calls GET /workspaces to validate and resolves the workspace ID:
bron config init --name default --key-file ~/.config/bron/keys/me.jwk
If you want to skip the validation round-trip and just reprint the public half (e.g. you already know the registration is fine), pass --workspace explicitly — the CLI then skips GET /workspaces and writes the profile as-is:
bron config init --name default --workspace <workspaceId> --key-file ~/.config/bron/keys/me.jwk

Profiles

A profile binds a key file, workspace, and base URL together so you don’t repeat them on every call. Configs live in ~/.config/bron/config.yaml (override with BRON_CONFIG).
# Set up the default profile (interactive: workspaceId resolved automatically).
bron config init --key-file ~/.config/bron/keys/me.jwk

# Add a second profile (e.g. for a different workspace).
bron config init --name staging \
  --key-file ~/.config/bron/keys/staging.jwk \
  --base-url https://api.qa.bron.org   # optional; default is production

# Switch the active profile.
bron config use-profile staging

# Modify keys without re-running init.
bron config set workspace=<otherWorkspaceId> proxy=http://proxy:8080

# Inspect.
bron config show              # active profile + config file path (env overrides applied)
bron config show --raw        # unmodified YAML entry
bron config show --output json
bron config list              # all profiles, with the active one annotated

Per-call overrides

Every flag a profile sets has a CLI override:
bron --profile staging tx list
bron --workspace <workspaceId> tx list
bron --key-file ~/.config/bron/keys/other.jwk tx list
bron --proxy http://proxy:8080 tx list

Env-var overrides

Useful for CI / containers / one-off scripts:
BRON_PROFILE=staging                                 bron tx list
BRON_WORKSPACE_ID=<workspaceId>                      bron tx list
BRON_API_KEY="$(op read 'op://Personal/Bron/jwk')"   bron tx list   # raw JWK bytes; never lands on disk
BRON_API_KEY_FILE=~/.config/bron/keys/other.jwk      bron tx list
BRON_BASE_URL=https://api-staging.bron.org           bron tx list
BRON_PROXY=http://user:pass@proxy:8080               bron tx list
HTTPS_PROXY=http://proxy:8080                        bron tx list   # standard env vars are honored too
BRON_CONFIG=/tmp/cli.yaml                            bron config show
BRON_API_KEY (raw JWK bytes) wins over BRON_API_KEY_FILE and key_file: when all are set — pair it with a secret store (1Password, Vault, sops) so the private JWK never lives on disk. The CLI strips the var from its environment after reading, so child processes don’t inherit it. Precedence (highest first): explicit flag → env var → active profile → built-in default.

Proxy

Outbound from the CLI honors:
  • BRON_PROXY env var
  • standard HTTPS_PROXY / HTTP_PROXY env vars
  • proxy field set on the active profile (bron config set proxy=...)
If you sit behind a proxy that requires auth, embed the credentials: http://user:pass@host:8080. The same proxy is used for both REST and WebSocket transports (the bron tx subscribe socket goes through it too).

Key rotation

  1. Generate a new keypair and point the active profile at it in one step: bron config init --key-file ~/.config/bron/keys/me-new.jwk (the non-existent path triggers a fresh keygen + private file at mode 0600 + prints the public JWK).
  2. Register the new public JWK in Settings → API keys.
  3. Verify with a no-op call: bron workspace info
  4. Revoke the old kid in the UI.
You can have multiple active keys at once — the server matches by kid, so old and new keys coexist during a rotation window.

Permissions

API keys inherit the permissions of the workspace member they belong to. If the user can approve transactions in the UI, the CLI can too — there’s no separate “API mode” with reduced privileges. Reduce scope by creating a member with limited permissions and registering the key under that member’s account.

Troubleshooting

SymptomLikely cause
403 Forbidden on every callPublic key not registered, or the kid was revoked
401 Unauthorized immediately after rotationOld kid still in active profile — bron config show to inspect
dial: x509: certificate signed by unknown authorityCorporate proxy MITM — set HTTPS_PROXY or import the CA
403 on some endpoints, 200 on othersMember’s role doesn’t grant the action — check workspace permissions
If a request fails with a 4xx / 5xx, the CLI prints the API error envelope plus an id: line containing the correlation ID. Quote that ID when reporting issues — it lets us pull the exact ES log line for your call.