CLI
Install, authenticate, discover commands, and read the `oxygen` output envelope.
Compact reads
JSON output is compact by default. Add --pretty for human reading. Command lists show short summaries while preserving cost and approval guidance; selected commands retain complete flag descriptions and examples. Use --help-full to expand the command list or oxygen commands get <exact-name> --json for exact grammar. Start discovery with oxygen commands search <goal> --json.
Raw oxygen tables query <table> --json defaults to 20 rows and a 12,000-character compact JSON envelope. Select needed columns with --fields and follow nextCursor with the same filters. Oversized results return table_query_result_too_large with recovery instructions; values are never silently shortened. Use tables rows inspect to read an exact cell or JSON path through lossless value windows.
--full restores legacy raw query defaults. --output <new-path> writes the full current page to a private local JSON file and returns its path, counts and continuation. It preserves existing files. A saved page is not a whole-table export; use tables export for that.
Table run get/wait now return progress summaries with counts, costs, failures and next actions. Sequence enrollment reads default to compact rows with invite state and next-message timing. Add --full to either read for the full stored details. Native API defaults and existing MCP host limits remain unchanged.
For formula discovery, oxygen formulas functions --query "dot-separated path" --json returns matching functions with their signatures and dialect guidance.
Every command is listed in the CLI reference. MCP tools and the web app call the same /api/cli/* contract, so state created here is visible from all three.
Install and authenticate
npm install -g @oxygen-agent/cli
oxygen login
oxygen status --jsonoxygen status compares the local CLI against the deployed API. It stays usable — along with oxygen whoami and oxygen update — when an outdated CLI is refused with cli_update_required.
Updates
The CLI keeps itself current. Once a day it checks npm in the background and installs a newer release; the command you ran never waits, and the next command prints one line saying what was updated. If the API refuses your CLI as too old (cli_update_required), the CLI updates itself and re-runs that command once.
oxygen update --status # installed vs newest version, and whether automatic updates are on
oxygen update # update now
oxygen update --disable-auto # keep this computer on its current version
oxygen update --enable-autoAutomatic updates need a global install (npm install -g @oxygen-agent/cli). They are off when CI is set, when OXYGEN_NO_AUTO_UPDATE=1 is set, and for a CLI run through npx or from a project's node_modules; oxygen update --status --json then names the reason (auto_update.reason_text) and the step that works (auto_update.next_step). On a build server that must stay pinned, install the version you want (oxygen update --package @oxygen-agent/cli@<version>), then set OXYGEN_NO_AUTO_UPDATE=1 or run oxygen update --disable-auto once. oxygen update also refreshes the Oxygen agent skills in the global skill folders of Codex, Claude Code and Cursor; set OXYGEN_SKIP_SKILLS=1 to skip that. A pinned CLI that falls below the API's minimum still stops with cli_update_required until you run oxygen update.
oxygen login registers the terminal server-side and sends you to Settings → CLI and MCP to approve it; the browser and the terminal show the same confirmation code. No loopback server is involved, so it also works over SSH, WSL, and in containers — open the printed URL in any browser. It works when your agent runs it for you, too (Claude Code, Codex or Cursor): their command shells are not interactive terminals, and you approve the sign-in in your browser. --no-browser skips the handoff; oxygen login --token <token> stores a token minted on that same page.
Where nobody can approve a sign-in, such as CI, use a token (with CI set, oxygen login without --token stops at once):
oxygen api-keys create --name "automation key" --json
oxygen auth use-token --token <token> --jsonoxygen talks to https://oxygen-agent.com. oxygen-dev targets the Oxygen dev deployment and is not for customer workspaces.
Profiles and organizations
oxygen profiles list --json
oxygen profiles use <profile> --json
oxygen orgs list --json
oxygen orgs use <organization-slug> --json
oxygen whoami --jsonA profile stores one host plus one token. The active organization scopes tables, context, integrations, runs, and credits.
Discovery
Start from the outcome, then hydrate one exact command:
oxygen capabilities search "waterfall-enrich work emails in this table" --json
oxygen commands search "preview a work-email waterfall" --limit 5 --json
oxygen commands get "enrich-column preview" --jsonThe capability card names the owning primitive, what it is not for, execution and spend posture, related skills, and gateway commands. commands get returns one command's exact arguments, flags, and safety markers. oxygen commands --json still emits the full manifest for diagnostics, but agents should not load it by default.
Skills and provider operations are separate catalogs:
oxygen skills search "host a deterministic signup workflow" --json
oxygen skills get <skill-name> --json
oxygen tools search "public LinkedIn post engagers" --json
oxygen tools get <tool-id> --jsonProvider operations are not CLI commands — they are the units a tool column or oxygen tools run invokes, listed in the provider reference. Public LinkedIn reads prefer native cookieless scraper.* operations; connected linkedin.* is for the workspace account's private data and writes.
Output envelope
--json returns one shape on every state-bearing command:
{
"ok": true,
"data": {
"web_url": "https://oxygen-agent.com/workspaces/<workspace-id>/tables/<table-id>"
},
"meta": {
"command": "tables preview",
"version": "<deployed server version>",
"minimum_cli_version": "<oldest CLI this API accepts>"
}
}A failure keeps meta and replaces data with error.code, error.message, and an optional error.details. The exit code classifies the failure so a shell agent can branch without parsing the body:
| Exit | Meaning |
|---|---|
| 0 | ok |
| 1 | unclassified error |
| 2 | usage or input validation |
| 3 | auth or CLI compatibility (not_authenticated, cli_update_required) |
| 4 | not found |
| 5 | provider or server failure |
| 6 | rate limited — wait error.details.retry_after_seconds, then retry |
| 7 | approval, spend gate, or subscription recovery — follow error.details.next_step |
| 8 | timeout |
data.web_url opens the same state in the web app. Run-oriented commands add run ids, status, item counts, credits, and error summaries.
Safety posture
Previews and dry runs make no provider calls and spend nothing. A paid provider call, AI or tool column run, enrichment run, CRM write, outbound enrollment, or LinkedIn action refuses to execute until you pass --approved, and refuses again without a --max-credits ceiling on anything that carries a price. approval_required and max_credits_required both exit 7 and spend nothing.
oxygen tools run <tool-id> --input-json '{...}' --mode dry-run --json
oxygen tools run <tool-id> --input-json '{...}' --mode live --approved --max-credits 5 --json--max-credits is a ceiling, not a charge: unused reserved credits are released. See Approvals for what each action requires, and check what a run actually cost with:
oxygen billing balance --json
oxygen billing usage --limit 50 --jsonTrack deals in the CRM
Keep companies, people, and deals as canonical records — open them in the app, write them from the CLI, enrich them, merge duplicates, keep a sample record as real, and promote table columns onto them.
CLI command reference
Every public oxygen command, generated from the CLI's own command tree.