AI Agents
CLI
The bearlumen CLI gives you the same AI cost intelligence as the MCP server, from your terminal. Human-readable tables by default, raw JSON for piping to jq, and a command for every MCP tool.
Prerequisites
- Node.js 20 or newer. The CLI wraps
@bearlumen/node-sdk, which signs requests with WebCrypto and declaresengines.node >= 20.bearlumen loginalso uses the built-infetch, which shipped in Node 20. - A Bear Lumen account.
bearlumen logincreates the API key for you; if you prefer to create one by hand, see Required scopes below.
For version pinning, upgrades, and CI usage, see the install guide.
Install
npm install -g @bearlumen/cli
# or run without installing:
npx @bearlumen/cli --help
Authenticate
Sign in once and the CLI keeps a key for you. This is the recommended path on a developer machine:
bearlumen login
# Opening https://app.bearlumen.com/activate?user_code=BCDF-GHJK
# If the browser did not open, visit that URL and enter the code: BCDF-GHJK
# Waiting for approval...
# Signed in to acme-inc as "CLI on blaise-mbp" (live). Scopes: costs:read, revenue:read, usage:read, dimensions:read
login runs the OAuth device grant: it prints a short code, opens https://app.staging.bearlumen.com/activate in your browser (or prints the URL when it cannot, and always with --no-browser), and waits while you approve it in the dashboard. Approving creates an API key named after your machine with exactly the four read scopes below. That key appears in your API Keys page like any other, and it expires after 90 days, at which point login again.
Two alternatives when a browser is not available, such as in CI or on a remote host. Set the environment variable the SDKs also read:
export BEARLUMEN_API_KEY="sk_live_..."
Or pass the key per command:
bearlumen cost summary --api-key "sk_live_..."
Create that key in your dashboard at app.bearlumen.com/developer/api-keys and select the CLI and MCP (read-only) preset when creating it. Use --base-url or BEARLUMEN_BASE_URL to target a non-production host.
Where the key comes from
When more than one source is set, the first match wins, so a flag always overrides a login:
--api-keyon the command lineBEARLUMEN_API_KEYBEAR_LUMEN_API_KEY(deprecated, see below)- The credentials file entry for the active base URL
The credentials file
login stores the key at $XDG_CONFIG_HOME/bearlumen/credentials.json, which is ~/.config/bearlumen/credentials.json on most systems. The file is created with mode 0600 and its directory with 0700, so only your user can read it. Entries are keyed by API origin, so a staging login and a production login coexist and --base-url selects between them. The CLI never prints the key back to you.
bearlumen logout revokes the stored key on the server and removes the entry. If your key came from a flag or an environment variable instead, logout tells you so and changes nothing: revoke that key from the API Keys page.
Test and live keys
A key created in the test environment starts with sk_test_; every other key starts with sk_live_. The CLI reads whichever you give it, and whoami reports which one is active as environment: test or live. Test-key data is kept apart from live data, so a test key only ever returns what test keys sent. login always creates a live key.
Deprecated variable names
BEAR_LUMEN_API_KEY and BEAR_LUMEN_BASE_URL are still read so an existing shell profile keeps working, but they are deprecated and will be removed in a future release. When both spellings are set, BEARLUMEN_* wins. Rename them now.
The authentication guide covers scopes, key expiry and rotation, and the OAuth flow in full.
Required scopes
Every query command needs the four read scopes below. A key with fewer of them can still run ping, which then names what is missing and exits 1, because a key that cannot query is not a passing ping. When you create a key by hand, select the CLI and MCP (read-only) preset and you get exactly this set. A key with usage:write is the SDK ingestion key, not a query key: it cannot read anything.
| Scope | Grants | Needed by |
|---|---|---|
costs:read | Cost summaries, breakdowns, trends, and per-run session trees. | cost *, session tree, insights |
revenue:read | Margin and profitability analysis. | margin * |
usage:read | Recorded usage events and aggregations. | usage * |
dimensions:read | Custom dimension definitions. | dimensions, cost by-dimension |
$ bearlumen ping
Connected to acme-inc as "Ingestion key" (live)
Missing scopes: costs:read, revenue:read, usage:read, dimensions:read. Create a key with the "CLI and MCP (read-only)" preset.
$ echo $?
1
Usage
bearlumen ping # verify key, connectivity, and scopes
bearlumen whoami # org, key name, environment, scopes, expiry
bearlumen cost summary # spend now vs previous period
bearlumen cost by-model --start 2026-06-01 --end 2026-06-30
bearlumen cost by-dimension workflow # any axis: agent, workflow, custom key
bearlumen margin by-end-user
bearlumen insights --limit 5
bearlumen usage summary
bearlumen dimensions
bearlumen logout # revoke the stored key and forget it
Run bearlumen <command> --help for the options of any command. ping and whoami print the same diagnostic: organization, key name, environment, scopes, and expiry.
Dates and windows
--start/--endaccept ISOYYYY-MM-DD. Omit them and the command defaults to the trailing 30 days, the same default the MCP server uses.cost summarytakes--windowinstead (current-period,last-period,last-7-days,last-30-days,last-90-days,ytd,last-year) and already returns a period-over-period comparison.
JSON output
Add --json to emit raw JSON instead of a table, for piping:
bearlumen cost by-model --json | jq '.items | max_by(.total_cost)'
bearlumen margin by-end-user --json | jq '.end_users[] | select(.margin_amount < 0)'
Parity with the MCP server
Every CLI query command maps to one MCP tool and back. An agent and a shell script see identical data. If a command exists here, the matching tool exists there. login, logout, and whoami are the exception by design: they manage the credential the CLI uses, which an MCP client handles through its own OAuth flow, so they have no tool counterpart.
Exit codes
0 on success, 1 on any error, including a ping against a key that is missing a query scope. API errors print a code, status, and a ref correlation id to stderr, so failures are easy to script around and to quote in a support request.