# Oxygen — Full documentation (llms-full.txt)
> Full-text export of every Oxygen documentation page, concatenated into one
> file for AI agents and LLMs. This is the companion to the short link index
> at /llms.txt.
Docs home: https://oxygen-agent.com/docs
Index (llms.txt): https://oxygen-agent.com/llms.txt
Pages: 64
---
# What is Oxygen
> Pick the guide for the step you are on, and find the screen that owns each job.
Source: https://oxygen-agent.com/docs
Target lists, enrichment, email sending, the shared inbox, CRM records, and the automation between them run in one workspace. Every job is reachable three ways — the web app, the `oxygen` CLI, and any MCP client — over one API, with the same approvals and one credit balance.
Need help with the product? The support chat is in the bottom-right corner of
every page — expand it and write. **Retry** is the only recovery control if it
cannot connect; it returns after each failed attempt and never creates another
case. See the [Support guide](/docs/surfaces/support).
**Reading these docs with an agent?** Fetch [`/llms.txt`](/llms.txt) for the map of every public surface and [`/llms-full.txt`](/llms-full.txt) for every documentation page and every capability, audience and list-target page in one file.
For plan credits, coupons and the partner bonus, read [Billing](/docs/safety/billing#agency-partner-bonus). For applying, editing and publishing a partner listing, read [Agency directory](/docs/workspace/agency-directory).
## The guides, in order
Before a lookup, read [own-key fees and retries](/docs/providers/waterfalls#own-key-fees-and-retries): what `max_credits` covers, why an own-key miss can spend again, and how to interpret `retry_safe` and `own_key_spend`.
1. **[First session](/docs/guides/first-session)** — sign up, pick a plan, install the CLI.
2. **[Source leads](/docs/guides/source-leads)** — build a target list into a table.
3. **[Enrich leads](/docs/guides/enrich-leads)** — add work emails, firmographics, AI columns.
4. **[Email setup](/docs/guides/email-setup)** — sending domains, inboxes, DNS, OXYGEN Warm-up.
5. **[First sequence](/docs/guides/first-sequence)** — attach senders, write the steps with lead-column and sender-name variables, launch.
6. **[Handle replies](/docs/guides/handle-replies)** — triage what comes back and answer it.
7. **[Track deals in the CRM](/docs/guides/crm-records)** — turn replies into records, activity, and pipeline.
Signing up needs no card and starts nothing you have to cancel. You land in a permanently free workspace with a one-time grant of 1,000 [credits](/docs/safety/billing). The CRM, Tables, Workflows, Knowledge, Agents, and the Workspace Copilot are free to use; credits pay for enrichment and AI. A plan is what lets you act on the outside world — connecting a sending mailbox, LinkedIn account, or WhatsApp number, dispatching a sequence, publishing, buying managed email infrastructure, or bringing your own provider keys.
Anything that spends credits or reaches a real person previews first. From the CLI: run it, read the preview, then re-run with `--approved` and `--max-credits `. In the app the same gate is a button you press on purpose — the sequence stepper's **Review & start**.
## Where each job lives
All fifteen primitives are below. The sidebar carries most of them under Data, Action, External, and Knowledge — close to the layers here, not identical. ⌘K searches that same sidebar list.
{/* SCREENSHOT: /home | the expanded left sidebar with the Data, Action, External, and Knowledge group headers and every nav label readable */}
| Layer | Primitive | Where it is |
|---|---|---|
| Knowledge | [Knowledge Graph](/docs/knowledge/knowledge-graph) — company profile, ICP, positioning, connected GitHub or Obsidian repositories | **Knowledge Graph** → `/knowledge` |
| Knowledge | Recipes — installable GTM plays | **Recipes** → `/blueprints` |
| Data | [Records](/docs/guides/crm-records) — companies, people, deals, plus any object you define | **CRM** → `/crm` |
| Data | [Tables](/docs/data/tables) — working datasets and their columns | **Tables** → `/tables` |
| Data | Messages — email, LinkedIn, WhatsApp threads | **Unibox** → `/unibox` |
| Data | Posts — published content and engagement | **Publishing** → `/publishing` |
| Data | Signals — visits, profile views, reactions, follows | no screen yet; `oxygen signals list` |
| Data | Dashboards — funnel from touch to won | `/dashboards`, not in the sidebar |
| Data | Ads — competitor ad intelligence | a tool column in **Tables** |
| Data | Tags — one label vocabulary | **Tags** → `/tags` |
| Action | Sequences — multichannel outbound | **Sequencer** → `/sequencer` |
| Action | Publishing — approval-gated posting | **Publishing** → `/publishing` |
| Action | Workflows — triggers, branches, retries | **Workflows** → `/workflows` |
| Action | Agents — standing workers on a credit budget | **Agents** → `/agents` |
| Action | Observability — runs, costs, errors | **Observability** → `/observability` |
Missing a page from the sidebar? You may have hidden it from your own sidebar in **Settings → Customise** (`/settings#/customise`, or `oxygen settings pages list`); each person chooses their own pages in each workspace; see [Customise the sidebar](/docs/surfaces/web#customise-the-sidebar). Agents and Approvals stay out of the sidebar on purpose, and their pages still open from links.
Two things are deliberately not primitives. **Control** is where you drive from — the web app, the [`oxygen` CLI](/docs/surfaces/cli), [MCP](/docs/surfaces/mcp) clients, the Workspace Copilot — all on one API, so nothing you do in one is invisible in another. **External** is what Oxygen connects to rather than owns: enrichment providers, mailbox accounts, LinkedIn, HubSpot, Attio, under [**Connections**](/docs/providers/integrations) → `/connections`. Run `oxygen integrations list --json` to see every supported provider and its connection status.
---
# Quickstart
> Three ways to connect — the CLI, an MCP client, or an AI assistant. Pick one and start asking for what you want.
Source: https://oxygen-agent.com/docs/quickstart
All three reach the same workspace, the same approvals, and the same credit balance.
Signing up lands you in a working workspace on the free tier — no card required, no trial deadline. Eligible billing owners receive a one-time grant of 1,000 [credits](/docs/safety/billing) when signup grants are enabled; Free has no monthly refill. Check `oxygen billing balance --json` for your available credits. Sending, supported publishing and managed email purchases use credits on Free when `oxygen billing estimate --json` reports `sender_billing: credit_reservations`; the legacy model also requires a paid plan and sending seats. Your own provider keys and Instagram, TikTok, YouTube and Facebook publishing still require a paid plan.
## From the CLI
Requires Node.js >=22.22.0 and npm >=10.9.0.
```sh
npm install -g @oxygen-agent/cli
oxygen login
```
A global install keeps itself up to date; see [Updates](/docs/surfaces/cli#updates) to check the version or pin a build server.
`oxygen login` opens your browser and shows a confirmation code — approve the terminal there and it connects. No browser? Create a token under **Settings → CLI and MCP** and run the `oxygen login --token ` command it shows.
Now describe what you want. The CLI ships its own discovery, so you do not need to memorise commands:
```sh
oxygen capabilities search "find companies hiring sales reps" --json
oxygen commands search "import a csv" --json
```
Every command is in the [CLI reference](/docs/surfaces/cli-reference).
## From an MCP client
Point any MCP-capable client at the hosted server:
```
https://oxygen-agent.com/mcp
```
Authenticate with OAuth in the client, or a bearer token from **Settings → CLI and MCP**. Then ask for what you want in plain language — the client picks the tools.
A fresh connection sees the core tools. Find any other customer tool with `oxygen_capabilities_search`, inspect its arguments with `oxygen_capabilities_schema`, then run it through `oxygen_capabilities_read` or `oxygen_capabilities_call`. A domain pack (`?toolset=`) optionally lists its tools directly. Every tool is in the [MCP reference](/docs/surfaces/mcp-reference).
Client-specific setup: [Claude Code](/docs/surfaces/claude-code), [Claude Desktop](/docs/surfaces/claude-desktop), [Claude Cowork](/docs/surfaces/claude-cowork), [Codex](/docs/surfaces/codex), [Cursor](/docs/surfaces/cursor), [any other client](/docs/surfaces/generic-mcp).
## With an AI assistant
Same connection as above, with the assistant driving.
```sh
claude mcp add --transport http oxygen https://oxygen-agent.com/mcp
```
Then talk to it:
> Build me a list of Seed-stage B2B SaaS companies in the US that are hiring their first AE, find work emails, and show me what it will cost before you run anything.
The assistant plans the work, previews the spend, and asks before anything paid or outbound happens. You approve or you don't.
Anything that spends credits or reaches a real person previews first. Read the preview, then approve it on purpose — `--approved` with `--max-credits ` from the CLI, or the button in the app.
## Choose a Recipe or Blueprint
Connected, and not sure what to run? Browse the catalogs and choose the outcome
that fits your workspace.
```sh
oxygen recipes list --json
oxygen blueprints list --json
```
[Recipes](/docs/knowledge/recipes) transfer the operating judgment for a proven
business case. Blueprints describe installable Tables, Workflows, and other
workspace resources. Inspect the selected item before applying or running it;
paid work and external actions still require their own preview and approval.
## Next
[The guides](/docs) walk the whole journey: source leads, enrich them, set up sending, launch a sequence, handle replies, and track deals.
---
# Your first session
> Choose how you work with OXYGEN, find your way around Home, connect the CLI, and create your first table without spending a credit.
Source: https://oxygen-agent.com/docs/guides/first-session
Sign-up runs **create organization** (your company website is the one required field, or your company's LinkedIn page if you have no website: OXYGEN reads it once to seed your workspace knowledge) → **How did you hear about us?** → **How do you want to work?** There is no plan to pick, no trial, and no checkout on the way in.
The last step is one choice:
- **Your own agent.** Connect Claude, ChatGPT, Cursor, Codex or another agent through MCP or the CLI on the **Install OXYGEN** step, then paste the onboarding prompt it gives you into your agent.
- **OXYGEN Copilot.** OXYGEN's own agent, in the app, with nothing to install. Your onboarding conversation starts right away: it tells you in a few lines what OXYGEN's research found about your company, drafts your ideal customer profile for you to correct and asks what you want to build first. Then it walks you through the **Get started** steps one at a time: your first leads in a **First leads** table, a first sequence, connecting your LinkedIn account, and the launch.
You can use both later; the choice only decides where your first session starts. If the Copilot is not available to your account, sign-up goes straight to **Install OXYGEN**.
## What the free tier gives you
The Free plan has no recurring charge or trial deadline. Eligible billing owners receive **1,000 signup credits** once when signup grants are enabled, with no monthly refill. Read `oxygen billing balance --json` for your available balance. Live enrichment and other paid work consume credits; author and preview your outbound motion before running it. Plan prices, included credits, and what each unit costs: [pricing reference](/docs/safety/pricing-reference).
Read `oxygen billing estimate --json` for your connection model. With `credit_reservations`, an eligible Free workspace can fund supported publishing and managed infrastructure from its balance. Connecting a sending account (a LinkedIn account, mailbox, WhatsApp number, X account or phone number) needs a plan on either model, as do plan-gated providers; new provider API keys need $99 or above after repricing, with existing-key exceptions ([billing](/docs/safety/billing#managed-vs-byok)). Use **Billing & credits** (sidebar footer → **Settings** → `/settings#/billing`) to add credits or choose a plan. Everything you built carries over; separately funded purchases keep their own billing terms.
## Reading Home
Home is where you talk to OXYGEN Copilot. Ask for what you want in your own words, or start from one of the suggested plays under the composer. Each message opens a conversation at `/copilot/`, and your earlier conversations are listed beside it. The Copilot runs the same tools as the CLI and MCP, shows what each paid or outbound step costs, and asks before it spends credits beyond a small allowance or sends anything.
If the Copilot is not available to your account, Home shows the featured plays as prompts to copy into your own agent, your last 30 days of outreach and content, and what is running: sequences, scheduled posts and workflows.
A read-only standup of your workspace is in the terminal, 0 credits:
```sh
oxygen home --json
```
## The sidebar
| Group | Item | What it holds |
|---|---|---|
| | Home `/home` | OXYGEN Copilot, or featured plays and recent activity without it. |
| Data | CRM `/crm` | Companies, people, deals, and their timelines. |
| Data | Tables `/tables` | Working datasets — lists, enrichment, scoring. |
| Data | Unibox `/unibox` | Email, LinkedIn, and WhatsApp conversations in one inbox. |
| Action | Sequencer `/sequencer` | Outbound programs, sending accounts, analytics. |
| Action | Publishing `/publishing` | Scheduled posts and their engagement. |
| Action | Workflows `/workflows` | Deterministic multi-step automations. |
| External | Connections `/connections` | Provider accounts and API keys. |
| Knowledge | Tags `/tags` | Shared vocabulary across records, tables, and campaigns. |
| Knowledge | Observability `/observability` | Every run, its cost, and its provenance. |
Agents, Knowledge Graph, Recipes, and Approvals appear only once an organization turns on **Beta features** in Settings. `Cmd`-`K` opens a palette that jumps to any visible destination by name.
## Where credits live
The sidebar footer holds the workspace switcher and a settings popover. **Billing & credits** (`/settings#/billing`) there answers every money question in one place: your plan, top-ups, seats and cancellation, and below them where credits went — by feature, provider, and day. From the CLI, `oxygen billing balance --json` and `oxygen billing usage --json`.
## Connect the CLI
Home's top bar has a **CLI and MCP** button (Home only — other pages give that space to their own actions). It opens the same setup block as the settings popover's **CLI and MCP** entry at `/settings/cli`.
```sh
npm install -g @oxygen-agent/cli
oxygen login
```
Needs Node.js 22.22.0+ and npm 10.9.0+. `oxygen login` opens the browser and waits; check the confirmation code matches your terminal, then click **Approve this terminal**.
If the handoff never completes — no browser on that box, a network that blocks the wait — the terminal prints the manual path. On `/settings/cli`, click **Create session** and paste the `oxygen login --token ` line it shows into that terminal. The token is shown once.
Confirm you are connected, against the right workspace:
```sh
oxygen whoami --json
oxygen orgs list --json
oxygen orgs use
```
The CLI updates itself, including when a command fails with `cli_update_required` because it is older than the deployed API. If automatic updates are off (see [Updates](/docs/surfaces/cli#updates)), run `oxygen update` and retry. `oxygen status --json` compares the two versions directly.
Using an MCP client instead of a terminal? The panel's **MCP** tab prints the endpoint and per-client steps; [MCP setup](/docs/surfaces/mcp) has the full list.
## A first action that costs nothing
Create a table and look at it.
Click **Tables** in the sidebar. An empty workspace opens the source picker straight away; otherwise click **New table** in the table rail (`/tables/new`). The picker lists every way a table can start — a file or a public link, Supabase or HubSpot, company and people searches (including lookalikes and local businesses on Google Maps), signal feeds, a webhook, a Function draft — and under each card the number of providers behind it and what a row costs, before anything runs. Pick **Blank table**: it creates a table named `New table` with one text column, `Name`, and opens the grid. Rename it in the breadcrumb. The grid's controls are **Import rows**, **Add column** and **Export CSV** in the toolbar, a magnifier in the breadcrumb that searches the rows, and **New row** as the last row of the grid itself — rows are appended at the bottom, where that button is.
{/* SCREENSHOT: /tables/new | The source picker showing the Blank table and Import a CSV cards */}
The same thing from the terminal:
```sh
oxygen tables create "First list" \
--columns-json '[{"key":"company","label":"Company","dataType":"text"},{"key":"domain","label":"Domain","dataType":"text"}]' \
--json
oxygen tables list --json
oxygen tables preview --limit 10 --json
```
The create response carries a `web_url`. Open it and you are looking at the same grid.
**Blank table** and **Import a CSV** spend nothing. Every other card on that screen — the **Total addressable market** and **Signals** groups — runs a priced provider search, as do AI columns, enrichment columns, and sending. Those paths price the work first and wait for your approval: [approvals](/docs/safety/approvals), [spend caps](/docs/safety/caps).
## Next
- [Tables](/docs/data/tables) and [Columns](/docs/data/columns) — what a table does once it has rows.
- [Billing](/docs/safety/billing) — credit math, top-ups, failed payments.
---
# Source your first leads
> Get real target companies or people into an Oxygen table — sourced from your ICP, or uploaded from a file you already have.
Source: https://oxygen-agent.com/docs/guides/source-leads
Rows land in a Table either way: Oxygen buys them from a provider, or you upload them.
## Start a table in the app
Open **Data → Tables**, then **New table** at the top of the table rail (`/tables/new`). Choose **Import a CSV** to upload your list, **Import from a link** to fetch a public CSV, JSON or XLSX file or a Google Sheet (preview first, free), **Import from HubSpot** to bring CRM companies or contacts into Records, or **Blank table** to start with an empty grid. The same picker offers company sources (Company Search, lookalikes, local businesses on Google Maps, web search, a known page), a people search, the signal feeds and a webhook; every card shows its providers and per-row credit estimate before anything runs. Two cards read LinkedIn through accounts you have already connected rather than buying data: **LinkedIn Post Engager Scraper** collects the people who engage with posts you watch, and **LinkedIn Profile Viewers** collects the people who viewed your own profiles — you tick which connected accounts to read, they fill one table in the background at your accounts' safe daily read budget, and it is free. The same account list, with each account's status, sits behind the LinkedIn chip on that table, where unticking an account pauses it and keeps its rows. LinkedIn hides anonymous and private-mode viewers, so that one is always a partial sample of real viewers. **Scrape LinkedIn Company Followers** is different: it reads no account of yours. Paste a company page — a competitor's, say — and a follower count, and the free **Check this page** quotes the exact order (per follower, 100 minimum) before you buy. Our data provider fulfils the order on its side, so the table is created at once and fills when the followers arrive; there is no published delivery time. The same order runs from the terminal as `oxygen tables followers check --company --records ` and then `oxygen tables followers order --approved` with the quoted `--max-credits`. From the terminal, `oxygen tables sources` lists the same catalog.
Under **People**, the **People — Blitz** card sources everyone who works at the companies you already have. Pick the table holding your companies, then the column holding each company's LinkedIn URL, narrow by job level, job function, connections, country, continent and sales region, and Oxygen fetches the first 50 people from the first company for 1 credit so you can look before buying the rest. **Pages per company** in the footer sets how deep each company goes — 50 people per page, 1 credit per page.
The Total addressable market and Signals source groups are temporarily hidden while their setup is redesigned. To source companies or signals, use the CLI paths below and the [Signals guide](/docs/data/signals).
## From your ICP, from the CLI
Planning is free — the only provider call is the people planner's zero-credit count probe, which `--no-estimate` skips.
```sh
oxygen companies search plan \
--prompt "Seed-stage B2B SaaS in the US hiring their first AE" \
--target-count 500 --json
oxygen people search plan \
--prompt "Heads of Sales at US B2B SaaS companies" \
--titles "Head of Sales,VP Sales" --employees 20-200 --countries US --json
```
The plan returns ordered `routes` — each with `estimated_credits` — plus `estimated_match_count`, `filter_application` (which of your filters the provider applies, and which it drops), and the `table_blueprint` it would create. `--target-count` is capped at 50,000 per plan; larger asks return a clamp warning.
Not sure whether you want accounts or contacts? `oxygen sourcing plan --prompt ` and `oxygen lead-sourcing plan --prompt ` classify the request and recommend routes without executing any paid tool.
Dry-run next — still free, and `--mode` defaults to `dry_run`:
```sh
oxygen companies search run --prompt "Seed-stage B2B SaaS in the US" --target-count 500 --json
```
Then live. This spends credits:
```sh
oxygen companies search run \
--prompt "Seed-stage B2B SaaS in the US" --target-count 500 \
--mode live --approved --max-credits 2500 --json
```
Both flags are mandatory. Without `--approved` the run fails `approval_required` (409); without `--max-credits`, `spend_cap_required` (400); with a ceiling under the route estimate, `spend_cap_too_low` (400), and the error names the `estimated_max_credits` you need.
Omit `--table` and Oxygen creates the table for you. Company rows dedupe on `domain`, people rows on `linkedin_url`, so re-running the same search updates rows instead of duplicating them.
## Everyone at the companies you already have
When the account list is already a table, point people search at it instead of describing the companies again. `--from-table` names the table, `--linkedin-url-column` names the column holding each company's LinkedIn URL, and Oxygen runs Blitz Employee Finder once per company: **1 credit per company per page**, 50 people per page. `--prompt` is optional here — the table is the request — but pass one to steer the persona further.
```sh
oxygen people search plan \
--from-table accounts --linkedin-url-column company_linkedin_url \
--job-functions Sales,Marketing --seniorities VP,Director \
--countries US --sales-regions EMEA --min-connections 200 --json
```
The plan's `source.companies_planned` is the real company count the run will spend against. Buy the first company first, then source the rest into the same table:
```sh
oxygen people search run --plan-json ./plan.json --route-id employee-roster-from-table \
--company-limit 1 --mode live --approved --max-credits 10 --json
oxygen people search run --plan-json ./plan.json --route-id employee-roster-from-table \
--table --company-offset 1 \
--pages-per-company 2 --mode live --approved --max-credits 1000 --json
```
`--max-pages` means pages **per company** on a `--from-table` run; `--pages-per-company` is the same ceiling spelled the way it reads. The people table's default columns are First Name, Last Name, LinkedIn URL and a **Company** link back to the row the person was found at, so every person stays attached to their account.
## From a file you already have
Free — no provider call, no credits.
In the app: open the table and click **Import rows** in the top bar (an icon button; the tooltip names it), or pick **Import a CSV** in the wizard. The dialog is **Import file**, or **Create table from file** when there is no table yet: **Click to upload** or drag and drop, **CSV, JSON, JSONL, or XLSX**. Set **Table name** and **Folder** when it is creating the table, press **Preview** to check the parsed rows — importing into an existing table then draws **Column mapping** — then **Import**.
```sh
oxygen tables import --create "Starter TAM" --file leads.csv --background --json
oxygen tables import --file leads.csv --upsert-key domain --json
```
`--format` is inferred from the extension (`json`, `jsonl`, `csv`, `xlsx`). Files over 500 rows load in the background and the command returns before the rows land — wait on the `table-ingestions wait ` it prints before you trust a row count. The per-file row ceiling equals your plan's rows-per-Table limit (`oxygen limits show`). The file-size ceiling is 500 MiB on free, 1 GiB on $49–$99, 2 GiB on $199–$499 and 5 GiB on $999 and up ([table and signal limits](/docs/safety/pricing-reference#table-and-signal-limits)); an import into a non-empty Table must also fit its remaining capacity. JSON and XLSX are read whole, so they stop at 100 MiB on every plan: save a larger file as CSV or JSONL. A CSV or JSONL file over 64 MiB uploads straight from disk to file storage and always loads in the background.
## Watch it fill
A live search returns a durable ingestion run, not rows. The envelope carries `ingestion_run` and a `web_url` for `/tables//ingestions/`, which shows **Items**, **Rows**, **Inserted**, **Updated**, and the **Pending / Running / Completed / Failed** breakdown.
```sh
oxygen table-ingestions get --json
oxygen table-ingestions wait --json # polls until terminal; 600s default
oxygen tables preview --limit 25 --json
```
`counts.rows` at 0 while the status is still `queued` or `running` is normal — the envelope's `message` says so explicitly.
If the run ends `completed_with_errors` or `failed`, the table holds whatever landed first; `oxygen table-ingestions items --status failed --json` names the items that broke.
If a live search returns `search_ingestion_enqueue_failed` (503), the table was created but nothing was queued into it. The error's `next_step` says whether Oxygen already archived the empty table or you must archive it before retrying.
---
# Enrich your leads
> Fill work emails, mobile phones, LinkedIn URLs, and company facts onto a table you already have, for a cost you approve first.
Source: https://oxygen-agent.com/docs/guides/enrich-leads
Start from a table whose rows carry one identity signal each: a LinkedIn profile URL, or a full name plus a company domain.
## Add the column in the app
Open **Tables** in the sidebar, open your table (`/tables/`), then click the **+** at the right end of the column header row (tooltip: **Add column**).
The panel opens on **Column types**. The first two rows are bundles: **Person enrichment** (one LinkedIn profile lookup, then 13 free formula columns — headline, bio, location, followers, full/first/last name, job title, current company, current company LinkedIn URL, job start date, education, school — needs a LinkedIn URL column; rows without one are skipped and cost nothing) and **Company enrichment** (one company lookup, about 1 credit a company, then 8 free formula columns — name, domain, LinkedIn URL, headcount, industry, description, founded year, HQ country — with the whole profile kept in its JSON column; needs a domain or company LinkedIn URL column, rows with neither are skipped and cost nothing, and it auto-binds to a `current_company_linkedin_url` column left by Person enrichment). Clicking one asks which column holds its input, then creates the whole bundle and opens the one paid column; nothing runs until you run it. The rows after them are the single-field waterfalls: **Work email**, **Mobile phone**, **LinkedIn URL** (a person's profile URL from their full name plus their company's domain, name or LinkedIn page). Everything under the **Integrations** divider is one vendor's tool rather than a waterfall.
Choosing an entry creates the column and opens its editor, which has five parts:
- **Intent** — what the column resolves.
- **Waterfall sequence** — the ordered provider lanes. On a work-email column you also pick a keying: **Auto** is recommended; **LinkedIn URL**, **Name + Domain**, and **First/Last + Domain** force every row down one.
- **Input mapping** — map your row columns onto the canonical inputs. A column with nothing mapped cannot run.
- **Email verification** (work email only) — a toggle. On, every found address is verified before it lands in the cell.
- **Estimated cost** — the typical spend, with the worst case shown as "up to".
Nothing is charged yet. The footer has **Save without running** and **Run**; **Run** offers **Run for first 10 rows**, **Run for next 25 rows**, **Run missing results**, **Rerun full table**, and selected rows, then a cost step showing **Estimated credits**, **Rows affected**, **Per row**, **Recommended cap**, **Available**, and a **Max credits** field ("Hard cap on credits spent. The run stops before exceeding it."). Credits move only when you confirm that step.

## Why a waterfall is cheaper than one provider
Lanes run in order and a row stops at the first lane that returns a result. On OXYGEN’s managed credentials, billing depends on the intent: **work email and phone bill on a hit** — a lane that finds nothing releases its reservation, so a row resolved early never pays the lanes behind it. **Company-field enrichment bills every lane it attempts**, hit or miss, and so does LinkedIn URL until the 2026-09 repricing date. From that date **a LinkedIn URL costs a flat 5 credits when one is found that matches the person**, and nothing when none is. Full rules: [tool costs](/docs/providers/tool-costs#how-a-provider-call-is-charged). On **Auto**, a lane a row cannot drive is skipped, so a row with only a name and domain never pays for a LinkedIn-keyed provider. On `linkedin_url`, managed lanes over 50 credits per call stay off unless you pass `--allow-premium-lanes` (until the repricing date); on managed work email and phone there is nothing to gate, because a lane that misses costs nothing. Successful calls on your own provider key pay the separate platform fee even on a miss, and a dispatched own-key miss is not retry-safe. Your provider may charge separately, outside the OXYGEN credit cap. See [own-key fees and retries](/docs/providers/waterfalls#own-key-fees-and-retries).
## The same thing from the CLI
Preview first. It makes no provider calls and costs nothing:
```sh
oxygen enrich-column preview leads \
--capability work_email \
--linkedin-url-column linkedin_url \
--company-domain-column domain \
--limit 10 --json
```
Read `expected_credits` (typical), `estimated_credits` (worst case), `recommended_max_credits`, `estimated_row_count`, `selected_providers`, `blocked_providers`, and `runnable`.
The next command spends credits. `--approved` authorizes this one run; `--max-credits` is the ceiling it cannot cross.
```sh
oxygen enrich-column run leads \
--capability work_email \
--linkedin-url-column linkedin_url \
--company-domain-column domain \
--only-missing \
--max-credits 200 \
--approved --json
```
`--capability` also takes `mobile_phone` and `linkedin_url`; add `--verify-phone` to get line type and carrier. Follow the run with `oxygen table-runs wait --json` and `oxygen table-runs provider-summary --json`. The response's `web_url` opens the same run in the app.
Three errors stop this command:
- `approval_required` (exit 7) — you left off `--approved`. Read the preview, then retry with it.
- `selection_required` — pass `--limit `, `--all`, or `--only-missing`.
- `invalid_enrichment_mapping` — no provider can run on the columns you mapped. Map a LinkedIn URL column, or a name column plus `--company-domain-column`.
## What lands in the table
A `work_email` run writes `email`, `email_provider`, `email_status`, and `email_enriched_at`, plus the JSON column `work_email_enrichment` holding every attempt. A `mobile_phone` run writes `mobile_phone_e164`, `phone_source`, `phone_line_type`, `phone_carrier`, `phone_enrichment_status`, and `phone_enriched_at`.
## Read a cell before you trust it
Unsettled cells wear a chip: **Queued**, **Running**, **Retrying**, **Rate limited**, **Failed**. A settled cell shows none, so a blank cell with no chip means the waterfall ran and found nothing — not that it never ran.
Double-click a cell (or select it and press Enter) to open **Cell details**: **Last run** (Status, Attempts, Completed), the **Value** tree, and **Rerun this cell**. The hover button on a filled cell's right edge is **Expand into result columns** — or **Expand sub-columns** on the column header — which fans the waterfall out into one column per provider attempt; clicking one opens it as a **Waterfall attempt**.
Same data on the terminal:
```sh
oxygen cells inspect leads work_email_enrichment --json
```
{/* SCREENSHOT: /tables/:id | an enrichment column expanded into per-provider attempt columns, with the Cell details panel open on one attempt */}
## One row, no table
Each lookup previews for free (`dry_run` is the default) and needs `--mode live --max-credits ` to actually spend:
```sh
oxygen find email --full-name "Ada Lovelace" --company-domain acme.com --json
oxygen find email --full-name "Ada Lovelace" --company-domain acme.com --mode live --max-credits 20 --json
oxygen find personal-email --linkedin-url https://www.linkedin.com/in/ada --json
oxygen find personal-email --linkedin-url https://www.linkedin.com/in/ada --mode live --max-credits 20 --json
oxygen find person --linkedin-url https://www.linkedin.com/in/ada --json
oxygen find person --linkedin-url https://www.linkedin.com/in/ada --mode live --max-credits 10 --json
```
`oxygen find phone`, `oxygen find linkedin`, and `oxygen find company --fields headcount,industry,funding_stage,latest_funding_round,revenue,technologies,job_openings` take the same two modes. `find personal-email` finds a personal (non-work) address through its own managed lane (see `oxygen enrichment catalog --intent find_personal_email`), billed only on a hit and graded by MillionVerifier. `find person` is a single managed LinkedIn profile lookup (10 credits) returning the full profile block — name, current company, title, job start date, education, headline, bio, location, and follower count. With no identity signal at all they fail with `missing_identity_input`. `oxygen find company --list-fields` prints the whole company field catalog (identity, firmographics, funding, relationships, signals, technology, web presence) with each field's per-row credits: a `free` field is read from the profile the run already fetched, a `fixed` field costs one priced lane, and an `~estimated` field walks a cascade that bills only on a hit. An unknown field key is refused, never silently replaced by the defaults. Revenue and valuation are not in that catalog — no provider sells them — so they come from the `company_revenue_estimate_v1` and `company_valuation_estimate_v1` column templates as a labelled estimate with a range.
## Verify addresses you already have
```sh
oxygen verify email ada@acme.com --json
oxygen verify email ada@acme.com --mode live --max-credits 40 --json
```
The free first call returns `estimate.recommended_max_credits` — use that number, because catch-all addresses escalate to a second, dearer verifier. Verdicts are `valid`, `invalid`, `catch_all`, or `unknown`; see [Email verification](/docs/providers/email-verification) before you filter on them.
## Company facts across the table
```sh
oxygen companies enrich preview leads --missing-fields domain,linkedin_url,headcount,industry --limit 10 --json
oxygen companies enrich run leads --missing-fields domain,linkedin_url,headcount,industry --limit 100 --approved --max-credits 150 --json
```
More on the mechanics: [Waterfalls](/docs/providers/waterfalls), [Cells](/docs/data/cells), [Spend caps](/docs/safety/caps).
---
# Set up email sending
> Buy or bring sending domains, provision mailboxes, fix DNS, and warm up — so a Sequence has somewhere to send from.
Source: https://oxygen-agent.com/docs/guides/email-setup
Cold email needs separate sending domains, mailboxes on them, correct DNS, and a warm-up before the first campaign. Pick a road first — switching later means buying twice.
| | Managed (OXYGEN buys) | BYOK (your Cloudflare) |
| ----------------------- | ------------------------------------------ | ------------------------------------------------ |
| Prerequisite | none | a Cloudflare account; Registrar access for new domains |
| Domain purchase | billed in OXYGEN credits at the live price | billed to your Cloudflare card, 0 OXYGEN credits |
| SPF / DKIM / DMARC / MX | set by the vendor | vendor setup for managed inboxes, or `domains dns plan` then `dns apply` |
| Mailbox | billed in OXYGEN credits per inbox monthly | buy managed inboxes or supply existing Google/Microsoft accounts |
Managed inboxes bill monthly per inbox, in credits (100 credits = $1). From the 2026-09 repricing date a managed Google Workspace or Microsoft 365 inbox is **400 credits ($4) a month together**: a flat 300-credit mailbox plus the 100-credit ($1) connected-inbox fee every sending mailbox pays, billed separately, with warm-up included. An Azure tenant (one dedicated Microsoft tenant per domain, a flat monthly charge for up to 100 inboxes) is **4,000 credits ($40) a month**, and every inbox on it holds the same connection. The [pricing page](/pricing) lists the prices in force in credits and dollars, and `oxygen managed-inboxes list --json` reports them under `prices`. A domain registered through OXYGEN costs the registrar's price once a year, 1,250 credits ($12.50) for a .com. Until the repricing date warm-up is its own monthly line. Inbox placement is always an optional add-on. Warm-up is not a managed-road-only cost: a BYOK mailbox enrolled with `oxygen mailboxes warmup enable` carries the same monthly per-inbox line, so both roads pay it while warm-up runs. From the 2026-09 repricing, warm-up on a mailbox you connected yourself is included in that mailbox's 100-credit monthly connection once the connection is charged; the warm-up preview's `included_in_connection` says whether it applies to you yet, and then quotes 0. Every price is in the [pricing reference](/docs/safety/pricing-reference). The live preview reports the connection commitment and any separately billed add-ons.
## Where this lives
Sidebar **Sequencer → Accounts** (`/sequencer/accounts`), tabs **Senders / LinkedIn / Email / WhatsApp / Phone numbers**. The **Email** tab nests inboxes under their domains; top-right is **Add inboxes**. Domains have their own page at `/sequencer/domains` — by URL only, deliberately not in the sidebar.
{/* SCREENSHOT: /sequencer/accounts?tab=email | the Email tab with the top-right "Add inboxes" button and one domain expanded to show its inboxes */}
## Road A — managed inboxes
In the app: **Email** tab → **Add inboxes** → **Buy managed**. The wizard steps **Domains → Inboxes → Review**; the last button is **Buy · <n> cr**. The first order asks for a **Registrant contact** (the WHOIS record); later orders reuse it. Closing mid-order saves the cart — the button becomes **Resume order**.
From the CLI, preview first — without `--approved` nothing is ordered or charged:
```sh
oxygen managed-inboxes subscribe send-acme.com --provider google \
--file ./mailboxes.json --billing ./registrant.json --json
```
The order includes warm-up by default (`--no-warmup` opts out); inbox placement is added only with `--placement`. The preview lists the mailbox line, the add-on lines and, once the all-in price applies, each inbox's mailbox connection (`connection_monthly_credits`, reserved from your balance once the inbox connects, not charged with the order); `total_monthly_credits` is what the inboxes cost every month. Check `quote_id`, the lines, and `warmup_activation`, then order:
```sh
oxygen managed-inboxes subscribe send-acme.com --provider google \
--file ./mailboxes.json --billing ./registrant.json \
--approved --quote
```
`--approved` spends real credits and registers a real domain. Without a fresh `--quote` it is refused with `quote_required`, never charged; a stale quote is refused with `quote_mismatch`.
`subscribe` registers a **new** domain, puts the first inboxes on a domain you bought on its own through OXYGEN, or uses an existing Cloudflare domain with `--existing-domain` (below). A domain that already has inboxes grows with `add-inboxes` instead. A domain holds at most 5 Google or Microsoft inboxes (100 on azure), counting existing ones:
```sh
oxygen managed-inboxes add-inboxes send-acme.com --count 3 --prefix ada --json
oxygen managed-inboxes add-inboxes send-acme.com --count 3 --prefix ada --approved --quote
```
### Who the inboxes are ordered for — the sender profile and its photo
An order is placed **for a person**: pass `--sender ` (from `oxygen senders profiles list --json`) and every mailbox in it is stamped with that sender profile's first name, last name, and profile picture. The vendor cannot change any of the three after provisioning, so the profile is the identity to get right, once.
The photo follows one rule. A sender profile with a LinkedIn account attached carries that account's LinkedIn photo automatically — attaching the account (`oxygen senders profiles attach --senders `, or picking it when creating the sender) mirrors the picture into Oxygen's own storage, and profiles connected before this rule are backfilled. A photo you upload yourself (`oxygen senders profiles set-photo --file `) or set by URL is your choice and is never overwritten by the LinkedIn one, so an upload always wins; removing the photo of a LinkedIn-connected sender is temporary, because the LinkedIn photo is adopted again on the next sync. Read the result back on the profile: `avatar_source` says where the picture came from, and `avatar_durable: true` means Oxygen hosts it and the vendor will still be able to fetch it hours after the order. `avatar_durable: false` means only an expiring LinkedIn link could be kept — Oxygen re-syncs the LinkedIn account and retries on its own; to fix it right now, upload a file.
## Recover canceled managed inboxes
Recovery keeps the original domain, addresses, sender profiles and history when the provider still permits restoration. Inspect canceled subscriptions, then request a free preview:
```sh
oxygen managed-inboxes list --status cancelled --json
oxygen managed-inboxes recover send-acme.com --json
```
Review eligibility, upfront credits and ongoing hosting plus connection costs. Approve only that scope with `oxygen managed-inboxes recover send-acme.com --approved --quote --max-credits --json`. Microsoft replacement licenses require a new `--rebuy` preview and separate approval. Hosted MCP offers the same flow through `oxygen_managed_inboxes_recover`.
An unfinished cancellation must settle before recovery. After provider restoration, verify each inbox's sending authorization and warm-up progress, then resume healthy senders within their existing bounce protections and ramp limits.
## Buy a domain on its own
Without a Cloudflare account of your own, **Buy domains** on `/sequencer/domains` registers the domain through OXYGEN. It costs the registrar's price in credits for one year (a .com is 1,250 credits) and renews yearly at the registrar's renewal price, charged 30 days before expiry. If your balance cannot pay the renewal, OXYGEN retries for 7 days and then lets the domain lapse.
```sh
oxygen domains search acme-mail --json # free: names with their yearly price in credits
oxygen domains buy acme-mail.com --json # free preview + quote_id
oxygen domains buy acme-mail.com --approved --quote --billing ./registrant.json
oxygen domains check acme-mail.com try-acme.com # free: exact names, same prices
oxygen domains renewal acme-mail.com --off # stop renewing; it lapses at expiry
```
The first purchase needs the registrant (`--billing`); later ones reuse it. `oxygen domains list --json` shows the domain under `registered_domains` with its expiry and next renewal charge. OXYGEN hosts its DNS and sets the mail records when inboxes are added; editing them yourself is not offered.
To send from it, order its first inboxes with the same `subscribe` command as Road A, or **Add inboxes** on its row on `/sequencer/domains`. The preview shows `domain_source: owned` and no registration charge; Google and Microsoft inboxes are offered:
```sh
oxygen managed-inboxes subscribe acme-mail.com --provider google --sender --locals ada,ada.lee --json
```
`oxygen domains delete acme-mail.com` (or **Delete** on its row) ends the registration: any inboxes on it are cancelled, renewal stops, and the domain leaves the workspace. It stays registered until its expiry, which is not refunded, and this cannot be undone.
## Road B — your own Cloudflare
Connect the account once at **Connections** (`/connections`), or **Connect Cloudflare** on `/sequencer/domains`. The dialog needs a **user-owned** Cloudflare API token (account-owned tokens cannot use the Registrar API) scoped **Zone → Zone: Read**, **Zone → DNS: Read** (DNS Edit to let OXYGEN fix records), and **Account → Registrar: Domains: Edit**; finish with **Verify & connect**. Until then the Domains page shows the connect card, not the domain table.
{/* SCREENSHOT: /sequencer/domains | the header actions "Sync from Cloudflare", "Add domain", "Buy domains" above the domain table */}
With Cloudflare connected, **Buy domains** buys through your own Registrar instead. In the app: **Buy domains** → **Get quote** → **Approve purchase**, or from the CLI:
```sh
oxygen domains check acme-mail.com try-acme.com # free
oxygen domains buy acme-mail.com --json # priced preview + quote_id
oxygen domains buy acme-mail.com --approved --quote
```
That purchase is **non-refundable and bills your Cloudflare account**. Registration can stay pending — `oxygen domains registration-status acme-mail.com --wait` polls to a terminal state.
Already own the domain? **Add domain** → **Apex domain** → **Create zone**, then set the printed nameservers at your registrar (CLI: `oxygen domains add acme.com`). Nothing works until the nameservers move.
Then write the mail records: `plan` is free, `apply` writes into your zone for 0 credits:
```sh
oxygen domains dns plan send-acme.com --provider google --json
oxygen domains dns apply send-acme.com --provider google --approved --plan
```
A stale `plan_hash` is rejected — re-run `plan`. Both only work on Cloudflare zones; a managed domain's records are vendor-held, so read them with `oxygen domains dns send-acme.com --json` instead (`--deep` is ignored there).
### Buy managed inboxes on your existing Cloudflare domains
You can keep the domain at your registrar and purchase Google or Microsoft inboxes through Oxygen. After syncing the domain from Cloudflare, preview:
In the app, open **Buy inboxes → Use Cloudflare domains**, select domains and set **Max inboxes** on each domain. Review the DNS scope, blockers and costs before Buy.
```sh
oxygen managed-inboxes subscribe acme-mail.com --existing-domain --provider google \
--sender --locals ada,ada.lee --max-per-domain 2 --json
```
The preview shows `domain_source: external`, zero domain registration charge, the monthly cost and sender identity. `existing_domain` lists occupied addresses, connection requirements, and the DNS scope. `--max-per-domain 2` saves a limit with the approved order of two addresses on that domain, including existing or parked inboxes; future `add-inboxes` orders honor it. Preview does not save the limit or change workspace data.
For a free connection setup preview, run `oxygen integrations connect cloudflare --json` without credentials, then use the returned Connections link to enter the token. Use only the permissions required by this mailbox quote; the general integration recommendations also cover domain registration. Submitting credentials creates or replaces the connection immediately. Run `oxygen domains sync --json` after connecting, then preview the mailbox order again.
Approval connects only the named domain using your customer Cloudflare token and then buys mailboxes once the connection is confirmed active. It does not transfer the registrar, change nameservers or set website forwarding. Use a token with Zone Read and DNS Edit scoped to the selected domain. Oxygen verifies the token's complete policy before sharing it; an unavailable verification or broader grant blocks the connection. DNS Edit permits changes to any DNS record on that domain; the planned connection changes email records. Keep token-management permissions off the delegated token. Oxygen keeps its shared platform token private. During approved managed setup, the [inbox provider generates and applies MX, SPF, DKIM and DMARC](https://www.inboxkit.com/resources/knowledge-base/dns-management). This preview shows current records and planned record types; it does not include the provider-generated values. The separate `domains dns plan/apply` tools are for self-managed DNS. A new provider connection requires all listed existing email DNS records to be absent, even when they match the chosen provider. Your DNS administrator can remove them in Cloudflare after confirming they are unused and approving the exact removal. If the domain receives email, keep the records and choose another domain. Preview again after the records are removed. Oxygen does not delete them automatically. A first subscription on an occupied domain is also blocked until its existing inboxes are reconciled; use `add-inboxes` for a domain already subscribed through Oxygen. If `executable` is false, resolve the listed blockers and get a fresh quote. Repeat the same inputs with `--approved --quote ` only after reviewing the cost and DNS scope.
## Connect the mailboxes
### Your existing Gmail or Microsoft 365 inbox
Where managed mailbox connection is enabled, **Add inboxes → Connect existing**
uses Composio's managed sign-in application for Gmail, Microsoft 365, Exchange
Online and Outlook. Each mailbox owner signs in and grants mail access. Reviews
contain up to 10 exact addresses. Self-hosted Exchange is not supported.
After importing a missing address, preview its connection:
```sh
oxygen mailboxes connect-oauth --provider google --vendor composio \
--mailboxes ada@acme.com --json
```
Use `--provider microsoft` for Microsoft accounts. Review the **100 credits per
mailbox per month**, then repeat with `--approved` and open the returned
authorization link. Existing paid mailbox coverage is reused. History import,
ongoing sync and CRM analysis are included; analysis adds no separate credit charge.
If the managed connection is unavailable, contact support to finish connecting.
Inbox, Sent and archive history imports in bounded pages while recent mail keeps
syncing. Spam, trash and drafts are excluded. Business messages create contacts,
companies and email activities, with summaries and intent in Unibox. Personal and
automated messages remain in Unibox without CRM records. Existing CRM fields and
relationships are preserved; ambiguous identities and deal/stage suggestions need
review. Historical messages do not execute campaign reply actions.
```sh
oxygen mailboxes sync ada@acme.com --json
oxygen mailboxes sync ada@acme.com --action pause --json
oxygen mailboxes sync ada@acme.com --action pause --approved --json
```
The first command reads history and CRM progress. Actions preview before applying;
`resume` continues, `start` restarts history, and `disconnect` stops importing,
analysis and sending while retaining mail and CRM records. The mailbox panel also
shows progress and links to its Unibox. Existing native and provisioned connections
continue on their current authorization until explicitly reconnected.
### Provisioned inboxes and existing native authorization
Provisioning and native campaign sending use separate authorization contracts. For an InboxKit-managed Google order, OXYGEN completes its destination-bound OAuth authorization automatically and unattended after the domain approval lands; verify the exact mailbox with `oxygen mailboxes oauth-health` instead of opening a second customer sign-in by default. The vendor approval usually lands within minutes, but that is not an SLA: while `oauth-health` reports `client_id_not_approved`, no customer action is required and the worker keeps retrying. Zapmail-linked rows use the same operator rule when `automatic_repair` is non-null: `queued` or `cooldown` means OXYGEN owns the next retry, even if a lower-level compatibility verdict still says `consent_required`; do not ask the mailbox owner to sign in or run `connect-oauth`. Only rows with `automatic_repair: null` follow their explicit manual remedy. Only `oxygen_native_send.state: connected` proves the transport is authorized, and even that does not mean warm-up or the actual-sending campaign ramp is complete. BYOK/imported Google and ordinary Microsoft accounts sign in individually, in reviews of at most 10. In the app: **Add inboxes** → **Connect existing** (paste up to 500 exact addresses) or **Import a file** for a CSV/JSON/JSONL/XLSX export. A dedicated Microsoft sending tenant can instead use one Entra **Global Administrator** or **Privileged Role Administrator** authorization per resolved tenant, followed by read-only verification of only the exact addresses you submitted. Those built-in roles are required because tenant mode requests Microsoft Graph application permissions; an ordinary Application Administrator cannot grant them.
```sh
oxygen mailboxes import --file ./mailboxes.csv --validate-only --json # local, no network
oxygen mailboxes import --file ./mailboxes.csv
oxygen mailboxes connect-oauth --provider google --vendor oxygen \
--mailboxes ada@send-acme.com --json # preview
oxygen mailboxes connect-oauth --provider google --vendor oxygen \
--mailboxes ada@send-acme.com --approved
```
Verify with `oxygen mailboxes oauth-health --json`: it lists every Google/Microsoft inbox with no usable grant — a token on one mailbox proves nothing about another. The detailed [existing-mailbox guide](/docs/providers/mailboxes) covers the Entra tenant and individual paths, secure file fields, and managed-mailbox fallback. Which origins support warm-up and monitoring at all: [mailbox compatibility](/docs/providers/mailbox-compatibility).
Which IP address connected mailboxes are used from, for sends, reply reads and token refreshes: `oxygen egress status`. That is the address your IT team allowlists in Microsoft Conditional Access or Google context-aware access; a workspace-only IP is described under [dedicated sending IP](/docs/safety/billing#dedicated-sending-ip-billing).
## Warm up before you send
A managed order with the warm-up add-on activates itself after provisioning — do not enable it a second time. A non-managed Microsoft mailbox first needs one separate OXYGEN Warm-up Outlook authorization for that exact mailbox, even when an Entra administrator authorized the selected tenant for native sending; there is no tenant-wide warm-up shortcut. A compatible Google import uses its mailbox-scoped app password. A connected Google inbox without that credential uses separate owner sign-in: preview `oxygen mailboxes warmup google --mailboxes `, approve its fresh setup plan at `--max-credits 0`, open the returned link as that exact inbox, then poll with `--status`. The app's Enable Warmup button follows this Google sign-in flow. Authorization starts no warm-up and charges no credits. Then, for BYOK, imported, or opted-out inboxes:
```sh
oxygen mailboxes warmup enable --mailboxes ada@send-acme.com --json
oxygen mailboxes warmup enable --mailboxes ada@send-acme.com \
--approved --plan --max-credits
```
Both `--plan` and `--max-credits` must echo the fresh preview. The JSON field `plan_hash` supplies the value for the CLI flag `--plan`. A [pending enrollment hold](/docs/safety/billing#pending-warm-up-enrollment) is reserved credit, not a captured charge; its recovery preview reports existing and additional credits separately. In the app: the flame icon on a mailbox row (**Enable OXYGEN Warm-up**); the dialog quotes 4 weeks and confirms with **Approve <n> credits/month**, or **Start warm-up** when warm-up is included in the mailbox connection (`--max-credits 0`). Track it with `oxygen mailboxes warmup status --json`.
For read-only activity inspection, use `oxygen mailboxes get --json`.
The status refresh above persists state and may auto-pause a runaway mailbox.
An enabled warm-up or a missing graph is not proof of sending or zero sending:
see [warm-up activity and history troubleshooting](/docs/providers/mailboxes#missing-warm-up-history-or-enabled-without-sends).
Campaign ramp-up and warm-up are separate. A new inbox's campaign sending ramps up over actual days with accepted sends: by default 5/day with 0–2 completed UTC sending days, 10/day with 3–5, 20/day with 6–8, then the mailbox's daily campaign limit from 9 completed sending days onward (25/day by default, maximum 50/day). Idle days since import do not advance this ramp. Historical accepted sends count. `oxygen mailboxes get --json` exposes configured and effective limits under `effective_cap`, including the ramp's levels (`ramp_schedule`) and the sending day it reaches the daily limit (`full_cap_on_sending_day`); `oxygen limits show` reports technical limits.
Optional standard warm-up starts at 1/day, increases by 1/day and targets 10/day. Dedicated infrastructure retains its more restrictive domain-density profile. Warm-up settings remain configurable; OXYGEN Warm-up does not support the configured reply-rate percentage, which the panel and API report explicitly. Before launching, account for campaign plus known warm-up volume; Oxygen warns when that combined volume exceeds 50/day and cannot measure mail sent outside Oxygen. This combined-volume warning is separate from the 50/day maximum campaign cap per mailbox. These defaults do not guarantee inbox placement.
Click a mailbox address to open its panel — **OXYGEN Warm-up / Settings / Campaigns**. On **Settings**, set **Daily campaign limit** and **Ramp-up**: **Standard** (5, 10, then 20 a day), **Custom** (a starting volume plus an increase every few sending days, climbing to the daily limit), or **Off** for an inbox that already has a sending history elsewhere. The panel shows the resulting levels and the inbox's current sending day. The same settings from the CLI, or `oxygen_mailboxes_set_ramp` over MCP:
```sh
oxygen mailboxes cap set ada@send-acme.com --daily-cap 30
oxygen mailboxes ramp set ada@send-acme.com --start-per-day 5 --increase-every-days 2 --step 5
oxygen mailboxes ramp set ada@send-acme.com --off # full daily limit from the first sending day
oxygen mailboxes ramp set ada@send-acme.com --clear # back to the standard ramp
```
A custom ramp's optional `--cap` holds the inbox at that number for good, even when its daily limit is higher; leave it out to climb to the limit.
## Check before launching
Check recipient addresses separately from your sending mailboxes: [Email verification](/docs/providers/email-verification) explains the free preview, catch-all handling, provider availability and the credit ceiling needed for a live check.
```sh
oxygen mailboxes health --json # deliverability reputation per mailbox
oxygen mailboxes oauth-health --json
oxygen billing balance --json
```
If one inbox degrades, pull it from rotation without losing its warm-up: tick its checkbox and hit **Pause** in the selection bar, or `oxygen mailboxes status ada@send-acme.com --status paused`. Sequences pick from this pool at their **Senders** stage.
---
# First sequence
> Build a multichannel sequence, load leads without sending anything, then launch it behind a preview and a spend cap.
Source: https://oxygen-agent.com/docs/guides/first-sequence
A sequence is one journey per lead, mixing email, LinkedIn, WhatsApp, rep call tasks, and CRM tasks. Building it and enrolling leads spends nothing and sends nothing; only starting it dispatches.
## Attach a sender first
Sidebar → **Sequencer → Accounts** (`/sequencer/accounts`). Tabs: Senders, LinkedIn, Email, WhatsApp, Phone numbers.
- **Email** tab → **Add inboxes**
- **LinkedIn** tab → **Connect LinkedIn account**: the account becomes a sender on its own, named and pictured from its LinkedIn profile (or it joins the sender with the same name who has no LinkedIn account yet)
- **Senders** tab → **New sender** — one person's inboxes plus their LinkedIn and WhatsApp accounts as one sending identity.
`oxygen senders list --json` and `oxygen mailboxes list --json` show what is connected. `oxygen senders connect --country DE` mints a shareable hosted-auth link, valid 10 minutes; `--country` is the account owner's normal LinkedIn login country, not your target market.
## Build it in the app
Sidebar → **Sequencer** (`/sequencer`) → **New sequence** opens `/sequencer/sequences/`: an empty draft with four stages — **Leads → Senders → Sequence → Launch**. The **Next: …** button at the bottom moves through them.

**Leads.** **Import leads** offers **Upload a file** (CSV, JSON, JSONL, or XLSX), **Copy from a table**, or **HubSpot list**. Imported rows are deduped and enrolled automatically — there is no separate enroll button. On the toast *N leads imported but not enrolled — no LinkedIn URL*, open **Identifiers** beside the import button, map the LinkedIn column, and re-import.
**Senders.** **Add senders** chooses who this sequence sends from.
With several senders, Oxygen gives each lead one of those people: its LinkedIn steps come from that person's account and its emails from one of their inboxes, even while that account or inbox is at a limit or needs reconnection. To send one step from someone specific, open the step in **Sequence** → **Advanced** → **From**. On a **Send email** step you pick a person, whose inboxes then share that email across your leads (each lead keeps the same one), or one exact inbox; a change of From starts a new email thread, so give that step a subject. On a LinkedIn connection or message step, the person you pick sends every lead's connection request and messages (LinkedIn allows one of your accounts per conversation), while email still comes from each lead's own person. A profile visit, follow, like or comment can each come from anyone. The launch review lists the sender of every step.
**Sequence.** The canvas opens on **Sequence start**. Click the **+** between steps ("Add a step") and pick from the catalogue: **Send email**, **Reply email**, **Send invite**, **Send message**, **Send InMail**, **WhatsApp message**, **Call task**, **Create CRM task**, **Wait**, **Wait for signal**, **Branch on signal or data**. Copy fields interpolate `{{column}}` from the lead's row; use `{{column|fallback}}` where a value may be missing. `{{sender_first_name}}`, `{{sender_last_name}}` and `{{sender_full_name}}` fill in the person who sends that step, on every channel, with no table column; email steps also take `{{sender_email}}`. The `{{ }}` button beside a copy field inserts any of them.
{/* SCREENSHOT: /sequencer/sequences/:id?stage=sequence | the step catalogue popover open on the "+" inserter, showing the LinkedIn / Email / WhatsApp / Call / CRM / Timing / Logic groups */}
**Launch.** One **Sending schedule** (timezone, days, From/To) applies to every channel in the journey. **Sending limits** caps sends per day across every sender (blank for no limit, reset at UTC midnight; profile views and other reads don't count). **Unsubscribe** adds a visible link and one-click headers to first-touch emails. Details: [Sending schedule](/docs/execution/sequences#sending-schedule) and [Unsubscribe option](/docs/execution/sequences#unsubscribe-option).
## Build it from the CLI
```sh
oxygen sequences create --name "Q3 founders" --slug q3-founders \
--steps-file ./steps.json --table --json
```
`steps.json` holds `{ "steps": [...] }`, each step with its own `id`:
```json
{
"steps": [
{ "id": "s1", "channel": "email", "kind": "email_send",
"subject_template": "{{company}} + inbound",
"body_template": "Hi {{first_name|there}} — quick question." },
{ "id": "s2", "kind": "wait", "days": 3 },
{ "id": "s3", "channel": "email", "kind": "email_send",
"body_template": "Bumping this once, {{first_name}}." }
]
}
```
`s3` has no `subject_template`, so it continues the lead's previous email: it goes out as `Re: ` inside that thread, like a reply. Give a step its own `subject_template` to start a new email instead. The first email step always needs one.
To send one email from a person, set `sender_profile_id` on that `email_send` step to a selected sender profile's ID: each lead gets one of that person's inboxes and keeps it for every step naming them. For one exact inbox, set `sender_mailbox_id` to that inbox's ID instead (never both), and give the step a `subject_template`. For a LinkedIn step, set `sender_profile_id` to a selected sender profile's ID; on `invite`, `message`, `inmail` and `withdraw_invite` it must be the same on all of them (or absent). Select people with `--sender-profiles ` when creating or updating the sequence. `oxygen sequences start ` previews `sender_journey` before anything sends: every email and LinkedIn step with its sender, and for default steps the people a lead can be assigned. Contacts shows the lead's **Sender** and the **Last email From** separately; sequence analytics groups actual sends and attributed replies by inbox and step.
Enrolling is inert — no provider call, no credits, no message:
```sh
oxygen sequences enroll q3-founders --from-table --json
```
`--from-table` takes up to 500 not-yet-enrolled rows per run; re-run while `from_table.has_more` is `true`. For leads outside the bound table, pass `--leads-file` with `{ "leads": [{ "row_values": { "email": "…" }, "lead_name": "…" }] }`. Attach senders with `oxygen sequences update q3-founders --senders `.
Set when it sends and add an unsubscribe option:
```sh
oxygen sequences update q3-founders --schedule-timezone Europe/Berlin --schedule-days mon-fri \
--schedule-hours-start 09:00 --schedule-hours-end 17:00 --include-unsubscribe --json
```
The schedule applies to every channel; LinkedIn sends also stay within each LinkedIn account's working hours and are spread across them: an account's 20 daily invites go out 30–45 minutes apart, starting at a different time each day. `--include-unsubscribe` adds a visible link to first-touch emails (plain text shows the URL, HTML a linked **Unsubscribe**) and one-click headers that mail apps show as an Unsubscribe button. On MCP, use `sending_schedule` and `include_unsubscribe` on `oxygen_sequences_update`.
## Set the do-not-contact list before launching
Sidebar → **Sequencer → Do not contact** (`/sequencer/do-not-contact`). **Add entries** takes pasted people, emails, phones, or company identities; **Sync HubSpot** pulls in a saved list. Enrollment always enforces this list.
```sh
oxygen suppressions add --lead --reason manual
oxygen suppressions import --file ./dnc.txt --reason manual
oxygen suppressions addresses --json
```
`import` takes a mixed file of emails, bare domains, and LinkedIn URLs, up to 5000 entries. `--reason` is required when the file contains any domain — a domain block silences everyone at that company.
## Launch
No flags means preview only: it activates nothing and sends nothing.
```sh
oxygen sequences start q3-founders --json
```
Read `launch_readiness.blockers`, `sender_journey`, `copy_preview` (rendered LinkedIn/WhatsApp samples per lead), and the estimated credits. Email copy is not rendered in this check; use `sequences get` to inspect the saved email templates and unsubscribe settings before approval.
`--dry-run` activates the sequence in simulated mode: every step advances, with no provider call, CRM write, or credit. A later `--approved` start restarts those leads from the first step so they are contacted for real, except a lead whose source row was deleted, a person another live campaign contacts under `exclude_contacted`, and older duplicates of a person.
```sh
oxygen sequences start q3-founders --dry-run --json
```
**This command sends real messages to real people.**
```sh
oxygen sequences start q3-founders --approved --max-live-sends 200 --max-credits 5000 --json
```
`--max-live-sends` is a positive-integer ceiling on real external actions, **required** for any sequence with email, WhatsApp, or CRM-task steps — those cost 0 Oxygen credits, so `--max-credits` cannot bound them. Omitting it fails with `sequence_send_cap_required`. `--max-credits` bounds the LinkedIn track and is optional — omit it for an unbounded run. Every per-action LinkedIn charge is 0 credits today ([pricing reference](/docs/safety/pricing-reference)).
In the app the same gate is **Review & start** on the Launch stage: a dialog listing pending enrollments, estimated credits, rendered copy samples, and any blockers. **Start live** confirms, and stays disabled while a blocker is listed.
{/* SCREENSHOT: /sequencer/sequences/:id?stage=launch | the Review & start dialog with pending enrollments, estimated credits, a rendered copy sample, and the "Start live" button */}
It is hidden until the draft has at least one step and — for LinkedIn or WhatsApp — at least one sender; the CLI reports these as `sequence_no_steps` and `sequence_no_senders`.
## Watch it, pause it, or retire it
A reply stops that lead's enrollment automatically, on every channel — nothing to configure. To pause the replier's colleagues too, create the sequence with `--company-reply-pause default` (freemail domains are never company-matched); `oxygen sequences paused-companies` lists what is paused and `oxygen sequences resume-company` resumes it. To pause a company yourself — say, after a meeting is booked — run `oxygen sequences pause-company --domain acme.com`.
| What you want | Where |
|---|---|
| Funnel: enrolled, sent, replied, reply rate | `oxygen sequences stats q3-founders --json`, or **Analytics → Outreach** (`/analytics/outreach`) |
| Every send, failure, deferral, open, click, reply, bounce | `oxygen sequences events q3-founders --limit 50 --json` |
| Per-lead state and the last error | `oxygen sequences enrollments q3-founders --json` |
| The replies themselves | **Unibox** (`/unibox`) |
`oxygen sequences pause q3-founders` stops new dispatches without deleting the campaign; `oxygen sequences resume q3-founders` restarts them, and enrollments pick up where they left off. In the app: **Pause** while active, **Resume live** while paused.
To retire the Sequence permanently, preview the exact blast radius first, then approve that same deletion:
```sh
oxygen sequences delete q3-founders --json
oxygen sequences delete q3-founders --approved --json
```
The current CLI does not create new archived Sequences. Legacy archived rows remain readable and taggable, but new retirement uses pause for a reversible stop or the preview-first delete flow above for permanent removal.
---
# Handle replies
> Triage and answer every email, LinkedIn, and WhatsApp reply from one inbox — in the app or from the CLI.
Source: https://oxygen-agent.com/docs/guides/handle-replies
Replies to your sequences, plus LinkedIn and WhatsApp DMs, land in one place: **Unibox** in the sidebar under **Data**, at `/unibox`.
## Read the inbox
Three panes. Left: a rail with **Senders** (once two people in the workspace have sending accounts), **Channels** (an **All channels** row, then each channel down to the individual mailbox or account), **Replies** (on Primary), **Status**, and **Tags**. Middle: icon-only tabs — **Primary**, **All**, **Others**, **Sent**, **Warmup**, **DMARC** (hover for the name) — with **Mark all read** at the end of that row, over a full-width search field and the conversation rows. Right: the thread and the reply box. **Sync** in the top bar reloads the list and the open thread.
Primary shows sent and received conversations. Check **Unanswered** under **Replies** to keep only conversations whose last message is inbound; clear it to bring back threads you already answered. **Mark all read** counts what your filters match, asks to confirm, and says to run it again if more still match.
The view chip in the top bar (**Unibox › All conversations**) saves the current filters as a view your whole team can open. Star a view to make it the one `/unibox` opens for you.
{/* SCREENSHOT: /unibox | the three panes, with the icon-only segment tab strip hovered so the "Primary" tooltip is readable */}
The same list from the terminal:
```sh
oxygen inbox list --channel all --unanswered --json
oxygen inbox get --channel email
```
`list` defaults to the merged stream (every channel, interleaved) and narrows with `--channel`; `get` and `send` resolve a conversation's channel from the conversation itself when `--channel` is omitted. `status`, `tag`, `archive`, and `analyze` still default to email, so pass `--channel linkedin` or `--channel whatsapp` there for a DM thread. A search spans every non-warmup conversation — all channels, every folder except the Warmup and DMARC tabs, and message text — whichever tab it is typed on.
## Triage
Each row and each open thread carries a status pill. Click it for the picker: a search box, the label list, and **Create Label** at the bottom. The eight system labels are Interested, Neutral, Out of office, Wrong person, Not now, Not interested, Lost, and Bounced — the rail's **Status** section groups them under **Positive** / **Neutral** / **Negative**.
```sh
oxygen inbox labels list --json
oxygen inbox status interested --channel email
oxygen inbox tag --add "q3 outbound" --channel email
oxygen inbox archive --channel email
```
Setting a status by hand is an override — the AI classifier will not change it again. Tags cost 0 credits and are never shown to the counterpart; `oxygen tags list` shows the workspace vocabulary. `oxygen inbox tag` with neither `--add` nor `--remove` exits 1 with `Pass --add and/or --remove.`
Triage up to 100 conversations at once. Without `--yes` you get counts only:
```sh
oxygen inbox bulk --action set-status --ids , --status interested --channel email
oxygen inbox bulk --action set-status --ids , --status interested --channel email --yes
```
In the thread header, **Archive** works; **Forward** is disabled and its tooltip says forwarding ships with the inbox actions update.
## Reply
In the app, type into the composer at the bottom of the thread. Its footer names the mailbox you are sending from. Enter sends, Shift+Enter adds a line.
From the CLI, run it once without `--approved` — that returns a preview of exactly what would go out — then send:
```sh
oxygen inbox send --channel email --text "Thursday 10:00 works. Here is the link."
oxygen inbox send --channel email --text "Thursday 10:00 works. Here is the link." --approved
```
Sends cost 0 credits per message on all three channels. Connected senders have separate monthly costs: credit reservations when `sender_billing` is `credit_reservations`, or dollar sending seats in the legacy model. Check `oxygen billing estimate --json` for the workspace's model and current prices ([pricing reference](/docs/safety/pricing-reference#sending-seats)). The message still reaches a real person, so `--approved` is required.
When it fails: `mailbox_not_active` or `mailbox_not_sendable` means the mailbox that owns the conversation is paused or has no send transport — fix it under **Sequencer → Accounts**. `email_conversation_no_recipient` means the thread has no address to reply to. A LinkedIn send returning `unibox_stale: true` did send, it is only missing from the thread; run `oxygen inbox sync` (which pulls LinkedIn and WhatsApp — email is polled by the background worker).
## Let the agents take the first pass
Neither agent sends anything.
**AI Inbox Tagger** tags each new inbound conversation using only the allowlist you give it, additively, and never re-adds a tag you removed. It has no web form — set it from the CLI:
```sh
oxygen inbox auto-tagger set --enabled --tags "pricing,demo request,not now"
```
**AI Sales Agent** classifies replies and writes draft answers into a review queue — each draft it writes spends credits, so cap it. A human approves every one.
```sh
oxygen inbox reply-agent set --enabled --persona "Jonas, founder of Acme (dev-tools for CI caching)" --tone "warm, concise, low-pressure" --max-drafts-per-day 25
oxygen inbox drafts list --json
oxygen inbox drafts edit --text "Rewritten answer."
oxygen inbox drafts reject
oxygen inbox send --channel email --text "Rewritten answer." --draft-id --approved
```
Configuring is free. In the app, the **AI Sales Agent** link at the bottom of the Unibox rail opens `/agents/inbox-reply-drafts`: a **Configuration** card (Persona, Tone, Instructions, Signature, Draft for these statuses, Draft for these campaigns, Max drafts per day, **Save settings**) above a **Review queue** with **Approve & send**, **Edit**, and **Reject** on every draft.
{/* SCREENSHOT: /agents/inbox-reply-drafts | one queued draft showing the Approve & send / Edit / Reject buttons */}
## What a reply changes elsewhere
- The lead's sequence enrollment stops and its open steps are cancelled on every channel, before the next step can dispatch.
- If the campaign pauses the company on reply (**Launch → Reply handling**, or `oxygen sequences update --company-reply-pause default`), the replier's colleagues in that campaign are held at once. When the reply is classified, the pause stays if its category is one you chose and lifts on its own if not. Resume from **Sequencer → Do not contact → Paused companies** or `oxygen sequences resume-company`. To pause a company yourself, for example after a meeting is booked, run `oxygen sequences pause-company --domain acme.com`; unlike a do-not-contact entry, a pause can be resumed.
- A hard opt-out in the reply body sets the conversation to Not interested and suppresses that address, so the sequencer never emails it again (**Sequencer → Do not contact**).
- A timeline activity is logged on the matching CRM person, when that person already exists.
- Once classified, the reply emits the workspace event `crm.email_reply_classified`, which a workflow can trigger on.
## Search conversations and message bodies
`oxygen inbox list --search` is fuzzy — typos, word order and prefixes all match — and it always spans every non-warmup conversation: all channels, archived and sent-only threads included, matching names, addresses, subjects and the text of every message in both directions. The folder, `--unanswered` and the Primary tab's negative-tier exclusion are ignored while a term is set; explicit facets such as `--status` still narrow. Conversations come back newest first:
```sh
oxygen inbox list --search "sandra prak" --json
```
For a relevance-ranked, message-level read across every channel:
```sh
oxygen messages query -q "pricing" --channel all --since 2026-07-01 --json
```
---
# Track 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.
Source: https://oxygen-agent.com/docs/guides/crm-records
The CRM holds one canonical row per company, person, and deal, each with identities, an owner, a stage, and a timeline.
## Records are truth, Tables are work
A [table](/docs/data/tables) builds and enriches a list: a TAM pull, a CSV, a scrape. A record is that entity deduped, addressed by identity — companies by `domain`, people by `email`, deals by `deal_key`. They connect one way: bind rows to records, then promote the columns worth keeping.
```sh
# 1. Resolve each row to a CRM record. Free. In the app: "Add column" → "Bind to CRM record".
oxygen columns add my-leads --label "CRM person" --bind-object people --bind-map email=work_email
oxygen columns run my-leads crm_person --limit 25
# 2. Preview which record fields would change. Free, writes nothing.
oxygen tables promote my-leads --object people --map job_title=job_title,seniority=seniority
# 3. The same command plus --approved writes them onto the records.
```
`columns add` prints the key it derived from the label — pass that to `columns run`. `promote` defaults to `--policy fill-empty-only` (also `overwrite`, `skip-conflicts`), never touches identity or system attributes, and queues a background run you follow with `oxygen table-runs wait `.
### Work a Records view in a table
The other direction copies records into a table to work them: a whole object or one saved view, once or kept in sync. In the app: **New table → Import from Records**.
```sh
oxygen tables records import --object deals --view "Open deals" --dry-run # free: record count and columns
oxygen tables records import --object deals --view "Open deals" --refresh sync --every daily@6 --approved
oxygen tables records status # last sync and schedule
```
The copy is one way and costs 0 credits; a kept-in-sync table bills one [workflow step](/docs/safety/billing#workflow-steps) per scheduled sync. Records never change; rows are keyed by `record_id`. On each sync, changed record values update the table, but a cell you edited in the table and any column you added stay as they are. A record that leaves the view keeps its row with `in_records` set to false, so nothing you worked on disappears. `oxygen tables records sync --refresh once` stops the schedule. MCP: `oxygen_tables_records_import`, `oxygen_tables_records_sync`, `oxygen_tables_records_status`.
## Set up the objects
Sidebar **Data → CRM**; each object is a child: Companies, People, Deals, plus any custom object. **Data model** (`/crm/objects`) sits under them and is where the workspace's objects are listed, created and read: what each one records, which field makes two records the same, and how they link. An empty workspace lands on **No CRM objects yet**.
```sh
oxygen crm setup # dry run: what it would create or repair
oxygen crm setup --live # creates companies, people, deals
```
Most `crm` writes preview first and need `--live`: `setup`, `assert`, `activity log|note`, `objects create|delete|add-attr|update-attr|remove-attr`, `relationships define|upsert`, `merge`, `automation set`, and `sync import|configure|run`. `crm tag`, `crm keep`, every `enrichment` verb, and `sync enable|disable` write on the spot. Check any command's own `--help` before running it.
Custom objects come from **Data model → New object** (`/crm/objects/new`) or `oxygen crm objects create --slug projects --display-name Projects --columns-json '[…]' --live`. `oxygen crm objects` lists what exists, and `/crm/objects/` shows one object's fields, identities and links.
Two slug groups are reserved. `companies`, `people`, `deals`, `lists` and `activities` belong to standard objects and the engines behind them; `objects`, `automation`, `calls` and `new` are fixed `/crm/*` routes, and an object named after one would be shadowed by the page of the same name.
Adding a field to an object you already have — including Companies, People and Deals — is **Settings → CRM Data Model → the object → Add field**, or `oxygen crm objects add-attr --column-json '{…}' --live`. A field you add belongs to the workspace and survives later `crm setup` runs.
Changing a field is the same page: click its row to rename it, make it required or optional, change a select or status field's choices, or remove it. On the terminal that is `oxygen crm objects update-attr --name "…" | --required | --no-required | --options-json '[…]' --live` and `oxygen crm objects remove-attr --live`. The field's key never changes, so anything that reads it by key keeps working. A removed field's column is archived rather than dropped and its key is free again immediately; `oxygen columns restore` brings it back as the same field. `oxygen crm describe --field ` reads one field on its own. What Oxygen ships on a standard object keeps its key, type and required flag and cannot be removed, but its name and its choices — the deal pipeline, the lead stages — are yours to shape.
An identity is what makes two records the same one — it is what stops a re-import creating a second copy of the same company. Each identity names a column plus how its value is compared: `email_v1`, `domain_v1`, `linkedin_url_v1`, `exact_text_v1` or `uuid_v1`. These are not the short `exact`/`email`/`domain` spellings that `--lookup-normalize` takes on a Table column. At most one identity per object is primary.
A select or status column carries its choices at create time, in the column's own `options` array alongside `option_model_type` (`status`, `single_select` or `multi_select`) — not in a `metadata` block, which is part of what `crm describe` reports back rather than something create accepts:
```json
{ "key": "status", "label": "Status", "data_type": "text", "semantic_type": "status",
"option_model_type": "status",
"options": [{ "value": "prospect", "label": "Prospect" }, { "value": "active", "label": "Active" }] }
```
## Sample records
A new workspace starts with Companies, People and Deals already holding sample records, so every view has something to show: five well-known companies (Stripe, Vercel, OpenAI, Anthropic, Notion), their CEOs, and eight `sample-` deals across the pipeline. The sample people can never be reached: their emails use the reserved `.example` domain, their phone numbers are fictional, and their LinkedIn profiles are on your do-not-contact list.
Samples always say they are samples:
- **Reads mark them.** Rows from `crm get`, `crm search`, `tables query` and `tables preview` carry `_sample: true`; `crm search --suggest` hits and `crm pipeline` deals carry `sample: true`. The record page shows a **Sample** badge.
- **Totals leave them out, and say so.** `crm pipeline` drops samples from stage counts, amounts and `totals` and reports them under `samples`. Dashboard summaries report `caveats.sampleRecordsExcluded` for the funnel, lifecycle and cold-deal numbers, a chart over a CRM object reports `sampleRecordsExcluded`, and the pipeline dashboard, the Command Center and chart cards add a line such as "Leaves out 8 sample deals."
When a sample turns out to be real, keep it. Its marker clears and it counts like any other record:
```sh
oxygen crm pipeline --json # sample deals carry "sample": true and their row id
oxygen crm keep deals # keep one deal as real
oxygen crm keep companies stripe.com # an identity value works too
```
`crm keep` writes immediately. It is free, cannot be undone, and changes nothing on a record that is already real. It keeps that one record only: a kept deal's company and contact stay samples until you keep each of them. Agents call `oxygen_crm_record_keep` over MCP (through `oxygen_capabilities_call` when their connector does not list it), the record page has **Keep as real**, and the Copilot asks you before it keeps one.
## Work a record
`/crm/deals` opens on a seeded board view named **Pipeline**, grouped by Stage: Lead → In Progress → Won / Lost. Drag a card to move the deal. The stage set is workspace-editable, so a team that wants a longer ladder adds its own.
Switch to the table view and a deal opens on six fields — **Deal Name**, **Stage**, **Deal Owner**, **Associated People**, **Associated Company**, **Created at**. Everything else it carries (amount, priority, close date, source, the buying committee, tags) is one click away in the column menu, and `oxygen crm describe deals --json` names the opening set as `openingGrid` so an agent can read it too.
Any cell opens the account view: the record's attributes on the left and, on the right, **Activity**, **Inbox** / **Sequences** where the object has them, **Notes**, **Tasks** and **Files**. The stage cell opens its picker in place instead.
**Notes** are the record's own notes — written in the same markdown editor as a markdown field, pinnable, editable, and mirrored onto the timeline. **Tasks** are the reminders filed on the record (a title, an optional owner, deadline and priority), grouped **To do** / **Done**. **Files** are what the customer sent you, attached to the record. Every one of them is free and internal: no preview, no approval. **CRM → Tasks** (`/crm/tasks`) is the same list across the whole workspace — every open reminder, which record it is about, its owner and deadline — with a **Mine** filter.

From the CLI:
```sh
oxygen crm search "acme.com" --object companies
oxygen crm get companies --json
oxygen crm assert companies --identity domain=acme.com --values-json '{"lifecycle_stage":"customer"}' --live
oxygen crm activity note companies "Intro call booked" --live
oxygen crm activity log deals --type meeting_booked --summary "Demo with CTO" --live
oxygen crm activity timeline companies acme.com
oxygen crm tag companies --add tier-1
oxygen crm pipeline --pipeline sales
oxygen crm notes add companies "They want a pilot with 3 seats; decision maker is the Head of RevOps"
oxygen crm tasks add companies "Send the deck" --due 2026-09-25 --priority high --assignee you@company.com
oxygen crm tasks list # every open reminder in the workspace, with its record
oxygen crm tasks list --assignee me # just yours
oxygen crm tasks complete
oxygen crm files attach companies ./proposal.pdf
```
`search` takes exactly one query — narrow it with `--object`, never a second argument. `timeline` accepts a row id *or* an identity value (`acme.com`, `sarah@acme.com`); a miss returns `crm_record_not_found` naming what to pass instead. `crm tag` writes deltas (`--add` unions, `--remove` subtracts) against the same [tag](/docs/workspace/tags) vocabulary as sequences and conversations, and needs the `tags` attribute `crm setup` adds.
For a large record, `oxygen crm get companies --projection compact --max-chars 10000 --json` leaves out the object's field configuration and names any omitted cells in `omitted_row_fields`. MCP record reads use this compact window by default. The result's `detail` points to the Table row inspector, where `projection=value` retrieves a complete cell in resumable windows; retained values are never shortened. An ordinary CLI read keeps the full result.
A live `crm assert` fires the object's standing automatic enrichment on the record it wrote, spending credits up to that object's per-batch ceiling. Run `oxygen crm enrichment list` first to see what is armed.
## Automatic enrichment (paid)
Every CRM grid's top bar carries the enrichment popover, headed **New records added to Companies are enriched automatically.** It lists each preset's per-record credit cost, the per-batch ceiling, and **Backfill existing records** with an **Enrich … now** button and **Enrich all**.
```sh
oxygen crm enrichment list --object companies # armed presets, cost per record, ceiling, how many records were never enriched. Free.
oxygen crm enrichment enable company_linkedin_profile --object companies
oxygen crm enrichment backfill --object companies # free preview: one batch's cost, and the cost to finish
oxygen crm enrichment backfill --object companies --limit 200 --live --approved --max-credits 2000
```
Arming covers only records written after it, so existing records stay blank until you backfill. `crm setup` arms the default presets on objects it creates; `crm setup --with-enrichment` arms them on objects that already existed. When your plan runs fewer columns per record than the defaults, setup arms the ones that fit and lists the rest under `autoRunColumnsOverLimit`. A live batch without `--approved` fails with `approval_required` (exit 7). Records past `--max-credits` are skipped with `credit_limit_reached` — the preview says how many. `oxygen crm enrichment off --object companies` clears the configuration entirely.
## Merge duplicates
`/crm/companies/duplicates` (no sidebar entry yet — type the URL) ranks candidate pairs. **Review merge** opens the field-level diff, **Confirm merge** writes it.
```sh
oxygen crm duplicates companies --limit 25
oxygen crm merge companies # dry run: field diff + relink plan
oxygen crm merge companies --live --confirm
```
The survivor keeps its values, the loser fills its blanks and is tombstoned with its links moved over. `--live` without `--confirm` refuses: *"crm merge --live requires --confirm after inspecting the dry-run field diff."*
## Standing automations
`/crm/automation` lists the templates that advance a record when a reply, meeting, or signup arrives — `crm-lead-stage-router`, `crm-meeting-booked`, `crm-signup-to-person` — each badged **Armed** or **Disarmed** with a toggle. The lead-stage router arms itself the first time a sequence goes live; once disarmed, nothing re-arms it but you.
```sh
oxygen crm automation rules
oxygen crm automation set crm-meeting-booked --armed --live --approved --max-credits 1 # drop --live to preview it first
oxygen crm automation audit --limit 20
```
An armed rule is a standing permission for free internal CRM writes; `--max-credits` is the ceiling per event delivery.
## Two-way sync with HubSpot or Attio
Connect the provider under **External → Connections**, then:
```sh
oxygen crm sync import hubspot --object contacts --into people # dry run
oxygen crm sync configure --provider hubspot --object contacts --direction bidirectional # dry run of the next cycle
oxygen crm sync enable --provider hubspot --object contacts --approved --max-rows 500 --max-credits 1000
```
`sync enable` is always live: it arms the cron trigger and the standing write permission, then runs a first cycle. Inbound previews and every cycle read through your own provider credentials, consuming your CRM's API quota. Details in [Integrations](/docs/providers/integrations).
### Importing one HubSpot saved list instead of a whole object
`crm sync import` pulls **every** record in an object into Records. It has no
list or segment filter. To bring **one HubSpot saved list** in as rows you can
filter and enrich, import it into a table instead:
```sh
oxygen tables hubspot lists # the portal's saved lists; free
oxygen tables hubspot import --list --dnc-list # free preview, returns a fingerprint
oxygen tables hubspot import --list --dnc-list \
--live --approved --reviewed-fingerprint
```
Choose by destination: **Records** for canonical truth about every contact, a
**Table** for one segment you want to work. The table path also imports a
do-not-contact list — any list passed as `--dnc-list` is synchronised into your
suppression ledger *before a single row is written*, and if that snapshot fails
no row lands. Suppression is additive: removing someone from the HubSpot list
never un-suppresses them in Oxygen. Importing with no DNC list is allowed but
must be deliberate (`--no-dnc`). Oxygen suppresses from a saved **list** only —
a HubSpot opt-out property such as `hs_email_optout` is not a supported source.
---
# CLI
> Install, authenticate, discover commands, and read the `oxygen` output envelope.
Source: https://oxygen-agent.com/docs/surfaces/cli
## 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 --json` for exact grammar. Start discovery with `oxygen commands search --json`.
Raw `oxygen tables query --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 ` 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](/docs/surfaces/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
```sh
npm install -g @oxygen-agent/cli
oxygen login
oxygen status --json
```
`oxygen 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.
```sh
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-auto
```
Automatic 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@`), 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 ` 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):
```sh
oxygen api-keys create --name "automation key" --json
oxygen auth use-token --token --json
```
`oxygen` talks to `https://oxygen-agent.com`. `oxygen-dev` targets the Oxygen dev deployment and is not for customer workspaces.
## Profiles and organizations
```sh
oxygen profiles list --json
oxygen profiles use --json
oxygen orgs list --json
oxygen orgs use --json
oxygen whoami --json
```
A 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:
```sh
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" --json
```
The 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:
```sh
oxygen skills search "host a deterministic signup workflow" --json
oxygen skills get --json
oxygen tools search "public LinkedIn post engagers" --json
oxygen tools get --json
```
Provider operations are not CLI commands — they are the units a tool column or `oxygen tools run` invokes, listed in the [provider reference](/docs/providers/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:
```json
{
"ok": true,
"data": {
"web_url": "https://oxygen-agent.com/workspaces//tables/"
},
"meta": {
"command": "tables preview",
"version": "",
"minimum_cli_version": ""
}
}
```
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](/docs/surfaces/web). 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.
```sh
oxygen tools run --input-json '{...}' --mode dry-run --json
oxygen tools run --input-json '{...}' --mode live --approved --max-credits 5 --json
```
`--max-credits` is a ceiling, not a charge: unused reserved credits are released. See [Approvals](/docs/safety/approvals) for what each action requires, and check what a run actually cost with:
```sh
oxygen billing balance --json
oxygen billing usage --limit 50 --json
```
---
# CLI command reference
> Every public oxygen command, generated from the CLI's own command tree.
Source: https://oxygen-agent.com/docs/surfaces/cli-reference
Every released public command the `oxygen` CLI registers — over 1,100 commands across 101 groups — generated from the CLI's own self-index (`oxygen commands --json`, which returns the exact total for the version you have installed). Hidden compatibility commands and unreleased internal pilots are omitted from this public reference. Run `oxygen commands get "" --json` for one public command's full description, arguments, and flags.
Markers in **Notes**:
| Marker | Meaning |
| --- | --- |
| `paid` | Some invocation mode spends credits or performs an approval-gated external write. |
| `writes` | Mutates workspace, provider, or account state. |
| `staff` | OXYGEN staff only; a customer identity is refused. |
| `deprecated` | Retired, removed, or superseded — kept listed so the replacement is discoverable. |
| `alias` | A second spelling of another command. |
A blank **Notes** cell means the command is read-only and free.
## action-column
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen action-column add-provider` | Add a catalog-backed provider action picker column to a workspace table. | `writes` |
## activation
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen activation checklist` | Read this workspace's getting-started checklist: leads in a table, a first sequence, a connected sending account and a launched sequence, each with whether it is done and a link to do it; eligible… | |
## admin
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen admin automation-usage divergences` | List every automation-usage window whose counter and event ledger disagree, including windows that have outlived the detector's lookback and can only be cleared by a repair. | `staff` |
| `oxygen admin automation-usage reconcile` | Write the one audited adjustment that closes a window's counter/ledger divergence. | `writes` `staff` |
| `oxygen admin costs` | Show provider costs (COGS) per workspace. Staff only. | `staff` |
| `oxygen admin directory delist` | Remove an organization's listing from the public directory (kill switch). | `writes` `staff` |
| `oxygen admin directory enable` | Invite an organization to the directory, optionally prefilling its profile. | `writes` `staff` |
| `oxygen admin directory list` | List every agency directory listing across all organizations. | `staff` |
| `oxygen admin egress` | Read-only Fly email-egress overview: shared IP, dedicated workspace apps and IPs, liveness, image drift, billing, and stuck orders. OXYGEN staff only. | `staff` |
| `oxygen admin kpis` | Show the company conversion funnel (visitors → signups → activation on any surface, web, CLI or MCP → paid, with step rates and agent connected beside it), self-reported signup-channel… | `staff` |
| `oxygen admin lead-magnets get` | Show one lead magnet (resource) by slug: every field, draft or published, and its public /resources URL. Staff only, read-only. | `staff` |
| `oxygen admin lead-magnets list` | List every lead magnet (resource) on /resources, drafts included, with status and public URL. Staff only, read-only. | `staff` |
| `oxygen admin lead-magnets unpublish` | Unpublish a lead magnet (resource): set it to draft, which removes it and its page from /resources and keeps its email records. Dry run by default; --live applies it. Staff only. | `writes` `staff` |
| `oxygen admin lead-magnets upsert` | Publish or update the lead magnet (resource) at a slug on /resources from a resource JSON file and/or flags; --cover uploads a local image. | `writes` `staff` |
| `oxygen admin price-book list` | List every pricing-book row with its stored value, what charging bills now, the committed default, and who reads it. Read-only. | `staff` |
| `oxygen admin price-book restore` | Put a pricing-book row back to its committed default. For a plan, --field restores one allowance field; without it all three are restored. | `writes` `staff` |
| `oxygen admin price-book set` | Set one editable pricing-book field. | `writes` `staff` |
| `oxygen admin primary-providers` | Provider board: primary managed data providers, inference, fallbacks, conditional companions and product services with default/conditional/legacy selection and required configuration. | `staff` |
| `oxygen admin spend` | Global managed-provider spend limiter: burn, ceilings, breakers. Staff only. | `staff` |
| `oxygen admin spend halt` | Force a breaker OPEN — the platform kill switch for managed provider spend. --scope managed_credit --key <provider> benches Oxygen's managed account for one provider (the same bench a vendor 402… | `staff` |
| `oxygen admin spend resume` | Close a breaker and clear its backoff, resuming managed provider spend. | `writes` `staff` |
| `oxygen admin spend set-limit` | Set a ceiling for one scope + window. action=warn meters only; block arms it. | `writes` `staff` |
## ads
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen ads searches delete` | Archive a saved search; hide it from lists and tag footprints. | `writes` |
| `oxygen ads searches get` | Read one saved Ads search definition without running it. | |
| `oxygen ads searches list` | List saved Ads search definitions, optionally filtered by tag. | |
| `oxygen ads searches save` | Save a named Ads search query for 0 credits; no provider call. | `writes` |
| `oxygen ads searches update` | Replace a saved search's name or query; keep its tags. No provider call. | `writes` |
## agent
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen agent approval-decide` | Approve or reject one pending Workspace or custom Agent tool call, then resume its durable run. | |
| `oxygen agent cancel` | Request cancellation of an active Workspace or custom Agent run. | `writes` |
| `oxygen agent create` | Create a custom Agent and publish its first immutable version. This internal configuration write starts no chat/run and spends no credits. | `writes` |
| `oxygen agent custom` | List the org's user-defined custom agents (distinct from `agent list`, which shows the built-in roster). | |
| `oxygen agent delete` | Archive a custom agent (soft delete): its triggers stop firing and it leaves the roster; versions/runs are preserved. | `writes` |
| `oxygen agent disable` | Disable a workspace or specialist agent so it stops new runs on the next worker tick. | `writes` |
| `oxygen agent enable` | Enable a workspace or specialist agent so it resumes its governed runs. | `writes` |
| `oxygen agent file-create` | Store a tenant-owned text file for Agent context and sandbox input. | `writes` |
| `oxygen agent files` | List tenant-owned Agent context files. | |
| `oxygen agent get` | Show one agent — the Workspace Agent, a specialist, or a custom agent — with its active version and recent runs. | |
| `oxygen agent list` | List the Workspace Agent and built-in specialists with state and recent run history. | |
| `oxygen agent run` | Start a durable chat/run for the Workspace Agent or a custom Agent on the Fly worker. | `paid` `writes` |
| `oxygen agent run-get` | Inspect one Workspace or custom Agent run and its append-only event ledger. | `writes` |
| `oxygen agent runs` | List recent runs across all agents (or one via <slug>), newest first. | |
| `oxygen agent session activate` | Approve the exact preview revision and activate scoped standing authority. | `paid` `writes` |
| `oxygen agent session archive` | Archive this ongoing session, retaining conversation and run history. | `writes` |
| `oxygen agent session complete` | Complete this ongoing session, retaining conversation and run history. | `writes` |
| `oxygen agent session configure` | Replace settings at the expected revision. Clears standing authority and pauses active work; review again before activation. | `writes` |
| `oxygen agent session create` | Create a draft ongoing session. Explicit caps are required; review and activate separately. | `writes` |
| `oxygen agent session get` | Read this session's configuration revision, conversation, memory, next check, approvals and budget reservations. | |
| `oxygen agent session list` | List independent ongoing sessions under an Agent, including status, next check and spend. | |
| `oxygen agent session message` | Queue durable human steering. Draft chat proposes settings for review; active chat resumes the same memory. A bounded run reserves the approved per-run cap. | `paid` `writes` |
| `oxygen agent session pause` | Pause this ongoing session, retaining conversation and run history. | `writes` |
| `oxygen agent session preview` | Preview the exact pinned Agent version, resource scope, actions, schedule and caps. Returns the revision and approval token; starts no inference. | `writes` |
| `oxygen agent session resume` | Resume this ongoing session. Requires unchanged approved settings. | `paid` `writes` |
| `oxygen agent session run` | Run this active session's next check now, within its approved caps. Refused while a check runs or a cap is reached. | `paid` `writes` |
| `oxygen agent session templates` | Discover eight ongoing Agent job templates, reviewed actions, required resources, the full config schema and a draft example. Staff on dev only; legacy Agents remain available. | |
| `oxygen agent session webhook` | Create this session's webhook or rotate its secret (returned once); remove deletes it. A delivery wakes the active session within its caps; its external writes then ask first. | `writes` |
| `oxygen agent set` | Publish an immutable version (reconfigure) for a runtime agent: the Workspace Agent or a custom agent. | `writes` |
| `oxygen agent trigger-create` | Create a cron, internal event, or signed-webhook trigger for the Workspace Agent. | `paid` |
| `oxygen agent trigger-set` | Activate, pause, or archive one Workspace Agent trigger. | |
| `oxygen agent triggers` | List Workspace Agent cron, internal event, and webhook triggers. A legacy cron held to the plan minimum includes slowed_to_plan_minimum and its next run time. | |
## api-keys
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen api-keys create` | Create a CLI API key. The token is shown once. | `writes` |
| `oxygen api-keys list` | List active CLI API keys for the current user and organization. | |
| `oxygen api-keys revoke` | Revoke a CLI API key for the current user and organization. | `writes` |
## approvals
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen approvals cancel` | Withdraw a pending request you filed (or, as an admin, clear a stale one). | `writes` |
| `oxygen approvals client grant` | Restrict a member to the client role. | `writes` |
| `oxygen approvals client list` | Every member of this workspace and what they may do — the workspace role plus the Oxygen client overlay — followed by anyone invited who has not joined yet, and what they will land as. | |
| `oxygen approvals client revoke` | Clear the client role and restore full workspace access. Works on a pending invitation too, clearing what that address would land as. | `writes` |
| `oxygen approvals decide` | Answer a pending request. | `writes` |
| `oxygen approvals gate list` | Which gates this workspace requires. | |
| `oxygen approvals gate set` | Require (or stop requiring) an approval before the live action. | `writes` |
| `oxygen approvals inbox` | What is waiting on YOU: pending approvals assigned to you plus open threads that name you, each with the command that answers it. This is the surface a client logs in to. | |
| `oxygen approvals list` | Approval requests in this workspace, newest first. Use --mine for the ones assigned to you, or `approvals inbox` for the daily view. | |
| `oxygen approvals request` | Ask a named second party to decide. | `writes` |
| `oxygen approvals show` | One approval request by its own id: what is being asked, on what, by whom, who must decide, and whether it can still be decided at all. | |
## auth
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen auth doctor` | Diagnose the active Oxygen CLI credentials without printing token material. | |
| `oxygen auth use-token` | Store a CLI API token non-interactively. | `writes` |
## billing
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen billing activate` | Activate a trial subscription now and charge its saved payment method; administrator approval is required. An optional tier reprices the active trial in the same call. | `paid` `writes` |
| `oxygen billing allowance` | Show this billing cycle's credit pool as one breakdown: fixed spend, flexible spend, credits committed to the next renewal, and what is free to spend — the numbers behind the bar on the… | `writes` |
| `oxygen billing allowance view` | Inspect the current-cycle allowance, billing owner and partner-bonus eligibility; due plan grants or credit expiry may apply. 0 credits; reserves nothing. | `writes` |
| `oxygen billing audit` | Summarize where managed credits were granted, reserved, captured, released, or spent. | `writes` |
| `oxygen billing balance` | May apply due plan grants or credit expiry. | `writes` |
| `oxygen billing cancel` | Turn off subscription renewal. | `writes` |
| `oxygen billing change` | Create an approval link (`approval_url`) to start or change a plan; no charge or plan change until confirmation. | `writes` |
| `oxygen billing checkout` | Open browser Checkout; payment approves purchase. First purchase: admin/owner. New yearly plans use interval month, term year and the current terms_version. | `writes` |
| `oxygen billing commitments` | List recurring commitments, or inspect monthly connection prices and first-debit timing with --view connection-prices without creating authorization. | |
| `oxygen billing commitments view` | Read the complete fixed-credit commitment view and linked billing-owner display, without enumerating a child's sibling resources. | |
| `oxygen billing confirm` | Confirm a plan-change preview within 15 minutes; approved accepts payment, term and effective date. Unrestricted members allowed; restricted clients denied. | `paid` `writes` |
| `oxygen billing estimate` | Quote prospective enrichment, senders, X/WhatsApp, EmailGuard tests and an unsaved Workflow without provider calls, writes or reservations. | |
| `oxygen billing grant` | Grant managed credits to the current organization (staff only). | `writes` `staff` |
| `oxygen billing invoices` | List every invoice Stripe has issued for this workspace, newest first, each with a direct PDF link. | |
| `oxygen billing invoices view` | Read the browser invoice-history projection, including exact native timestamps, amounts and signed Stripe invoice links. | |
| `oxygen billing ownership clear` | Restore this workspace's own billing ownership after the same administrator checks as the browser. | `writes` |
| `oxygen billing ownership get` | Read the active workspace's shared billing owner, candidate owners and credit cap. | |
| `oxygen billing ownership set` | Set the billing owner and optional monthly credit cap using the browser's administrator and workspace eligibility checks. | `writes` |
| `oxygen billing portal` | Create a Stripe billing-portal URL. Unrestricted members allowed; restricted clients denied. | `writes` |
| `oxygen billing reconcile-paid-period` | Find active subscriptions whose current billing period was paid in Stripe but never had its plan credits minted, and restore them (staff only). | `writes` `staff` |
| `oxygen billing resume` | Remove a scheduled cancellation so the subscription renews (or the trial converts) normally. Free (no fee, no credits). Prints the next charge date and amount. | `writes` |
| `oxygen billing retain` | Stay subscribed with the one-month retention discount from billing retention-offer. Restores renewal if cancellation was scheduled. No charge today; the normal price returns afterwards. | `writes` |
| `oxygen billing retention-offer` | Preview a one-month discount before cancelling your monthly subscription. Reports eligibility, the next invoice price and normal price. Reads only; no discount is applied. | |
| `oxygen billing seats` | Show sending seats, current billing-period end and next-connection eligibility (null: unknown, with a reason). | `writes` |
| `oxygen billing seats set` | Manage legacy dollar sending seats for one channel; check `billing seats` for retirement status. | `writes` |
| `oxygen billing set-plan` | Create or update an off-Stripe custom plan for an organization (staff only). | `writes` `staff` |
| `oxygen billing summary` | Read wallet, plan, partner-bonus eligibility/timing and billing owner without grants. | |
| `oxygen billing topup` | No amount: read-only price quote, no checkout. | `writes` |
| `oxygen billing usage` | Credit-ledger and BYOK views may apply due plan grants or credit expiry. 0 credits. | `writes` |
| `oxygen billing usage view` | Credit spend over 7, 30 or 90 days by category and provider, each with its share, plus permitted linked-workspace rollups. totalSpent is reserved minus released; billing usage managed_credits_used… | |
## blueprints
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen blueprints apply` | Apply a blueprint: 0 credits and no provider calls or external writes, but creates workspace tables, columns, prompts, and a disabled workflow. | `writes` |
| `oxygen blueprints archive` | Archive a saved blueprint (seed blueprints cannot be archived). | `writes` |
| `oxygen blueprints describe` | Describe one blueprint (seed or saved) by slug. The workflow's compiled bundle is left out (its size and sha256 are listed) unless --include-bundle is passed. | |
| `oxygen blueprints export` | Build a portable blueprint JSON from an existing workflow. | |
| `oxygen blueprints list` | List Oxygen blueprints visible in this workspace (seeds + saved). | |
| `oxygen blueprints marketplace` | Browse the public Oxygen blueprint marketplace. | |
| `oxygen blueprints preflight` | Preflight a blueprint (slug, local file, or shared URL) against this workspace. | |
| `oxygen blueprints publish` | List a blueprint on the public Oxygen marketplace. Auto-creates a share URL if none exists. | `paid` `writes` |
| `oxygen blueprints save` | Persist a blueprint envelope into this workspace's gallery. | `writes` |
| `oxygen blueprints share` | Create a public share URL for a saved blueprint (oxygen-agent.com/b/<code>). | `writes` |
| `oxygen blueprints shares` | List existing share URLs for this workspace. | |
| `oxygen blueprints tag` | Replace a saved blueprint's workspace tags (whole set; `--tags ""` clears). Works on already-saved blueprints — no re-export needed. See `oxygen tags list` for the vocabulary. | `writes` |
| `oxygen blueprints unpublish` | Remove a blueprint from the public marketplace. The share URL stays valid for direct visitors. | `writes` |
| `oxygen blueprints unshare` | Revoke a public share URL by short code. | `writes` |
## budget
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen budget delete` | Delete a standing budget policy by id. | `writes` |
| `oxygen budget list` | Read-only, 0 credits. | |
| `oxygen budget set` | Set, raise, or lower a standing credit cap (idempotent per scope+window). Daily/monthly windows start at 00:00 UTC and count reservations minus releases; inspect current use with `oxygen budget list`. | `paid` `writes` |
## callables
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen callables bind` | Add a callable-function column to a source table with explicit input and callback mappings. | `paid` `writes` |
| `oxygen callables describe` | Describe a callable's typed input/output contract and pinned backing columns. | |
| `oxygen callables disable` | Disable new invocations without changing existing tables or in-flight runs. | `writes` |
| `oxygen callables enable` | Enable a callable table. | `writes` |
| `oxygen callables list` | List published callable tables and their current credit posture. | |
| `oxygen callables publish` | Publish an existing table as a versioned callable function. | `paid` `writes` |
## capabilities
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen capabilities get` | Hydrate one exact capability card by id. | |
| `oxygen capabilities search` | Find the owning capability, boundary, gateways, and next hydration step. | |
## cells
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen cells history` | Show cell change history. | |
| `oxygen cells inspect` | Inspect one cell's value, row context, and recent history. | |
| `oxygen cells resolve` | Record what a human verified about a cell whose external write was dispatched but never confirmed. | `writes` |
## columns
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen columns add` | Add a nullable column, a catalog template (--prompt-key) or a multi-column enrichment bundle (--preset) to a workspace table. | `writes` |
| `oxygen columns archive` | Archive a workspace column without dropping physical data. Hides it indefinitely with no purge timer; for cleanup with a restorable deadline use `columns delete`. | `writes` |
| `oxygen columns catalog` | List column templates and native Classify; multi-column enrichment bundles (presets such as person_enrich and company_enrich) are listed by `oxygen enrichment catalog`. | |
| `oxygen columns convert` | Convert a column between an AI column and a Web Research Agent column (--to agent or --to ai), or switch an agent to Keyword search and back. | `writes` |
| `oxygen columns create` | Create a Table column at an optional zero-based position; type is a field type, and a choice type takes options (cells store each value). | `writes` |
| `oxygen columns delete` | Delete workspace columns: archives now, frees the key for reuse, and schedules the physical purge (default 14 days; restorable via `columns restore` until then). --now purges immediately and… | `writes` |
| `oxygen columns deps` | Show the column dependency graph: which columns feed which (formulas, input mappings, run conditions, waterfall targets), transitive up/downstream, and cycles. Read-only. | |
| `oxygen columns duplicate` | Duplicate a Table column and its definition with an optional new label. | `writes` |
| `oxygen columns edit` | Save a column's label, type, order or definition. Returns downstream reference warnings rather than silently discarding them. | `writes` |
| `oxygen columns execute` | Run one column over an exact row or bounded selection. Paid execution requires approval and a max_credits ceiling; uncertain prior effects need explicit resolution approval. | `paid` `writes` |
| `oxygen columns fields` | List what a column's output exposes: every field you can reference as {{column.field}}, filter on, sort by, or promote to its own column with `columns materialize`. | |
| `oxygen columns kind-estimates` | Read managed credit estimates for available Table column kinds. | |
| `oxygen columns materialize` | Copy JSON paths from a result column into existing or new target columns. | `writes` |
| `oxygen columns provider-action` | Preview or create a provider action column; creating it does not execute provider actions. | `writes` |
| `oxygen columns rename` | Rename a workspace column's stable key (requires --key), optionally updating its display label. | `writes` |
| `oxygen columns reorder` | Move a workspace column to a new position, by absolute index or relative to another column. | `writes` |
| `oxygen columns rerun` | Re-run a single AI column cell, optionally threading a prior message review's feedback into the prompt. | `paid` `writes` |
| `oxygen columns restore` | Restore an archived or delete-scheduled column: cancels the purge timer and reclaims its key. | `writes` |
| `oxygen columns retype` | Convert a manual text column to a stronger data type, migrating stored values. | `writes` |
| `oxygen columns run` | Run an executable AI, tool, formula, enrichment, bind, lookup, or custom HTTP column for one row or a bounded batch. | `paid` `writes` |
| `oxygen columns update` | Update a workspace column: label, note, position and visibility; a choice column's options; a lookup or bind column's source, join and mode; and for AI/research columns the prompt, named inputs… | `writes` |
| `oxygen columns web-search-mode` | Convert a web-search column between agent, AI or keyword modes. Conversion requires confirm=true; mode plus column seeds an AI or keyword replacement. | `writes` |
## commands
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen commands` | Discover CLI commands. With no subcommand, print the backwards-compatible full manifest. | |
| `oxygen commands get` | Hydrate one exact CLI command with its arguments, flags, and safety markers. | |
| `oxygen commands search` | Find a bounded set of CLI commands from a natural-language outcome. | |
## comments
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen comments add` | Comment on a workspace object. | `writes` |
| `oxygen comments delete` | Retract one of your own comments. AUTHOR ONLY, idempotent. The row stays so the thread remains a complete audit trail; the text is redacted on every read path. | `writes` |
| `oxygen comments edit` | Rewrite one of your own comments. AUTHOR ONLY. The edit stamps edited_at — a thread that decided a launch is evidence, and evidence that changes without a trace is not evidence. | `writes` |
| `oxygen comments list` | Every comment thread on one object, newest first, with its comments inline. Defaults to open threads only. | |
| `oxygen comments resolve` | Mark a thread settled, or reopen it with --reopen. Idempotent both ways: re-resolving keeps the original resolver and timestamp. This is conversation state only — it never unblocks an approval gate. | `writes` |
| `oxygen comments show` | One thread by its own id, with every comment. | |
## companies
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen companies enrich preview` | Inspect missing company fields, provider routing, and credit estimates without provider calls. | |
| `oxygen companies enrich run` | Queue a live company enrichment waterfall after explicit approval, or return a dry-run plan. | `paid` `writes` |
| `oxygen companies search filters` | List Company Search filter fields and options without a provider call, including every enum field's full accepted-value list. --source hiring lists the Job postings filters instead (job.* and… | |
| `oxygen companies search plan` | Compile a company-search prompt into ordered provider routes without provider calls. | |
| `oxygen companies search preview` | Preview up to 50 rows free, using native filters from companies search filters. --source google_maps previews 20 businesses with a q business-and-area filter; total_results is unavailable when the… | |
| `oxygen companies search run` | Return a dry-run request or queue a live company-search ingestion run. | `paid` `writes` |
## connections
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen connections import` | Start (or re-arm) a connections import. | `writes` |
| `oxygen connections status` | Show connections-import progress (per-sender drip status, connections ingested, last error) plus a preview of the connections table and a deep-link to open it. | |
## connectors
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen connectors events get` | Show one connected app's event subscriptions (filters, status, granted, renew-by and expiry, workspace) and its recent deliveries (status, attempts, failure category, times; never content). | |
| `oxygen connectors events revoke` | Stop OXYGEN sending events to one connected app: revoke one of its event subscriptions (--subscription <id>) or every live one (--subscription all), optionally only in one --workspace. | `writes` |
| `oxygen connectors get` | Show one connected app: its default workspace, its daily credit ceiling and what it spent in the last 24 hours in each workspace where it spends, and how many event subscriptions it holds. | |
| `oxygen connectors list` | List your connected apps with each one's default workspace, its live event subscriptions, its daily credit ceiling and what it spent in the last 24 hours, when it was last used, and the workspaces… | |
| `oxygen connectors set` | Change one connected app's settings (ChatGPT, Claude, Codex or another app connected to OXYGEN with OAuth); only that app changes. --default-workspace: where it works without asking (the same… | `writes` |
## context
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen context assets archive` | Archive a context asset. Archiving the canonical brand, voice, positioning or playbook files an approval proposal and fails with knowledge_approval_required. | `writes` |
| `oxygen context assets get` | Read one context asset. | |
| `oxygen context assets list` | List workspace context assets. | |
| `oxygen context assets search` | Full-text 'second brain' search across context assets, ranked by relevance. | |
| `oxygen context assets set-default` | Pin a context asset as the canonical default for its type. | `writes` |
| `oxygen context assets upsert` | Create or update a context asset. | `writes` |
| `oxygen context canonical get` | Read the current canonical (pinned) voice, brand or positioning that AI copy uses, or any type's pinned asset. present=false means none is pinned; grounding_when_absent says what AI copy uses instead. | |
| `oxygen context profile get` | Read the current workspace company profile. | |
| `oxygen context profile update` | Merge one or more profile sections into workspace GTM memory. | `writes` |
| `oxygen context resolve` | Resolve task-scoped workspace GTM context with readiness and revision provenance. | `writes` |
## copilot
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen copilot approve` | Approve (or, with --reject, reject) an action a Workspace Copilot session is waiting on; approving re-queues the paused turn. | `paid` `writes` |
| `oxygen copilot attach` | Attach a file to a Workspace Copilot session without sending a message yet. | `writes` |
| `oxygen copilot attachments` | List the files attached to a Workspace Copilot session, sent and unsent. | |
| `oxygen copilot attachments complete` | Verify and describe an uploaded Copilot attachment in its session. | `writes` |
| `oxygen copilot attachments delete` | Detach an unsent Copilot attachment; attachments already quoted by a turn cannot be removed. | `writes` |
| `oxygen copilot attachments list` | List sent and unsent attachments in one Copilot session. | |
| `oxygen copilot attachments prepare` | Reserve a Copilot attachment and return its scoped upload URL; complete only after uploading the exact bytes. | `writes` |
| `oxygen copilot cancel` | End a Workspace Copilot session for good, stopping any in-flight turn. The session cannot take new messages afterwards — to stop only the current turn, use `copilot interrupt`. | `writes` |
| `oxygen copilot feedback` | Rate one attended Copilot turn and optionally explain the rating. | `writes` |
| `oxygen copilot follow` | Turn screen-follow ON (or, with --off, OFF) for an open Workspace Copilot session: while it is open in the browser, your screen opens onto whatever the copilot creates or changes, with the live… | |
| `oxygen copilot get` | Show one Workspace Copilot session: its state, turns, and event log. Use --after-seq to page through the event stream, --before to read earlier turns of a long chat. | |
| `oxygen copilot interrupt` | Stop the turn a Workspace Copilot session is currently working on, leaving the session open for your next message. | `writes` |
| `oxygen copilot list` | List Workspace Copilot conversations by session status, newest first; this read starts no inference. | |
| `oxygen copilot plan` | Show how far along a Workspace Copilot session is: its plan's major steps, the substeps under each, what is done, and how much longer the rest is expected to take. | |
| `oxygen copilot policy set` | Set an attended Copilot session's approval and screen-follow policies. Paid auto-approval is explicit standing authorization. | `paid` `writes` |
| `oxygen copilot send` | Send a message to a Workspace Copilot session and stream the reply to stderr. Waits for the turn to finish (or pause for an approval) unless --no-wait. Managed inference uses workspace credits. | `paid` `writes` |
| `oxygen copilot start` | Start an attended Workspace Copilot session on Oxygen Balanced by default. | `writes` |
## crm
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen crm activity log` | Log a timeline activity on a CRM record. Defaults to dry-run. | `writes` |
| `oxygen crm activity note` | Log a free-text note on a CRM record. Defaults to dry-run. | `writes` |
| `oxygen crm activity timeline` | Show a CRM record's activity timeline, newest first. Address the record by row id OR by any of the object's identities — a company domain, a person's email or LinkedIn URL. | |
| `oxygen crm assert` | Create or update one CRM record by object identity. | |
| `oxygen crm automation audit` | Show recent CRM automation rule changes, newest first. | |
| `oxygen crm automation rules` | List the standing CRM automation templates and their armed state. | |
| `oxygen crm automation set` | Arm or disarm a standing CRM automation template. | `paid` `writes` |
| `oxygen crm connections` | Show the conversations and sequence enrollments connected to one CRM record, resolved through its people and identities — never by fuzzy name or domain. | |
| `oxygen crm describe` | Describe one configured CRM object: its fields, identities and relationships. | |
| `oxygen crm duplicates` | List ranked duplicate-candidate record pairs for one CRM object (identity-overlap + fuzzy-label). Read-only. | |
| `oxygen crm enrichment backfill` | Enrich the records you ALREADY have. | `paid` `writes` |
| `oxygen crm enrichment disable` | Disarm one enrichment on a CRM object and leave every other choice untouched. New records stop running its columns; already-written values stay. | `writes` |
| `oxygen crm enrichment enable` | Arm one enrichment on a CRM object and leave every other choice untouched. | `writes` |
| `oxygen crm enrichment list` | Show the enrichments available per CRM object: which are armed, what each costs per record, the per-record total, the per-batch credit ceiling, how much of the column allowance is spent, and how… | |
| `oxygen crm enrichment off` | Turn automatic enrichment off for a CRM object: revokes the standing permission and clears the WHOLE configuration — every named preset plus any columns you added to it yourself, so nothing keeps… | `writes` |
| `oxygen crm enrichment set` | Replace the armed enrichment set for a CRM object outright — any preset not listed is disarmed, while columns you added to the config yourself are kept. | `paid` `writes` |
| `oxygen crm fields` | Fill the stored CRM fields (Industry, Employees, HQ, and their siblings) from enrichment data this workspace already holds. | |
| `oxygen crm files attach` | Upload a local file and attach it to a CRM record. | `writes` |
| `oxygen crm files attach-inline` | Attach inline base64 bytes to a CRM record; each call creates a new file and attachment, including identical retries. | `writes` |
| `oxygen crm files complete-upload` | Verify a reserved CRM upload and attach it to its record; mismatched bytes remain pending. | `writes` |
| `oxygen crm files detach` | Remove a file from a record. Removes the LINK only — the stored file is kept, so anywhere else it is attached still has it. | `writes` |
| `oxygen crm files download` | Download a tenant-owned record attachment by attachment_id. The native authenticated response contains its exact bytes. | |
| `oxygen crm files list` | List one record's attachments, newest first. | |
| `oxygen crm files prepare-upload` | Reserve a CRM file upload by exact name, length and SHA-256; returns a scoped upload URL. | `writes` |
| `oxygen crm files read` | Read a bounded chunk of original file bytes, separate from extracted text. Follow next_offset with the same sha256. No credits. | |
| `oxygen crm get` | Get one CRM record aggregate with row values, identities, and relationships. | |
| `oxygen crm keep` | Keep one sample record as real. | `writes` |
| `oxygen crm merge` | Merge two CRM records: survivor-wins-with-loser-fill field write + relink/tombstone. Defaults to dry-run; --live requires --confirm. | `writes` |
| `oxygen crm notes add` | Write a note on a CRM record. | `writes` |
| `oxygen crm notes delete` | Delete a note. Soft: the note stops showing its text while its place in the timeline stays, so the record still shows that a note was written and removed. | `writes` |
| `oxygen crm notes list` | List one record's notes, pinned first then newest. Address the record by row id OR by any of the object's identities. | |
| `oxygen crm notes update` | Edit a note's body, title or pin. Addressed by note id because one note can be filed on several records. | `writes` |
| `oxygen crm objects` | List configured CRM objects, or create/extend custom objects. | |
| `oxygen crm objects add-attr` | Add one field to an existing CRM object, optionally as an identity. Works on custom objects and on companies/people/deals — a field you add is yours and survives `crm setup`. Defaults to dry-run. | `writes` |
| `oxygen crm objects create` | Create or repair a custom CRM object. Defaults to dry-run. | `writes` |
| `oxygen crm objects delete` | Delete a CUSTOM CRM object: removes the object and schedules its backing table for deletion (restorable for 14 days). | `writes` |
| `oxygen crm objects remove-attr` | Remove a field you added to a CRM object. | `writes` |
| `oxygen crm objects update-attr` | Change one field on a CRM object: rename it, make it required or optional, or replace the choices of a select/status field. | `writes` |
| `oxygen crm photos` | Fill CRM people photos from LinkedIn data this workspace already holds — inbox conversations, connections, followers, and post engagers. | `writes` |
| `oxygen crm pipeline` | Show the deals pipeline grouped by stage, with per-stage counts and amount totals. Seeded sample deals are listed with `sample: true` but never counted; `samples` reports them. | |
| `oxygen crm related` | Show the records linked to one CRM record, grouped by relationship with a true count per group. | |
| `oxygen crm relationships define` | Define a relationship (and its relation column) from a custom object to any object. Defaults to dry-run. | |
| `oxygen crm relationships upsert` | Create or replace a CRM relationship edge. Defaults to dry-run. | `writes` |
| `oxygen crm rollup` | Recompute the Open Deal column on companies (and the copy stamped on their people) from this workspace's deals. | |
| `oxygen crm search` | Search CRM records by identity or record label. Takes ONE query; narrow the objects with --object, not a second argument. | |
| `oxygen crm setup` | Create or repair standard CRM object-backed tables; defaults to dry-run. | `writes` |
| `oxygen crm signals leads-today` | List people to contact today, ranked by their most recent GTM intent signal. | |
| `oxygen crm signals record` | Record one inbound GTM signal (website_visit, profile_view, post_engager, new_follower) into the CRM. Internal write — free, no approval. Idempotent on --external-event-id. | `writes` |
| `oxygen crm sync configure` | Configure a standing bidirectional sync for one CRM object pair. | `paid` `writes` |
| `oxygen crm sync disable` | Disable the scheduled sync for one CRM object pair: stops the cron trigger and revokes the standing write permission. | `writes` |
| `oxygen crm sync enable` | Enable continuous (scheduled) bidirectional sync for one CRM object pair: arms the cron trigger + the standing write permission, and runs an immediate first cycle. | `paid` `writes` |
| `oxygen crm sync import` | Import provider records into an Oxygen CRM object (canonical CRM truth) as a durable workflow run. | `paid` `writes` |
| `oxygen crm sync links` | Show provider record links (HubSpot/Attio/Pipedrive ids) mapped to one Oxygen CRM record. | |
| `oxygen crm sync run` | Run one bidirectional reconciliation cycle for a configured CRM object pair as a durable workflow run. Defaults to dry-run. | `paid` `writes` |
| `oxygen crm sync status` | Show a CRM sync status: pass --run-id for one workflow run, or --provider/--object for the standing sync config (cadence, watermarks, last-cycle counts). | |
| `oxygen crm tag` | Add/remove workspace tags on one CRM record (Tags primitive — the same vocabulary as sequences, tables, conversations; see `oxygen tags list`). | `writes` |
| `oxygen crm tasks add` | Create a task on a CRM record. | `writes` |
| `oxygen crm tasks complete` | Mark a task done. Completing an already-completed task keeps the original completion time and adds no second timeline entry. | |
| `oxygen crm tasks list` | List open reminders across the whole workspace, or one record's with <object> <record>. | |
| `oxygen crm tasks reopen` | Reopen a completed task, clearing its completion stamp. | |
| `oxygen crm tasks update` | Change a task's title, body, status, priority, deadline or assignee. Addressed by task id because one task can be filed on several records. | `writes` |
## custom-integrations
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen custom-integrations apply` | Create or update a custom HTTP integration manifest. Attach credentials with `custom-integrations connect`. Manifest schema + worked examples: https://oxygen-agent.com/docs/providers/custom-http | `writes` |
| `oxygen custom-integrations connect` | Attach the credential (bearer token, API key, or basic password) for an applied custom HTTP integration. | `writes` |
| `oxygen custom-integrations list` | List custom HTTP integrations for the active organization. | |
## dashboards
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen dashboards create` | Create a saved dashboard. It starts with one empty tab; add widgets to it with `dashboards widgets add`. | `writes` |
| `oxygen dashboards delete` | Archive a dashboard. Its slug becomes free to reuse; the definition is kept, not destroyed. | `writes` |
| `oxygen dashboards get` | Read one dashboard with its tabs and widgets. | |
| `oxygen dashboards list` | List the dashboards saved in this workspace. | |
| `oxygen dashboards summary` | Show the GTM funnel summary: touches → replies → positive → meetings → deals → won, with this-period revenue, channel split, and current needs-action triage. | |
| `oxygen dashboards tabs add` | Add a tab to a dashboard. | `writes` |
| `oxygen dashboards tabs remove` | Remove a tab and every widget on it. A dashboard always keeps at least one tab. | `writes` |
| `oxygen dashboards update` | Rename a dashboard, change its description or icon, or make it the default. | `writes` |
| `oxygen dashboards widgets add` | Add a widget. Kinds: chart, view, iframe, rich_text, code, live_source. The configuration shape depends on the kind — run `oxygen dashboards widgets kinds` to see each one with an example. | `writes` |
| `oxygen dashboards widgets data` | Read the data behind one widget — the same numbers the web page draws. | |
| `oxygen dashboards widgets kinds` | List the widget kinds, what each one shows, whether it can cost credits, and an example configuration. | |
| `oxygen dashboards widgets refresh` | Refresh a live-source widget now. This is the only dashboard command that can cost credits, bounded by the ceiling saved on the widget. Opening a dashboard never spends. | `writes` |
| `oxygen dashboards widgets remove` | Remove a widget from a dashboard. | `writes` |
| `oxygen dashboards widgets update` | Change a widget's title, configuration or placement, or pause/resume a live source. | `writes` |
## db
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen db attach` | Attach an existing Postgres database as the current organization's tenant database. | `writes` |
| `oxygen db backfill-table-order-indexes` | Converge stable row-order indexes on existing customer tables. Staff only; the default dry-run uses 0 credits and makes no database changes. | `writes` `staff` |
| `oxygen db backfill-upsert-indexes` | Create missing upsert-key secondary indexes on customer tables. Staff only; defaults to dry-run. | `writes` `staff` |
| `oxygen db cost-policy` | Read-only, 0 credits. Show the retired Neon cost-policy status. Its managed field describes the policy, not database hosting; PostgreSQL has no per-workspace sleep control. | |
| `oxygen db migrate` | Apply pending tenant database migrations for the current organization. | `writes` |
| `oxygen db migrate-all` | Apply pending tenant database migrations across all ready tenants (staff only). | `writes` `staff` |
| `oxygen db provision` | Provision the current organization on a registered PostgreSQL shard. Staff can pass global --org to repair another org. | `writes` |
| `oxygen db query` | Run one read-only SQL statement against the current tenant database. | |
| `oxygen db reconcile` | Inspect tenant database registry drift. Staff only; defaults to dry-run. | `writes` `staff` |
| `oxygen db reconcile-cost-policy` | Retired compatibility command: report that Neon endpoint controls no longer apply. | `writes` `deprecated` |
| `oxygen db repair-preview` | Preview tenant database repair issues without mutating production state (staff only). | `staff` |
| `oxygen db status` | Read-only, 0 credits: show the current database host and status, including historical Neon IDs, recorded region labels, and plan-included hosting; staff can pass global --org. | |
## deliverability
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen deliverability placement-test get` | Inspect one saved directional inbox-placement test by id: status, seed counts, per-provider results, and a web result link. | |
| `oxygen deliverability placement-test list` | Inspect recent directional inbox-placement tests, their status, results, and credits used, plus `pricing`: EmailGuard monitoring credits per inbox-month, two included tests per inbox per cycle… | |
| `oxygen deliverability placement-test run` | Create a placement test for one sending mailbox. | `paid` `writes` |
| `oxygen deliverability placement-test send` | Preview or send the exact EmailGuard seed message for a provider-created test. | `paid` `writes` |
## directory
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen directory apply` | Apply to be listed in the public agency directory (reviewed by the OXYGEN team). | `writes` |
| `oxygen directory get` | Read-only, 0 credits. Read the listing, publish state, and public/settings deep-links. | |
| `oxygen directory logo upload` | Upload a public agency-directory logo and read back the updated listing; PNG, JPEG, WebP or SVG, at most 2 MB. | `writes` |
| `oxygen directory publish` | Publish at https://oxygen-agent.com/agencies. Requires a tagline, description, and at least one contact method (website, booking link, email, or LinkedIn). | `writes` |
| `oxygen directory unpublish` | Remove the listing from the public directory (keeps the draft editable). | `writes` |
| `oxygen directory update` | Update listing fields. Changes to a published listing are public immediately. Only invited organizations can edit. | `writes` |
## domains
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen domains add` | BYOK CLOUDFLARE: onboard a domain registered elsewhere by creating a zone in your connected Cloudflare account. For managed domain + inbox provisioning use `managed-inboxes subscribe`. | `writes` |
| `oxygen domains adopt` | STAFF LEGACY RECOVERY: attach domains that already exist in the shared Oxygen-managed Cloudflare account to their workspace. | `writes` `staff` |
| `oxygen domains archive` | Hide a domain from the default list — an Oxygen-side declutter flag only. | `writes` |
| `oxygen domains buy` | Buy sending domains. | `paid` `writes` |
| `oxygen domains check` | Check availability and first-year registration price for up to 20 exact domains. | |
| `oxygen domains delete` | Delete domains and every inbox on them: cancels OXYGEN inbox orders; a domain bought through Oxygen on its own (`domains buy`) stops renewing and leaves the workspace, staying registered until… | `writes` |
| `oxygen domains dns` | Run a live read-only DNS health check (SPF, DKIM, DMARC, MX) against the domain's Cloudflare zone and persist the result. | |
| `oxygen domains dns apply` | Write the planned cold-email DNS records into your own Cloudflare zone. | `writes` |
| `oxygen domains dns plan` | Preview the cold-email DNS records a domain should hold for its mailbox provider (SPF, per-provider DKIM, DMARC, MX, optional tracking) as a create/update/keep/conflict diff plus a plan_hash. | |
| `oxygen domains forwarding get` | Show the domain's current web-root forwarding destination. Read-only, 0 credits. | |
| `oxygen domains forwarding set` | Point the domain's web root at a URL. WITHOUT --approved this previews current -> new and writes nothing. Free (0 credits), but it changes what every visitor to the domain sees. | `paid` `writes` |
| `oxygen domains get` | Get one domain's infrastructure/readiness detail: zone state, age with provenance, mailboxes, cached sending volume, and the last DNS health check. | |
| `oxygen domains list` | List the org's cached Cloudflare domains with cold-email metadata (age, mailboxes, warmup, sending volume, DNS health). | |
| `oxygen domains registration-status` | Get one domain registration's ledger state (the server performs a gated live poll when due — safe to call repeatedly). Pass --wait to poll until it settles. | |
| `oxygen domains registrations` | List the org's domain purchase ledger: every registration attempt with status and price snapshot. | |
| `oxygen domains renewal` | Turn the yearly renewal of a domain bought through Oxygen on or off. No charge. On: the registrar's renewal cost is charged in credits 30 days before expiry. Off: the domain lapses when it expires. | `writes` |
| `oxygen domains search` | Search available domains with their first-year registration price. | |
| `oxygen domains sync` | Refresh Cloudflare-backed domains only: zone pages, registrar metadata, RDAP age backfill, and DNS health. | `writes` |
| `oxygen domains tag` | Replace a domain's workspace tags (whole set; `--tags ""` clears) — e.g. pool the domains behind one campaign tag. | `writes` |
| `oxygen domains tracking setup` | Provision the open/click tracking CNAME (<track-host> CNAME <tracking target>) on the domain's Cloudflare zone. | `writes` |
| `oxygen domains tracking status` | Show the open/click tracking status for a domain (configured host, verification status, CNAME target, whether the tracking secret is set). Reads the cache — 0 Oxygen credits. | |
| `oxygen domains unarchive` | Restore an archived domain to the default list. | `writes` |
## egress
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen egress assign` | Converge mailbox policy assignments: managed/shared by default, or the workspace's dedicated IP for every current and future inbox once that add-on is active. | `writes` |
| `oxygen egress dedicated cancel` | Cancel the dedicated sending-IP add-on. | `writes` |
| `oxygen egress dedicated request` | Preview the dedicated native egress add-on (2,500 credits per 30-day period, $25 face value). | `paid` `writes` |
| `oxygen egress dedicated status` | Show this org's dedicated sending-IP add-on state (status, quantity, activation, price). Read-only, 0 credits. | |
| `oxygen egress ips` | List the configured shared email-proxy IP and this workspace's dedicated IP history. | |
| `oxygen egress register` | STAFF RECOVERY: register legacy/manual logical policy inventory for this environment. | `writes` `staff` |
| `oxygen egress rotate` | RETIRED compatibility command. | `writes` `deprecated` |
| `oxygen egress status` | Show this workspace's configured native email routing, active IP, transport readiness, health counts, dedicated add-on, and one bounded page of the mailbox policy ledger. | |
## email
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen email send` | Send ONE email right now. Without --approved, returns a preview naming the exact mailbox + transport. --from pins a mailbox; otherwise the pool's LRU rotation picks one. | `paid` `writes` |
## engagement
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen engagement comment` | Comment on a LinkedIn post (or reply to a comment with --comment-id). | `paid` `writes` |
| `oxygen engagement engagers` | Read one post's reactors and commenters right now as a de-duplicated people list ready to enroll. | |
| `oxygen engagement harvest` | Start (or re-arm) a harvest of a post's engagers into a workspace table you can enroll into a sequence. | `paid` `writes` |
| `oxygen engagement react` | React to a LinkedIn post (or to a comment with --comment-id). | `paid` `writes` |
| `oxygen engagement status` | Show an engagement harvest's progress (drip status, engagers ingested, last error) plus the workspace table it fills and a preview of harvested engagers. | |
## enrich-column
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen enrich-column preview` | Preflight an enrichment column without provider calls or credit usage. | |
| `oxygen enrich-column run` | Create or reuse an enrichment column and queue a background run. | `paid` `writes` |
## enrichment
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen enrichment apply-default-cascade` | Patch an existing enrichment column to the server-side default provider cascade for its intent. | `writes` |
| `oxygen enrichment catalog` | Name the DATA, not the provider: list every data type you can ask a table to fill (person profile, work email, phone, headcount, funding, tech stack, hiring, competitors, news, decision makers… | |
## feedback
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen feedback` | Send feedback or a bug report to the OXYGEN team. | |
## feeds
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen feeds bind` | Bind a feed to a table: a scheduled provider harvest (pull), with --schema-json a typed-or-rejected push feed, or with --source rb2b the web-intent feed landing RB2B website-visit reveals as rows. | `paid` `writes` |
| `oxygen feeds deliveries` | List the shared table delivery ledger: pull-feed sync cycles and inbound webhook deliveries land in the same place. | |
| `oxygen feeds get` | Get one table feed. Optional summary or lossless value JSON windows recover every public setting; resume value-cursor with the same feed/path/include-cursor. Read-only. | |
| `oxygen feeds list` | List table feeds for the workspace, newest first. Optional summary/full windows resume with next-offset; exact settings use feeds get --projection value. Read-only. | |
| `oxygen feeds pause` | Pause a feed: the cron stays armed but every cycle it fires is refused, so nothing is fetched and nothing is billed until you resume. Free. | `writes` |
| `oxygen feeds resume` | Resume a feed: re-activates it AND clears an error/exhausted stop, so the next cron tick can claim it again. Re-uses the cadence and spend cap already approved at bind time. Free. | `writes` |
| `oxygen feeds run` | Run one sync cycle now through the feed's own cron workflow (one harvest path, one cursor). --mode dry_run (default) renders the exact next-cycle provider request with the cursor or watermark… | `paid` `writes` |
| `oxygen feeds unbind` | Delete a feed: removes its cron FIRST, then the feed row. The table and every row it already wrote are kept. | `writes` |
| `oxygen feeds update` | Update an existing feed in place. | `writes` |
## find
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen find company` | Enrich a company via a waterfall: identity, firmographics, structured funding, competitors, corporate structure, acquisitions, news, job openings, tech stack, web-presence URLs. | `paid` |
| `oxygen find email` | Find a person's work email via an input-aware multi-provider waterfall: a LinkedIn URL, name+domain, or first/last+domain each select the best provider profile, with an email-pattern pre-step and… | `paid` |
| `oxygen find linkedin` | Resolve a person's LinkedIn URL from name + company (or email), with identity validation. | `paid` |
| `oxygen find person` | Enrich one person from a LinkedIn URL, a LinkedIn public id or member id, a Sales Navigator link, or an email / name + company: one managed profile lookup returns the profile block — first, last… | `paid` |
| `oxygen find personal-email` | Find a person's personal (non-work) email — for ad-audience uploads, recruiting, or founder outreach — via a cost-ordered multi-provider waterfall that bills only on a hit and grades the address… | `paid` |
| `oxygen find phone` | Find a person's mobile phone via a multi-provider waterfall. | `paid` |
## followers
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen followers import` | Start (or re-arm) a followers import. | `writes` |
| `oxygen followers status` | Show followers-import progress (per-sender drip status, followers ingested, last error) plus a preview of the followers table and a deep-link to open it. | |
## formulas
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen formulas functions` | List every formula function (name, signature, examples), the operator grammar, and the expression_notes that a signature cannot teach (bare column keys, string escapes, no regex flags, read-time… | |
| `oxygen formulas validate` | Validate a formula against a table and preview its output on sample rows — free, no writes. Draft → validate → attach with `oxygen columns add --kind formula`. | |
## functions
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen functions bind` | Add a Function column with explicit input/output mappings and a caller credit cap. | `writes` |
| `oxygen functions delete` | Preview removal from the Function library, then remove it with --yes; preserves backing tables, rows and run history. | `writes` |
| `oxygen functions describe` | Inspect a Function's inputs, outputs, steps, per-row credit estimate, caps, and draft or published version. | |
| `oxygen functions disable` | Disable future Function invocations; captured runs are unchanged. | `writes` |
| `oxygen functions draft` | Create a Function draft, or save an existing Function's draft; executes nothing. | `writes` |
| `oxygen functions duplicate` | Copy a Function's steps into a new editable draft (same inputs and outputs, no rows). | `writes` |
| `oxygen functions enable` | Enable future Function invocations; captured runs are unchanged. | `writes` |
| `oxygen functions favorite` | Favourite a Function so it appears under `functions list --favorites` and the Favorites tab; per user, per workspace. | |
| `oxygen functions list` | List your workspace's drafts and published Functions with per-row credit estimates (up to 500). | |
| `oxygen functions publish` | Publish the inspected draft for every caller's future invocations; preserves captured runs and caller caps. | `writes` |
| `oxygen functions rename` | Rename a Function while preserving its identity, callers and published execution. | `writes` |
| `oxygen functions restore` | Retired: OXYGEN-provided Functions can no longer be restored. Create a workspace Function instead. | `writes` `deprecated` |
| `oxygen functions runs` | Inspect a Function's latest 100 invocations, the table that called each one, and their captured versions and bindings: each run's overwrite policy, output mapping and run condition as they were… | |
| `oxygen functions unfavorite` | Remove a Function from your favourites. | |
## home
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen home` | Your workspace standup: what happened since you last looked, what needs you, and a year of workspace activity. 0 credits. | `writes` |
## inbox
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen inbox analyze` | Run analysis on a conversation now: status + a drafted reply (Oxygen's default model). The worker also does this automatically on inbound conversations. | |
| `oxygen inbox archive` | Archive a conversation (triage it out of the inbox). --unarchive restores it. --channel linkedin/whatsapp archives a DM. | `writes` |
| `oxygen inbox auto-tagger get` | Show the auto-tagger config (enabled, tag allowlist, channels). | |
| `oxygen inbox auto-tagger set` | Update the auto-tagger. --tags replaces the whole allowlist (max 50; `--tags ""` clears, which pauses tagging while keeping the agent enabled). | `writes` |
| `oxygen inbox backfill` | Opt-in, LinkedIn only: pull a LinkedIn account's OLDER message history into the unibox. | `writes` |
| `oxygen inbox bulk` | Bulk-apply one triage action — set-status / archive / unarchive — across up to 100 hand-picked conversations (the ids `inbox list` returns) in one call. | |
| `oxygen inbox delete-message` | Delete your sent LinkedIn message for everyone within 60 minutes. This cannot be undone. Omit --approved for a preview; show it before approving. Other channels and inbound messages are unsupported. | `writes` |
| `oxygen inbox drafts edit` | Edit an open draft's body before approval. Does not send. | `writes` |
| `oxygen inbox drafts list` | List drafts awaiting review (queued + edited by default), across email + LinkedIn. | |
| `oxygen inbox drafts reject` | Reject an open draft so it leaves the queue. Does not send. | `writes` |
| `oxygen inbox forget-whatsapp-chat` | Permanently erase a terminal old WhatsApp chat and its messages from OXYGEN. | `writes` |
| `oxygen inbox get` | Get one conversation with its full message thread. <conversation> accepts a conversation id, Unipile chat id, or (email) Zapbox thread id, and is resolved on any channel by default (email first… | |
| `oxygen inbox labels create` | Create a custom status label. | `writes` |
| `oxygen inbox labels delete` | Archive a custom status label (system labels and in-use labels are rejected). | `writes` |
| `oxygen inbox labels list` | List status labels. | |
| `oxygen inbox labels restore` | Restore an archived custom status label under its original key. | `writes` |
| `oxygen inbox labels update` | Update a status label's name, color, bucket, description, or (custom labels only) ai-settable flag. | `writes` |
| `oxygen inbox list` | List conversations newest first across email, LinkedIn, and WhatsApp — the merged stream is the default, --channels narrows it, and --channel email/linkedin/whatsapp lists a single channel. | |
| `oxygen inbox mark-all-read` | Mark EVERY conversation matching the filters as read — the whole filtered set across email + LinkedIn + WhatsApp, not just the conversations on the page you can see. | `writes` |
| `oxygen inbox mark-read` | Mark visible messages in a conversation as read (LinkedIn by default; use --channel email or whatsapp for those channels). Sender filters retain the selected DM history window. | `writes` |
| `oxygen inbox reply-agent get` | Show the reply-agent config. | |
| `oxygen inbox reply-agent set` | Configure the reply agent (enable, persona/tone, targets). | `writes` |
| `oxygen inbox rescan` | Re-queue conversations for AI re-classification (status + drafted reply). | `writes` |
| `oxygen inbox send` | Reply into a conversation on its own channel, resolved from the conversation when --channel is omitted: an email thread replies from its own mailbox (Zapbox/native Gmail/Graph, threaded); a… | `paid` `writes` |
| `oxygen inbox start-whatsapp` | Start a one-to-one WhatsApp chat from the Unibox. | `paid` `writes` |
| `oxygen inbox status` | Set a conversation's status (the Instantly-style tier). A manual override that locks out AI re-classification. --channel linkedin/whatsapp sets a DM's status. | |
| `oxygen inbox sync` | Force a backstop inbox sync from Unipile for the active LinkedIn and WhatsApp sender accounts (pulls recent chats + messages into the unibox). | `writes` |
| `oxygen inbox tag` | Add/remove workspace tags on a conversation (Tags primitive — the same vocabulary as sequences, tables, posts; see `oxygen tags list`). | `writes` |
| `oxygen inbox views create` | Save a view for the team. | `writes` |
| `oxygen inbox views delete` | Delete a view for the whole team. Anyone using it as their default opens on the built-in view. | `writes` |
| `oxygen inbox views list` | List the team's saved views; is_default marks your own default. | |
| `oxygen inbox views update` | Rename, re-filter or reorder a view, or set it as (or stop using it as) your own default. | `writes` |
## integrations
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen integrations actions` | List actions available for a connected integration — Composio toolkits and native providers (e.g. Instantly) alike. | |
| `oxygen integrations cloudflare-connect` | Verify a Cloudflare token, choose an account when required, and save the encrypted connection. account_id is optional for initial account discovery; no credential is returned. | `writes` |
| `oxygen integrations connect` | Connect an integration. | `writes` |
| `oxygen integrations connection-test` | Test one workspace integration connection and save its health without changing its default or returning credentials. | `writes` |
| `oxygen integrations connections` | List this workspace's stored integration connections and health without credentials. | |
| `oxygen integrations default` | Set the default active integration connection within this workspace. | `writes` |
| `oxygen integrations destinations` | List where a connected integration can send — for Microsoft Teams, your teams and your chats, plus one team's channels with --team-id. | |
| `oxygen integrations disconnect` | Disconnect an integration. LinkedIn and WhatsApp remove the connected account; pass --connection-id when more than one is connected. | `writes` |
| `oxygen integrations events deliveries` | List recent provider webhook deliveries (Composio triggers, HubSpot webhooks, etc.) and the workflow runs they kicked off. | |
| `oxygen integrations events disable` | Disable a provider event for a connected integration account. | `writes` |
| `oxygen integrations events enable` | Enable a provider event for a connected integration account. | `writes` |
| `oxygen integrations events list` | List raw provider event definitions and this org's enabled subscriptions. To choose a workflow trigger, use `oxygen workflows events list`. | |
| `oxygen integrations github branches` | | |
| `oxygen integrations github repositories` | | |
| `oxygen integrations github-start` | Create the authenticated GitHub authorization URL for this workspace. | `writes` |
| `oxygen integrations hubspot-start` | Create the authenticated HubSpot authorization URL for this workspace. | `writes` |
| `oxygen integrations list` | List supported integrations and this org's connections. Add --integration <id> to read one integration and its connection state. | |
| `oxygen integrations managed-endpoints` | Read a managed integration's full action catalog and parameter schemas. | |
| `oxygen integrations openrouter-models` | Read model and pricing metadata using this workspace's connected OpenRouter account; credentials are never returned. | |
| `oxygen integrations run` | Run an action for a connected integration — Composio toolkits and native providers alike. | `paid` `writes` |
| `oxygen integrations status` | Read active connection counts, sender connection state and the workspace's usable BYOK plan entitlement. | |
| `oxygen integrations test` | Re-validate a stored integration API key against the provider and heal the connection when it passes (recovers benched or scope-degraded connections without re-pasting the key). | |
## knowledge
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen knowledge agent get` | Show the synthesis-agent config (enabled, cadence, per-day credit cap). | |
| `oxygen knowledge agent set` | Configure the synthesis agent. Enabling lets the background worker distill new sources on the cadence; it only writes working learnings pages. | `paid` `writes` |
| `oxygen knowledge bootstrap` | Research this workspace's company through direct LinkedIn company enrichment and website reads. | `paid` `writes` |
| `oxygen knowledge bootstrap status` | Report the once-ever bootstrap marker for this workspace: status (queued, running, completed, partial, skipped, failed, or never attempted), when it ran, its system run id, the credits it actually… | |
| `oxygen knowledge files archive` | Archive a file with revision checking. A connected two-way repository publishes the deletion; history remains. | `writes` |
| `oxygen knowledge files download` | Download exact original bytes with digest verification; refuses to overwrite an existing local file. | |
| `oxygen knowledge files get` | Read original file content, properties and download link at an optional immutable revision. | |
| `oxygen knowledge files list` | | |
| `oxygen knowledge files upsert` | Create or replace an original file, or update frontmatter properties. Canonical copy still requires a proposal. | `writes` |
| `oxygen knowledge folders create` | Create a persistent knowledge folder, optionally inside another folder. | `writes` |
| `oxygen knowledge folders list` | List workspace folders and page locations, including empty folders. Read-only, 0 credits. | |
| `oxygen knowledge folders move` | Move a folder and its contents to another folder or the workspace root. | `writes` |
| `oxygen knowledge graph` | Knowledge graph of pages and their [[wikilink]] edges. Pass --center to render one page's local neighborhood instead of the whole graph. Read-only, 0 credits. | |
| `oxygen knowledge index` | Compact wiki index: each page's slug, one-liner, tags, link degree, plus type/status counts over the whole wiki. | |
| `oxygen knowledge lint` | Read-only structural wiki health report, 0 credits: orphans (unfilled seed stubs excluded), dead-ends, unresolved links, contradictions (disputed pages, conflicting trust tags, competing live-copy… | |
| `oxygen knowledge lint relink` | Recompute [[wikilink]] edges (and gap-fill unlinked mentions) across wiki pages. | `writes` |
| `oxygen knowledge log append` | Append an entry to the knowledge log. | |
| `oxygen knowledge log list` | List knowledge log entries, newest first. Read-only, 0 credits. | |
| `oxygen knowledge page archive` | Archive a knowledge wiki page while retaining its content and history. Links become unresolved. Restore with page upsert --status draft and the current --expected-revision. | `writes` |
| `oxygen knowledge page get` | Read one knowledge wiki page by slug or UUID. Use --view sources for its evidence ledger or --view full for content, links and sources. Read-only, 0 credits. | |
| `oxygen knowledge page list` | List knowledge wiki pages. Read-only, 0 credits. | |
| `oxygen knowledge page pin` | Pin a knowledge wiki page as the canonical default for its type. Canonical voice/brand/positioning pages are auto-applied to AI copy generation. | `writes` |
| `oxygen knowledge page restore` | Restore a knowledge wiki page to an earlier revision, as a new revision; history is kept. Use --expected-revision to refuse if the page changed since. | `writes` |
| `oxygen knowledge page revision` | Read one full revision snapshot of a knowledge wiki page. Read-only, 0 credits. | |
| `oxygen knowledge page revisions` | List the revision history of a knowledge wiki page, newest first. Read-only, 0 credits. | |
| `oxygen knowledge page upsert` | Create or update a knowledge wiki page. Free internal write; canonical edits require proposal approval. | `writes` |
| `oxygen knowledge profile` | Company profile and ICP memory. | |
| `oxygen knowledge profile update` | Merge one or more profile sections into workspace GTM memory. | `writes` |
| `oxygen knowledge proposals` | Review pending captured wiki changes. Optional summary traverses the live queue; exact proposal + value reads raw captured JSON. Read-only, 0 credits. | |
| `oxygen knowledge proposals approve` | Approve a knowledge proposal and apply it to the target page. | `writes` |
| `oxygen knowledge proposals reject` | Reject a knowledge proposal without changing the target page. | `writes` |
| `oxygen knowledge purge` | Delete the whole local knowledge mirror for the active API host and organization. | `writes` |
| `oxygen knowledge push` | Push locally edited or newly created mirror pages back to the workspace wiki. Edits to canonical voice/brand/positioning pages become approval proposals instead of writing live. | `writes` |
| `oxygen knowledge repositories conflicts` | Read conflicts; add --path to inspect preserved base, Oxygen, and GitHub versions. | |
| `oxygen knowledge repositories connect` | Approve the exact preview and start importing. two_way authorizes future automatic GitHub writes to the selected branch. 0 Oxygen credits. | `writes` |
| `oxygen knowledge repositories disconnect` | Disconnect this repository; keep its files and history in Knowledge. | `writes` |
| `oxygen knowledge repositories list` | Read connected repositories, import progress, sync freshness, pending changes, and errors. 0 credits. | |
| `oxygen knowledge repositories pause` | Pause automatic sync; keep all imported files and history. | `writes` |
| `oxygen knowledge repositories preview` | Preview branch/folder contents, exclusions and the future sync policy. Does not activate sync. 0 credits. | |
| `oxygen knowledge repositories resolve` | Apply a reviewed conflict decision. Canonical copy remains proposal-gated; GitHub publishes under the saved sync policy. | `writes` |
| `oxygen knowledge repositories resume` | Resume the previously approved sync policy. | `writes` |
| `oxygen knowledge repositories sync` | Request an immediate sync attempt. Saved changes remain safe if GitHub is unavailable. | `writes` |
| `oxygen knowledge resolve` | Resolve task-scoped workspace GTM context with readiness and revision provenance. | `writes` |
| `oxygen knowledge search` | Search wiki pages by meaning and keywords. | |
| `oxygen knowledge seed` | Seed the knowledge starter pages: on first run creates draft ICP and Offers pages, [[wikilinked]] to each other. Idempotent; never overwrites your edits. | `writes` |
| `oxygen knowledge status` | Report the local knowledge mirror: path, page count, last sync, quarantined conflicts. Pass --all to report every locally mirrored workspace for the active API host. | |
| `oxygen knowledge sync` | Clone or refresh the local knowledge mirror: server-rendered page markdown under the CLI config dir. Pass --all to mirror every workspace the credential can access. | `writes` |
| `oxygen knowledge sync-delta` | Sync complete wiki pages/tombstones; first call may seed missing starter pages. Follow next_cursor; an oversized page is refused without skipping. 0 credits. | `writes` |
| `oxygen knowledge sync-manifest` | Read complete wiki revision/hash metadata. has_more/truncated mean more pages, not cut entries. last_cursor marks the last returned page; next_cursor resumes when more remain. | |
| `oxygen knowledge synthesize` | Synthesize knowledge from workspace evidence (one low-cost AI call, priced as one low-reasoning AI column cell): campaign learnings from auto-filed outreach outcomes, or your writing voice (a… | `paid` `writes` |
## lead-sourcing
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen lead-sourcing audit` | Audit a sourced lead table against a lead-sourcing spec. | |
| `oxygen lead-sourcing plan` | Compile a natural-language ICP into an account-first lead sourcing plan. | |
## limits
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen limits provider delete` | Delete one provider override after approving its selector; admin/owner only, 0 credits; remaining matches apply, otherwise a code default if defined. | `writes` |
| `oxygen limits provider list` | List enforced workspace provider overrides and the plan-tier BYOK daily threshold with its enforcement mode; read-only, 0 credits. | |
| `oxygen limits provider set` | Set an enforced provider request limit; admin/owner only. Approve the exact provider, operation and window before running; execution saves the policy. Raising a cap can permit more use. 0 credits. | `writes` |
| `oxygen limits show` | Compare every plan size: price, monthly credits, volume bonus and price per 100 credits (`plan_bands`). | |
## linkedin
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen linkedin connections import-status` | Read the durable LinkedIn connections import status and target Table. | |
| `oxygen linkedin connections invite` | Send a LinkedIn connection invitation. | `paid` `writes` |
| `oxygen linkedin followers import-status` | Read the durable LinkedIn followers import status and target Table. | |
| `oxygen linkedin inbox backfill-status` | Read the durable LinkedIn inbox backfill status. | |
| `oxygen linkedin ingestion status` | Unified status of every LinkedIn ingestion drip (connections import, engagement harvest, message-history backfill) plus each account's remaining ingest read budget for the day. | |
| `oxygen linkedin intent autoenroll` | Authorize the captures armed by `linkedin intent setup` to enroll the people they capture into a sequence — the step that turns captured rows into outreach. | `paid` `writes` |
| `oxygen linkedin intent setup` | Create/reuse the canonical OXYGEN Tables, link them, and arm capture-only worker-backed engagement workflows for profile viewers, followers, and connections. | `writes` |
| `oxygen linkedin intent status` | Show the canonical intent tables, their linked-table deep-links, and the capture feeds filling them. | |
| `oxygen linkedin invitations list` | List the account's pending sent LinkedIn invitations with their invitation ids — the ids `linkedin invitations withdraw --ids` cancels. | |
| `oxygen linkedin invitations pause` | Stop checking open connection requests for one account (--account) or every account. The table and its rows stay; `linkedin invitations setup` switches it back on. Free. | `writes` |
| `oxygen linkedin invitations setup` | Switch on the open connection requests table. | `writes` |
| `oxygen linkedin invitations status` | Show the open connection requests table: `accounts[]` lists every connected LinkedIn account with `on`, its state (off\|collecting\|waiting\|paused\|attention), and when it was last and will next be… | |
| `oxygen linkedin invitations withdraw` | Withdraw pending sent LinkedIn invitations. | `paid` `writes` |
| `oxygen linkedin network pause` | Switch network capture off: the worker stops reading that account's connections and followers until you run `linkedin network setup` again. | `writes` |
| `oxygen linkedin network setup` | Arm (or re-arm) network capture. | `writes` |
| `oxygen linkedin network status` | Show network capture progress: `accounts[]` lists every connected LinkedIn account with its headline, `on` (switched on or not), and state (off\|collecting\|waiting\|paused\|attention); which accounts… | |
| `oxygen linkedin viewers list` | Read named LinkedIn profile viewers, respecting the connected account's privacy ceiling. | |
## login
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen login` | Connect this terminal to Oxygen. Opens the browser to approve this terminal (matching confirmation code shown in both); paste a token with --token instead if you prefer. | `writes` |
## logout
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen logout` | Remove the active stored CLI API token. | `writes` |
## mailboxes
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen mailboxes cap set` | Set one sending mailbox's daily send cap (sends per day; new mailboxes get 25). --daily-cap must be a positive whole number; `oxygen limits show` reports the maximum in force. | `writes` |
| `oxygen mailboxes compatibility` | Read-only compatibility report per mailbox — select with --mailboxes <address,…> (omit for the whole pool; filter here, not in a script): generic origin class, real infrastructure tier (including… | |
| `oxygen mailboxes connect-oauth` | Connect Gmail/Microsoft 365 with --vendor composio to import all mail into Unibox and business activity into CRM. | `writes` |
| `oxygen mailboxes delegation` | Google sending-domain delegation only — not Microsoft OAuth and not a credential-file handoff to OXYGEN Warm-up or EmailGuard. | |
| `oxygen mailboxes delete` | Preview or approve removal of exact mailboxes from Oxygen at 0 credits. | `writes` |
| `oxygen mailboxes emailguard auto-enroll` | Standing permission to connect NEW eligible mailboxes to EmailGuard automatically, so monitoring keeps up with the fleet instead of needing a manual connect per inbox. | `paid` `writes` |
| `oxygen mailboxes emailguard connect` | Preview or connect selected mailboxes to EmailGuard. | `paid` `writes` |
| `oxygen mailboxes emailguard disconnect` | Preview or remove selected mailboxes from EmailGuard and cancel their recurring monitoring subscription. Remote absence is confirmed before billing stops. | `paid` `writes` |
| `oxygen mailboxes get` | Get one sending mailbox's configuration/readiness detail (provider, status, daily cap, warmup state, auth mode, and source — managed vs bring-your-own) plus a one-row pool summary. effective_cap… | |
| `oxygen mailboxes health` | Fleet email-health: the sending pool rolled up by external deliverability reputation (healthy/degraded/critical/unknown), per-mailbox scores, connected health providers, and DIRECTIONAL… | |
| `oxygen mailboxes import` | Register (or refresh) sending mailboxes in bulk. | `writes` |
| `oxygen mailboxes list` | List the org's sending mailboxes with provider, status, warmup state, source (managed = bought through Oxygen, byok = bring-your-own), worker-owned connectionRepair and warmupRepair state, and a… | |
| `oxygen mailboxes oauth-health` | Show every Google/Microsoft inbox with neither a usable per-mailbox OAuth token nor verified delegation/application access. automatic_repair marks Zapmail-linked rows whose safe retries OXYGEN… | |
| `oxygen mailboxes order` | RETIRED — managed mailboxes are now purchased as monthly subscriptions via `oxygen managed-inboxes subscribe` (InboxKit-backed). | `writes` `deprecated` |
| `oxygen mailboxes ramp set` | Set one mailbox's campaign ramp-up: a custom --start-per-day plus --step every --increase-every-days sending days until its daily cap, --off for the full daily cap from the first sending day, or… | `writes` |
| `oxygen mailboxes sequences` | Read the sequences using one sending mailbox by id or email address. | |
| `oxygen mailboxes status` | Set a sending mailbox's status. Pausing/disabling takes the inbox out of the rotation pool without losing its warmup state. | |
| `oxygen mailboxes sync` | Read or control full Inbox, Sent and archive import for Gmail or Microsoft 365. | `writes` |
| `oxygen mailboxes tag` | Replace a sending mailbox's workspace tags (whole set; `--tags ""` clears) — e.g. pool the mailboxes behind one campaign tag. See `oxygen tags list` for the vocabulary. | `writes` |
| `oxygen mailboxes update` | Update a sending mailbox's rich-content profile: the From display name and/or the HTML signature appended to its sends. | `writes` |
| `oxygen mailboxes warmup config` | Read or override optional provider warm-up traffic, separate from the campaign ramp. | |
| `oxygen mailboxes warmup disable` | Disable warmup and unenroll each mailbox from the rail that actually enrolled it. | `writes` |
| `oxygen mailboxes warmup enable` | Optional provider warm-up defaults to 1/day, +1/day, max 10/day (dedicated-tenant profiles stay stricter); see `mailboxes warmup config` for the effective plan and unsupported OXYGEN Warm-up… | `paid` `writes` |
| `oxygen mailboxes warmup google` | Legacy Google owner consent for one to ten connected inboxes. | `writes` `deprecated` |
| `oxygen mailboxes warmup microsoft` | NON-INBOXKIT FALLBACK ONLY: authorize eligible Microsoft/Outlook mailboxes for OXYGEN Warm-up with ONE browser consent PER MAILBOX, never a password or app password. | `paid` |
| `oxygen mailboxes warmup pause` | Pause warmup at the rail that actually enrolled each mailbox — OXYGEN Warm-up for current enrollments, TrulyInbox for inboxes still warming there. | `writes` |
| `oxygen mailboxes warmup profile` | Pin the SENDING ARCHITECTURE a domain is run as, which every inbox on it inherits: `standard` (a few mailboxes on a real business tenant, each climbing to a real number), `dedicated_tenant`… | `writes` |
| `oxygen mailboxes warmup reactivate` | Manual reactivation of an existing live paid seat: ask the warm-up provider to re-run the connection check on an inbox it has DISABLED, without touching the credential, subscription, or ramp day. | `writes` |
| `oxygen mailboxes warmup reconnect` | Manual repair for an existing live paid seat when automatic credential repair is disabled, exhausted, or needs a new credential: push the mailbox's CURRENT credential to its warmup provider. | `writes` |
| `oxygen mailboxes warmup resume` | Resume paused warmup at each mailbox's recorded rail (OXYGEN Warm-up, or TrulyInbox for inboxes still warming there). 0 Oxygen credits; the existing subscription is unchanged. | `writes` |
| `oxygen mailboxes warmup status` | Read warmup analytics back from the rail each mailbox is enrolled on and refresh each mailbox's warmupTruth (state, last send, pause reason, dispatch counters, next_action). | `writes` |
## managed-inboxes
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen managed-inboxes add-inboxes` | Add mailboxes to a managed domain you ALREADY own — no new domain is registered and there is NO domain registration charge, only the extra inboxes' monthly rate (plus their add-ons). | `paid` `writes` |
| `oxygen managed-inboxes avatars confirm` | Verify and normalize a mailbox profile picture owned by this workspace. | `writes` |
| `oxygen managed-inboxes avatars prepare` | Prepare a scoped mailbox profile-picture upload; confirm the stored bytes before using its URL. | `writes` |
| `oxygen managed-inboxes cancel` | Cancel a managed inbox order by domain: the inboxes AND every recurring add-on on them (warm-up, inbox placement). | `paid` `writes` |
| `oxygen managed-inboxes exit` | Transfer ONE managed domain out of OXYGEN: stop every OXYGEN renewal for this domain after the paid period; keep the domain, mailboxes, DNS, warm-up state and data exactly as they are. | `paid` `writes` |
| `oxygen managed-inboxes get` | Get one managed inbox subscription by domain (vendor, platform, mailbox count, monthly USD price, vendor order id, lifecycle status, auto-renew, period end, internal billing status). | |
| `oxygen managed-inboxes list` | List the org's managed inbox orders: vendor, platform, live inbox count, lifecycle status, internal billing posture, and each order's FULL monthly cost — the inbox line, each inbox's mailbox… | |
| `oxygen managed-inboxes recover` | Restore a cancelled managed subscription using its original addresses and domain. | `paid` `writes` |
| `oxygen managed-inboxes registrant` | Show the registrant (WHOIS) contact this workspace files domain registrations under, or null if it has never bought one. | |
| `oxygen managed-inboxes search-domains` | Search available domains for managed mailboxes; buys nothing. | |
| `oxygen managed-inboxes subscribe` | Buy managed monthly inboxes on a new domain or your existing Cloudflare domain. | `paid` `writes` |
| `oxygen managed-inboxes upload-avatar` | Host a one-off mailbox profile picture and print the URL to pass as profile_picture_url in --mailboxes JSON. | `writes` |
| `oxygen managed-inboxes verify` | Compare purchased inbox inventory with the vendor and legacy Stripe mailbox seats. | |
## messages
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen messages query` | Query messages across channels newest first, or relevance-ranked when -q is set. --channel all merges email + LinkedIn + WhatsApp (narrow with --channels); a campaign filter (--sequence-id)… | |
| `oxygen messages stats` | INBOX-WIDE message-ledger analytics over the WHOLE corpus, not your campaigns: outbound/inbound totals, a conversation-level reply rate (has-inbound over has-outbound) by channel, status… | |
## notetaker
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen notetaker calendar connect` | Create the OAuth authorization URL for a Google Calendar or Outlook notetaker connection. | `writes` |
| `oxygen notetaker calendar schedule` | Schedule recording for an existing calendar event after approval; an external CLI or MCP caller must supply an explicit max_credits ceiling. | `paid` `writes` |
| `oxygen notetaker calendar sync` | Synchronize upcoming Google Calendar or Outlook meeting events into this workspace's notetaker calendar. | `writes` |
| `oxygen notetaker desktop-upload` | Prepare an approved desktop meeting recording and its scoped upload URL. Upload and completion remain separate steps. | `writes` |
| `oxygen notetaker notes edit` | Save the markdown note for one meeting session and return the committed note. | `writes` |
| `oxygen notetaker schedule` | Schedule an invited meeting bot. Defaults to dry-run. | `paid` `writes` |
| `oxygen notetaker setup` | Configure the Recall-backed Oxygen Notetaker. Defaults to dry-run. | `writes` |
| `oxygen notetaker status` | Get one notetaker session with artifacts and credit state. | |
## observability
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen observability approvals` | List everything waiting for a human decision across workflows, publishing, message reviews, inbox reply drafts, and collaboration approval requests — the cross-primitive approvals inbox. | |
| `oxygen observability events` | List recent redacted OXYGEN operation events and failures. Customer support triage and support-event history live in Plain Inbox. | |
| `oxygen observability runs` | List active and failed runs across workflows and table action/ingestion runs — the cross-primitive runs lens. Read-only; each failed item carries the command that resolves it. | |
## onboarding
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen onboarding complete` | Complete the active workspace's onboarding step and record its discovery-source choices. The other choice requires source_other. | `writes` |
| `oxygen onboarding start` | Answer onboarding's choice card. own_agent continues to connecting your own agent. copilot opens the Workspace Copilot with the onboarding conversation already started, billed in credits like any… | `paid` `writes` |
## orgs
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen orgs billing-link` | Cover a workspace with another organization's paid plan instead of buying a second subscription. | `writes` |
| `oxygen orgs billing-owners` | Read-only, 0 Oxygen credits; does not reconcile credits. | |
| `oxygen orgs billing-unlink` | Return a workspace to its own billing owner and credit balance. Its own subscription state, plan and sender_billing model determine which actions need a plan. | `writes` |
| `oxygen orgs create` | Create a workspace for the authenticated person's account and begin native company setup. Workspace API keys cannot create personal workspaces. | `writes` |
| `oxygen orgs list` | List organizations available to the current CLI identity. | |
| `oxygen orgs member-role` | Move a member between the admin and member workspace roles. | `writes` |
| `oxygen orgs select` | Alias for orgs use: this CLI profile only. For ChatGPT, Claude or another connected app, use `oxygen connectors set`. | `writes` `alias` |
| `oxygen orgs use` | Select the active organization for this CLI profile. Apps connected with OAuth (ChatGPT, Claude…) keep their own default workspace: `oxygen connectors`. | `writes` |
## oxygents
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen oxygents activity` | List an Oxygent's recent work: its runs and the actions taken in its chats, as metadata only (no goals or messages). | |
| `oxygen oxygents chat` | Open your ongoing private chat with an Oxygent, creating it the first time. Starts no inference. | `writes` |
| `oxygen oxygents create` | Add an Oxygent to the workspace, named "New Bot" unless you name it; tell it its job in your chat with it. | `writes` |
| `oxygen oxygents forget` | Remove one entry from an Oxygent's team memory. | `writes` |
| `oxygen oxygents get` | Read one Oxygent's profile and your ongoing private chat with it. | |
| `oxygen oxygents group` | Read one of your group chats: its name, members and the chat's state. | |
| `oxygen oxygents group-create` | Start a private group chat with 2 to 6 Oxygents (members, by slug), named name. Starts no inference: @mention a member in a message to have it answer. | `writes` |
| `oxygen oxygents group-end` | End a group chat: nobody answers in it again, and its messages stay readable. | `writes` |
| `oxygen oxygents group-message` | Send a message in a group chat. | `paid` `writes` |
| `oxygen oxygents group-read` | Mark a group chat read up to its newest turn, or up to turn_index. | `writes` |
| `oxygen oxygents group-update` | Rename a group chat, or add or remove Oxygents (by slug); it keeps 2 to 6. A removed member's earlier messages stay. | `writes` |
| `oxygen oxygents groups` | List your group chats with Oxygents: name, members and the chat (working or waiting for you, unread, the latest words and who said them). Private to you. | |
| `oxygen oxygents handoff` | From your chat with an Oxygent, ask another Oxygent (to) to do something: an unattended run of it, as you, within max_credits. | `paid` `writes` |
| `oxygen oxygents hide` | Hide an Oxygent from your own sidebar, or show it again with hidden:false. Its chat is kept; only your sidebar changes. Free. The first Oxygent cannot be hidden. | `writes` |
| `oxygen oxygents list` | List this workspace's Oxygents, the first one (is_default) on top: name, what each does, its look and your chat with each (working or waiting for you, unread, its latest words). | |
| `oxygen oxygents memory` | List what the team asked an Oxygent to remember. Every chat with it reads this; it is a Knowledge page. | |
| `oxygen oxygents message` | Send a message in your ongoing private chat with an Oxygent. Starts a turn billed from workspace credits; paid or external actions still need approval. | `paid` `writes` |
| `oxygen oxygents notes` | Read what an Oxygent keeps about you: private to you, read only in your own chat with it. | |
| `oxygen oxygents notes-set` | Replace what an Oxygent keeps about you; empty clears it. Private to you. | `writes` |
| `oxygen oxygents pin` | Pin an Oxygent near the top of your own sidebar, or unpin it with pinned:false. Only your sidebar changes. Free. | `writes` |
| `oxygen oxygents read` | Mark your chat with an Oxygent read up to its newest turn, or up to turn_index. | `writes` |
| `oxygen oxygents remember` | Add one thing to an Oxygent's team memory: every chat with it reads it, and the whole workspace can see it. Free. | `writes` |
| `oxygen oxygents routines` | List your routines with an Oxygent: schedule, status, next run and last report. Manage one with `agent session` (pause, resume). | |
| `oxygen oxygents task` | Start a background task from your chat with an Oxygent: an unattended run of it, as you, within max_credits. | `paid` `writes` |
| `oxygen oxygents update` | Edit an Oxygent's name, what it does (description) or its look (avatar_key, avatar_color). Its instructions, tools and versions are unchanged. Free. | `writes` |
## people
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen people search filters` | List Find people filter fields and options without a provider call: people.* (title, level, function, location, education) and company.* (industry, headcount, location, funding, up to 50 company… | |
| `oxygen people search plan` | Compile a people-search prompt and optional typed persona filters into ordered provider routes without provider calls. | |
| `oxygen people search preview` | Preview up to 50 people free, using native filters from people search filters. | |
| `oxygen people search run` | Return a dry-run request or queue a live people-search ingestion run. Upsert dedup is on linkedin_url. | `paid` `writes` |
## posts
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen posts comments` | Read one post's comments live from LinkedIn (or one comment's replies with --comment-id). | |
| `oxygen posts create` | Publish a LinkedIn post from the connected account. | `paid` `writes` |
| `oxygen posts delete` | Delete a LinkedIn post the connected account authored — a REAL, irreversible public write. | `paid` `writes` |
| `oxygen posts get` | LIVE provider read of one LinkedIn post. | |
| `oxygen posts reactions` | List a post's reactions (or a comment's reactions with --comment-id). --post MUST be the composite social_id from `posts get`. Metered as an account read. | |
## pricing
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen pricing customer-credit-prices` | Read the customer credit-price catalog, quantity decisions and price provenance used by the Table picker. | |
## profiles
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen profiles current` | Show the profile the next command will use, and where it came from. | |
| `oxygen profiles env` | Print shell `export` lines that pin this terminal to a stored CLI profile. | |
| `oxygen profiles list` | List stored CLI credential profiles. | |
| `oxygen profiles remove` | Remove one stored CLI credential profile. | `writes` |
| `oxygen profiles use` | Switch the active CLI credential profile. | `writes` |
## projects
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen projects color` | Set a folder's colour in the Tables sidebar (rail) for everyone in the workspace. `--color auto` restores the automatic colour. Free. | `writes` |
| `oxygen projects create` | Create a schema-backed table project (folder). Free. Group tables into it with `oxygen tables move --project `. | `writes` |
| `oxygen projects delete` | Delete a non-General folder and its tables. | `writes` |
| `oxygen projects list` | List table projects (folders) with each one's active table count (`tableCount`), so empty and oversized folders show without listing every folder's tables. Free. | |
| `oxygen projects rename` | Rename a table project's display name and slug without changing its tables. | `writes` |
| `oxygen projects tag` | Replace a project's workspace tags (whole set; `--tags ""` clears). See `oxygen tags list` for the vocabulary. | `writes` |
## prompts
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen prompts archive` | Archive a prompt template. Seeded templates cannot be archived. | `writes` |
| `oxygen prompts get` | Read one prompt template by id or slug. | |
| `oxygen prompts list` | List prompt templates in the workspace. | |
| `oxygen prompts upsert` | Create or update a prompt template. | `writes` |
## publishing
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen publishing amplification actions` | The policy's action ledger: what each participant account did (or is about to do) on which post, with status and cost. | |
| `oxygen publishing amplification create` | Create an amplification policy. | `paid` `writes` |
| `oxygen publishing amplification delete` | Delete a policy. | `writes` |
| `oxygen publishing amplification disable` | Disarm a policy and skip every action it had already planned. Always allowed — the off switch is never gated. | `writes` |
| `oxygen publishing amplification enable` | Arm a policy. | `paid` `writes` |
| `oxygen publishing amplification get` | Get one policy: scope, participants, caps, pacing, enabled state, and standing approval. | |
| `oxygen publishing amplification list` | List amplification policies with their scope, caps, and enabled state. | |
| `oxygen publishing amplification update` | Update a policy's participants, actions, caps, or pacing. Tightening a cap takes effect on the next cycle. | `paid` `writes` |
| `oxygen publishing analytics account` | Stored per-account metric series (followers) for connected LinkedIn and X publishing accounts, read once a day in the background. | |
| `oxygen publishing analytics emv` | Set the workspace CPM used for earned-media value, per channel. EMV stays null on any channel whose provider does not expose impressions. | |
| `oxygen publishing analytics post` | One post's stored daily metric series, totals, growth curve, 24h/7d benchmarks against the workspace median, and earned-media value. | |
| `oxygen publishing analytics summary` | Workspace LinkedIn or X analytics. | |
| `oxygen publishing analytics timeseries` | Impressions and engagements EARNED per day across all tracked posts (not only posts published in the range), with reactions, comments and reposts also reported on their own, whether each is… | |
| `oxygen publishing comments approve` | Post one exact previewed reply publicly. A REAL LinkedIn write; refused without --approved and the preview's content hash. | `paid` `writes` |
| `oxygen publishing comments get` | Get one stored public comment with its provider thread and immutable reply-action history. Read-only: no provider call, 0 credits. | |
| `oxygen publishing comments list` | List the Publishing Community work queue, oldest first, with polling freshness/backoff even when empty. | |
| `oxygen publishing comments reply` | Preview an exact public reply and return its action_id + content_hash. Makes no provider call, posts nothing, and uses 0 credits. | `writes` |
| `oxygen publishing comments resolve` | Resolve, ignore, mark spam, or reopen one local public-comment work item. No provider write, 0 credits. | `writes` |
| `oxygen publishing comments update` | Save local draft, notes, assignment, or triage state. Nothing is posted publicly and no credits are used. | `writes` |
| `oxygen publishing drafts accept` | Accept a draft variant into the publish queue. The post is created needs-approval — approve it separately before it can publish. | `writes` |
| `oxygen publishing drafts edit` | Rewrite one variant's text. The first edit snapshots the AI's original copy, so accepting it teaches the Knowledge Graph what you changed. | `writes` |
| `oxygen publishing drafts list` | List post drafts. Defaults to the open queue (queued + edited). | |
| `oxygen publishing drafts reject` | Reject a draft. The reason is filed to the Knowledge Graph so the next drafts learn from it. | `writes` |
| `oxygen publishing ideas add` | File an idea into the backlog. Free — no AI call, nothing scheduled. Turn one into a post later with `publishing drafts accept --publish-at`. | `writes` |
| `oxygen publishing ideas list` | List the idea backlog. | |
| `oxygen publishing import` | Bulk-load scheduled posts from a .csv or .json file. | `paid` `writes` |
| `oxygen publishing media upload` | Upload a local image, video, or PDF in one step and print its media id. | `writes` |
| `oxygen publishing media upload-url` | Create a Publishing media asset and presigned upload URL with required upload headers. | `writes` |
| `oxygen publishing media uploaded` | Verify an uploaded Publishing media object and mark the media asset uploaded. | |
| `oxygen publishing mentions resolve` | Resolve @handles, LinkedIn profile/company links, provider ids, and URNs — through a connected sender (notify=false, free) or the managed scraper (--source scraper, paid, no sender/window needed). | `paid` `writes` |
| `oxygen publishing mentions search` | Find LinkedIn company or person identities for a mention; free, subject to the connected account's read quota. | |
| `oxygen publishing posts approve` | Approve a draft or scheduled post; drafts become scheduled for their saved publish time. | `writes` |
| `oxygen publishing posts boost` | Boost ONE post: your teammates' connected accounts react to and comment on it, once. | `paid` |
| `oxygen publishing posts cancel` | Cancel a draft, scheduled, queued, or failed post and revoke its approval. Use `publishing posts uncancel` to reopen it as an unapproved draft; approve it again before it can publish. | `writes` |
| `oxygen publishing posts create` | Create a personal Publishing post. Use --ugc-participation-id to save it into one program as an unapproved draft; otherwise it defaults to scheduled and publishes only after approval. | `paid` `writes` |
| `oxygen publishing posts delete` | Permanently delete the OXYGEN copy and its settled history, keeping the live platform post intact. | `writes` |
| `oxygen publishing posts draft` | Draft posts with AI, grounded in the workspace Knowledge Graph. | `paid` `writes` |
| `oxygen publishing posts get` | Get one scheduled post with the sender account it publishes from (id, name, profile URL), resolved media previews, its LinkedIn video cover, and attempt history. | |
| `oxygen publishing posts list` | List scheduled posts by publish time, oldest first; pass --order newest for the latest first. Follow next_cursor for more than one page. | |
| `oxygen publishing posts note` | Leave an internal review note on a post, or reply to one with --parent. Never published. | `writes` |
| `oxygen publishing posts notes` | List the internal review notes on a post. Notes are workspace-only — they are never published. | |
| `oxygen publishing posts resolve-note` | Resolve a review note, or reopen it. | `writes` |
| `oxygen publishing posts restore` | Roll a post's TEXT back to an earlier revision (see `publishing posts revisions`). | `writes` |
| `oxygen publishing posts retry` | Move a failed post back to scheduled for another worker attempt. A post that failed with publishing_effect_outcome_uncertain stays locked until you check the account and pass --confirm-not-published. | `writes` |
| `oxygen publishing posts review` | Pre-publish review of a post: deterministic channel lint (free, and blocking at approve) plus an AI voice/claims check against the Knowledge Graph. | `paid` |
| `oxygen publishing posts revisions` | List a post's content history: newest-first revisions with their number, title, text, author, and time. | |
| `oxygen publishing posts uncancel` | Reopen a canceled post as an unapproved draft, keeping its publish time and its attempt history. | |
| `oxygen publishing posts update` | Update an editable draft, scheduled, or failed post. Changing its text or content, the first comment included, revokes approval on an approved post: approve it again. | `writes` |
| `oxygen publishing tags set` | Add and/or remove workspace tags on a post. | `writes` |
## recipes
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen recipes apply` | Install a recipe's kit: every Blueprint stage in order under ONE approval — 0 credits, no provider calls, no external writes, every installed Workflow disabled until you arm it with its own credit… | `writes` |
| `oxygen recipes install` | Install a recipe into the workspace wiki as a playbook page (revisioned, retrieval-grounded, with per-version provenance). | |
| `oxygen recipes list` | Find a GTM play for a goal: recipes ranked by relevance to your words; --view summary for a compact index. Filter by business-case category, journey stage, or audience. | |
| `oxygen recipes show` | Show one recipe: its kit, the install status of each stage here, prerequisites, credits, approval gates, and the playbook body. Alias: `get`. | |
## reviews
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen reviews accept` | Accept a pending message review. | `writes` |
| `oxygen reviews list` | List message reviews. | |
| `oxygen reviews next` | Read the oldest pending review. | |
| `oxygen reviews reject` | Reject a pending message review with optional highlights and auto-rerun. | `writes` |
## rows
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen rows history` | Show row change history. | |
## runs
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen runs get` | Get one run with events. | |
| `oxygen runs list` | List workspace runs, newest first; --table gives one table's full run history. | |
## search
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen search plan` | Plan an Oxygen search or scrape route before running provider jobs. | |
| `oxygen search run` | Preview or enqueue a durable table-backed search/scrape job from a search plan. | `paid` `writes` |
| `oxygen search runs cancel` | Request cancellation for a queued or running search/scrape run. | `writes` |
| `oxygen search runs get` | Get one durable search/scrape run. | |
| `oxygen search runs items` | List search/scrape run items. | |
| `oxygen search runs retry-failed` | Requeue failed search/scrape run items. | `writes` |
| `oxygen search runs wait` | Poll a durable search/scrape run until it finishes. | |
## senders
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen senders checkpoint resend` | Ask LinkedIn to resend the checkpoint code so you can read a fresh one, then submit it with `senders checkpoint solve`. <id> accepts a sender account id, connection id, or Unipile account id. | `writes` |
| `oxygen senders checkpoint solve` | Submit the LinkedIn checkpoint code Unipile is waiting on to finish authentication. <id> accepts a sender account id, connection id, or Unipile account id; <code> is the verification code LinkedIn… | `writes` |
| `oxygen senders checkpoints` | List LinkedIn senders stuck on a security checkpoint (2FA / OTP / in-app validation), each with status, warm-up day, today's usage vs. caps, and the latest error — plus a fleet tally of every… | |
| `oxygen senders connect` | Get a hosted sign-in link to connect a new LinkedIn account (or reconnect with --reconnect). | `writes` |
| `oxygen senders disconnect` | Disconnect a LinkedIn sender account so it stops sending. Works on an account that is already disconnected. <id> accepts a sender account id, connection id, or Unipile account id. | `writes` |
| `oxygen senders get` | Get one LinkedIn sender account with status, limits, daily-reset timezone, and usage. <id> accepts a sender account id, connection id, or Unipile account id. | |
| `oxygen senders health` | Show a one-call health snapshot for a LinkedIn sender: status, the latest error reason, any open security checkpoint, today's usage, the warm-up ramp, when the daily quota resets, and inbox sync… | |
| `oxygen senders inbox-scope get` | Show whether a sender syncs only OXYGEN-started conversations or its entire LinkedIn inbox. | |
| `oxygen senders inbox-scope set` | Set LinkedIn inbox privacy. oxygen_initiated hides and stops ingesting unrelated chats; all opts into the full inbox. | `writes` |
| `oxygen senders inmail-balance` | Show remaining LinkedIn InMail credits for a sender (Premium / Sales Navigator / Recruiter each hold a separate pool). | |
| `oxygen senders limits get` | Show current limits, overrides, working hours (timezone, days, start, end), defaults, hard maximums, and the caution levels above which LinkedIn restriction risk rises, for an account. <id>… | |
| `oxygen senders limits set` | Adjust per-account action limits and working hours. | `writes` |
| `oxygen senders list` | List connected LinkedIn sender accounts with health status, rate limits, and today's usage. Disconnected accounts are hidden unless you pass --status disconnected. | |
| `oxygen senders profiles attach` | Attach senders and/or inboxes to a profile. | `writes` |
| `oxygen senders profiles create` | Create a sender profile: one person's sending identity — their LinkedIn/WhatsApp senders and email inboxes under one name and photo. --from-linkedin seeds the name + avatar from a LinkedIn account… | `writes` |
| `oxygen senders profiles delete` | Delete a sender profile. Refused while the profile still owns inboxes — move them to another profile first; LinkedIn/WhatsApp accounts detach (return to the pool) and are never deleted. | `writes` |
| `oxygen senders profiles detach` | Detach LinkedIn/WhatsApp senders from a profile, returning them to the unassigned pool. --mailboxes is refused: an email inbox always belongs to a sender, so there is no unassigned pool for it —… | |
| `oxygen senders profiles get` | Get one sender profile with the LinkedIn/WhatsApp senders and inboxes attached to it. | |
| `oxygen senders profiles list` | List sender profiles with their per-channel account counts (LinkedIn / WhatsApp / inboxes). | |
| `oxygen senders profiles set-photo` | Set the reusable sender identity's profile picture for FUTURE managed-inbox orders made with --sender <id>. | `writes` |
| `oxygen senders profiles tag` | Replace a sender profile's workspace tags (whole set; `--tags ""` clears) — one edit pools the whole sending identity behind a campaign tag. | `writes` |
| `oxygen senders profiles update` | Update a sender profile's own fields (display name, first/last name, avatar, status). | `writes` |
| `oxygen senders proxy-country` | Move a LinkedIn sender's automatic proxy to another country without reconnecting. | `writes` |
| `oxygen senders sync` | Refresh LinkedIn account state (status, profile) from Unipile. Pass --connection-id to sync one account, or omit it to sync all. | `writes` |
| `oxygen senders tag` | Replace a sender account's workspace tags (whole set; `--tags ""` clears) — e.g. pool the senders behind one campaign tag. See `oxygen tags list` for the vocabulary. | `writes` |
## sequences
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen sequences analytics` | Show selected-window sequencer analytics with persisted status kept separate from operational state, fleet marked-active versus operationally-live counts, current open work… | |
| `oxygen sequences contacts` | List a launched campaign's table-backed contacts with full source variables, contact tags, and factual or assigned sender. | |
| `oxygen sequences contacts rows` | Read the full contact grid projection with exact contact-state filter and native synthetic status columns. | |
| `oxygen sequences contacts-remove` | Remove leads from this campaign only: selected source-table rows (--table-row-ids), or every enrolled lead whose source-table row was deleted (--missing-source-rows; deleting a row never removes… | `paid` |
| `oxygen sequences create` | Create a draft multichannel sequence from a steps JSON file. | `writes` |
| `oxygen sequences delete` | Permanently delete a sequence and everything it owns (enrollments, actions, sender links, schedules). | `paid` `writes` |
| `oxygen sequences draft` | Draft an email outreach sequence with AI, grounded in the workspace Knowledge Graph (voice, positioning, campaign learnings) — Instantly's AI sequence generator, with provenance. | `paid` `writes` |
| `oxygen sequences duplicate` | Duplicate a sequence as a new DRAFT: copies the steps, settings, channels, source table, caps, tags and sender pool. | `writes` |
| `oxygen sequences enroll` | Enroll leads into a sequence. | `writes` |
| `oxygen sequences enrollments` | List per-lead enrollment state plus the latest action status, error, attempts, and retry time. --view compact answers 'when is each lead's next message due' per lead: lead, status, invite… | |
| `oxygen sequences esp` | ESP breakdown of this sequence's email sending scope: which provider each enrolled lead's mail routes through (google/microsoft, plus named gateways like Proofpoint/Mimecast and non-matchable… | |
| `oxygen sequences events` | Chronological activity feed for a sequence (like Instantly's Sending Activities): sends, failures, deferrals, opens, clicks, replies, bounces, unsubscribes, and positive reply-status transitions… | |
| `oxygen sequences get` | Get a sequence's definition, senders, status, and credit usage. --readiness adds the launch check — whether it CAN go live, why not, and the mailbox pool it would send from — without touching it… | |
| `oxygen sequences hubspot-list-import configure` | Preview or start a scheduled HubSpot-list import. Preview first; then pass its reviewed fingerprint with --live --approved. The complete DNC list is applied before leads are read or enrolled. | `paid` `writes` |
| `oxygen sequences hubspot-list-import lists` | List saved HubSpot contact/company segments and readable identity fields available for a Sequence import. | |
| `oxygen sequences hubspot-sync configure` | Preview or save the workspace-wide HubSpot projection. Existing fields need no new grant; creating missing properties requires --approved and HubSpot property-creation access. | `paid` `writes` |
| `oxygen sequences hubspot-sync show` | Show the connected portal, live contact schema, activity/status configuration, component health, and enabled state. | |
| `oxygen sequences leads rows` | Read the complete enrolled-lead grid projection, including sequence status, step, action and failure columns. | |
| `oxygen sequences list` | List sequences with persisted launch status kept separate from current operational state. | |
| `oxygen sequences pause` | Pause an active sequence (stops new dispatches; enrollments resume on un-pause). | `writes` |
| `oxygen sequences pause-company` | Pause messaging to a company in your campaigns — e.g. after a meeting is booked — and resume it later. | `writes` |
| `oxygen sequences paused-companies` | List the companies paused in your campaigns — by a reply (waiting for its classification, or classified into a paused status) or by hand/automation — with the leads each one holds. | |
| `oxygen sequences preview` | The free launch check, as a read: the same preview sequences start returns without --approved. | |
| `oxygen sequences push-external` | Inspect a possible push from an Oxygen table into an existing Smartlead, Instantly, lemlist, or HeyReach campaign. | `paid` `writes` |
| `oxygen sequences reconcile` | Safely reconcile one ambiguous LinkedIn invite/message from provider reads. Zero credits. Preview-only unless --approved; never resends. | `writes` |
| `oxygen sequences recover-capacity` | Preview definitive no-effect terminal failures that Oxygen can replay safely: provider-capacity denials and exact allowlisted request-format defects. | `writes` |
| `oxygen sequences render` | Render a sequence's copy as the web step editor's Preview does: every A/B variant of each step (email subject/body, LinkedIn note/message/InMail, WhatsApp, comments) for leads of the bound table… | |
| `oxygen sequences resume` | Resume a paused sequence. | `writes` |
| `oxygen sequences resume-company` | Resume messaging to a paused company: its held leads continue where they stopped (due steps are spread over the next hour, waits keep their remaining time). | `writes` |
| `oxygen sequences retry-deferred` | Preview or re-ready pending actions deferred by LinkedIn working hours or an email send window on a PAUSED sequence. | `paid` `writes` |
| `oxygen sequences send` | Initiate one net-new LinkedIn message through a one-recipient, one-step hosted Sequence. | `paid` `writes` |
| `oxygen sequences signal` | Record an external GTM signal (e.g. linkedin_connected, email_replied, company_raised_funds, job_change, web_visit, intent) onto a running sequence's enrollment(s) to drive signal-triggered… | |
| `oxygen sequences start` | Preview or start a sequence. | `paid` `writes` |
| `oxygen sequences stats` | Show one sequence's persisted launch status and current operational state separately, including reasons, open work, lifetime sent/terminal-failed/deferral counts, and the funnel. | |
| `oxygen sequences update` | Update a sequence. | `writes` |
| `oxygen sequences variants` | Generic per-step action/base-variant scoreboard for one sequence, plus native email by_mailbox, by_domain, reply types, rates, and explicit unattributed facts. | |
| `oxygen sequences workflows configure` | Preview or maintain an existing legacy preset. | `paid` `writes` |
| `oxygen sequences workflows list` | List the two legacy sequencer presets with armed state, editable config, and ordinary workflow deep-links. | |
## session
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen session output` | Register a local session output file or table. | |
| `oxygen session start` | Start a local Oxygen agent session or update a step. | `writes` |
| `oxygen session status` | Attach a live status message to the current local session. | |
| `oxygen session usage` | Summarize the current local session. Org credit usage is available through billing usage. | |
## sessions
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen sessions list` | List your personal CLI sessions across workspaces, including your organizations; OAuth or personal user session required, organization API keys are refused. | |
| `oxygen sessions revoke` | Revoke one personal CLI session; if this client uses it, calls stop until you reconnect with a new session. OAuth or personal user session required; organization API keys are refused. | `writes` |
## settings
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen settings beta-features get` | Read this workspace's beta-navigation opt-in. | |
| `oxygen settings beta-features set` | Enable or disable beta navigation for every workspace member; admin or owner only. Approve the preference change. This does not disable routes. 0 credits. | `writes` |
| `oxygen settings pages list` | Page visibility in your own sidebar navigation menu in this workspace (Settings → Customise; only you see your choices): hidden_pages, then every page (path, name, section, parent) with hidden… | |
| `oxygen settings pages set` | Hide or show pages in your own sidebar navigation menu in this workspace (Settings → Customise): --hide Unibox,Publishing, --show Unibox, --show-all. | `writes` |
## signals
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen signals leads-today` | List people to contact today, ranked by their most recent GTM intent signal. | |
| `oxygen signals list` | List the raw GTM signal-event feed newest-first (website_visit / profile_view / post_reaction / new_follower), each resolved onto the person it attached to. Read-only. | |
| `oxygen signals record` | Record one inbound GTM signal (website_visit, profile_view, post_engager, new_follower). Internal write — free, no approval. Idempotent on --external-event-id. | `writes` |
| `oxygen signals registry` | Show registered signal types with intent weight, capture status, and workspace tags. Tag a type with `oxygen tags attach signal_type --tags `. Read-only. | |
| `oxygen signals search filters` | Read the LinkedIn post-search filter catalog and credential status; runs no search. | |
| `oxygen signals search plan` | Compile a signal-sourcing request into ordered provider routes without provider calls: the chain, per-route applied/dropped filters, credit estimate, table blueprint, and whether the route can be… | |
| `oxygen signals search preview` | Preview public LinkedIn posts for free on Oxygen's Managed rail (family linkedin_posts): up to 25 per keyword, with author, engagement and the --ai-filter applied. | |
| `oxygen signals search run` | Return a dry-run request or queue a live signal-search ingestion run. | `paid` `writes` |
## signup-leads
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen signup-leads deliveries get` | Get one signup lead webhook delivery by delivery id or event id. | |
| `oxygen signup-leads deliveries list` | List signup lead webhook deliveries for the current organization. | |
| `oxygen signup-leads deliveries retry` | Retry one failed signup lead webhook delivery. | `writes` |
## skills
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen skills doctor` | Check Oxygen skill index reachability and local installer prerequisites. | |
| `oxygen skills get` | Hydrate one exact Oxygen skill entrypoint and its document index. | |
| `oxygen skills install` | Install Oxygen agent skills into local agent skill directories only; uses 0 credits and does not change the Oxygen workspace or call a provider. | |
| `oxygen skills list` | List Oxygen agent skills available from the hosted skill index. | |
| `oxygen skills search` | Find a bounded set of Oxygen skills and matching documents from an outcome. | |
| `oxygen skills workspace archive` | Archive a workspace skill, retaining files and Knowledge history; 0 credits, no inference/provider calls or new tool/spend/approval authority. | `writes` |
| `oxygen skills workspace create` | Create workspace-<name>, visible to this workspace's members; 0 credits, no inference/provider calls or new tool/spend/approval authority. | `writes` |
| `oxygen skills workspace get` | Read a workspace skill's SKILL.md or one supporting text file, with exact content, revision and the document index. Skills are task guidance; they grant no tool, spend or approval authority. | |
| `oxygen skills workspace import` | Import to workspace members atomically, create-only; ≤50 text files/1 MB; scripts inert; 0 credits, no inference/paid provider calls or new tool/spend/approval authority. | `writes` |
| `oxygen skills workspace list` | Find skills shared with workspace members by literal substring of name or description; short keywords work best; read-only, 0 credits; next_cursor continues the list. | |
| `oxygen skills workspace update` | Replace a skill file at its expected revision; read first, stale revisions refuse; 0 credits, no inference/provider calls or new tool/spend/approval authority. | `writes` |
## sourcing
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen sourcing plan` | Classify a sourcing request and recommend provider routes without executing paid tools. | |
## spintax
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen spintax generate` | Generate wording or copy variations as spintax: live (default) costs 3 credits and requires approval and a credit ceiling; explicit dry_run is a free preview. | `paid` `writes` |
## status
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen status` | Compare the local Oxygen CLI version against the active profile's deployed Oxygen API. | |
## supabase
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen supabase cancel` | Request cancellation of every still-active child table run in an import. | `writes` |
| `oxygen supabase catalog` | Inspect readable base tables, columns, PostgreSQL types, primary keys, and estimated rows through the saved read-only connection. | |
| `oxygen supabase connect` | Validate and encrypt a managed Supabase PostgreSQL URL. | `writes` |
| `oxygen supabase get` | Get aggregate and per-table status, row counts, failures, and deep-links for a Supabase import. | |
| `oxygen supabase import` | Start the previously previewed snapshot/refresh as durable Postgres-backed work. | `writes` |
| `oxygen supabase plan` | Preview exact Oxygen Table creates/refreshes, row-limit posture, deletion semantics, and the schema fingerprint required to start. No writes and 0 credits. | |
| `oxygen supabase retry` | Retry failed child table items without duplicating already-upserted source rows. | `writes` |
## support
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen support admin assign` | Hand a live Thread to a named human, for escalation past an agent's authority or judgment boundary (staff only). | `writes` `staff` |
| `oxygen support admin claim` | Claim a live Plain Thread and move it to In progress without overwriting another assignee (staff only). | `writes` `staff` |
| `oxygen support admin done` | Preview or mark a Plain Thread Done after the exact verified agent reply; new customer activity reopens it to Todo (staff only). CLI completion is agent-only. | `writes` `staff` |
| `oxygen support admin draft` | Stage a reply as a team-only Plain note; this never sends to the customer (staff and agents). | `writes` |
| `oxygen support admin field-set` | Record OXYGEN workflow state on a live Thread as structured, filterable Plain data — which version and commit carry a fix, and the PR that shipped it (staff only). | `writes` `staff` |
| `oxygen support admin get` | Show one live Plain Thread, its routing metadata, and customer-visible messages (staff only). | `staff` |
| `oxygen support admin label-add` | Add an active Plain label by external ID (staff only). | `writes` `staff` |
| `oxygen support admin label-remove` | Remove a Plain label by external ID (staff only). | `writes` `staff` |
| `oxygen support admin list` | List live Plain Threads across customer Tenants (staff only). | `staff` |
| `oxygen support admin note` | Add a team-only internal note to a live Plain Thread (staff only). | `writes` `staff` |
| `oxygen support admin open` | Return the exact Plain Inbox URL for one live Thread (staff only). | `staff` |
| `oxygen support admin priority` | Set the native Plain priority for a live Thread (staff only). | `writes` `staff` |
| `oxygen support admin reply` | Preview or send a guarded public reply on the Thread's native Plain channel as Oxygen Support (staff only). CLI delivery is agent-only; named humans use Plain Inbox or Plain MCP. | `writes` `staff` |
| `oxygen support admin setup` | Reconcile the shared Plain workspace against the taxonomy OXYGEN declares in code: request-type labels and intake fields, plus the workflow-state labels and release fields the support loop writes. | `writes` `staff` |
| `oxygen support admin snooze` | Park a live Thread until a named time, so work blocked on a release, a provider, or a scheduled retry stops reading as unanswered (staff only). | `writes` `staff` |
| `oxygen support admin start` | Set a live Plain Thread to Plain TODO with the In progress detail when OXYGEN work remains after a reply, preserving its assignee (staff only). | `writes` `staff` |
| `oxygen support admin todo` | Return a snoozed Thread to the queue when its blocker clears (staff only). Never reopens a Done Thread: Plain does that on real customer activity. | `writes` `staff` |
| `oxygen support chat` | Start a Plain Chat conversation from one message, or pass an existing Thread ID to continue it. | `writes` |
| `oxygen support file` | Create a structured Plain support conversation with a subject and required message. | `writes` |
| `oxygen support get` | Show one Plain support Thread and its customer-visible timeline. | |
| `oxygen support list` | List Plain support Threads for the active organization. | |
| `oxygen support reply` | Reply to a Plain Chat thread; migrated or native-channel history continues in one linked Chat thread. | `writes` |
## suppressions
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen suppressions add` | Add or refresh selected lead ids on the org do-not-contact list so the sequencer never enrolls them again. Use --lead or --leads (1-500). Idempotent; --reason defaults to manual. | `writes` |
| `oxygen suppressions addresses` | List the org's blocked email ADDRESSES, newest first (bounces, unsubscribes, and `suppressions import` land here). | |
| `oxygen suppressions companies` | List explicit company-domain and LinkedIn-company suppressions. These stop every Sequence channel. | |
| `oxygen suppressions crm-backfill` | Create a CRM person record for everyone already on the do-not-contact list, so you can see who they are. | `writes` |
| `oxygen suppressions domains` | List the org's whole-domain email blocks, newest first. Filter by --reason (manual \| complaint \| policy) or --search (case-insensitive substring of the domain). | |
| `oxygen suppressions hubspot lists` | List contact/company saved lists and readable identity properties. Reads definitions only; no memberships or writes. | |
| `oxygen suppressions hubspot sync` | Preview or arm additive HubSpot → DNC sync. Requires at least one contact/company list. Live requires the exact dry-run fingerprint and approval; never enrolls or sends. | `paid` `writes` |
| `oxygen suppressions import` | Bulk-import a do-not-contact blocklist from a file (newline / comma / whitespace separated, max 5000). | `writes` |
| `oxygen suppressions import-identities` | Import a source-neutral typed JSON array into DNC. | `writes` |
| `oxygen suppressions import-person` | Import one person as one DNC subject with any combination of email, LinkedIn, E.164 phone, and an explicitly supplied company domain. The domain is company-wide and is never inferred from --email. | `writes` |
| `oxygen suppressions list` | List the org's do-not-contact suppressions, newest first. Filter by --reason or by --search (case-insensitive substring of the lead provider id). | |
| `oxygen suppressions phones` | List phone suppressions (strict E.164) used by call, WhatsApp, and Sequence safety gates. | |
| `oxygen suppressions policy reset` | Return one rule (--rule) or every rule (--all) to the shipped default. | `writes` |
| `oxygen suppressions policy set` | Change one rule. Example: `oxygen suppressions policy set --rule linkedin_reply --effect stop_only` stops a LinkedIn replier's current campaign without blocking them from every future one. | `writes` |
| `oxygen suppressions policy show` | Show every do-not-contact rule with its current setting, whether that is your change or the shipped default, and the values it accepts. | |
| `oxygen suppressions remove` | Remove selected leads or every identity of selected merged people from the org do-not-contact list. | `writes` |
| `oxygen suppressions remove-address` | Remove one blocked email address or 1-500 with --emails immediately; this can restore sending eligibility. | `writes` |
| `oxygen suppressions remove-company` | Remove one explicit company suppression or 1-500 exact identities with --identities-json. | `writes` |
| `oxygen suppressions remove-domain` | Remove one whole-domain email block or 1-500 with --domains immediately; this can restore sending eligibility. | `writes` |
| `oxygen suppressions remove-phone` | Remove one phone suppression or 1-500 exact E.164 numbers with --phones. | `writes` |
## table-actions
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen table-actions resolve` | Record a human-verified uncertain Table action outcome without repeating it. Use cells resolve for row/column coordinates. | `writes` |
## table-ingestions
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen table-ingestions append` | Append generated row chunks with items [{position:0,payload:{rows:[{column:value}]}}]. | `writes` |
| `oxygen table-ingestions cancel` | Request cancellation for a durable table ingestion run. | `writes` |
| `oxygen table-ingestions create-tool-page` | Create a bounded paged tool-source ingestion. | `paid` `writes` |
| `oxygen table-ingestions get` | Get one durable table ingestion run. For provider pages, completed means its bounded work finished; inspect table-ingestions items for the source cursor and exhaustion. | |
| `oxygen table-ingestions items` | List ingestion items, including completed pages. | |
| `oxygen table-ingestions retry-failed` | Requeue failed items for a durable table ingestion run. | `writes` |
| `oxygen table-ingestions wait` | Wait for a table ingestion run (read-only, no credits). | |
## table-runs
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen table-runs cancel` | Request cancellation for a durable table action run. | `writes` |
| `oxygen table-runs create` | Create a durable background run for table tool-column actions. | `paid` `writes` |
| `oxygen table-runs effect-unknown` | List the items of a run whose external write was dispatched but never confirmed. Oxygen will not retry them on its own: verify each destination, then record what you found with `oxygen cells resolve`. | |
| `oxygen table-runs get` | Get one durable table action run. | |
| `oxygen table-runs items` | List row items for a durable table action run. | |
| `oxygen table-runs list` | List durable table action runs for one table. For every run of the table, imports included, use `runs list --table `. | |
| `oxygen table-runs pause` | Pause a durable table action run before it starts more row jobs. | `writes` |
| `oxygen table-runs provider-summary` | Summarize provider attempts, upstream request events, and credit capture/release for a table action run. | |
| `oxygen table-runs resume` | Resume a paused durable table action run. | `writes` |
| `oxygen table-runs retry-failed` | Retry failed Table items or wake guarded Function callbacks from completed results at zero additional credits. | `paid` `writes` |
| `oxygen table-runs wait` | Poll a durable table action run until it finishes. | |
## tables
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen tables activity` | Show background runs active on a workspace table right now, with a worker-queue health rollup. | |
| `oxygen tables archive` | Archive a workspace table without dropping physical data. Hides it indefinitely with no purge timer; for cleanup with a restorable deadline use `tables delete`. | `writes` |
| `oxygen tables auto-dedupe disable` | Disable (clear) a table's standing auto-dedupe configuration. | `writes` |
| `oxygen tables auto-dedupe get` | Show a table's standing auto-dedupe configuration. | |
| `oxygen tables auto-dedupe set` | Enable a standing auto-dedupe: after every write (insert, upsert, import, send, webhook), duplicate groups containing a just-written row are collapsed by the keep policy — losers are DELETED… | `writes` |
| `oxygen tables auto-run disable` | Disable (clear) a table's standing auto-run configuration. | `writes` |
| `oxygen tables auto-run get` | Show a table's standing auto-run configuration (columns queued automatically when new rows are written). | |
| `oxygen tables auto-run set` | Enable a standing auto-run: automatically queue the given columns for rows written to this table (imports, inserts, upserts), including workflow audience upserts and own-follower capture. | `paid` `writes` |
| `oxygen tables changes` | Read a Table's live runs and queue health. | |
| `oxygen tables column-stats` | Read per-column completion and provider statistics; large Tables use labeled samples. | |
| `oxygen tables create` | Create a table private to the active workspace. Free — 0 Oxygen credits. To create a table and import a file in one step, use `tables import --create `. | `writes` |
| `oxygen tables dedupe` | Collapse duplicate rows by normalized (email/domain/linkedin) or fuzzy-label keys, or cross-check a column against another table. | `paid` |
| `oxygen tables delete` | Delete workspace tables: archives now and schedules the physical purge (default 14 days; restorable via `tables restore` until then). --now purges immediately and permanently — it previews and… | `writes` |
| `oxygen tables delete-row` | Delete one workspace table row. A lead enrolled in a campaign stays enrolled; the response names those campaigns. | `writes` |
| `oxygen tables delete-rows` | Delete exact workspace row IDs. For a matching filtered selection, use tables rows remove-selection. Campaign enrollments stay enrolled; the response names those campaigns. | `writes` |
| `oxygen tables describe` | Describe a workspace table and its columns. | |
| `oxygen tables duplicate` | Duplicate a workspace table. Copies row values unless --schema-only is set. | `writes` |
| `oxygen tables edit` | Rename a Table or move it to a workspace project; returns the saved Table. | `writes` |
| `oxygen tables export` | Export workspace table rows as JSON, JSONL, CSV, or a human-readable table. Rows only, capped at 1000; to copy a whole table including its columns and every row, use `tables export-bundle`. | |
| `oxygen tables export-bundle` | Export a workspace table as a portable bundle (schema + every row) for cross-environment / cross-org copies. | |
| `oxygen tables export-csv` | Download every row in the exact filtered Table view as streamed CSV. | |
| `oxygen tables favorite` | Star/unstar exactly one table or folder (saved per-member preference). Free (0 credits). Catalog stars differ. | `writes` |
| `oxygen tables favorites` | Read starred Tables/folders (per-member preference; free (0 credits)); next_cursor. Catalog stars differ. | |
| `oxygen tables fill-progress` | Read hosted Table fill progress and any actionable ingestion failure. | |
| `oxygen tables followers check` | Free order preview. | |
| `oxygen tables followers order` | Place the follower order after checking it. | `paid` `writes` |
| `oxygen tables followers status` | Read a fee-budgeted own-key follower order's total fee ceiling, allocated attempts, recorded fees and recovery outcome by its original request ID, including interrupted setup. | |
| `oxygen tables hubspot import` | Preview or import HubSpot contacts/companies into a new table or Records. | `paid` `writes` |
| `oxygen tables hubspot lists` | List the connected portal's saved contact/company segments and readable identity properties. | |
| `oxygen tables import` | Import JSON, JSONL, CSV, or XLSX rows into a workspace table. | `writes` |
| `oxygen tables import-bundle` | Recreate a workspace table from an export-bundle file in this org. | `writes` |
| `oxygen tables import-csv` | Import inline CSV into a hosted Table through its durable ingestion run. Use staged upload for large files. | `writes` |
| `oxygen tables import-file` | Import small base64 file bytes through the shared multipart import API; use staged upload for large files. | `writes` |
| `oxygen tables import-preview` | Preview a staged file's headers, rows and existing-table mapping; writes no imported rows. | |
| `oxygen tables import-staged` | Start a durable hosted import from this workspace's staged file; choose an existing table or create_name. | `writes` |
| `oxygen tables import-upload` | Prepare a scoped storage upload for a hosted Table import; uploads and imports are separate, inspectable steps. | `writes` |
| `oxygen tables ingestion retry` | Retry failed items in this Table's hosted ingestion run. | `writes` |
| `oxygen tables ingestion stop` | Cancel this Table's active hosted ingestion run. | `writes` |
| `oxygen tables insert` | Insert rows into a workspace table. Table writes cost 0 Oxygen credits; paid column runs are separate. | `writes` |
| `oxygen tables link` | Link two tables: Oxygen finds the column that joins them, works out the direction, shows you how many rows will match, and on approval links every row. | `paid` |
| `oxygen tables link-suggest` | Plan column links and matching row counts between Tables; creates no relation. Apply with tables link --to (MCP oxygen_tables_link_bulk). | |
| `oxygen tables list` | List workspace tables in the current tenant database. | |
| `oxygen tables move` | Move one or more workspace tables into a project (folder) in one call. Rows, columns, runs, and provenance are preserved. Free; reverse it by moving the table back. | `writes` |
| `oxygen tables pipedrive filters` | Read connected Pipedrive saved filters and custom-field definitions; no people imported. | `paid` |
| `oxygen tables pipedrive import` | Preview or run a Pipedrive saved people filter into a NEW table. | `paid` `writes` |
| `oxygen tables preview` | Preview a workspace table with projected rows and summary stats. | |
| `oxygen tables promote` | Write bound rows' columns onto their matched CRM records (Records<->Tables). | `paid` |
| `oxygen tables query` | Read raw Table rows or --format grid cell previews/state with grid.nextCursor, in a JSON envelope. | |
| `oxygen tables records import` | Create a Table from a Records object or saved view. --dry-run counts the records and lists the columns without creating anything. --refresh sync also arms a schedule (a Workflow you can pause)… | `paid` `writes` |
| `oxygen tables records status` | Show a Records-imported Table's source object and view, the last sync's counts and its schedule. Read-only, 0 credits. | |
| `oxygen tables records sync` | Copy a Records-imported Table's source again now: new records are added, changed cells updated, edited cells kept, and departed records marked in_records=false (they flip back if they return). | `paid` `writes` |
| `oxygen tables recover-pending` | Recover existing BetterContact email or phone requests and inspect terminal verification blockers; no new orders. | `writes` |
| `oxygen tables relate` | Link two tables (the web's "Link to another table"): creates an empty linked-record column on BOTH tables, so links show and can be removed from either side; matching values are not required. | |
| `oxygen tables relations archive` | Archive a native relation, its active links, and both relation columns while preserving history. Previews by default. | `paid` `writes` |
| `oxygen tables relations list` | List the native relations visible from one table, including cardinality, target, and active link count. | |
| `oxygen tables relations update` | Rename either side of a relation or change its cardinality. Endpoints and slugs stay immutable. Previews by default. | `paid` `writes` |
| `oxygen tables rename` | Rename a workspace table display name and slug. | `writes` |
| `oxygen tables restore` | Restore an archived or delete-scheduled table: cancels the purge timer and reclaims its slug. A table whose purge has begun (lifecycle.purgeStartedAt) can no longer be restored. | `writes` |
| `oxygen tables rows edit` | Patch one row's values and return the committed row. | `writes` |
| `oxygen tables rows insert` | Insert Table row values and return the committed rows plus any existing automatic run or dedupe grant. | `writes` |
| `oxygen tables rows inspect` | Read one row; field selects column keys and hydrate_relations=1 includes relations. projection=value returns lossless JSON fragments; resume value_cursor with identical table/row/field/path. | |
| `oxygen tables rows page` | Read a Table row page with the same filter, sort, counts and CRM relationship projection as the grid. | |
| `oxygen tables rows range-ids` | Resolve a bounded row range into exact ids, preserving the current filter, search, sort and CRM scope. | |
| `oxygen tables rows relationship-set` | Link one Table row to a target row through a relation (Table or CRM) and return the link. | `writes` |
| `oxygen tables rows relationships` | Read one Table row's linked records, across Table relations and CRM relationships, and the relations it can link through. | |
| `oxygen tables rows remove` | Remove one row from a workspace Table. | `writes` |
| `oxygen tables rows remove-selection` | Permanently delete Table rows by a readable filter tree, exact ids or a matching selection. Unsupported scope fields are refused. | `writes` |
| `oxygen tables runs history` | Read this Table's action-run history and progress. | |
| `oxygen tables runs pause` | Pause one durable Table run without discarding its approved scope. | `writes` |
| `oxygen tables runs preview` | Preview selected Table action costs and provider availability, including draft column definitions; starts no run. | `writes` |
| `oxygen tables runs provider-summary` | Read a Table run's provider outcomes, fulfilled rows, costs and timing. | |
| `oxygen tables runs resume` | Resume a paused Table run within its existing approved scope and credit ceiling. | `writes` |
| `oxygen tables runs retry` | Retry failed cells; a fresh allowance requires approved, retry_plan_hash and max_additional_credits. Uncertain effects require separate approval. | `paid` `writes` |
| `oxygen tables runs start` | Start selected Table actions using the browser's exact row-selection contract. Paid runs require an approved max_credits ceiling. | `paid` `writes` |
| `oxygen tables runs stop` | Cancel one durable Table run; never repeats external provider effects. | `writes` |
| `oxygen tables schedule list` | List a table's scheduled column refreshes. | |
| `oxygen tables schedule remove` | Remove a column's scheduled refresh (deletes the backing cron workflow; future scheduled runs stop). | `writes` |
| `oxygen tables schedule set` | Create or replace a column's scheduled refresh (a cron-triggered hosted workflow; visible via `oxygen workflows list`). | `paid` `writes` |
| `oxygen tables send` | Copy rows from one table into another as a durable background run (free, resumable). | `writes` |
| `oxygen tables sources` | List every way a table can start — imports, company/people/signal sources, webhooks, functions — with the provider count and per-row credit estimate behind each. | |
| `oxygen tables tag` | Replace a table's workspace tags (Tags primitive; "" clears). Tags link the table to sequences, wiki pages, and workflows carrying the same tag — browse with `oxygen tags get `. | `writes` |
| `oxygen tables tidy-suggest` | Read-only tidy analysis for a workspace table: duplicate columns, formatting issues, hide candidates, and value-sanity findings. | |
| `oxygen tables unlink` | Unlink one exact pair of rows by archiving their relation edge. The relation definition and both rows remain. Previews by default. | `paid` |
| `oxygen tables update` | Update one workspace table row. | `writes` |
| `oxygen tables upload` | Preview or import small uploaded CSV, JSON or XLSX bytes through the exact browser import contract. Preview writes no rows. | `writes` |
| `oxygen tables upsert` | Insert or update rows in a workspace table by a column key. | `writes` |
| `oxygen tables views create` | Create a saved view. | `writes` |
| `oxygen tables views delete` | Delete a saved view by id. | `writes` |
| `oxygen tables views get` | Get one saved view by id. | |
| `oxygen tables views list` | List a table's saved views. | |
| `oxygen tables views update` | Update a saved view. | `writes` |
| `oxygen tables watcher create` | Create and activate a Professional Network Post Engagers table after approval of its exact preview. Starts collection now and daily at 07:00 UTC under the approved per-cycle cap. | `paid` `writes` |
| `oxygen tables watcher get` | Read a table's Professional Network Post Engagers configuration and status. Free. | |
| `oxygen tables watcher pause` | Pause daily monitoring while retaining the table and collected rows. | `writes` |
| `oxygen tables watcher preview` | Free configuration and credit preview: no provider calls, writes, or scheduling. Omit --max-credits for a recommendation and preview hash. Ask for real profile URLs; never invent them. | |
| `oxygen tables watcher resume` | Resume paid daily monitoring after reviewing a fresh preview and approving its per-cycle credit cap. | `paid` `writes` |
| `oxygen tables watcher update` | Edit watched profiles or the per-cycle cap from the table. Preview the changes first; approval binds the exact new configuration. | `paid` `writes` |
| `oxygen tables webhook create` | Create a direct webhook endpoint that writes inbound JSON into a table (600–12,000 requests a minute by plan size, per endpoint and sender IP; 429 returns Retry-After; `oxygen limits show` lists… | `writes` |
| `oxygen tables webhook deliveries` | List direct table webhook deliveries and auto-run enqueue status. | |
| `oxygen tables webhook get` | Get one direct table webhook by endpoint id. | |
| `oxygen tables webhook list` | List direct table webhooks. | |
| `oxygen tables webhook update` | Update a direct table webhook endpoint. | `writes` |
## tags
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen tags attach` | Replace tags on a Signal type, saved Dashboard, runtime Agent, or saved Ads search. [] clears the item; no provider call is made. | `writes` |
| `oxygen tags create` | Declare a tag before anything carries it, with an optional description, color, and pin. Idempotent: run it on a tag already in use to annotate it — carriers are never touched. | `writes` |
| `oxygen tags delete` | Delete one or more tags: strips them from EVERY carrier (archived and finished items included) and removes their declaration. | `writes` |
| `oxygen tags get` | Everything carrying one tag — publishing posts, knowledge pages, sequences, tables, workflows, recipes, inbox conversations, CRM records, mailboxes, sender accounts, sending domains, projects… | |
| `oxygen tags list` | List every workspace tag with per-primitive counts, most-used first. | |
| `oxygen tags merge` | Merge one or more tags into a single target, EVERYWHERE they appear (archived rows included). | `writes` |
| `oxygen tags rename` | Rename one tag EVERYWHERE it appears (every primitive, archived rows included). | `writes` |
| `oxygen tags update` | Change a tag's description, color, or pin. Only the flags you pass change; use the --clear-* flags to remove a value. To change the LABEL use `tags rename`. | `writes` |
## tools
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen tools check-access` | Read tool access for this workspace; verify_credential explicitly opts into a provider credential probe. | |
| `oxygen tools enums get` | Fetch the accepted values for one provider enum catalog. Use this before drafting payloads with enumRef fields. | |
| `oxygen tools enums list` | List enum catalogs for a provider (or all providers). | |
| `oxygen tools favorite` | Favourite one column-catalog entry for this workspace: a native column (find_email, preset:person_enrich, prompt:icp_fit_score_v1) or a vendor tool (tool:<tool_id>). | |
| `oxygen tools favorites` | List your favourite column-catalog entries for this workspace, with each native entry's per-row price. | |
| `oxygen tools get` | Read one provider operation's workspace-effective fee with --view pricing --json. | |
| `oxygen tools run` | Preview or run one tool. `--mode dry-run` quotes the exact inputs at 0 credits without a provider call or data write; `--mode live` executes after any required approval and credit ceiling. | `paid` `writes` |
| `oxygen tools search` | Search provider operations and OXYGEN columns for 0 credits; the default list is bounded. | |
| `oxygen tools unfavorite` | Remove one column-catalog entry from your favourites for this workspace. | |
## ugc
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen ugc amplification get` | Read this program's current amplification authority and immutable action history. Master workspace only; 0 credits, no provider call. | |
| `oxygen ugc amplification reconcile` | Preview recording a provider observation for an uncertain program action. Confirmation needs a signed-in operator and --approved; it never contacts the provider or authorizes a retry. | `writes` |
| `oxygen ugc amplification save` | Save exact opted-in sender scope and bounded post-specific amplification. Enabling needs explicit approval. | `paid` `writes` |
| `oxygen ugc analytics get` | Read UGC analytics in the active workspace. | |
| `oxygen ugc applications list` | Applications to public programs. Without --program-id: the ones this creator workspace sent, with status. With --program-id: the ones your program received (brand), pending first. Read-only. | |
| `oxygen ugc calendar list` | Read the program's enrolled post calendar in a bounded UTC date range (up to 42 days). Stored data only, 0 credits. | |
| `oxygen ugc creators accept` | Accept an exact invitation in the creator workspace. Check it first with creators invitation --token; a refusal names its reason (wrong account, the program's own workspace, withdrawn or expired). | `writes` |
| `oxygen ugc creators approve` | Approve a pending application to your program (from applications list --program-id). The applicant becomes a creator at once and is emailed. Free: 0 credits. | `writes` |
| `oxygen ugc creators decline` | Decline a pending application to your program. No email is sent, and the applicant cannot apply to this program again (you can still invite them). Free: 0 credits. | `writes` |
| `oxygen ugc creators invitation` | Read what an invitation link points at before accepting it: the program, the invited email (masked), the posting deal, and can_accept with the reason when this account or workspace cannot accept it. | |
| `oxygen ugc creators invite` | Preview an invitation email (0 credits) for one creator (--email) or up to 50 at once (--emails); send with --approved --preview-token from that preview and the same recipients. | `writes` |
| `oxygen ugc creators list` | Read creators (name, picture, LinkedIn URL and posting_target, their own deal; null follows the program standard) and invitations, including persisted email delivery status. Read-only. | |
| `oxygen ugc creators revoke-invite` | Revoke an unaccepted invitation. | `writes` |
| `oxygen ugc creators send-invite` | Preview email for an existing pending invitation; send or resend with --approved --preview-token. | `writes` |
| `oxygen ugc creators set-target` | Set one creator's own posting deal, e.g. 1/month while the program asks for 2/month, on a joined creator (--participation-id) or a pending invitation (--invitation-id). none returns them to the… | `writes` |
| `oxygen ugc creators update` | Connect an existing LinkedIn sender, change approval authority, or leave the entire program. | `writes` |
| `oxygen ugc knowledge list` | Read UGC knowledge in the active workspace. Read-only. | |
| `oxygen ugc memberships list` | Read active program memberships for the creator workspace. Free, stored and provider-free. | |
| `oxygen ugc peer-amplification get` | Read this creator's own peer-engagement policy, host gate, readiness and immutable receipts. Creator workspace only; free and provider-free. | |
| `oxygen ugc peer-amplification reconcile` | Preview recording observed evidence for this creator's effect_unknown peer action. Approval records the outcome without a provider call or retry. | `writes` |
| `oxygen ugc peer-amplification save` | Preview or save this creator workspace's own peer-engagement consent, sender, voice and caps. The creator wallet pays; the host gate must also be enabled. | `paid` `writes` |
| `oxygen ugc posts approve` | Record the creator's approval of the current post, or the organizer's if the creator delegated it. | `paid` `writes` |
| `oxygen ugc posts comment cancel` | Cancel a scheduled comment before it runs, including one still waiting for its post. Organizer workspace only; a comment that is already posting or posted cannot be cancelled. | `writes` |
| `oxygen ugc posts comment schedule` | Schedule one exact comment on a creator's program post from one of this workspace's LinkedIn accounts; on a post not live yet it waits. | `paid` `writes` |
| `oxygen ugc posts draft` | Draft a post from your topic in your voice, grounded in the program's shared pages. A bare call is a free preview; the creator repeats it with --request-id --approved --max-credits to run it. | `paid` `writes` |
| `oxygen ugc posts draft-status` | Read the original paid draft request and saved result without generating again. Creator workspace only, 0 credits. | |
| `oxygen ugc posts enroll` | Enroll one existing creator-owned post in this participation. | `writes` |
| `oxygen ugc posts history` | Read retained public comments, metrics, and publication receipts for one enrolled post. Stored data only, 0 credits. | |
| `oxygen ugc posts list` | Read UGC posts in the active workspace. Read-only. | |
| `oxygen ugc posts remove` | Remove one creator-owned post from a program before publication while retaining immutable enrollment history. The personal draft remains in Publishing. | `writes` |
| `oxygen ugc posts update` | Edit or schedule an enrolled post with creator or delegated authority; publishing gates still apply. | `writes` |
| `oxygen ugc profile get` | Read your creator profile (topics, audience and LinkedIn profile URL). Free, read-only. | |
| `oxygen ugc profile update` | Save your creator profile, which brands whose programs you joined can read. --topics replaces the list; --audience "" clears it. Free: 0 credits. | `writes` |
| `oxygen ugc programs apply` | Join or apply to a public program from programs discover or a join link: with join_policy automatic you join at once (joined: true, with your participation); otherwise the brand approves or… | `writes` |
| `oxygen ugc programs archive` | Archive a program: stop future access, publishing, tracking and amplification, revoke pending invitations and request cancellation of sponsorship renewals. | `writes` |
| `oxygen ugc programs create` | Create a master UGC program from its product link; the name and icon come from the site. Creators approve their own posts; brands cannot require approval. Free: 0 credits, no provider call. | `writes` |
| `oxygen ugc programs delete` | Permanently delete a program and its pending invitations. | `writes` |
| `oxygen ugc programs discover` | Public programs from every brand on Oxygen that you can apply to, with each brand's deal, brief excerpt and join_policy (automatic: you join at once; approval: the brand decides), and whether you… | |
| `oxygen ugc programs duplicate` | Copy a program's settings, shared knowledge and posting target into a new active program. Free: 0 credits. Never copies creators, invitations, posts or sponsorship. | `writes` |
| `oxygen ugc programs get` | Read UGC program in the active workspace. Read-only. | |
| `oxygen ugc programs list` | Read UGC programs in the active workspace, archived ones included unless --status filters. Read-only. | |
| `oxygen ugc programs restore` | Restore an archived program. Creators removed earlier stay removed, revoked invitations stay revoked, and cancelled sponsorships need a new preview and confirmation. | `writes` |
| `oxygen ugc programs update` | Update program settings and selected shared knowledge. | `writes` |
| `oxygen ugc sponsorship cancel` | Preview stopping one program sponsorship. | `writes` |
| `oxygen ugc sponsorship confirm` | Confirm the exact sponsorship quote as the same signed-in master admin. Card quotes return checkouts; credit quotes start the reservations or fail with insufficient_credits. | `paid` `writes` |
| `oxygen ugc sponsorship get` | Read sponsorship in the active workspace. Creators see their remaining credits and exact organizer access; masters see program payment status. Read-only. | |
| `oxygen ugc sponsorship preview` | Preview sponsoring creators who already joined, as a signed-in master admin: funding is card (seat plus 10,000-credit grant) or credits (one LinkedIn reservation per creator). | |
| `oxygen ugc voice get` | Read UGC voice in the active workspace. Read-only. | |
| `oxygen ugc voice import` | Preview all retrievable LinkedIn history and voice inference; approve a total credit ceiling to start. Use --import-id to resume a safely interrupted import with its saved progress and spend. | `paid` `writes` |
| `oxygen ugc voice save` | Save your own writing preferences and examples as a private provisional Knowledge voice. | `writes` |
## unibox
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen unibox metadata` | Read the complete authenticated inbox account, filter and tag metadata, including each sender profile (person) and its id. | |
## update
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen update` | Update the Oxygen CLI from npm, then refresh the Oxygen agent skills in the global skill folders of Codex, Claude Code and Cursor (OXYGEN_SKIP_SKILLS=1 skips that). | `writes` |
## verify
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen verify email` | Verify one or more email addresses. | `paid` |
## viewers
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen viewers enrichment` | Turn automatic full-profile enrichment of NEW profile viewers on or off for the viewers table (Up2Data profile: about, current role and company, experience, education, location). | `writes` |
| `oxygen viewers import` | Start (or re-arm, or resume a paused account) a durable profile-viewers (WVMP) import. | `writes` |
| `oxygen viewers pause` | Switch the profile-viewers import off for one account or all: rows and the table stay exactly as they are, and `viewers import --account [` switches it back on. | `writes` |
| `oxygen viewers status` | Show durable profile-viewers (WVMP) import progress: `accounts[]` lists every connected LinkedIn account with its display_name, headline, picture_url, per-account `on` (true when switched on… | |
## visuals
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen visuals download` | Download a file with SHA-256 verification; refuses to overwrite existing local files. | |
| `oxygen visuals file-get` | Read source, file metadata, provenance and web/download links. | `writes` |
| `oxygen visuals render-cancel` | Request cancellation; read state to verify it stopped. | |
| `oxygen visuals render-get` | Read render state and output downloads; optionally wait for a terminal state. | |
| `oxygen visuals render-preview` | Preview rendering without starting paid compute. | |
| `oxygen visuals render-start` | Approve an exact preview and enqueue one idempotent render job. | `paid` |
| `oxygen visuals source-create` | Save an immutable HTML/CSS/SVG source revision; no code executes. | |
## voice
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen voice numbers buy` | Buy phone numbers for the dialer. | `paid` `writes` |
| `oxygen voice numbers cap set` | Set one phone number's daily dial cap (dials per day, 1-300; new numbers get 100). | `writes` |
| `oxygen voice numbers list` | List the org's phone numbers with warm-up state, daily cap, and what each one costs per month. Optional --tag narrows to one campaign's numbers. | |
| `oxygen voice numbers release` | Give a number back to the carrier and stop its monthly charge. | `writes` |
| `oxygen voice numbers requirements` | What a country demands before it sells a number (business details, documents). Free, and read live from the carrier. | |
| `oxygen voice numbers search` | Find numbers you could buy, by area code or region. Free: searching buys nothing and reserves nothing, so a listed number can be gone by the time you buy it. | |
| `oxygen voice numbers tag` | Replace a phone number's workspace tags (whole set; `--tags ""` clears) — e.g. pool the numbers dialing one campaign behind its tag. See `oxygen tags list` for the vocabulary. | `writes` |
| `oxygen voice tasks claim` | Take the next due call task, or a specific one with --task. | `writes` |
| `oxygen voice tasks complete` | Record the outcome of a claimed call. Lease-guarded: a lease reclaimed mid-call fails with 409 rather than overwriting the new holder's outcome. | |
| `oxygen voice tasks extend` | Renew a claimed task's 15-minute lease. Completing needs a live lease, so a longer call must heartbeat or its outcome and notes are rejected as stale. | |
| `oxygen voice tasks list` | List the call queue, best-first (highest priority, then earliest due). Defaults to every status; filter with --status. | |
| `oxygen voice tasks override` | Waive a guardrail for ONE lead — the exception path for a prospect who asked to be called outside their window, or one whose timezone you know you do not have. | |
| `oxygen voice tasks queue` | Put a lead INTO the call queue. | |
| `oxygen voice tasks skip` | Drop a task out of the queue without dialing (bad data, a rep pass, a guardrail block). Needs no lease — the guardrail gate skips tasks it never claimed. | |
## whatsapp
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen whatsapp accounts` | Read stored WhatsApp account health. | |
| `oxygen whatsapp chat-action` | Act on one WhatsApp chat: read/mute/archive/pin state, labels, group membership, or the group invite link. | `paid` `writes` |
| `oxygen whatsapp connect` | Get a hosted sign-in link to connect a new WhatsApp account by scanning a QR in WhatsApp → Linked Devices (or reconnect with --reconnect). | `writes` |
| `oxygen whatsapp disconnect` | Disconnect a WhatsApp account so it stops sending. Works on an account that is already disconnected. <id> accepts an account id, connection id, or Unipile account id. | `writes` |
| `oxygen whatsapp draft` | Generate a WhatsApp reply draft in the workspace voice, or approve a reviewed draft for an existing chat. Draft generation uses managed AI credits. | `paid` `writes` |
| `oxygen whatsapp drafts list` | Read stored WhatsApp agent drafts; personal composer drafts stay private. Use summary and exact draft_id/value for long content. | |
| `oxygen whatsapp drafts reject` | Reject an open WhatsApp draft without sending it. | `writes` |
| `oxygen whatsapp drafts update` | Edit an open WhatsApp draft before approving or sending it. | `writes` |
| `oxygen whatsapp forward` | Forward an existing WhatsApp message into another chat. This delivers a new message, so it spends send budget and is approval-gated: omit --approved for a preview. | `paid` `writes` |
| `oxygen whatsapp get` | Get one WhatsApp account with limits, warm-up ramp state (account age + today's effective send ceiling), daily-reset timezone, and usage. | |
| `oxygen whatsapp history` | Backfill one WhatsApp conversation's full message history. | `writes` |
| `oxygen whatsapp limits get` | Show current WhatsApp limits, the warm-up ramp state, direct-versus-Sequence delivery policy, daily-reset timezone, defaults, and safe maximums. <id> accepts an account id, connection id, or… | |
| `oxygen whatsapp limits set` | Adjust per-account WhatsApp daily limits and the daily-reset timezone. | `writes` |
| `oxygen whatsapp profile edit` | Edit the connected number's WhatsApp profile. Every contact who has the number sees the change, so this is approval-gated: omit --approved for a preview. | `paid` `writes` |
| `oxygen whatsapp profile show` | Show the connected number's WhatsApp profile. | |
| `oxygen whatsapp sync` | Refresh WhatsApp account state (status) from Unipile. Pass --connection-id to sync one account, or omit to sync all. | `writes` |
| `oxygen whatsapp warm-send` | Send ONE warm WhatsApp message into an EXISTING conversation (warm-only; a cold phone number with no prior conversation is rejected). | `paid` `writes` |
## whoami
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen whoami` | Show the current Oxygen CLI identity. | |
## worker
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen worker failures` | List failed background action and ingestion items. | |
| `oxygen worker queue-stats` | Show background action and ingestion queue health. | |
| `oxygen worker repair` | Repair stale background action, ingestion, and workflow queue state. | `writes` |
| `oxygen worker run-once` | Compatibility alias for worker repair; repairs Postgres-backed worker state for the current organization. | `writes` `alias` |
## workflows
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen workflows apply` | Compile and save a workflow definition; --draft appends an editable revision without publishing it. | `paid` `writes` |
| `oxygen workflows approvals` | List workflow runs awaiting a human approval decision (the mid-run approval inbox). | |
| `oxygen workflows call` | Run a workflow — or preview it first. | `paid` `writes` |
| `oxygen workflows cancel` | Cancel a queued or running workflow run. | `writes` |
| `oxygen workflows delete` | Preview or permanently delete one or more workflow automations. | `writes` |
| `oxygen workflows disable` | Disable one or more workflow automations and their current triggers. | `writes` |
| `oxygen workflows duplicate` | Duplicate a workflow automation as a disabled copy by default. | `writes` |
| `oxygen workflows enable` | Enable one or more workflow automations and their current triggers. | `paid` `writes` |
| `oxygen workflows events emit` | Emit a normalized workflow event and enqueue matching event-triggered workflows. | `paid` `writes` |
| `oxygen workflows events get` | Get one curated workspace-event preset and its ready-to-copy trigger object. | |
| `oxygen workflows events list` | Search and filter every registered app-native and connected event this workspace can use as a workflow trigger, including setup-required events. | |
| `oxygen workflows export` | Export one graph-native workflow as a portable, editable definition with source account ids and trigger authority removed. | |
| `oxygen workflows failures` | List failed workflow runs and trigger scheduler failures. | |
| `oxygen workflows get` | Get one workflow automation, including any cron slowdown to your plan's minimum interval and `draftRevision` when a saved revision is newer than the published one. | |
| `oxygen workflows import` | Preflight or install a portable workflow definition. Imports are create-only and always disabled. | `writes` |
| `oxygen workflows init` | Create a local editable workflow graph. Use --format recipe only for the legacy durable-recipe authoring path. | |
| `oxygen workflows lint` | Compile and validate an authored workflow file against the same draft/publish readiness contract as the web editor and apply. | |
| `oxygen workflows list` | List workflow automations. | |
| `oxygen workflows mcp disable` | Unpublish a workflow's MCP tool. The workflow stays active and callable via `oxygen workflows call`. | `writes` |
| `oxygen workflows mcp enable` | Publish an active workflow as a callable MCP tool so any MCP client can run it. The published tool appears to MCP clients as oxygen_workflow_<slug>. | `writes` |
| `oxygen workflows mcp list` | List workflows currently published as MCP tools. | |
| `oxygen workflows observed-output` | Inspect observed output paths and bounded samples from an exact run or recent matching workflow revision. | |
| `oxygen workflows rename` | Rename a workflow automation's display name only — its id and slug are unchanged, and the next `workflows apply` from source overwrites the name. | `writes` |
| `oxygen workflows resume` | Approve or reject a paused mid-run workflow approval, resuming the run. | `writes` |
| `oxygen workflows retry` | Preview retrying a failed run from its first failed step. Completed steps stay preserved; ambiguous external writes are refused. | `paid` `writes` |
| `oxygen workflows revisions` | Saved revision history for one workflow, newest first — includes unpublished drafts and published versions; use --include-manifest to inspect either. | |
| `oxygen workflows revisions restore` | Re-publish an earlier version as the newest one. | `paid` `writes` |
| `oxygen workflows run` | Read one workflow run, including waiting and awaiting_approval pause state. This command changes nothing. | |
| `oxygen workflows runs` | List stored workflow runs. Optional windows preserve complete public values without executing a workflow. | |
| `oxygen workflows runs events` | Read the exact Workflow run's bounded event history and whether it is still active. | |
| `oxygen workflows runs step-statuses` | Read the current Workflow run status and every step status for immediate execution readback. | |
| `oxygen workflows schema` | Print workflow JSON schemas. | |
| `oxygen workflows status-set` | Enable or disable a Workflow and record an optional reason. Enabling paid recurring execution requires standing approval and max_credits; CRM-sync workflows use their paired lifecycle instead. | `paid` `writes` |
| `oxygen workflows tag` | Replace a workflow's workspace tags (Tags primitive; "" clears). | `writes` |
| `oxygen workflows tail` | Poll until a workflow finishes or parks in waiting/awaiting_approval; clock waits resume automatically. | |
| `oxygen workflows templates apply` | Deprecated alias for `oxygen blueprints apply`. Creates a disabled workflow (plus its tables, columns, and prompts) from a blueprint. | `paid` `writes` `deprecated` |
| `oxygen workflows templates describe` | Deprecated alias for `oxygen blueprints describe`. | `deprecated` |
| `oxygen workflows templates preflight` | Deprecated alias for `oxygen blueprints preflight`. Validates inputs and previews effects without running. | `paid` `deprecated` |
| `oxygen workflows templates run` | Removed: returns a typed 410 deprecation. Use `oxygen blueprints apply ]` then `oxygen workflows call `. | `paid` `writes` `deprecated` |
| `oxygen workflows templates search` | Deprecated alias for `oxygen blueprints list`. Searches Oxygen blueprints (seed templates plus saved blueprints). | `deprecated` |
| `oxygen workflows tool-output-paths` | Discover bounded workspace-observed tool output paths and run/revision provenance, without exposing provider values. | |
| `oxygen workflows webhooks deliveries` | List inbound workflow webhook deliveries: what arrived, whether it verified, and the run it started. | |
| `oxygen workflows webhooks replay` | Create a durable, inspectable run in dry_run mode from one verified outcome=ran delivery's exact original revision and payload. | `writes` |
| `oxygen workflows webhooks rotate` | Replace a workflow webhook's shared secret. Previews by default; the old sender secret stops working immediately after approval. | `writes` |
## workspace
| Command | What it does | Notes |
| --- | --- | --- |
| `oxygen workspace infrastructure-exit` | Leave, close or offboard a workspace's managed external infrastructure in one action. | `paid` `writes` |
| `oxygen workspace map` | What this workspace actually contains: the newest tables, CRM objects, sequences, workflows, agents, wiki pages, posts and projects, each with its id, last activity, tags and link. | |
---
# MCP & AI agents
> Connect an MCP client to the hosted `oxygen_*` tool server.
Source: https://oxygen-agent.com/docs/surfaces/mcp
Oxygen runs a hosted MCP server at `https://oxygen-agent.com/mcp`. It exposes the same primitives as the CLI, over the same `/api/cli/*` contract. Every tool is listed in the [MCP reference](/docs/surfaces/mcp-reference), grouped by the toolset pack that advertises it.
Per-client setup and verification: [Claude Code](/docs/surfaces/claude-code), [Claude Desktop](/docs/surfaces/claude-desktop), [Claude Cowork](/docs/surfaces/claude-cowork), [Codex](/docs/surfaces/codex), [Cursor](/docs/surfaces/cursor), [any other MCP client](/docs/surfaces/generic-mcp).
The [ChatGPT connection](/docs/surfaces/chatgpt#what-you-can-do) uses a separate
reviewed allowlist at `?toolset=chatgpt-v1`. It lists named search, recurring-feed
and column operations; it does not expose capability dispatch or arbitrary catalog
tools. The core and domain-pack discovery flows below apply to general MCP clients.
## Connecting a client
For Claude Desktop, add a custom connector pointing at:
```text
https://oxygen-agent.com/mcp
```
Sign in when the OAuth flow opens, then ask Claude to run `oxygen_whoami` and `oxygen_tables_list`.
For clients that need a bearer token, create a CLI API key and configure the client to send it as `Authorization: Bearer `:
```sh
oxygen api-keys create --name "mcp client" --json
```
Do not paste API keys into prompts or docs. Store them in the client's credential or connector configuration.
## Session flow
1. `oxygen_whoami`.
2. `oxygen_orgs_select` if an organization is not already selected. An app connected with OAuth remembers the choice as its own default workspace; the person can change each app's default in [Connected apps](/docs/workspace/orgs#connected-apps).
3. `oxygen_context_resolve` for workspace context.
4. `oxygen_capabilities_search` to route the outcome.
5. `oxygen_capabilities_schema` on only the selected names, then call the gateway tool.
6. Open the returned `web_url` values and `ui://` widgets to inspect results.
## Search first, hydrate exactly
A bare URL advertises the core toolset plus the always-listed `oxygen_capabilities_*` tools: search, schema, and the two runners. Some hosts — including Claude Cowork and Claude Desktop — refuse to call a name absent from their `tools/list`, so every other customer tool runs through `oxygen_capabilities_read` (read-only tools; it refuses writes and credit spend) or `oxygen_capabilities_call` (anything else), each taking `{ tool, arguments }`.
`oxygen_capabilities_search` returns an ownership card (layer, primitive, negative boundary, posture, skills, endpoint families, recommended gateways) plus bounded MCP matches. Each match carries its `toolset_pack`, the smallest connector profile that advertises it. Follow with `oxygen_capabilities_schema` for one or a few exact names, then run the tool through the matching runner. The run is the tool's own: same validation, previews, spend caps, approvals and result. `?toolset=` remains available when you want a pack listed natively; use `?toolset=full` only when an automation truly needs the complete advertised registry.
Provider operations use a separate path: bounded `oxygen_tools_search` → exact `oxygen_tools_get`. Public or third-party LinkedIn reads route to native cookieless `scraper.*` operations; `linkedin.*` is for the connected workspace account's private data and writes.
## Workflows as MCP tools
`oxygen_workflows_apply`, `oxygen_workflows_call`, `oxygen_workflows_runs`, and `oxygen_workflows_tail` are the generic workflow surface. You can also **publish one workflow as its own MCP tool** — the "Clay Functions" pattern — so an agent calls it by name instead of routing through the generic dispatcher.
- **Opt in per workflow.** `oxygen workflows mcp enable ` (or `oxygen_workflows_mcp_enable`). Only workflows you explicitly enable are published; `oxygen workflows mcp disable ` removes the tool again and leaves the workflow active and callable via `oxygen_workflows_call`.
- **The tool name is `oxygen_workflow_`.** The slug is used verbatim, hyphens preserved — `lead-cleanup` becomes `oxygen_workflow_lead-cleanup`. A name over 64 characters is skipped from `tools/list` until the slug is shortened; `oxygen workflows mcp enable` warns you when that happens.
- **Discovery is through `tools/list`.** Published workflows appear alongside the static `oxygen_*` tools; `oxygen workflows mcp list` shows what is currently published with each resolved `tool_name`.
- **A bare call runs a dry run.** `mode` defaults to `dry_run`, which previews without spending credits or writing externally.
- **Live execution is gated.** Pass `mode: "live"` with `approved: true` and a `max_credits` ceiling, after inspecting a dry run. Same gate `oxygen_workflows_call` enforces.
## Widgets
The Table widget is the Oxygen grid itself, shown on MCP-Apps hosts such as Claude: previewing a table (`oxygen_tables_preview`) or a company search (`oxygen_companies_search_preview`) shows it beside readable text and structured JSON. Every other tool answers in text plus its deep-link. `oxygen_widgets_list` returns every advertised widget and the tools that render it; it sits in the `workspace` pack, so from core run it through `oxygen_capabilities_read`. Widgets are inspection surfaces — the JSON result stays the source for ids, cursors, and retry commands.
## Large files
Do not send large CSV, JSON, JSONL, or XLSX files through an MCP prompt. Call `oxygen_cli_file_import_prepare` instead: it returns a local `oxygen tables import ... --background` command, so the file stays on the user's machine and the resulting ingestion run stays inspectable in Oxygen.
## Safety in MCP calls
`oxygen_tools_run_dry` previews a tool call without spending credits. `oxygen_tools_run_live`, `oxygen_columns_run` on paid columns, enrichment runs, and external writes require the user's approved scope and credit ceiling first — see [Approvals](/docs/safety/approvals).
For bulk work, prefer table or enrichment runs over many one-off live tool calls. Runs produce timelines, failed-item lists, provider summaries, billing entries, and web deep-links.
---
# MCP tool reference
> Every released oxygen_* MCP tool, grouped by the toolset pack that advertises it.
Source: https://oxygen-agent.com/docs/surfaces/mcp-reference
A fresh general MCP client sees only the core set — 45 curated tools plus the 4 always-listed `oxygen_capabilities_*` tools — and runs every other customer tool through `oxygen_capabilities_read` (read-only) or `oxygen_capabilities_call`, with no reconnect. `?toolset=` or `?toolset=full` lists more tools natively. The packs are `workspace`, `collaboration`, `ugc`, `knowledge`, `crm`, `tables`, `runs`, `enrichment`, `signals`, `sequences`, `deliverability`, `inbox`, `publishing`, `workflows`, `agents`, `billing`, `integrations`, `admin`; several may be combined (`?toolset=crm,tables`). General profiles shape `tools/list` only: `CallTool` dispatches over the full registry.
The [ChatGPT reviewed profile](/docs/surfaces/chatgpt#what-you-can-do) at `?toolset=chatgpt-v1` is a separate allowlist for both listing and calls. Its named search, recurring-feed and column operations use narrower schemas than the general tools below. Capability dispatch, arbitrary catalog tools and broader packs cannot extend that connection. See the ChatGPT page for its supported operations and approvals.
Markers in **Notes**:
| Marker | Meaning |
| --- | --- |
| `core` | Advertised by default, before any `?toolset=` parameter. |
| `read-only` | Annotated `readOnlyHint` — inspects state without changing it. |
| `staff` | OXYGEN staff only; excluded from every profile including `?toolset=full`, but still dispatchable and still 403 for a customer identity. |
Over 900 tools total: 45 core, 7 staff-only, across 18 packs plus the always-listed capabilities pair — every released tool is listed below. Unreleased internal pilots are omitted from this public reference.
## capabilities (always listed)
| Tool | What it does | Notes |
| --- | --- | --- |
| `oxygen_capabilities_call` | Run a customer tool by name from any profile with its own previews, spend caps and approvals. Prefer oxygen_capabilities_read for reads. | `core` |
| `oxygen_capabilities_read` | Run a read-only tool or selected read_operations by name from any profile. Host approval may apply. Refuses writes and credit spend; use oxygen_capabilities_call. | `core` `read-only` |
| `oxygen_capabilities_schema` | Get up to 10 customer tool schemas by exact name; unknown names include did_you_mean. Run with the core read/call runners. | `core` `read-only` |
| `oxygen_capabilities_search` | Customer MCP tools beyond core; native GTM owners/boundaries, not the provider/enrichment catalog (oxygen_tools_search). oxygen_capabilities_schema →… | `core` `read-only` |
## workspace (`?toolset=workspace`)
| Tool | What it does | Notes |
| --- | --- | --- |
| `oxygen_activation_checklist` | Read this workspace's getting-started checklist: leads in a table, a first sequence, a connected sending account and a launched sequence, each with whether it is done and a link to do it; eligible… | `read-only` |
| `oxygen_activation_state` | Read this workspace's onboarding activation state and next available actions. | `read-only` |
| `oxygen_api_keys_create` | Create a workspace API key; requires the caller's personal user session. The token is returned once. | |
| `oxygen_api_keys_list` | List workspace API keys without revealing their tokens. | `read-only` |
| `oxygen_api_keys_revoke` | Revoke a workspace API key; requires the caller's personal user session. | |
| `oxygen_connector_events_get` | What one connected app (ChatGPT…) is subscribed to: the OXYGEN events it gets (reply classified, run settled, approval requested…), each with filters, status, workspace and expiry, plus what… | `read-only` |
| `oxygen_connector_events_revoke` | Destructive: stops OXYGEN sending events to one connected app (ChatGPT…) by revoking one event subscription, or "all" of its live ones, optionally in one workspace. | |
| `oxygen_connector_list` | Lists your OAuth apps, default workspaces, live event subscriptions and rolling 24-hour credit ceilings/usage; this_app marks the caller. | `read-only` |
| `oxygen_connector_settings_read` | This app's OXYGEN settings (its default workspace) as a form: schema, values, layout. Read-only. | `read-only` |
| `oxygen_connector_settings_update` | Saves the settings changed in this app's settings form and returns every value. | |
| `oxygen_connector_update` | Changes one connected app's settings (ChatGPT, Claude, Codex…), leaving your other apps unchanged: default_workspace (same setting as picking a workspace inside that app; latest wins) and… | |
| `oxygen_customer_credit_prices` | Read the customer credit-price catalog, quantity decisions and price provenance used by the Table picker. | `read-only` |
| `oxygen_database_attach` | Attach an owned PostgreSQL database and initialize this workspace's schema/roles immediately. | |
| `oxygen_database_cost_policy` | Read this workspace's retired Neon cost-policy status. PostgreSQL has no per-workspace sleep control; stored Neon policy is historical. 0 credits. | `read-only` |
| `oxygen_database_cost_policy_reconcile` | Retired Neon compatibility action: reports applied=false with no operations; does not suspend PostgreSQL. Native workspace write access applies; no preview or confirmation field. 0 credits. | |
| `oxygen_database_migrate` | Apply pending workspace database migrations immediately; optionally repair runtime/read passwords. | |
| `oxygen_database_query` | Read this workspace's database with one bounded SQL statement. | `read-only` |
| `oxygen_feedback` | Sends feedback as a Plain conversation. | `core` |
| `oxygen_home_standup` | The workspace standup as one read: what happened since this reader last looked, every queue waiting on a person (unread and positive replies, failed enrollments, cold deals, mailboxes needing… | `read-only` |
| `oxygen_onboarding_complete` | Complete the active workspace's onboarding step and record its discovery-source choices. The other choice requires source_other. | |
| `oxygen_onboarding_start` | Answer onboarding's choice card. own_agent continues to connecting your own agent. copilot opens the Workspace Copilot with the onboarding conversation already started, billed in credits like any… | |
| `oxygen_orgs_billing_link` | One paid plan for multiple workspaces/agency clients, no duplicate payment. | `core` |
| `oxygen_orgs_billing_unlink` | Stops sharing a plan: restores a workspace to paying for its own credits, reversing oxygen_orgs_billing_link. | |
| `oxygen_orgs_list` | Lists the OXYGEN workspaces this credential can reach, and which is active. An org-bound API key reaches only its own — `credential` says if it can switch. | `read-only` |
| `oxygen_orgs_select` | Switches the active OXYGEN workspace. An org-bound API key cannot: it is refused with org_scoped_credential. | `core` |
| `oxygen_sessions_list` | List your personal CLI sessions across workspaces, including your organizations; OAuth or personal user session required, organization API keys are refused. | `read-only` |
| `oxygen_sessions_revoke` | Revoke one personal CLI session; if this client uses it, calls stop until you reconnect with a new session. OAuth or personal user session required; organization API keys are refused. | |
| `oxygen_settings_beta_features_get` | Read this workspace's beta-navigation opt-in. | `read-only` |
| `oxygen_settings_beta_features_set` | Enable or disable beta navigation for every workspace member; admin or owner only. Approve the preference change. This does not disable routes. 0 credits. | |
| `oxygen_settings_pages_get` | Lists the OXYGEN web app's sidebar navigation pages (Settings → Customise) with which ones you hid from your own sidebar in this workspace; only you see your choices. | `read-only` |
| `oxygen_settings_pages_update` | Hides or shows pages in your own OXYGEN sidebar navigation in this workspace (Settings → Customise); teammates' sidebars do not change. hide/show take page paths or names from… | |
| `oxygen_signup_lead_deliveries_list` | Lists durable signup lead webhook deliveries for the current organization, including retry/error state. | `read-only` |
| `oxygen_signup_lead_delivery_get` | Fetches one durable signup lead webhook delivery by delivery id or event id, including retry/error state. | `read-only` |
| `oxygen_signup_lead_delivery_retry` | Queues a failed signup lead webhook delivery for retry by delivery id or event id. | |
| `oxygen_skills_get` | Read one authenticated, entitled product-skill entrypoint or manifest-listed supporting file. | `read-only` |
| `oxygen_support_ticket_create` | Opens a Plain support conversation with a required message and optional subject. | |
| `oxygen_support_ticket_get` | Fetch one Plain support Thread with its customer-visible message timeline. | `read-only` |
| `oxygen_support_ticket_reply` | Reply to a Plain Chat thread as its original customer. | |
| `oxygen_support_tickets_list` | List Plain support Threads scoped to the active OXYGEN organization. | `read-only` |
| `oxygen_tags_attach` | Replaces workspace tags on one Signal type, saved Dashboard, runtime Agent, or saved Ads search. This is metadata only and never runs a provider. | |
| `oxygen_tags_bulk` | Merges several workspace tags into one, or deletes them outright. | |
| `oxygen_tags_get` | Everything carrying one workspace tag across publishing posts, knowledge pages, sequences, tables, workflows, recipes, inbox conversations, CRM records, mailboxes, sender accounts, sending… | `read-only` |
| `oxygen_tags_list` | Lists every workspace tag with per-kind counts across publishing posts, knowledge pages, sequences, tables, workflows, recipes, inbox conversations, CRM records, mailboxes, sender accounts… | `read-only` |
| `oxygen_tags_rename` | Renames one workspace tag everywhere it appears (archived rows included). Preview-first: without apply=true, returns per-kind would-change counts and mutates nothing. Idempotent — safe to re-run. | |
| `oxygen_tags_set` | Declares a workspace tag before anything carries it, or annotates one already in use, with a description, pill color, and pinned flag. | |
| `oxygen_whoami` | Returns the Oxygen organization and user this connector session is authorized for, plus factual `onboarding` markers. | `core` `read-only` |
| `oxygen_widgets_list` | Lists the Oxygen MCP App widgets advertised through ui:// resources, including the tools that render them in Claude Desktop. | `read-only` |
| `oxygen_workspace_billing_owners` | Read the current workspace's billing owner, entitlement and payer candidates, including ineligibility reasons. Optional organization asserts the current workspace. Free. | `read-only` |
| `oxygen_workspace_create` | Create a workspace for the authenticated person's account and begin native company setup. Workspace API keys cannot create personal workspaces. | |
| `oxygen_workspace_database_provision` | Provision or retry this workspace database immediately; already-ready workspaces retain it. | |
| `oxygen_workspace_database_status` | Read this workspace's database status and latest completed provisioning/migration receipt; not a list of current pending migrations. | `read-only` |
| `oxygen_workspace_map` | What THIS workspace actually contains, by primitive: the newest tables, CRM objects, sequences, workflows, agents, wiki pages, posts and projects, each with its id, name, last activity, tags and… | `read-only` |
| `oxygen_workspace_queue_repair` | Repair this workspace's stalled execution queues through the native bounded recovery path. | |
| `oxygen_workspace_skills_archive` | Archive a workspace skill, retaining files and Knowledge history; 0 credits, no inference/provider calls or new tool/spend/approval authority. | |
| `oxygen_workspace_skills_create` | Create workspace-<name>, visible to this workspace's members; 0 credits, no inference/provider calls or new tool/spend/approval authority. | |
| `oxygen_workspace_skills_get` | Read a workspace skill's SKILL.md or one supporting text file, with exact content, revision and the document index. Skills are task guidance; they grant no tool, spend or approval authority. | `read-only` |
| `oxygen_workspace_skills_import` | Import to workspace members atomically, create-only; ≤50 text files/1 MB; scripts inert; 0 credits, no inference/paid provider calls or new tool/spend/approval authority. | |
| `oxygen_workspace_skills_list` | Find skills shared with workspace members by literal substring of name or description; short keywords work best; read-only, 0 credits; next_cursor continues the list. | `read-only` |
| `oxygen_workspace_skills_update` | Replace a skill file at its expected revision; read first, stale revisions refuse; 0 credits, no inference/provider calls or new tool/spend/approval authority. | |
## collaboration (`?toolset=collaboration`)
| Tool | What it does | Notes |
| --- | --- | --- |
| `oxygen_approval_gates_list` | Read this workspace's approval gates, optionally for one exact subject. | `read-only` |
| `oxygen_approvals_cancel` | Withdraw an approval request you created; grants no approval. | |
| `oxygen_approvals_decide` | Answers one pending request: approve, reject, or changes_requested. | |
| `oxygen_approvals_gate_set` | Turns the HARD gate on or off — the policy that makes an approval blocking rather than advisory. | |
| `oxygen_approvals_inbox` | What this user must answer: approval requests assigned to them and still pending, plus open comment threads that name them — newest first, each with the exact command that answers it. | `read-only` |
| `oxygen_approvals_list` | Approval requests across the workspace — who asked, who must decide, the decision and its note, and whether the request opens its gate. | `read-only` |
| `oxygen_approvals_request` | Asks named workspace members to decide before work goes live — the client's documented go/no-go. launch gates a sequence (approve before a sequence starts sending live); signoff gates a table… | |
| `oxygen_comments_add` | Opens a comment thread on one workspace object, or replies inside an existing one — the review conversation an agency has with its client, kept next to the work instead of in a Google Doc. | |
| `oxygen_comments_delete` | Retract your own internal workspace comment while retaining its audit trail. | |
| `oxygen_comments_edit` | Edit your own internal workspace comment; records the edit time. | |
| `oxygen_comments_list` | Every internal comment thread on one workspace object, with its replies, authors, mentions, and resolution state. | `read-only` |
| `oxygen_comments_resolve` | Marks one comment thread resolved, or reopens it with reopen=true. | |
| `oxygen_members_client_role_set` | Set or clear the restricted client overlay; admin only. May read pending Clerk invitations; sends no invitation. Free. | |
| `oxygen_members_workspace_role_set` | Change a member's workspace role in Clerk; admin only, with self-role and last-administrator protection. Free. | |
| `oxygen_workspace_members_list` | Read workspace member roles, with Clerk profiles and pending invitations. Free. | `read-only` |
## ugc (`?toolset=ugc`)
| Tool | What it does | Notes |
| --- | --- | --- |
| `oxygen_ugc_amplification_reconcile` | Preview an immutable observation for an effect_unknown action. Confirm with approved as an operator. Records evidence only; authorizes no provider call or retry. | |
| `oxygen_ugc_amplification_save` | Save exact opted-in sender scope and bounded post-specific amplification. Enabling needs explicit approval. | |
| `oxygen_ugc_application_create` | Apply to a public program (oxygen_ugc_get view discover, or a join link's program id). join_policy automatic joins at once (joined: true); otherwise the brand approves or declines, and approval… | |
| `oxygen_ugc_application_decide` | Brand approves or declines a pending application (view applications with program_id). Approval adds the creator at once and emails them; a declined applicant cannot reapply. Free. | |
| `oxygen_ugc_comment_cancel` | Cancel a scheduled program post comment before it runs. Organizer workspace only. | |
| `oxygen_ugc_comment_schedule` | Schedule one exact public LinkedIn comment on a program post from an organizer-workspace sender; on a post not live yet it waits and posts once live (fails after 14 days). | |
| `oxygen_ugc_creator_profile_update` | Save this creator workspace's profile (topics it posts about, its audience), readable by brands whose programs it joined. Free. | |
| `oxygen_ugc_creator_target_update` | Organizer sets one creator's own posting deal (e.g. 1/month vs the program's 2/month) by participation_id or pending invitation_id; null returns them to the program standard. Free. | |
| `oxygen_ugc_draft_create` | Draft a post from the creator's topic, voice and shared program pages. A bare call is a free preview returning request_id; only the creator repeats it with approved and max_credits. | |
| `oxygen_ugc_get` | Read programs, creator memberships, posts, calendar/history, analytics, shared Knowledge, voice, sponsorship or host/peer amplification. post_history uses post_id + enrollment_version; voice… | `read-only` |
| `oxygen_ugc_invite_accept` | Accept an exact invitation in the creator workspace. Check it first with oxygen_ugc_get view invitation; a refusal names its reason. | |
| `oxygen_ugc_invite_create` | Preview a free creator invite email to one email or up to 50 emails, optionally sponsoring their LinkedIn accounts. | |
| `oxygen_ugc_invite_revoke` | Revoke an unaccepted invitation. | |
| `oxygen_ugc_invite_send` | Preview one pending invite email. | |
| `oxygen_ugc_participation_update` | Change sender or approval authority, or leave permanently: posts and shared history remain, and neither this workspace nor its LinkedIn profile can rejoin. oxygen_ugc_post_remove removes one post. | |
| `oxygen_ugc_peer_amplification_reconcile` | Preview an immutable observation for this creator's effect_unknown peer action. Approval records evidence without a provider call or retry. | |
| `oxygen_ugc_peer_amplification_save` | Preview or save this creator's own peer-engagement consent, sender, voice and caps. The creator wallet pays; the host gate must also be enabled. | |
| `oxygen_ugc_post_approve` | Record the creator's approval of the current post, or the program organizer's if the creator delegated approval (oxygen_ugc_participation_update). Brands cannot require approval. | |
| `oxygen_ugc_post_enroll` | Enroll one existing creator-owned post in this participation. | |
| `oxygen_ugc_post_remove` | Remove a creator-owned post from one program before publication. Keeps the personal draft and immutable enrollment history. | |
| `oxygen_ugc_post_update` | Edit or schedule an enrolled post with creator or delegated authority; publishing gates still apply. | |
| `oxygen_ugc_program_create` | Create a master UGC program from its product link; name defaults to the site's name and its icon is fetched. Creators approve their own posts; brands cannot require approval. Free. | |
| `oxygen_ugc_program_delete` | Permanently delete a program and pending invites. Omit approved to preview. Refused after a creator joins; archive via program_update. | |
| `oxygen_ugc_program_duplicate` | Copy settings, shared Knowledge and posting target to a new active program. Creators, invitations, posts and sponsorship are excluded. | |
| `oxygen_ugc_program_update` | Update program settings and selected shared knowledge. | |
| `oxygen_ugc_sponsorship_cancel` | Preview stopping one sponsorship without revoking participation. | |
| `oxygen_ugc_sponsorship_confirm` | Confirm the exact sponsorship quote as the same signed-in master admin. Card quotes return checkouts; credit quotes start the reservations or fail with insufficient_credits. | |
| `oxygen_ugc_sponsorship_preview` | Preview sponsoring creators who already joined, as a signed-in master admin: funding is card (seat plus 10,000-credit grant) or credits (one LinkedIn reservation per creator). | `read-only` |
| `oxygen_ugc_voice_import` | Preview LinkedIn history and voice inference. | |
| `oxygen_ugc_voice_save` | Save your writing preferences/examples as a private provisional Knowledge voice. | |
## knowledge (`?toolset=knowledge`)
| Tool | What it does | Notes |
| --- | --- | --- |
| `oxygen_blueprints_apply` | Applies a blueprint as a 0-credit internal workspace write: creates the declared tables, grafts columns, upserts prompt templates, and registers the workflow as disabled. | |
| `oxygen_blueprints_archive` | Archives a saved blueprint in this workspace by id or slug. Seed blueprints cannot be archived. | |
| `oxygen_blueprints_describe` | Returns a single blueprint envelope: tables it creates, columns and prompt templates it grafts, required integrations and workspace context keys, and the workflow it produces. | `read-only` |
| `oxygen_blueprints_export` | Builds a portable blueprint envelope from an existing workflow in this workspace, packaging its tables, columns, and prompt templates. | `read-only` |
| `oxygen_blueprints_list` | Lists Oxygen blueprints — scaffolding bundles of tables, columns, prompt templates, and a workflow (seeds like account sourcing, waterfalls, ICP scoring, outbound pilots, plus workspace-saved ones). | `read-only` |
| `oxygen_blueprints_marketplace_list` | Browse the public Oxygen blueprint marketplace. Returns every blueprint that has been opted into public listing, with category and listing kind filters. Read-only and public — does not require auth. | `read-only` |
| `oxygen_blueprints_preflight` | Checks a blueprint against this workspace: lists missing integrations, context keys, and collisions. | `read-only` |
| `oxygen_blueprints_publish` | Lists a blueprint on the public Oxygen marketplace at oxygen-agent.com/marketplace. | |
| `oxygen_blueprints_save` | Persists a blueprint envelope into this workspace's blueprint gallery so it can be re-applied, listed, and shared as JSON. | |
| `oxygen_blueprints_share` | Creates a public share URL for a blueprint (oxygen-agent.com/b/<code>). | |
| `oxygen_blueprints_shares_list` | Lists existing public share URLs for blueprints in this workspace. | `read-only` |
| `oxygen_blueprints_tag` | Replaces a saved blueprint's workspace tags (Tags primitive; see oxygen_tags_list). Whole-set: pass the full list, [] clears. Works on already-saved blueprints. | |
| `oxygen_blueprints_unpublish` | Removes a blueprint from the public marketplace. The share URL stays valid for visitors who already have it; the blueprint is only hidden from /marketplace. | |
| `oxygen_blueprints_unshare` | Revokes a public blueprint share URL by short code. Existing recipients will get a 404. | |
| `oxygen_context_asset_archive` | Archives one durable workspace GTM context asset by id and writes a revision snapshot. | |
| `oxygen_context_asset_get` | Reads one durable workspace GTM context asset by id. | `read-only` |
| `oxygen_context_asset_search` | Relevance-ranked 'second brain' search across durable workspace GTM context assets (playbooks, strategies, positioning, personas, competitor + research notes). | `read-only` |
| `oxygen_context_asset_set_default` | Pins a context asset as the canonical default for its type (or unpins with is_default=false). | |
| `oxygen_context_asset_upsert` | Creates or updates a durable workspace GTM context asset (brand, voice, positioning, persona, playbook, ...). | |
| `oxygen_context_assets_list` | Lists durable workspace GTM assets such as playbooks, strategies, campaigns, positioning, personas, competitor notes, and research notes. | `read-only` |
| `oxygen_context_canonical_get` | Read the current canonical (pinned) voice, brand or positioning that AI copy uses, or any type's pinned asset. present=false means none is pinned; grounding_when_absent says what AI copy uses instead. | `read-only` |
| `oxygen_context_profile_get` | Reads durable workspace GTM memory: company, offering, ICP, market, GTM stack, and custom fields. | `read-only` |
| `oxygen_context_profile_update` | Updates durable workspace GTM memory. Provide only sections that changed; section objects shallow-merge with existing profile sections and every update creates a revision snapshot. | |
| `oxygen_context_resolve` | Resolves workspace context and assets. purpose='onboarding' adds a research brief, inferred GTM hypotheses (user corrections win), workspace campaigns, data and access, and plays to offer; first… | `core` `read-only` |
| `oxygen_context_synthesize` | Runs one low-cost AI synthesis of workspace evidence into durable knowledge; every run spends a few managed AI credits, the preview included, and reports credits_used. kind='voice' learns your… | |
| `oxygen_knowledge_agent_get` | Read scheduled synthesis config: enabled (default off), cadence hours and daily managed-credit cap. | `read-only` |
| `oxygen_knowledge_agent_set` | Configure unattended synthesis of sources into working learnings, with a UTC-day spend cap. | |
| `oxygen_knowledge_bootstrap` | Research the company domain via LinkedIn and website reads; save company facts, a cited note and separate GTM hypotheses. | |
| `oxygen_knowledge_file` | List/read original Knowledge files or upsert/archive with revision CAS (0=create). Use text, property_patch, or bytes_base64. Canonical edits may need approval. Get supports ranges. | |
| `oxygen_knowledge_file_download` | Download exact bytes for one entitled Knowledge file or pinned revision. | `read-only` |
| `oxygen_knowledge_file_get` | Read one entitled Knowledge file's metadata and bounded text when supported; revision pins historical content. | `read-only` |
| `oxygen_knowledge_files_list` | List files in one entitled Knowledge repository mount; returns metadata and a bounded cursor. | `read-only` |
| `oxygen_knowledge_folders_create` | Creates a persistent folder. Place files with oxygen_knowledge_page_upsert page.folderId. Free internal write. | |
| `oxygen_knowledge_folders_list` | Lists folders and pages, including empty folders. Omit view for the existing explorer; view=folders returns id/name/parentId in bounded windows. Follow next_cursor; no sharing/permission metadata. | `read-only` |
| `oxygen_knowledge_folders_move` | Moves a folder and its contents. Page slugs stay stable. Free internal write. | |
| `oxygen_knowledge_graph` | Returns page nodes and [[wikilink]] edges, including unresolved targets. | `read-only` |
| `oxygen_knowledge_index` | Free active/draft catalog with page links/revisions. | `core` `read-only` |
| `oxygen_knowledge_lint` | Free structural health report: orphan/dead-end pages, unresolved links, contradictions, competing canonical copy, missing metadata, duplicate/oversized/stale pages, empty seed hubs, decisions… | |
| `oxygen_knowledge_log_append` | Append a wiki filing. Pair with oxygen_knowledge_page_upsert when filing an answer; reference its slug. | `core` |
| `oxygen_knowledge_log_list` | Read append-only wiki history: seeds, page writes, pins, filings, notes and decisions, newest first. Read-only, 0 credits. Skim before filing more; pass nextCursor as cursor for older entries. | `read-only` |
| `oxygen_knowledge_page_archive` | Archive a knowledge page; content/history remain, links become unresolved. Pass expected_revision for the version you reviewed. | |
| `oxygen_knowledge_page_get` | Free page read. | `core` `read-only` |
| `oxygen_knowledge_page_list` | Index pages filtered by type, status or tags. Read matching pages with oxygen_knowledge_page_get before answering; cite slugs. | `read-only` |
| `oxygen_knowledge_page_pin` | Pins an existing page as its type's default AI grounding copy; canonical=false unpins. | |
| `oxygen_knowledge_page_restore` | Restore a knowledge page to an earlier revision as a new revision; history is kept. Pass expected_revision to refuse if the page changed since. Sensitive pages still need approval. | |
| `oxygen_knowledge_page_revision_get` | Read full historical page metadata, Markdown and data by slug or id plus revision from oxygen_knowledge_page_revisions_list. | `read-only` |
| `oxygen_knowledge_page_revisions_list` | Page history, newest first, with metadata, actor and timestamp; no bodies. Address by slug or id. Open a snapshot with oxygen_knowledge_page_revision_get. | `read-only` |
| `oxygen_knowledge_page_upsert` | Free internal write: create/update by slug/id or title. | `core` |
| `oxygen_knowledge_proposal_decide` | Approves or rejects an open Knowledge Graph proposal by its id or proposal slug. | |
| `oxygen_knowledge_proposals_list` | Review pending captured Knowledge changes. | `read-only` |
| `oxygen_knowledge_repository` | Manage GitHub Knowledge mounts after GitHub auth. Preview before connect; two_way permits branch writes. Conflict resolves pin the reviewed revision and SHA. 0 credits. | |
| `oxygen_knowledge_search` | Free wiki search: hybrid when enabled (platform-funded allowance), else keywords. | `core` `read-only` |
| `oxygen_knowledge_seed` | Ensure the starter ICP and Offers draft pages exist. Idempotent; preserves edits. Also runs on onboarding and first sync. Returns scaffold state. | |
| `oxygen_knowledge_sync_delta` | Sync complete wiki pages/tombstones; first call may seed missing starter pages. Follow next_cursor; an oversized page is refused without skipping. 0 credits. | |
| `oxygen_knowledge_sync_manifest` | Read complete wiki revision/hash metadata. has_more/truncated mean more pages, not cut entries. last_cursor marks the last returned page; next_cursor resumes when more remain. | `read-only` |
| `oxygen_prompts_archive` | Archives a workspace-authored prompt template. Seeded OXYGEN defaults cannot be archived. | |
| `oxygen_prompts_get` | Reads one prompt template by id or slug. | `read-only` |
| `oxygen_prompts_list` | Lists reusable prompt templates layered into AI columns at run time. Includes the seeded outreach-message-default template plus any workspace-authored templates. | `read-only` |
| `oxygen_prompts_upsert` | Creates or updates a reusable prompt template. AI columns reference templates via promptTemplateSlug. | |
| `oxygen_recipes_apply` | Installs a recipe's kit under one approval: every Blueprint stage in order — tables and columns created or reused, each Workflow registered DISABLED, an already-active stage skipped, a receipt… | |
| `oxygen_recipes_get` | Returns one recipe: the playbook body (or one section), prerequisites with check commands, credit posture, benchmarks, its kit (ordered Blueprint stages) and the kit's install status here. | `read-only` |
| `oxygen_recipes_install` | Installs a recipe into the workspace wiki as a revisioned, retrieval-grounded playbook page with per-version provenance. | |
| `oxygen_recipes_list` | Lists Oxygen recipes (GTM plays with prerequisites, credit posture, approval gates) ranked by relevance to query. Use when the user asks what to do; view summary to pick one, then oxygen_recipes_get. | `read-only` |
| `oxygen_recipes_preflight` | Preflights a recipe's kit (its ordered Blueprint stages) into one forecast: missing integrations/context, collisions, priced upper bounds, and which stages are already installed or active. | `read-only` |
## crm (`?toolset=crm`)
| Tool | What it does | Notes |
| --- | --- | --- |
| `oxygen_crm_activity_log` | Logs a timeline activity (note, call, meeting, email, stage change, etc.) on a CRM record. | |
| `oxygen_crm_automation_audit` | Shows recent CRM automation rule changes (who armed/disarmed which template), newest first. Read-only. | `read-only` |
| `oxygen_crm_automation_rule_set` | Arms or disarms a standing CRM automation template (e.g. crm-lead-stage-router). | |
| `oxygen_crm_automation_rules_list` | Lists the standing CRM automation templates and whether each is armed. | `read-only` |
| `oxygen_crm_connections` | Read a CRM record's connected conversations, sequence enrollments and related activity. | `read-only` |
| `oxygen_crm_duplicates` | Lists ranked duplicate-candidate record PAIRS for one CRM object via two signals: identity-overlap (the same normalized identity value attached to more than one record) and fuzzy-label (records… | `read-only` |
| `oxygen_crm_enrichment` | Read CRM automatic-enrichment configuration for companies/people: list is free via the call gateway; omit object and set backfill=false to skip backlog counts. | |
| `oxygen_crm_fields` | Fills empty CRM fields from stored enrichment payloads. Free: no provider call, credits, external read, or overwrite. Dry-run by default; use live after reviewing the preview. | |
| `oxygen_crm_file_attach` | Attach inline base64 bytes to a CRM record; each call creates a new file and attachment, including identical retries. | |
| `oxygen_crm_file_complete_upload` | Verify a reserved CRM upload and attach it to its record; mismatched bytes remain pending. | |
| `oxygen_crm_file_delete` | Detach a CRM attachment by attachment_id, preserving the stored file. | |
| `oxygen_crm_file_download` | Download a tenant-owned record attachment by attachment_id. The native authenticated response contains its exact bytes. | `read-only` |
| `oxygen_crm_file_prepare_upload` | Reserve a CRM file upload by exact name, length and SHA-256; returns a scoped upload URL. | |
| `oxygen_crm_files_attach` | Attach inline base64 bytes to a CRM record; each call creates a new file and attachment, including identical retries. | |
| `oxygen_crm_files_detach` | Removes the attachment link by attachment_id from files_list; keeps the stored file and any other links. No credits. | |
| `oxygen_crm_files_list` | Lists attached originals, newest first: files[].id is the attachment id; fileId is storage identity, name is filename, sizeBytes is byte length and mimeType is opaque. | `read-only` |
| `oxygen_crm_files_read` | Reads up to 2048 original bytes by attachment id from files_list, separate from extracted text. Returns base64 and exact same-file continuation. Read-only, no credits. | `read-only` |
| `oxygen_crm_files_upload_complete` | Confirms a reserved file after its presigned PUT. Server verifies size, SHA-256 and type before attaching. file_id is the reserved file id; detach later uses attachment id. No credits. | |
| `oxygen_crm_files_upload_prepare` | Reserves a record file and returns a presigned PUT URL. Upload the exact declared bytes, then call oxygen_crm_files_upload_complete; this step alone does not attach. No credits. | |
| `oxygen_crm_merge` | Merges two CRM records of the same object into one. | |
| `oxygen_crm_note_delete` | Delete one CRM note in this workspace. | |
| `oxygen_crm_note_update` | Edit a CRM note's body, title or pinned state; an empty title clears it. | |
| `oxygen_crm_notes_add` | Writes a note on a CRM record. Free, internal and editable afterwards, so it writes immediately rather than previewing first. Also lands on the record's timeline. | |
| `oxygen_crm_notes_delete` | Soft-deletes a record note by note id. Its timeline position remains and reads redact its text. No credits. | |
| `oxygen_crm_notes_list` | Lists a CRM record's notes, pinned first then newest, with cursor pagination. | `read-only` |
| `oxygen_crm_notes_update` | Edits a tenant record note by note id. Omit unchanged fields; title=null clears and pinned=false unpins. No credits. | |
| `oxygen_crm_object_add_attribute` | Adds one attribute (column) to an existing CRM object, optionally promoting it to an identity. | |
| `oxygen_crm_object_create` | Creates or repairs a custom CRM object (its own object-backed table, attributes, and identities) over the same engine the standard objects use. | |
| `oxygen_crm_object_delete` | Deletes one CUSTOM CRM object and schedules its backing table for 14-day recoverable deletion. | |
| `oxygen_crm_object_describe` | Describes one configured CRM object, including its table binding, attributes, identities, and relationships. | `read-only` |
| `oxygen_crm_object_remove_attribute` | Removes a field the workspace added to a CRM object. | |
| `oxygen_crm_object_update_attribute` | Changes one field on a CRM object: rename it, make it required or optional, or replace the choices of a select/status field. | |
| `oxygen_crm_objects_list` | Lists CRM object names and table bindings in compact cursor pages. Describe one object for field configuration. Defaults to a bounded compact result; full projection is explicit. | `read-only` |
| `oxygen_crm_photos` | Fills people photos from LinkedIn data already held in this workspace. Free local join; no provider call. Default dry_run preview; live applies. | |
| `oxygen_crm_photos_backfill` | Preview or fill people photos from data this workspace already holds. Free; mode defaults to dry_run. | |
| `oxygen_crm_pipeline` | Reads the deals object grouped by pipeline stage (lead → in_progress → won/lost), with per-stage deal counts and amount totals. | `read-only` |
| `oxygen_crm_record_assert` | Creates or updates one CRM record by object identity. | |
| `oxygen_crm_record_connections` | Reads the recent Messages and Sequence links for a record, by row id or native identity. | `read-only` |
| `oxygen_crm_record_get` | Gets one record with identities and relationships. | `read-only` |
| `oxygen_crm_record_keep` | Keeps one sample record as real. | |
| `oxygen_crm_record_related` | Lists the records linked to one CRM record, grouped by relationship. Each group carries its real total, not just the preview length. | `read-only` |
| `oxygen_crm_record_search` | Finds CRM records by normalized identity (domain, email, LinkedIn URL, external ID) or label. Read-only and bounded. mode=suggest is ranked typeahead on a partial string. | `read-only` |
| `oxygen_crm_record_timeline` | Lists a CRM record's activity timeline (notes, emails, replies, meetings, stage changes, list moves, syncs), newest first, with cursor pagination. Read-only. | `read-only` |
| `oxygen_crm_relationship_define` | Defines a NEW relationship (and its relation column) from a CUSTOM CRM object to any object, custom or standard — e.g. projects.client -> companies. | |
| `oxygen_crm_relationship_upsert` | Creates or replaces a CRM relationship edge, such as people.company or companies.team. Defaults to dry_run; pass mode='live' or live=true only after inspecting the preview. | |
| `oxygen_crm_rollup` | Recomputes companies.deal_stage (Open Deal: the most advanced OPEN stage among an account's deals, blank once every deal is won or lost) and the copy stamped on its people. | |
| `oxygen_crm_setup` | Creates or repairs standard CRM object-backed tables and metadata; defaults to dry_run, so pass mode='live' or live=true only after inspecting the plan. | |
| `oxygen_crm_signal_record` | Records one inbound GTM intent signal (website_visit / profile_view / post_engager / new_follower) into the CRM by fanning it into the matching standing signal-touch automation, which asserts the… | |
| `oxygen_crm_signals_today` | Lists people to contact today, ranked by their most recent GTM intent signal (website visit > profile view > post reaction > new follower), dropping terminal-stage and do-not-contact contacts. | `read-only` |
| `oxygen_crm_sync_configure` | Configures a bidirectional sync between one CRM object (HubSpot contacts\|companies, Attio people\|companies) and the matching Oxygen object, and writes the standing (provider, object)… | |
| `oxygen_crm_sync_disable` | Disables the scheduled sync for one (provider, object) pair: stops the cron trigger and revokes the standing write permission so no further scheduled cycle can fire or write. | |
| `oxygen_crm_sync_enable` | Enables scheduled bidirectional CRM sync: arms a cron and standing provider-write permission, then runs an immediate first cycle. | |
| `oxygen_crm_sync_import` | Import records from connected HubSpot, Attio or Pipedrive into Oxygen Records. dry_run returns current unit prices with an unknown run total and makes no provider calls. | |
| `oxygen_crm_sync_links` | Lists the external provider-id registry for one CRM record — which HubSpot/Attio/Pipedrive external ids are mapped to this Oxygen record (the import/sync provenance). | `read-only` |
| `oxygen_crm_sync_run` | Run one CRM reconciliation cycle: pull provider changes and push changed Oxygen rows, using most-recent-edit-wins without echo loops. dry_run makes no provider calls and returns current unit… | |
| `oxygen_crm_sync_status` | Reads CRM sync status, newest cycle first. | `read-only` |
| `oxygen_crm_tag` | Adds/removes workspace tags on one CRM record (Tags primitive; see oxygen_tags_list). | |
| `oxygen_crm_tasks_add` | Creates a task on a CRM record — the human to-do, not the phone queue oxygen_voice_tasks_* serves. Free and internal, so it writes immediately. | |
| `oxygen_crm_tasks_list` | Lists record to-dos, or workspace tasks when object and row_id are both omitted. Workspace defaults to open; assignee=me reads your work. Distinct from the Voice dial queue. | `read-only` |
| `oxygen_crm_tasks_queue` | Read the workspace task queue by status, assignee and cursor. | `read-only` |
| `oxygen_crm_tasks_update` | Completes, reopens, reassigns or re-dates a CRM task. Re-completing a completed task keeps its original completion time and adds no second timeline entry. | |
| `oxygen_directory_apply` | Apply for an agency-directory listing for this workspace; reuses an existing open application. | |
| `oxygen_directory_get` | Reads this organization's agency directory listing: profile fields, publish status (invited/published/delisted), and public/settings deep-links. | `read-only` |
| `oxygen_directory_logo_upload` | Upload a public agency-directory logo and read back the updated listing; PNG, JPEG, WebP or SVG, at most 2 MB. | |
| `oxygen_directory_publish` | Publishes this organization's listing to the public agency directory (a public web page — confirm with the user first). | |
| `oxygen_directory_unpublish` | Removes this organization's listing from the public agency directory. The draft stays editable and can be re-published later. | |
| `oxygen_directory_update` | Updates this organization's agency directory profile (name, tagline, plain-text description, logo URL, website, company LinkedIn, founding team with per-founder LinkedIn URLs, booking link… | |
| `oxygen_notetaker_calendar_connect` | Create the OAuth authorization URL for a Google Calendar or Outlook notetaker connection. | |
| `oxygen_notetaker_calendar_schedule` | Schedule recording for an existing calendar event after approval; an external CLI or MCP caller must supply an explicit max_credits ceiling. | |
| `oxygen_notetaker_calendar_sync` | Synchronize upcoming Google Calendar or Outlook meeting events into this workspace's notetaker calendar. | |
| `oxygen_notetaker_desktop_upload_prepare` | Prepare an approved desktop meeting recording and its scoped upload URL. Upload and completion remain separate steps. | |
| `oxygen_notetaker_note_edit` | Save the markdown note for one meeting session and return the committed note. | |
| `oxygen_projects_color` | Sets color; auto resets. | |
| `oxygen_projects_create` | Creates table folders. | |
| `oxygen_projects_delete` | Preview/delete folder + tables; oxygen_tables_restore before the purge date restores both. | |
| `oxygen_projects_list` | Lists active folders. | `read-only` |
| `oxygen_projects_rename` | Renames table folder. | |
| `oxygen_projects_tag` | Sets tags; [] clears. | |
| `oxygen_table_row_relationship_set` | Link one Table row to a target row through a relation (Table or CRM) and return the link. | |
| `oxygen_table_row_relationships` | Read one Table row's linked records, across Table relations and CRM relationships, and the relations it can link through. | `read-only` |
| `oxygen_tables_records_import` | Copy a Records object or saved view into a new Table, keyed by record id, once or kept in sync. The copy is free; each scheduled sync bills one workflow step. Records stay unchanged. dry_run previews. | |
| `oxygen_tables_records_status` | Read a Records-imported Table's source object and view, last sync counts and schedule. Free. | `read-only` |
| `oxygen_tables_records_sync` | Copy a Records-imported Table's source again now: adds new records, updates changed cells, keeps edited cells (preserved_cells counts those copied-field cells; added columns are never touched)… | |
## tables (`?toolset=tables`)
| Tool | What it does | Notes |
| --- | --- | --- |
| `oxygen_action_column_add_provider` | Adds a provider action picker column: lists the provider's catalog operations as setup metadata; runs nothing until one becomes a tool column. | |
| `oxygen_callables_manage` | Workspace Functions: list_functions (all or favorites; credit_estimate/row) → describe → bind → oxygen_columns_run, or create_draft/save_draft → publish. | |
| `oxygen_cli_file_import_prepare` | Authenticated CLI import for any local CSV/JSONL/JSON/XLSX path (JSON/XLSX up to 100 MiB); rows bypass MCP. | `core` |
| `oxygen_column_kind_estimates` | Read managed credit estimates for available Table column kinds. | `read-only` |
| `oxygen_columns_add` | Add a column; AI {{column_key}}; inputMapping literals/context. | `core` |
| `oxygen_columns_archive` | Archives a column. Cell values are retained but hidden from queries. | |
| `oxygen_columns_catalog` | Lists column templates for oxygen_columns_add prompt_key, with the input each reads and its credits per row. Filter by category, kind, search, family. Bundles (preset): oxygen_enrichment_catalog. | `read-only` |
| `oxygen_columns_delete` | Deletes a column: archives now, frees the key, physically purges after a window (default 14d; restorable via oxygen_columns_restore until then). now=true purges immediately and permanently: first… | |
| `oxygen_columns_deps` | Read-only column dependency graph: formula/input-mapping/run-condition/waterfall edges, transitive up+downstream, cycles — what breaks if a column changes. | `read-only` |
| `oxygen_columns_materialize` | Copy JSON fields into columns; no provider calls. mappings reuse targets. preset=work_email writes email, email_provider, email_status, and email_enriched_at—not work_email. | |
| `oxygen_columns_rename` | Renames a column's stable key (key required); for a label-only change, use oxygen_columns_update with label. Costs 0 credits; read back with oxygen_tables_describe. | |
| `oxygen_columns_reorder` | Moves a column to a new 0-based position (0 first; beyond last = end). Values, definitions, and run history are unchanged. dry_run previews. | |
| `oxygen_columns_rerun_cell` | Re-run one AI cell. Preview with dry_run=true, then pass max_credits; from_review_id threads prior feedback. | |
| `oxygen_columns_restore` | Restores an archived or delete-scheduled column: cancels the purge and renames it back to its original key (usable as the ref). | |
| `oxygen_columns_retype` | Converts a manual column's stored type (the web's Data type choices) in one transaction; a non-convertible value rejects it. dry_run previews. | |
| `oxygen_columns_update` | Updates a column's label, semantic type or definition (definition shallow merges: arrays and objects like definition.options or a lookup's match are replaced whole). | |
| `oxygen_enrichment_catalog` | Name the data, not the provider: `intents` lists every data type a table can fill (profile, email, phone, headcount, funding, tech stack, hiring, news, decision makers, signals) with status… | `read-only` |
| `oxygen_formulas_list` | Lists the formula function library (signatures, examples) and operator grammar — the language of formula columns and per-column run conditions (only-run-if). | `read-only` |
| `oxygen_formulas_validate` | Validates a formula against a table and previews sample-row output — free, no writes. | `read-only` |
| `oxygen_reviews_decide` | Accept or reject a review. Rejected highlights propose a playbook bullet for approval. auto_rerun re-quotes and caps its AI cell before deciding. | |
| `oxygen_reviews_list` | Lists AI-generated outreach message reviews. Reviews are created automatically when an AI column with reviewRequired=true completes. | `read-only` |
| `oxygen_reviews_next` | Returns the oldest pending message review across the workspace, optionally scoped to a table. Use this to drive a one-at-a-time human review queue. | `read-only` |
| `oxygen_rows_delete` | Deletes exact row IDs; by filter: oxygen_table_rows_remove_selection filter_tree. | |
| `oxygen_rows_history` | Returns the cell-change provenance of one row across all its columns — who/what wrote each value (api/cli/tool/workflow/system, with run ids and statuses), old → new values, and timestamps — plus… | `read-only` |
| `oxygen_rows_insert` | Appends <=500 rows without value dedup. Reuse request_id after a timeout; payload changes are rejected. Use oxygen_rows_upsert for value dedup. | |
| `oxygen_rows_update` | Updates the values of a single row by id. | `core` |
| `oxygen_rows_upsert` | Inserts or updates a batch, deduplicating on the key column. dry_run=true first on messy lists; local files use oxygen_cli_file_import_prepare. | `core` |
| `oxygen_supabase_catalog` | Reads the saved read-only Supabase connection and lists accessible base tables, columns, mapped Oxygen types, primary keys, and estimated rows. | `read-only` |
| `oxygen_supabase_connection_open` | Returns the secure Oxygen Connections URL and exact setup instructions for a read-only Supabase PostgreSQL role. | `read-only` |
| `oxygen_supabase_import_cancel` | Requests cancellation of every still-active child table run in a Supabase import. Does not delete rows already imported and never writes to Supabase. | |
| `oxygen_supabase_import_get` | Returns aggregate and per-table status, row counts, failures, and deep-links for a durable Supabase import. Read-only; 0 credits. | `read-only` |
| `oxygen_supabase_import_plan` | Previews one Oxygen Table per selected Supabase table, exact create/refresh behavior, row-limit posture, deletion marking, and a schema fingerprint. | `read-only` |
| `oxygen_supabase_import_retry` | Retries failed child table items. Primary-keyed upserts make already-written source rows safe; 0 credits. | |
| `oxygen_supabase_import_start` | Starts the exact previewed selection as durable Postgres-backed table ingestion. | |
| `oxygen_table_action_item_resolve` | Record a human-verified uncertain Table action outcome without repeating it. Use cells resolve for row/column coordinates. | |
| `oxygen_table_cells_resolve` | Records a HUMAN-VERIFIED outcome for a cell whose external write was dispatched but never confirmed. | |
| `oxygen_table_column_create` | Create a Table column at an optional zero-based position; type is a field type, and a choice type takes options (cells store each value). | |
| `oxygen_table_column_duplicate` | Duplicate a Table column and its definition with an optional new label. | |
| `oxygen_table_column_edit` | Save a column's label, type, order or definition. Returns downstream reference warnings rather than silently discarding them. | |
| `oxygen_table_column_fields` | Read the output fields available from one hosted Table column. | `read-only` |
| `oxygen_table_column_stats` | Read per-column completion and provider statistics; large Tables use labeled samples. | `read-only` |
| `oxygen_table_column_web_search_mode` | Convert a web-search column between agent, AI or keyword modes. Conversion requires confirm=true; mode plus column seeds an AI or keyword replacement. | |
| `oxygen_table_export_csv` | Download every row in the exact filtered Table view as streamed CSV. | `read-only` |
| `oxygen_table_fill_progress` | Read hosted Table fill progress and any actionable ingestion failure. | `read-only` |
| `oxygen_table_provider_action_column` | Preview or create a provider action column; creating it does not execute provider actions. | |
| `oxygen_table_resource_activity` | Read a Table's live runs and queue health. | `read-only` |
| `oxygen_table_resource_edit` | Rename a Table or move it to a workspace project; returns the saved Table. | |
| `oxygen_table_resource_upload` | Preview or import small uploaded CSV, JSON or XLSX bytes through the exact browser import contract. Preview writes no rows. | |
| `oxygen_table_row_edit` | Patch one row's values and return the committed row. | |
| `oxygen_table_row_inspect` | Read one row; field selects column keys and hydrate_relations=1 includes relations. projection=value returns lossless JSON fragments; resume value_cursor with identical table/row/field/path. | `read-only` |
| `oxygen_table_row_remove` | Remove one row from a workspace Table. | |
| `oxygen_table_rows_insert` | Insert Table row values and return the committed rows plus any existing automatic run or dedupe grant. | |
| `oxygen_table_rows_page` | Read a Table row page with the same filter, sort, counts and CRM relationship projection as the grid. | `read-only` |
| `oxygen_table_rows_range_ids` | Resolve a bounded row range into exact ids, preserving the current filter, search, sort and CRM scope. | `read-only` |
| `oxygen_table_rows_remove_selection` | Permanently delete Table rows by a readable filter tree, exact ids or a matching selection. Unsupported scope fields are refused. | |
| `oxygen_table_webhook_create` | Create an inbound Table webhook or platform LinkedIn feed. Optional auto_run is standing permission with explicit or plan-default delivery ceilings. | |
| `oxygen_table_webhook_deliveries` | Lists direct table webhook deliveries and their auto-run enqueue status for the active organization. | `read-only` |
| `oxygen_table_webhook_get` | Returns one direct table webhook endpoint by id: mode, auth mode, event field paths, standing auto-run configuration, webhook URL, table deep-link and rate_limit. | `read-only` |
| `oxygen_table_webhook_update` | Edit a Table webhook's name, state or standing auto_run; auth_mode=secret rotates its secret and returns it once. | |
| `oxygen_table_webhooks_list` | Lists the organization's direct table webhook endpoints, optionally filtered by table or status, each with its webhook URL, table deep-link and standing auto-run columns, plus rate_limit… | `read-only` |
| `oxygen_tables_archive` | Archives a table. Rows and columns are retained but the table is hidden. | |
| `oxygen_tables_auto_dedupe` | Manage a table's standing auto-dedupe: get/set/disable. | |
| `oxygen_tables_cell_history` | Returns the cell-change provenance of one cell (table + row + column) — every recorded write with old → new value, the writing source (api/cli/tool/workflow/system) and run status, and timestamps. | `read-only` |
| `oxygen_tables_cell_inspect` | Returns one cell's final value plus the full provider attempt timeline, recent write history, and a deep-link into the web app. | `read-only` |
| `oxygen_tables_create` | Creates a table private to the active workspace. Mutates tenant schema. AI prompts read {{column_key}} or inputMapping {{name}}; unknown → invalid_prompt_column + near misses. | `core` |
| `oxygen_tables_csv_import_open` | Returns the Oxygen tables page where the Import file dialog accepts local CSV/XLSX uploads. | `read-only` |
| `oxygen_tables_dedupe` | Collapse duplicate rows by normalized (email/domain/linkedin) or fuzzy_label keys. dry_run previews groups; dry_run=false + approved=true deletes losers (kept in row history). | |
| `oxygen_tables_dedupe_cross_check` | Read-only: report rows in one table whose normalized key value already exists in another table (e.g. leads already in the CRM). No fuzzy matching. | `read-only` |
| `oxygen_tables_delete` | Archives a table, frees its slug; oxygen_tables_restore recovers it before purge (default 14 days). now=true purges permanently: preview (409), then approved=true; a large table returns purging. | |
| `oxygen_tables_describe` | Reads columns, types and config; `column` returns one. A UUID in another accessible org returns `table_in_other_org`; select the org in `details.recovery` with `oxygen_orgs_select`, then retry. | `core` `read-only` |
| `oxygen_tables_duplicate` | Duplicates a table (columns, definitions, row values); include_rows=false makes a schema-only copy. Response carries a deep-link. | |
| `oxygen_tables_favorite` | Star/unstar exactly one table or folder (saved per-member preference). Free (0 credits). Catalog stars differ. | |
| `oxygen_tables_favorites` | Read starred Tables/folders (per-member preference; free (0 credits)); next_cursor. Catalog stars differ. | `read-only` |
| `oxygen_tables_followers` | Preview, create or inspect a follower order. | |
| `oxygen_tables_hubspot_import` | Import HubSpot contacts/companies into a new table or Records after DNC sync. Never enrolls or sends. Live requires approval and the exact dry-run fingerprint. | |
| `oxygen_tables_hubspot_lists` | List a connected HubSpot account's saved contact/company lists and identity properties for table or Records imports. Definitions only; 0 credits, uses HubSpot API quota. | `read-only` |
| `oxygen_tables_import_csv` | Imports JSON-provided CSV; omit table to create from headers and queue durable row ingestion. Large local files: oxygen_tables_csv_import_open or CLI. | `core` |
| `oxygen_tables_import_file` | Import small base64 file bytes through the shared multipart import API; use staged upload for large files. | |
| `oxygen_tables_import_preview` | Preview a staged file's headers, rows and existing-table mapping; writes no imported rows. | `read-only` |
| `oxygen_tables_import_staged` | Start a durable hosted import from this workspace's staged file; choose an existing table or create_name. | |
| `oxygen_tables_import_upload` | Prepare a scoped storage upload for a hosted Table import; uploads and imports are separate, inspectable steps. | |
| `oxygen_tables_import_url` | Imports a public CSV, TSV, JSON, JSONL or XLSX file — or a Google Sheet shared with anyone-with-the-link or published to the web — into a new or existing table. | |
| `oxygen_tables_link` | Links one row to a row in the related table through a relation defined with oxygen_tables_relate. | |
| `oxygen_tables_link_bulk` | Bulk relation fill: Oxygen measures which column joins the two tables, infers direction and cardinality, and links every matching row in one background run. | |
| `oxygen_tables_link_suggest` | Plan column links and matching row counts between Tables; creates no relation. Apply with tables link --to (MCP oxygen_tables_link_bulk). | `read-only` |
| `oxygen_tables_list` | Lists 50 summary tables. Resume nextCursor with unchanged filters. null rowCount is unknown; measure with oxygen_tables_describe include_stats:true. Largest: oxygen_limits_show. | `core` `read-only` |
| `oxygen_tables_move` | Moves a table to another project. Rows, columns, runs, and provenance are preserved. Response carries a deep-link. | |
| `oxygen_tables_pipedrive_filters` | Read connected Pipedrive saved filters and custom-field definitions; no people imported. Four BYOK fees may apply: approve with max_credits. Refusal returns the required cap without provider calls. | |
| `oxygen_tables_pipedrive_import` | Preview or run a Pipedrive saved people filter into a NEW Oxygen table, once or on a schedule. | |
| `oxygen_tables_preview` | Rows, columns, stats, and a deep-link; 0 credits. UI in MCP Apps hosts; data in terminals. Fill exact to cap, else summary.statsSampled; rowCount exact. | `core` `read-only` |
| `oxygen_tables_promote` | Writes bound rows' columns onto their CRM records. Truth write: dry_run previews; approved=true writes. | |
| `oxygen_tables_query` | Raw rows or grid (JSON null; __oxygen_grid_cell_previews digests). Grid rejects raw selectors; nextCursor pages. Full: oxygen_table_row_inspect projection=value. | `core` `read-only` |
| `oxygen_tables_recover_pending` | Recover BetterContact email/phone requests and read verification blockers; no new orders or imports. | |
| `oxygen_tables_relate` | Links two tables (web: Link to another table): a linked-record column on BOTH, empty until rows link; no matching values needed; plain tables are never registered as CRM objects. | |
| `oxygen_tables_relations` | Table relation definitions: list is read-only; update changes display_name, inverse_display_name, or source-perspective cardinality, keeping endpoints/slugs. archive hides both columns and active… | |
| `oxygen_tables_rename` | Renames an existing workspace table. | |
| `oxygen_tables_restore` | Restores table and folder, cancels a purge that has not begun, and reclaims its slug when available. | |
| `oxygen_tables_schedule` | Scheduled column refresh (create/list/remove): a cron workflow re-runs one column — empty/failed cells only unless force. | |
| `oxygen_tables_send` | Copies rows between tables, or flattens a JSON array cell into one row per element, as a durable run (free). | |
| `oxygen_tables_sources` | Lists every way a table can start — imports, company/people/signal sources, webhooks, functions — with the provider count and per-row credit estimate behind each, derived from the routing registry. | `read-only` |
| `oxygen_tables_tag` | Replaces a table's workspace tags (whole-set; [] clears). Tags link the table to sequences, wiki pages, and workflows carrying the same tag — browse with oxygen_tags_get. | |
| `oxygen_tables_tidy_suggest` | Read-only tidy analysis of one Oxygen table. | `read-only` |
| `oxygen_tables_unlink` | Unlinks one exact source/target row pair by archiving its edge. | |
| `oxygen_tables_views_create` | Creates a named view (type defaults to table). Prefer v2 config; invalid v2 returns invalid_view_config. Legacy config stays unchanged. is_default clears the prior default. | |
| `oxygen_tables_views_delete` | Deletes a saved view by id. The table's rows and columns are untouched. | |
| `oxygen_tables_views_get` | Returns a single saved view (name, type, default flag, full config) by id. | `read-only` |
| `oxygen_tables_views_list` | Lists saved views by position. Read first to avoid duplicate names or find a view to edit. | `read-only` |
| `oxygen_tables_views_update` | Updates a saved view. | |
| `oxygen_tables_watcher` | Daily LinkedIn profile engagers in one editable table with source posts and employers. Preview is free; create/update/resume need approved, preview_hash and a per-cycle cap. Ask for real profile URLs. | |
## runs (`?toolset=runs`)
| Tool | What it does | Notes |
| --- | --- | --- |
| `oxygen_columns_run` | Runs a column on selected rows. Preview, then pass approved=true + max_credits. limit fills empties. Large runs: execution_status=planning. | `core` |
| `oxygen_table_action_runs_list` | Read durable Table action runs, optionally filtered by status or trace. | `read-only` |
| `oxygen_table_column_execute` | Run one column over an exact row or bounded selection. Paid execution requires approval and a max_credits ceiling; uncertain prior effects need explicit resolution approval. | |
| `oxygen_table_ingestions_append_items` | Appends small generated row chunks to an existing durable table ingestion. Use oxygen_tables_import_staged for owned CSV/Excel files; do not stream file rows through append. | |
| `oxygen_table_ingestions_cancel` | Requests cancellation for a queued or running durable table ingestion. | |
| `oxygen_table_ingestions_create` | Creates a durable Table ingestion for row chunks or bounded provider pages (source_type=tool_page; items contain the paging payload). | |
| `oxygen_table_ingestions_get` | Returns ingestion status/counts and its web link. | `read-only` |
| `oxygen_table_ingestions_items` | Lists ingestion items, including completed pages. tool_page item.output.has_next_cursor=true means more pages remain; item.output.stopped_by=provider_exhausted records cursor exhaustion. | `read-only` |
| `oxygen_table_ingestions_retry_failed` | Requeues failed items for a durable table ingestion after you have inspected and fixed the cause. | |
| `oxygen_table_ingestions_wait` | Polls an ingestion to a terminal status or timeout. | `read-only` |
| `oxygen_table_resource_ingestion_retry` | Retry failed items in this Table's hosted ingestion run. | |
| `oxygen_table_resource_ingestion_stop` | Cancel this Table's active hosted ingestion run. | |
| `oxygen_table_resource_run_pause` | Pause one durable Table run without discarding its approved scope. | |
| `oxygen_table_resource_run_preview` | Preview selected Table action costs and provider availability, including draft column definitions; starts no run. | |
| `oxygen_table_resource_run_provider_summary` | Read a Table run's provider outcomes, fulfilled rows, costs and timing. | `read-only` |
| `oxygen_table_resource_run_resume` | Resume a paused Table run within its existing approved scope and credit ceiling. | |
| `oxygen_table_resource_run_retry` | Retry failed cells; a fresh allowance requires approved, retry_plan_hash and max_additional_credits. Uncertain effects require separate approval. | |
| `oxygen_table_resource_run_start` | Start selected Table actions using the browser's exact row-selection contract. Paid runs require an approved max_credits ceiling. | |
| `oxygen_table_resource_run_stop` | Cancel one durable Table run; never repeats external provider effects. | |
| `oxygen_table_runs_cancel` | Cancels a table action run; imports use oxygen_table_ingestions_cancel. | |
| `oxygen_table_runs_create` | Creates a background table action run over selected rows (tool/AI/enrichment columns). Paid: approved=true + max_credits after a dry run. Large runs: execution_status=planning. | |
| `oxygen_table_runs_history` | Read this Table's action-run history and progress. | `read-only` |
| `oxygen_table_runs_pause` | Pauses a run so item jobs start no new provider calls until resumed. | |
| `oxygen_table_runs_resume` | Resumes a paused table action run and re-enqueues pending item jobs. | |
| `oxygen_table_runs_retry_failed` | Retry failed items or wake guarded callbacks from saved results. | |
| `oxygen_table_runs_retry_plan` | Read failed/dependent items or pending guarded callbacks, billing, refusals and approval hash. No writes or calls. Quote paid retries; callbacks-only delivery requires 0 additional credits. | `read-only` |
| `oxygen_tables_auto_run` | Manage a table's standing auto-run (columns auto-queued for rows from a subscribed import/insert/upsert): get/set/disable. Default off; max_credits caps each batch. | |
## enrichment (`?toolset=enrichment`)
| Tool | What it does | Notes |
| --- | --- | --- |
| `oxygen_ads_searches` | List, get, save, or update a named Ads search; action=delete archives it. | |
| `oxygen_adyntel_ads_search` | Finds one page of company ads via Adyntel; collect all pages into a Table with oxygen_table_ingestions_create (source_type=tool_page). | |
| `oxygen_companies_search_plan` | The canonical company-search entrypoint for a prompt or nonempty filters. | |
| `oxygen_companies_search_preview` | List native source filters or preview free. view=full adds raw_source. company_search: 50 companies; hiring: 50 job postings, exact total; google_maps: 20 businesses for {q:business type and area}. | `core` `read-only` |
| `oxygen_companies_search_run` | Dry-runs or queues company sourcing into a Table. | |
| `oxygen_company_enrichment_preview` | Inspects an existing company/account table and plans a fill-missing company enrichment waterfall without provider calls or credit usage. | `read-only` |
| `oxygen_company_enrichment_run` | Queues a live fill-missing company enrichment waterfall over existing table rows. | |
| `oxygen_enrich_column_preview` | Preflights an enrichment intent without provider calls or credits. | `read-only` |
| `oxygen_enrich_column_run` | Creates or reuses an enrichment column and queues a paid background table run. | |
| `oxygen_enrichment_apply_default_cascade` | Patches an existing enrichment column to the server-side default provider cascade for its stored intent. Use dry_run=true first to inspect the normalized would-be definition without writing. | |
| `oxygen_find_company` | Enrich one company (domain, name or linkedin_url) via a provider waterfall: firmographics, funding, competitors, corporate structure, news, jobs, tech stack, web URLs. | `core` |
| `oxygen_find_email` | Find work email via a provider waterfall. | `core` |
| `oxygen_find_linkedin` | Resolve a person's LinkedIn profile URL from full_name + company_domain (or email), with identity validation against the source name+company to avoid common-name false positives. | |
| `oxygen_find_person` | Enrich one person: a managed LinkedIn profile lookup returning first/last/full name, current company + its LinkedIn URL, job title, job start date, education, school, headline, bio, location and… | |
| `oxygen_find_personal_email` | Find a person's personal (non-work) email — ad-audience uploads, recruiting, founder outreach — via LeadMagic's personal-email finder, which bills only on a hit; MillionVerifier grades the address. | |
| `oxygen_find_phone` | Find a mobile phone via a provider waterfall, advancing on empty/error. | `core` |
| `oxygen_lead_sourcing_audit` | Audits a sourced lead table against a LeadSourcingSpec or prompt: title fit, geography fit, account qualification, hard-exclude leakage, contact coverage, duplicates, and enrichment waste. | `read-only` |
| `oxygen_lead_sourcing_plan` | Compiles a natural-language ICP into an account-first lead sourcing plan with explicit filters, segment confidence, risks, attrition estimate, dedupe policy, enrichment gates, and the active… | |
| `oxygen_people_search_plan` | Canonical people/contact search: compiles prompt + persona filters into provider routes, table columns, gates, credit/match estimates, filter coverage, and workspace context. | |
| `oxygen_people_search_preview` | Up to 50 people free; action=filters. Table: oxygen_people_search_plan then oxygen_people_search_run with same source and typed filters. Otherwise run source=people_search + native source_filters. | `core` `read-only` |
| `oxygen_people_search_run` | Dry-runs or queues a live table ingestion run for one people-search provider route. | |
| `oxygen_search_plan` | Plans signal, web or source-specific searches; no longer plans people or company search. | `read-only` |
| `oxygen_search_run` | Previews or enqueues a durable table-backed search/scrape job from an Oxygen search plan for signal, web, scrape, and local-business routes. | |
| `oxygen_search_run_items` | Read durable search ingestion items by run id and optional status. | `read-only` |
| `oxygen_search_runs_cancel` | Requests cancellation for a queued or running search/scrape run. | |
| `oxygen_search_runs_get` | Gets one durable search/scrape run by id. | `read-only` |
| `oxygen_search_runs_retry_failed` | Requeues failed items for a durable search/scrape run. | |
| `oxygen_search_runs_wait` | Polls a durable search/scrape run until terminal status or timeout. | `read-only` |
| `oxygen_sourcing_plan` | Classifies account, people, profile, or enrichment-handoff sourcing requests into an Oxygen strategy with runnable provider routes, cost posture, approval gates, and next commands. | |
| `oxygen_tool_favorites` | Read this member's favorite tool catalog entries in the active workspace. | `read-only` |
| `oxygen_tools_check_access` | Checks whether the active Oxygen organization can run a catalog tool. | `read-only` |
| `oxygen_tools_enums_get` | Returns the accepted values for one provider enum catalog (e.g. blitzapi.industry, blitzapi.employee_range). | `read-only` |
| `oxygen_tools_enums_list` | Lists provider enum catalogs (e.g. blitzapi industry, employee_range, country_code). Call before drafting payloads with enumRef fields so values match the provider contract. | `read-only` |
| `oxygen_tools_favorite` | Adds or removes one column-catalog entry from the caller's favourites for this workspace. Entry ids: find_email, preset:person_enrich, prompt:<key>, tool:<tool_id>. | |
| `oxygen_tools_get` | Catalog metadata (summary default); choose view/native field keys. Named omissions; exact schemas. MCP schemas: oxygen_capabilities_schema. enumRef: oxygen_tools_enums_get. | `core` `read-only` |
| `oxygen_tools_plan_table_batch` | Creates or reuses a table for pasted records, upserts them, creates a native tool column if needed, and starts a durable table action run. | |
| `oxygen_tools_run_dry` | Validates without provider calls/credit spend; returns resolved input, output schema, credit estimate and cache status. | `core` `read-only` |
| `oxygen_tools_run_live` | Catalog upstream call or free cached managed lookup (max_credits=0). | `core` |
| `oxygen_tools_search` | Provider operations and priced native_columns (Table kinds/presets/waterfalls), different from oxygen_capabilities_search (goal/price ownership; start there). | `core` `read-only` |
| `oxygen_verify_email` | Verify emails you already have. | |
## signals (`?toolset=signals`)
| Tool | What it does | Notes |
| --- | --- | --- |
| `oxygen_dashboard_summary` | Reads the GTM funnel: outbound touches → replies → positive replies across email, LinkedIn and WhatsApp → meetings → deals → won; revenue, channel split, lifecycle funnels and current triage. | `read-only` |
| `oxygen_dashboard_tab_create` | Create a named tab in a workspace dashboard. | |
| `oxygen_dashboard_tab_delete` | Remove one dashboard tab by its id. | |
| `oxygen_dashboards_create` | Creates a saved dashboard in the CRM with one empty tab. Add widgets with oxygen_dashboards_widget_add. No credits. | |
| `oxygen_dashboards_delete` | Archives a saved dashboard. The definition is kept, the slug becomes reusable, and the data it reported on is untouched. | |
| `oxygen_dashboards_get` | Reads one saved dashboard with its tabs and widget configurations. Read-only. | `read-only` |
| `oxygen_dashboards_list` | Lists the workspace's saved dashboards — the user-defined ones in the CRM, not the built-in Command Center funnel. Read-only. | `read-only` |
| `oxygen_dashboards_tab_add` | Adds a tab to a saved dashboard; maximum 20 tabs. Use oxygen_dashboards_widget_add to place widgets on the returned tab. No credits. | |
| `oxygen_dashboards_tab_remove` | Removes a tab and all its widgets. Dashboard keeps at least one tab; server refuses the final tab. No credits. | |
| `oxygen_dashboards_update` | Renames a saved dashboard or changes its description, icon or default flag. No credits. | |
| `oxygen_dashboards_widget_add` | Adds a widget to a saved dashboard. | |
| `oxygen_dashboards_widget_data` | Reads the data behind one widget — the same numbers the web page draws. A live_source serves its cached result and never fetches here. Read-only, no credits. | `read-only` |
| `oxygen_dashboards_widget_kinds` | Lists every dashboard widget kind with an example configuration and whether it can cost credits. Read this before building a widget. Read-only. | `read-only` |
| `oxygen_dashboards_widget_refresh` | Refreshes a live_source widget now, calling its external tool. | |
| `oxygen_dashboards_widget_remove` | Removes a widget from a saved dashboard. The data it reported on is untouched. | |
| `oxygen_dashboards_widget_update` | Changes a widget's title, configuration or placement, or pauses/resumes a live_source. | |
| `oxygen_feeds_bind` | Binds a table feed: pull (default) freezes one provider request and can arm a refill cadence; push (row_schema) mints a webhook that refuses rows not matching the schema (typed or rejected). | |
| `oxygen_feeds_get` | Read one stored feed. summary omits long settings; value returns lossless public JSON fragments at path (JSON Pointer, empty=root). | `read-only` |
| `oxygen_feeds_list` | List stored Table feeds. summary/full windows resume at next_offset with identical filters (live queue, unknown total). | `read-only` |
| `oxygen_feeds_pause` | Pauses a feed. The cron stays armed but every cycle it fires is refused, so nothing is fetched and nothing is billed until the feed is resumed — resuming therefore needs no re-approval. Free. | |
| `oxygen_feeds_resume` | Resumes a feed: re-activates it AND clears an error/exhausted stop, so the next cron tick can claim it again. | |
| `oxygen_feeds_run` | Runs one sync cycle now, through the feed's own cron workflow — one harvest path, one lease, one cursor. | |
| `oxygen_feeds_unbind` | Deletes a feed: removes its cron FIRST, then the feed row, so no orphan cron can keep spending at a feed that no longer exists. The table and every row the feed already wrote are kept. Free. | |
| `oxygen_feeds_update` | Update an existing Table feed in place. | |
| `oxygen_linkedin_ingestion_status` | One unified view of every 'read LinkedIn into the workspace' background drip — connections import, post-engagement harvest, and message-history backfill — across all connected accounts: each job's… | `read-only` |
| `oxygen_signals_leads_today` | Lists people to contact today, ranked by their most recent GTM intent signal (website visit > profile view > post reaction > new follower), dropping terminal-stage and do-not-contact contacts. | `read-only` |
| `oxygen_signals_list` | Lists the raw GTM signal-event feed newest-first — the typed intent events (website_visit / profile_view / post_reaction / new_follower) resolved onto the people they attached to. | `read-only` |
| `oxygen_signals_record` | Records one inbound GTM intent signal (website_visit / profile_view / post_engager / new_follower) into the stream by fanning it into the matching standing signal-touch automation, which asserts… | |
| `oxygen_signals_registry` | Shows the signal-type registry: each registered type with its human label, family, intent weight, and capture status. | `read-only` |
| `oxygen_signals_search_plan` | Compiles a signal-sourcing request into ordered provider routes without calling a provider: the registry chain, per-route applied/dropped filters, credit estimate, table blueprint, and whether… | |
| `oxygen_signals_search_preview` | linkedin_posts only: list the post-search filters, or preview public LinkedIn posts FREE (up to 25 per keyword) with author, engagement and the optional ai_filter applied. | `read-only` |
| `oxygen_signals_search_run` | Returns a dry-run request or queues a live table ingestion run for one signal-search route, creating the table from the plan blueprint when none is passed. | |
## sequences (`?toolset=sequences`)
| Tool | What it does | Notes |
| --- | --- | --- |
| `oxygen_linkedin_connections_import_status` | Read the durable LinkedIn connections import status and target Table. | `read-only` |
| `oxygen_linkedin_followers_import_status` | Read the durable LinkedIn followers import status and target Table. | `read-only` |
| `oxygen_sender_checkpoints` | Read connected sender authentication checkpoints that need human completion. | `read-only` |
| `oxygen_sequence_contacts_rows` | Read the full contact grid projection with exact contact-state filter and native synthetic status columns. | `read-only` |
| `oxygen_sequence_leads_rows` | Read the complete enrolled-lead grid projection, including sequence status, step, action and failure columns. | `read-only` |
| `oxygen_sequences_analytics` | Shows selected-window Sequence health: persisted/operational state, fleet markedActive versus operationallyLive, open work, outcomes by action kind/failure class, exact links and per-campaign… | `read-only` |
| `oxygen_sequences_company_pause` | Pauses messaging to one company in your campaigns (all, or only sequence_ids) until resumed, e.g. after a meeting is booked. | |
| `oxygen_sequences_company_pauses` | Lists companies paused in your campaigns (by a reply awaiting or after classification, or by hand/automation) with the leads each holds. | `read-only` |
| `oxygen_sequences_company_resume` | Resumes messaging to a paused company: its held leads continue where they stopped (due steps spread over the next hour). | |
| `oxygen_sequences_contacts` | Lists campaign contacts with every source variable, contact tags, and the factual or assigned sender. | `read-only` |
| `oxygen_sequences_contacts_remove` | Previews or applies permanent campaign-only removal of table_row_ids or of leads whose source row was deleted (missing_source_rows=true; preview names them). Stops queued work, keeps rows and history. | |
| `oxygen_sequences_create` | Creates a draft multichannel Sequence; nothing sends until approval-gated start. | |
| `oxygen_sequences_delete` | PERMANENTLY deletes a sequence and everything it owns — enrollments, actions, sender links, schedules. | |
| `oxygen_sequences_draft` | Drafts an email outreach sequence with AI, grounded in the workspace Knowledge Graph (voice, positioning, campaign learnings) with cited provenance. | |
| `oxygen_sequences_duplicate` | Copies a sequence as a new draft: steps, channels, settings, source table, caps, tags and (unless include_senders=false) senders. | |
| `oxygen_sequences_enroll` | Enrolls leads into a sequence (0 credits; an active sequence contacts them on its next tick, a draft or paused one holds them until started). from_table:true: unenrolled bound rows, no leads… | `core` |
| `oxygen_sequences_enrollments` | Lists per-lead enrollment state with current step and the latest action's status, error, attempt/max-attempt count, ready/retry time, and dispatch time. view=compact gives one short row per lead… | `read-only` |
| `oxygen_sequences_esp` | ESP breakdown of a sequence's email scope: the provider each enrolled lead's mail routes through (google/microsoft, named gateways like Proofpoint resolved behind via SPF, and non-matchable… | `read-only` |
| `oxygen_sequences_events` | Per-sequence activity feed: sends, failures, skips, opens/clicks (bot-filtered unless include_bots), replies, bounces, unsubscribes, and positive reply-status — newest first. | `read-only` |
| `oxygen_sequences_get` | Gets a sequence's definition, senders, status and credit usage, led by warnings and sending_schedule (each channel's window, labelled). include_readiness=true adds the launch check. | `read-only` |
| `oxygen_sequences_hubspot_list_import` | Preview or arm recurring HubSpot-list enrollment. DNC completes first; draft/paused recipients stay pending. Live requires approval and the dry-run fingerprint. | |
| `oxygen_sequences_hubspot_lists` | List saved HubSpot contact and company segments plus readable identity fields without reading members or writing. Pass separate lead/contact-DNC/company-DNC ids to the import tool. | `read-only` |
| `oxygen_sequences_hubspot_sync_configure` | Preview or save the workspace-wide HubSpot activity and lead-status projection for every Sequence. Dry-run first; live enable requires approval and installs two inspectable Workflows. | |
| `oxygen_sequences_hubspot_sync_get` | Reads the workspace-wide HubSpot projection across every Sequence. | `read-only` |
| `oxygen_sequences_list` | Status, work state, lifecycle and fleet markedActive/operationallyLive counts. | `core` `read-only` |
| `oxygen_sequences_push_external` | Pushes selected Table rows into an EXISTING external sequencer campaign (Smartlead, Instantly, lemlist, HeyReach) through the workspace's own connection; dry_run previews, live requires approved. | |
| `oxygen_sequences_reconcile` | Checks whether one failed/canceled live LinkedIn invite, message, or InMail actually landed at the provider. | |
| `oxygen_sequences_recover_capacity` | Read-only by default: previews the exact terminal Sequence actions Oxygen can prove were not applied and knows how to replay safely—provider-capacity denials plus explicitly allowlisted Oxygen… | |
| `oxygen_sequences_render` | Renders a sequence's copy like the web step editor's Preview: every A/B variant of each step (email subject/body, LinkedIn note/message/InMail, WhatsApp, comments) for leads of the bound table… | `read-only` |
| `oxygen_sequences_retry_deferred` | Preview or re-ready pending actions deferred by LinkedIn working hours or an email send window. | |
| `oxygen_sequences_send` | Starts a net-new LinkedIn conversation through hosted Sequences; reply to an existing thread with oxygen_inbox_send. | |
| `oxygen_sequences_set_status` | Transitions an active/paused sequence's operational status: 'paused' pauses dispatch (resumable), 'active' resumes a paused sequence; one paused at its live send cap re-pauses until… | |
| `oxygen_sequences_signal` | Records an external GTM signal onto a running sequence's enrollment(s) to drive signal-triggered branch/wait_for_signal control. | |
| `oxygen_sequences_start` | approved=false preview (0 credits, no writes; oxygen_capabilities_read): launch_readiness, sender_journey, copy_preview. | `core` |
| `oxygen_sequences_stats` | Shows one Sequence's persisted launch status separately from its current shared operational state, reason codes, open work, lifetime sent/terminal-failed/deferral analytics by action kind and… | `read-only` |
| `oxygen_sequences_update` | Updates one Sequence for 0 credits without sending; pass only changed fields. | |
| `oxygen_sequences_variants` | Shows a sequence's generic per-step action/base-variant scoreboard plus fact-grade email attribution by sending mailbox and sending domain: sent, replies, positive replies, reply-type counts… | `read-only` |
| `oxygen_sequences_variants_action` | Mutates a sequence's A/B auto-winner state — the reversible control behind oxygen_sequences_variants. action='auto_optimize' runs the auto-winner now on every step with variants (pauses variants… | |
| `oxygen_sequences_workflows_configure` | Compatibility surface that previews or saves one old sequencer preset. | |
| `oxygen_sequences_workflows_list` | Compatibility surface for the two old sequencer presets: internal CRM lead-stage routing and positive-reply Microsoft Teams notifications. | `read-only` |
| `oxygen_spintax_generate` | Generate wording or copy variations as spintax: live (default) costs 3 credits and requires approval and a credit ceiling; explicit dry_run is a free preview. | |
| `oxygen_suppressed_addresses_remove` | Remove one email-address sending block or up to 500 exact addresses after approval of the keys. | |
| `oxygen_suppressed_domains_list` | Read domain-wide sending blocks, newest first. Domain reasons differ from address reasons. MCP defaults to bounded summary pages; follow paging.next_offset with the same filters. 0 credits. | `read-only` |
| `oxygen_suppressed_domains_remove` | Remove one domain-wide sending block or up to 500 exact domains after approval of the keys. | |
| `oxygen_suppressions_add` | Adds or refreshes selected lead ids on the org DNC list. Choose lead_provider_id or lead_provider_ids (1-500). Idempotent; reason defaults to manual. Prevents enrollment and contact. 0 credits. | |
| `oxygen_suppressions_addresses_list` | Read blocked email addresses (bounces, unsubscribes and imports), newest first, with matching CRM identities. | `read-only` |
| `oxygen_suppressions_companies_list` | Lists explicit company-domain or LinkedIn-company DNC identities. These stop every Sequence channel and are never inferred from a contact email. 0 credits. | `read-only` |
| `oxygen_suppressions_company_remove` | Deliberately re-enables one explicit company-domain or LinkedIn-company identity. 0 credits. | |
| `oxygen_suppressions_crm_backfill` | Creates CRM person records for people already on the do-not-contact list. | |
| `oxygen_suppressions_hubspot_lists` | Lists HubSpot contact/company saved lists and readable property schemas for DNC mapping. Reads definitions only: no memberships, writes, enrollment, or outbound action. 0 credits. | `read-only` |
| `oxygen_suppressions_hubspot_sync` | Preview or arm a bounded, additive HubSpot contact/company list → shared Oxygen DNC Workflow. Live requires approval and the exact dry-run fingerprint. Never enrolls or sends. | |
| `oxygen_suppressions_import` | Import bundled `people`, typed `identities`, or legacy `entries`. | |
| `oxygen_suppressions_list` | Lists the org do-not-contact list (the people/multichannel suppression set the sequencer enroller always skips), newest first. | `read-only` |
| `oxygen_suppressions_phone_remove` | Deliberately re-enables one strict E.164 phone identity. List removal is never automatic. 0 credits. | |
| `oxygen_suppressions_phones_list` | Lists strict E.164 phone suppressions used by call, WhatsApp, and Sequence safety gates. 0 credits. | `read-only` |
| `oxygen_suppressions_policy_get` | Rules for who is auto-added to do-not-contact: email hard bounce, one-click unsubscribe, opt-out wording in a reply, ANY inbound LinkedIn or WhatsApp reply, do-not-call/wrong-number outcomes, and… | `read-only` |
| `oxygen_suppressions_policy_set` | Sets one do-not-contact rule, or resets it (reset) or all (reset_all) to the default. effect: off, stop_only (end this enrollment only), suppress (also add to the list). | |
| `oxygen_suppressions_remove` | Removes selected lead ids or every identity of selected subject ids from the org DNC list. Choose one singular selector or a 1-500 item array. 0 credits. | |
## deliverability (`?toolset=deliverability`)
| Tool | What it does | Notes |
| --- | --- | --- |
| `oxygen_dedicated_egress_status` | Read dedicated outbound egress status and its current monthly commitment without activating it. | `read-only` |
| `oxygen_domains_add` | BYOK CLOUDFLARE ONLY. | |
| `oxygen_domains_adopt` | STAFF-ONLY LEGACY RECOVERY. | `staff` |
| `oxygen_domains_archive` | Archives (or unarchives) a cached domain — an Oxygen-side declutter flag only. | |
| `oxygen_domains_buy` | Without approved=true, returns a free preview and quote_id; nothing is purchased. | |
| `oxygen_domains_check` | Checks availability + price for 1-20 exact domains: own Cloudflare Registrar (USD) or Oxygen (credits at cost; reason=owned: already theirs). Free; pass registrable ones to oxygen_domains_buy. | `read-only` |
| `oxygen_domains_delete` | Preview domain and inbox removal; execute with the exact plan hash and confirmation. Oxygen-bought domains stop renewing but stay registered until expiry; no refund. | |
| `oxygen_domains_dns` | Live read-only DNS health check for one domain's Cloudflare zone (0 credits): evaluates the cold-email posture (SPF, DKIM, DMARC, MX presence, proxied mail CNAMEs) PLUS a DNS-over-HTTPS… | |
| `oxygen_domains_dns_apply` | Writes planned cold-email DNS records into your own Cloudflare zone. | |
| `oxygen_domains_dns_plan` | FREE cold-email DNS preview: SPF, provider MX, DMARC, DKIM and optional tracking, diffed against live records as create/update/keep/conflict plus plan_hash. | |
| `oxygen_domains_forwarding_get` | Reads where an Oxygen-managed domain's WEB root forwards visitors (not mail — MX/SPF/DKIM/DMARC untouched). | `read-only` |
| `oxygen_domains_forwarding_set` | Points an Oxygen-managed domain's WEB root at a URL, or clears it (forwarding_url: ""). | |
| `oxygen_domains_get` | Fetches one domain's full detail. rail=cloudflare (cached zone): zone state, age with provenance (registrar/RDAP), mailboxes with warmup state, sending volume (7d/30d), reply rate (30d), DNS… | `read-only` |
| `oxygen_domains_list` | Lists the org's cold-email domains from the Cloudflare-synced cache (zero Cloudflare calls): zone status, domain age with provenance (registrar/RDAP), mailbox + warmup rollup, sending volume… | `read-only` |
| `oxygen_domains_registration_status` | Returns the purchase-ledger status for one domain registration (submitting, in_progress, succeeded, failed, action_required, or blocked, with failure_reason when failed). | |
| `oxygen_domains_registrations_list` | Lists the org's domain purchase ledger (newest first) from the tenant cache — every registration attempt with status, price snapshot, and failure_reason — plus count and open_count (non-terminal… | `read-only` |
| `oxygen_domains_renewal` | Turns yearly renewal of a domain bought through Oxygen on or off. No charge; off lets it lapse at expiry. | |
| `oxygen_domains_search` | Searches purchasable domains for a query, with price. | `read-only` |
| `oxygen_domains_sync` | Refreshes Cloudflare-backed domains only (BYOK — read-only against Cloudflare, 0 Oxygen credits): zone pages, registrar metadata, RDAP age backfill, and DNS health checks. | |
| `oxygen_domains_tag` | Replaces a sending domain's workspace tags (Tags primitive; see oxygen_tags_list). Whole-set: pass the full list, [] clears. Survives domain syncs. | |
| `oxygen_domains_tracking_setup` | Provisions the open/click tracking CNAME for a domain on its Cloudflare zone (the cluster-A DNS writer): ` CNAME `, DNS-only. | |
| `oxygen_domains_tracking_status` | Returns the open/click tracking status for a domain: whether a tracking CNAME is configured, the tracking host, its verification status (pending \| verified \| failed \| not_configured), the CNAME… | `read-only` |
| `oxygen_egress_assign` | Converges mailbox policy assignments: managed/shared by default, or the workspace's dedicated IP for every current and future inbox while its add-on is active. | |
| `oxygen_egress_dedicated_cancel` | Cancels at the end of the paid 30-day period. | |
| `oxygen_egress_dedicated_request` | Dedicated native egress add-on: 2,500 credits every 30 days ($25). | |
| `oxygen_egress_ips` | Lists the shared native worker IP and this workspace's dedicated IP history, with endpoint, tier, and status. Staff also see provider metadata. Routing is workspace-scoped. Read-only, 0 credits. | `read-only` |
| `oxygen_egress_register` | STAFF-ONLY RECOVERY: registers ONE legacy/manual logical policy-inventory row in this deployment environment (dev API -> dev policy inventory, prod -> prod). | `staff` |
| `oxygen_egress_rotate` | RETIRED compatibility tool: workspace-scoped egress cannot rotate one mailbox. | `read-only` |
| `oxygen_egress_status` | Shows actual native email egress: shared worker or dedicated drain, active endpoint, IP health, add-on state, and one page of mailbox policy assignments. | `read-only` |
| `oxygen_email_send` | Previews or sends ONE ad-hoc email without a Sequence. | |
| `oxygen_mailbox_sequences` | Read the sequences using one sending mailbox by id or email address. | `read-only` |
| `oxygen_mailboxes_compatibility` | Read-only origin/platform/auth verdicts for native send, OXYGEN Warm-up, and EmailGuard. catalog_only returns the import contract and provider matrix without workspace rows. | `read-only` |
| `oxygen_mailboxes_connect_oauth` | Composio Gmail/Microsoft 365: owner consent; max 10 exact registered addresses. | |
| `oxygen_mailboxes_connect_oauth_status` | Read consent/history progress by OAuth run id. Connected requires verified mailbox identity/scopes. | `read-only` |
| `oxygen_mailboxes_delegation_status` | Google sending-domain delegation only, not Microsoft OAuth or a credential-file handoff to OXYGEN Warm-up/EmailGuard. | `read-only` |
| `oxygen_mailboxes_delete` | Preview/approve deleting exact mailboxes, or whole domains with all their inboxes, at 0 credits; no refund. | |
| `oxygen_mailboxes_emailguard_auto_enroll_get` | Read the workspace's automatic monitoring enrollment grant and last sweep. | `read-only` |
| `oxygen_mailboxes_emailguard_auto_enroll_set` | Preview, arm or disarm automatic mailbox monitoring. Arming recurring spend requires approved=true and max_credits_per_cycle. | |
| `oxygen_mailboxes_emailguard_connect` | Preview every mailbox origin and approve EmailGuard monitoring for credential-capable Google Workspace mailboxes (managed, Zapmail, or a compatible encrypted external import). | |
| `oxygen_mailboxes_emailguard_disconnect` | Preview/approve owned EmailGuard account deletion with plan_hash. Billing stops only after confirmed remote deletion. | |
| `oxygen_mailboxes_get` | Gets one sender with connectionRepair/warmupRepair ownership; effective_cap is today's campaign limit and ramp-up. | `read-only` |
| `oxygen_mailboxes_health` | Fleet email health, 0 credits, pure read: reputation bands per mailbox/fleet, plus OXYGEN's provider-free evidence, scoped by `signals.window`/`sendSource` (7d, sequence). | `read-only` |
| `oxygen_mailboxes_import` | Imports non-secret identities, inline or Zapmail. Every inbox lands under a sender profile; sender_profile_id names it, else names on the row find or create one. Receipts carry the OAuth review plan. | |
| `oxygen_mailboxes_list` | Lists senders with connectionRepair/warmupRepair ownership. Today's limit: oxygen_mailboxes_get. | `read-only` |
| `oxygen_mailboxes_oauth_health` | Rolls up every Google/Microsoft sending mailbox with no usable individual OAuth or verified delegation/application access, minus Google domains already covered by delegation. | `read-only` |
| `oxygen_mailboxes_set_cap` | Sets one mailbox's campaign daily cap, default 25; oxygen_limits_show reports the maximum. The campaign ramp-up (oxygen_mailboxes_set_ramp) may lower it. Free write. | |
| `oxygen_mailboxes_set_ramp` | Sets the campaign ramp-up: start_per_day, then +step every increase_every_days sending days until the daily cap. off:true sends the full cap from day one; clear:true restores 5/10/20. | |
| `oxygen_mailboxes_set_status` | Sets a sending mailbox's status. | |
| `oxygen_mailboxes_sync` | Progress: oxygen_mailboxes_sync_status. Preview/approve controls. Disconnect stops sync/sends and mailbox renewals; mail/CRM stays. Seat/add-on contracts remain. | |
| `oxygen_mailboxes_sync_status` | Read mail history/CRM analysis progress. | `read-only` |
| `oxygen_mailboxes_tag` | Replaces a sending mailbox's workspace tags (Tags primitive; see oxygen_tags_list). Whole-set: pass the full list, [] clears. Pools identities under a campaign tag. | |
| `oxygen_mailboxes_update` | Update a mailbox’s display name, signature or configurable bounce protection. Empty text clears it. No credits. | |
| `oxygen_mailboxes_warmup_action` | Uses each inbox's recorded rail: OXYGEN Warm-up, or TrulyInbox for older rows. pause/resume: 0 credits, no preview, subscription unchanged. disable removes/cancels billing. reconnect uses the… | |
| `oxygen_mailboxes_warmup_config` | Provider warm-up settings, separate from the campaign ramp. | |
| `oxygen_mailboxes_warmup_enable` | STANDALONE path: OXYGEN Warm-up. | |
| `oxygen_mailboxes_warmup_google` | Legacy Google owner consent for 1–10 connected inboxes; managed Gmail uses warmup_enable. | |
| `oxygen_mailboxes_warmup_microsoft` | NON-INBOXKIT FALLBACK ONLY. | |
| `oxygen_mailboxes_warmup_profile_set` | Preview or apply an OXYGEN Warm-up profile to exact mailboxes or domains; approved=true applies the reviewed scope. | |
| `oxygen_mailboxes_warmup_profiles` | Read available OXYGEN Warm-up profiles and current bindings. | `read-only` |
| `oxygen_mailboxes_warmup_status` | Syncs and persists warmup at 0 credits; conditionally auto-pauses runaways on fresh evidence. | |
| `oxygen_managed_inbox_avatar_confirm` | Verify and normalize a mailbox profile picture owned by this workspace. | |
| `oxygen_managed_inbox_avatar_prepare` | Prepare a scoped mailbox profile-picture upload; confirm the stored bytes before using its URL. | |
| `oxygen_managed_inbox_domains_search` | Search available domains for managed mailboxes; buys nothing. | `read-only` |
| `oxygen_managed_inbox_registrant` | Read this workspace's domain-registration contact. | `read-only` |
| `oxygen_managed_inboxes_add_mailboxes` | Adds mailboxes to an owned domain. | |
| `oxygen_managed_inboxes_cancel` | Cancel inboxes and all recurring warm-up/placement add-ons. | |
| `oxygen_managed_inboxes_exit` | Stops every OXYGEN renewal for a managed domain (inboxes, warm-up, placement) after the paid period and records a handoff request. | |
| `oxygen_managed_inboxes_get` | Gets one managed subscription; poll until active; only `warmup_activation.automatic_after_provisioning=true` on a preview or receipt is authoritative. | `read-only` |
| `oxygen_managed_inboxes_list` | Lists subscriptions and orders. | `read-only` |
| `oxygen_managed_inboxes_recover` | Restore original canceled inboxes: 0-credit eligibility, upfront and recurring quote. Verify authorization and warmup after recovery. | |
| `oxygen_managed_inboxes_subscribe` | Quotes or buys managed inboxes on new, existing Cloudflare or Oxygen-bought domains. | |
| `oxygen_managed_inboxes_verify` | Compares purchased inbox inventory with the vendor and legacy Stripe mailbox seats. | `read-only` |
| `oxygen_placement_tests_get` | Read one directional placement test. Poll Zapmail while awaiting_results. Evaluation summary units are unverified; values are shown as recorded. | `read-only` |
| `oxygen_placement_tests_list` | Lists recent DIRECTIONAL placement tests with provider, status, billing, seeds, score, and credits, plus `pricing` (monitoring credits per inbox-month, included and extra tests, own-key platform… | `read-only` |
| `oxygen_placement_tests_run` | Free directional preview returns provider, cost and plan_hash. | |
| `oxygen_placement_tests_send` | Free EmailGuard preview shows exact sender, transport, all seeds, content and plan_hash. | |
| `oxygen_senders_checkpoint_resend` | Asks LinkedIn (via Unipile) to resend the security checkpoint notification (2FA / OTP / in-app validation) so the member can read a fresh code, then submit it with oxygen_senders_checkpoint_solve. | |
| `oxygen_senders_checkpoint_solve` | Submits the LinkedIn checkpoint code (2FA / OTP / in-app validation) Unipile is waiting on to finish authentication and bring a stuck sender back to active. | |
| `oxygen_senders_connect` | Creates 1-25 10-minute LinkedIn authorizations. | |
| `oxygen_senders_disconnect` | Disconnects a LinkedIn sender account so it stops sending and reading immediately. | |
| `oxygen_senders_get` | Gets one LinkedIn sender account with full limits, daily-reset timezone, and usage. id accepts sender account id, connection id, or Unipile account id. | `read-only` |
| `oxygen_senders_health` | One-call health snapshot for a LinkedIn sender: tenant + connection status, the latest account error reason, any open security checkpoint, today's usage, the warm-up ramp, when the daily quota… | `read-only` |
| `oxygen_senders_inbox_scope_get` | Reads whether one LinkedIn sender syncs only conversations started through OXYGEN or the entire LinkedIn inbox. No provider call and no credits. | `read-only` |
| `oxygen_senders_inbox_scope_set` | Changes LinkedIn inbox privacy for one sender. oxygen_initiated stops ingesting and hides unrelated chats; all explicitly opts into the full inbox. | |
| `oxygen_senders_limits_get` | Reads the per-account limits envelope: current effective limits, the org's overrides, working hours, the warm-up ramp state (whether the account is still warming and today's effective… | `read-only` |
| `oxygen_senders_limits_set` | Updates per-account daily limits for sends (invites/messages/InMails) AND reads (relations lists, message history, searches, profile views), working hours, and the warm-up ramp… | |
| `oxygen_senders_list` | Lists the workspace's connected LinkedIn sender accounts with health status, per-account rate limits, and today's usage. Use before creating sequences or to check account health. | `read-only` |
| `oxygen_senders_profiles_create` | Creates a sender profile. from_sender_account_id seeds name + avatar from a LinkedIn account and attaches it (the person's identity); then assign inboxes (mailbox_ids) and WhatsApp/LinkedIn… | |
| `oxygen_senders_profiles_delete` | Deletes a sender profile. Its accounts detach (return to the unassigned pool); they are never deleted. | |
| `oxygen_senders_profiles_get` | Gets one sender profile with the LinkedIn/WhatsApp senders and email inboxes attached to it. | `read-only` |
| `oxygen_senders_profiles_list` | Lists sender profiles (a person's LinkedIn/WhatsApp senders + inboxes as one sending identity) with per-channel account counts. | `read-only` |
| `oxygen_senders_profiles_tag` | Replaces a sender profile's workspace tags (Tags primitive; see oxygen_tags_list). | |
| `oxygen_senders_profiles_update` | Updates a sender profile's fields (name, first_name, last_name, photo, status) and/or membership. | |
| `oxygen_senders_proxy_country_set` | Moves a LinkedIn sender's proxy to another country without reconnecting (zero credits). If none is free there, the sender stays paused and each sync retries. | |
| `oxygen_senders_sync` | Refreshes account health/status from Unipile for all (or one) connected LinkedIn accounts. | |
| `oxygen_senders_tag` | Replaces a LinkedIn/WhatsApp sender account's workspace tags (Tags primitive; see oxygen_tags_list). Whole-set: pass the full list, [] clears. | |
## inbox (`?toolset=inbox`)
| Tool | What it does | Notes |
| --- | --- | --- |
| `oxygen_inbox_analyze` | Runs the default analysis on one conversation now — email (default), LinkedIn, or WhatsApp: assigns the triage status and a drafted reply. | |
| `oxygen_inbox_archive` | Archives a conversation (triages it out of the Unibox), or restores it with archived=false. | |
| `oxygen_inbox_attachment_upload` | Upload a PDF, DOCX, XLSX, PPTX, TXT, or CSV to one existing email conversation. | |
| `oxygen_inbox_auto_tagger_get` | Shows the AI Inbox Tagger config: enabled state, tag allowlist, target channels. Null when never configured. | `read-only` |
| `oxygen_inbox_auto_tagger_set` | Configures the AI Inbox Tagger: enable/disable, replace the tag allowlist (max 50; [] pauses tagging), pick target channels. | |
| `oxygen_inbox_backfill` | Opt-in, LinkedIn only: pull a LinkedIn account's OLDER message history into the unibox as a slow durable background drip (one bounded page per thread per tick, default 10 reads/day) so long… | |
| `oxygen_inbox_bulk` | Applies one triage action — set_status, archive, or unarchive — across up to 100 hand-picked conversation ids (from oxygen_inbox_list). | |
| `oxygen_inbox_delete_message` | Delete your sent LinkedIn message for everyone within 60 minutes; irreversible. Show the default preview before approved=true. Only your LinkedIn messages are supported. Costs 0 credits. | |
| `oxygen_inbox_draft_reject` | Rejects an open AI reply-agent draft so it leaves the review queue. Does not send anything. | |
| `oxygen_inbox_draft_update` | Edits an open AI reply-agent draft's body before approval. Does not send. | |
| `oxygen_inbox_drafts_list` | Lists the AI reply-agent review queue: queued + edited by default, across email + LinkedIn. | `read-only` |
| `oxygen_inbox_forget_whatsapp_chat` | Preview or permanently erase one terminal old WhatsApp chat and its messages from OXYGEN only. | |
| `oxygen_inbox_get` | Get one inbox conversation with its full chronological message thread, sales-intent status and suggested reply. | `read-only` |
| `oxygen_inbox_label_archive` | Archives a custom status label. System labels and labels still applied to a conversation are rejected. | |
| `oxygen_inbox_label_create` | Creates a custom inbox status label (the '+ Create Label' action). | |
| `oxygen_inbox_label_restore` | Restores an archived custom status label under its original key. Idempotent if already active. | |
| `oxygen_inbox_label_update` | Updates a status label's name, color, bucket, description, or (custom labels only) ai_settable flag. A system label's ai_settable flag is immutable and cannot be changed. | |
| `oxygen_inbox_labels_list` | Lists the org's inbox status labels (the Instantly-style system set plus any custom labels), each with its Primary/Others bucket and whether the AI may assign it. | `read-only` |
| `oxygen_inbox_list` | Unibox merges email/LinkedIn/WhatsApp by default, newest first; channel picks one. | `core` `read-only` |
| `oxygen_inbox_mark_all_read` | Marks EVERY conversation matching the filters read across email, LinkedIn, and WhatsApp, not just one page. | |
| `oxygen_inbox_mark_read` | Marks visible messages in an inbox conversation read, retaining selected DM sender scope: LinkedIn by default, WhatsApp with channel=whatsapp, or the email inbox with channel=email. | |
| `oxygen_inbox_reply_agent_get` | Gets the AI reply-agent config (persona, tone, target campaigns/statuses, enabled flag). The agent only ever drafts replies — it never sends. | `read-only` |
| `oxygen_inbox_reply_agent_set` | Configures the AI reply agent (the draft-only 'AI Sales Agent'). | |
| `oxygen_inbox_rescan` | Re-queues conversations for background re-classification (status + drafted reply). | |
| `oxygen_inbox_send` | Replies into a conversation on its own channel, resolved from the conversation when channel is omitted: an email thread replies from its own mailbox (threaded), a LinkedIn thread sends a Unipile… | |
| `oxygen_inbox_set_status` | Sets the triage status on a conversation — email (default), LinkedIn, or WhatsApp (e.g. interested, neutral, not_now, not_interested, or a custom label key). | |
| `oxygen_inbox_start_whatsapp` | Preview or send the first message of a one-to-one WhatsApp chat from a connected sender. | |
| `oxygen_inbox_sync` | Forces a backstop sync from Unipile for LinkedIn and WhatsApp sender accounts, pulling recent chats and messages into the unibox. | |
| `oxygen_inbox_tags` | Adds/removes workspace tags on a conversation — email (default), LinkedIn, or WhatsApp (Tags primitive; see oxygen_tags_list). | |
| `oxygen_inbox_view_create` | Saves a named Unibox view for the whole team. filters is a Unibox URL or a query string of oxygen_inbox_list params (e.g. sender_profile_id=<id>&channels=linkedin&status=interested); without… | |
| `oxygen_inbox_view_delete` | Deletes a team Unibox view. Members who used it as their default open on the built-in view. | |
| `oxygen_inbox_view_update` | Renames, re-filters (replaces filters) or reorders a team Unibox view. default=true makes it the caller's own default; default=false stops using it as one. | |
| `oxygen_inbox_views_list` | Lists the team's saved Unibox views (named filter states: senders, channels, statuses), each with its filters as inbox list params and web_url. is_default marks the caller's own default, which the… | `read-only` |
| `oxygen_linkedin_inbox_backfill_status` | Read the durable LinkedIn inbox backfill status. | `read-only` |
| `oxygen_messages_query` | Full-text search across every individual email, LinkedIn and WhatsApp message in the org — message-level, not conversation-level (use oxygen_inbox_list to triage threads). | `read-only` |
| `oxygen_messages_stats` | INBOX-WIDE analytics over the org's whole message corpus. | `read-only` |
| `oxygen_notetaker_schedule` | Schedules a Recall invited meeting bot. Defaults to dry_run and returns the credit estimate. Live scheduling requires live=true or mode='live', approved=true, and max_credits at or above the estimate. | |
| `oxygen_notetaker_setup` | Configures the Recall-backed Oxygen Notetaker. Defaults to dry_run; pass mode='live' or live=true to save settings after reviewing the webhook URL and required Recall subscriptions. | |
| `oxygen_notetaker_status` | Gets one notetaker session, including Recall status, artifacts, linked CRM activity id, and credit reservation/usage state. | `read-only` |
| `oxygen_unibox_metadata` | Read the complete authenticated inbox account, filter and tag metadata, including each sender profile (person) and its id. | `read-only` |
| `oxygen_voice_numbers` | The org's dialing pool. | |
| `oxygen_voice_tasks_list` | Lists the call queue: leads waiting for a human to dial, queued by sequence call steps, CRM records, table rows, replies, or by hand. Best-first (priority, then due). Read-only, 0 credits. | `read-only` |
| `oxygen_voice_tasks_update` | Moves one call task through the queue. queue puts a lead IN (needs lead_phone; idempotent, an already-queued lead returns created:false; warnings names anything undialable). claim takes the next… | |
| `oxygen_whatsapp_accounts_list` | Read stored WhatsApp accounts (disconnected hidden by default; presence is not send readiness), health, warm-up and usage. include_disconnected includes retained accounts; status takes precedence. | `read-only` |
| `oxygen_whatsapp_chat_action` | Acts on one WhatsApp chat (see the action enum). | |
| `oxygen_whatsapp_connect` | Creates pending WhatsApp authorization for QR/phone pairing where supported; users complete it in their browser. | |
| `oxygen_whatsapp_disconnect` | Disconnects a WhatsApp account so it stops sending and reading immediately. | |
| `oxygen_whatsapp_draft` | Drafts a WhatsApp message to a prospect in YOUR canonical voice (workspace voice/brand/positioning) with the right prospect context — attendee, prior thread, and (with row_id) CRM fields + buying… | |
| `oxygen_whatsapp_draft_reject` | Rejects an open WhatsApp draft so it leaves the review queue. | |
| `oxygen_whatsapp_draft_update` | Edits an open WhatsApp draft's body before approval/send. | |
| `oxygen_whatsapp_drafts_list` | Read stored WhatsApp agent drafts; personal composer drafts stay private. | `read-only` |
| `oxygen_whatsapp_forward` | Forwards a WhatsApp message into another chat. Delivers a NEW message: spends send budget, bounded by the warm-up ramp, APPROVAL-GATED (previews unless approved). WhatsApp only. | |
| `oxygen_whatsapp_get` | Gets one WhatsApp account with full limits, the warm-up ramp state (account age + today's effective send ceiling), daily-reset timezone, and usage. | `read-only` |
| `oxygen_whatsapp_history_sync` | Backfills ONE WhatsApp conversation's message history; call again with the same chat_id to poll. | |
| `oxygen_whatsapp_limits_get` | Reads the per-account limits envelope: current effective limits, the org's overrides, the warm-up ramp schedule and today's effective send ceiling, the direct-send versus Sequence cold-initiation… | `read-only` |
| `oxygen_whatsapp_limits_set` | Updates per-account daily caps for WhatsApp sends (max 40/day) AND reads, plus action spacing and the daily-reset timezone. | |
| `oxygen_whatsapp_profile_get` | Reads the connected number's own WhatsApp profile: display name, About/status, picture, business flag. | `read-only` |
| `oxygen_whatsapp_profile_update` | Edits the connected number's own WhatsApp profile (the only three fields WhatsApp allows). APPROVAL-GATED: every contact sees the change, so it previews unless approved. Pass at least one field. | |
| `oxygen_whatsapp_sync` | Refreshes account health/status from Unipile for all (or one) connected WhatsApp accounts. | |
| `oxygen_whatsapp_warm_send` | Sends ONE warm WhatsApp message to a contact who ALREADY has a WhatsApp conversation with a connected account. | |
## publishing (`?toolset=publishing`)
| Tool | What it does | Notes |
| --- | --- | --- |
| `oxygen_engagement_comment` | Comments on a LinkedIn post, or replies to a comment with comment_id. | |
| `oxygen_engagement_harvest` | Starts a durable background harvest of a post's reactors and commenters into a workspace table; no messages are sent. source=cookieless uses the managed scraper and requires post_url plus… | |
| `oxygen_engagement_harvest_status` | Shows the progress of a LinkedIn engagement harvest: the drip's status, engagers ingested so far, pages read, last error, plus the workspace table it fills (with a deep-link) and a preview of… | `read-only` |
| `oxygen_engagement_list_engagers` | Reads reactors and commenters on a post the connected account owns, returning a de-duplicated people list for a Sequence or Table. | `read-only` |
| `oxygen_engagement_react` | Adds a reaction to a LinkedIn post, or to a comment with comment_id. | |
| `oxygen_inmail_balance` | Reads the remaining LinkedIn InMail credit balance for a connected sender account (requires Premium / Sales Navigator / Recruiter on that account). | `read-only` |
| `oxygen_linkedin_connections_import` | Reads a LinkedIn account's 1st-degree connections into an enrichable Clay-like workspace table plus a deduped system-of-record mirror. | |
| `oxygen_linkedin_connections_status` | Shows the progress of LinkedIn connections imports: each drip's status, connections ingested so far, pages read, last error, plus a preview of the connections table and a deep-link to open it… | `read-only` |
| `oxygen_linkedin_followers_import` | Reads a LinkedIn account's followers into an enrichable workspace table and a deduped mirror. | |
| `oxygen_linkedin_followers_status` | Shows the progress of LinkedIn followers imports: each drip's status, followers ingested so far, pages read, last error, plus a preview of the followers table and a deep-link to open it. account… | `read-only` |
| `oxygen_linkedin_intent_autoenroll` | Binds the standing auto-enroll grant on LinkedIn intent captures: people a capture lands enroll into a Sequence each cycle, paced by the sender's warm-up ramp and the caps set here. | |
| `oxygen_linkedin_intent_setup` | Creates or reuses two durable OXYGEN Tables: one deduped LinkedIn Engaged People table and one linked LinkedIn Touchpoints table. | |
| `oxygen_linkedin_intent_status` | Shows the canonical linked people/touchpoint tables and the capture-only LinkedIn feeds filling them. Read-only. | `read-only` |
| `oxygen_linkedin_invitations_pause` | Stops checking open connection requests for one account, or every account when account is omitted. | |
| `oxygen_linkedin_invitations_setup` | Keeps one self-updating table of every open LinkedIn connection request on the workspace's own accounts: people who asked to connect (direction received) and requests sent that are still waiting… | |
| `oxygen_linkedin_invitations_status` | Shows the open connection requests table: accounts[] lists every connected LinkedIn account with on, state and next_read_at, plus a table preview and deep-link. | `read-only` |
| `oxygen_linkedin_invites_sent` | Live provider read of pending sent LinkedIn invitations; 0 credits, no provider write. | `read-only` |
| `oxygen_linkedin_invites_withdraw` | Withdraws pending sent LinkedIn invitations. | |
| `oxygen_linkedin_network_pause` | Switches LinkedIn network capture off: the worker stops reading that account's connections and followers until oxygen_linkedin_network_setup arms it again. | |
| `oxygen_linkedin_network_setup` | Captures everyone already in the workspace's LinkedIn network — 1st-degree connections AND followers — into ONE self-refreshing table, deduped to a single row per person with a Relationship column… | |
| `oxygen_linkedin_network_status` | Shows LinkedIn network capture progress: accounts[] lists every connected account with on (switched on or not), state and connections/followers counts; which accounts are armed, how far each… | `read-only` |
| `oxygen_linkedin_send_invite` | Sends a LinkedIn connection invitation. | |
| `oxygen_posts_comments_list` | Lists comments on a LinkedIn post (or, with comment_id, the replies under one comment). | `read-only` |
| `oxygen_posts_create` | Publishes a LinkedIn post from a connected sender account (or as a company with as_organization), with optional media, an external-link preview, mentions, a repost, or an embedded job. | |
| `oxygen_posts_delete` | Deletes a LinkedIn post the account authored — a real, irreversible LinkedIn write. post is the composite social_id returned by oxygen_posts_create (or oxygen_posts_get). | |
| `oxygen_posts_get` | Gets a LinkedIn post by id and returns its full record — crucially the composite social_id you must pass to oxygen_posts_comments_list / oxygen_posts_reactions_list /… | `read-only` |
| `oxygen_posts_reactions_list` | Lists who reacted to a LinkedIn post (or, with comment_id, to one comment). | `read-only` |
| `oxygen_profile_viewers` | Lists the named LinkedIn profile viewers exposed by the connected account's Who Viewed My Profile (WVMP) analytics page. | `read-only` |
| `oxygen_profile_viewers_enrichment` | Switches standing automatic full-profile enrichment of NEW profile viewers on or off (Up2Data profile: about, current role and company, experience, education, location). | |
| `oxygen_profile_viewers_import` | Promotes 'who viewed my profile' (WVMP) from a one-shot read into a durable, deduped signal: reads named viewers into a Clay-like workspace table you can enrich and qualify, plus a deduped… | |
| `oxygen_profile_viewers_pause` | Switches the profile-viewers (WVMP) import off for one account or all: rows and the table stay exactly as they are, and oxygen_profile_viewers_import switches it back on. account selects which… | |
| `oxygen_profile_viewers_status` | Shows durable LinkedIn profile-viewers (WVMP) import progress: accounts[] lists every connected LinkedIn account with its display_name, headline, picture_url, per-account on (true when switched… | `read-only` |
| `oxygen_publishing_amplification` | Standing engagement from named accounts, paced and capped. list/get/actions read; create/update/enable/disable/delete govern policies. create needs approved=true and both caps, lands DISABLED… | |
| `oxygen_publishing_analytics` | Stored LinkedIn/X snapshots; no provider call. summary ranks posts; timeseries reports earned trends and followers; post/account read metric rows (MCP default 20); set_cpm writes EMV config… | |
| `oxygen_publishing_comments` | Read and triage Publishing Community, the local public-comment queue for owned posts. list/get make no provider call; update/resolve are local. | |
| `oxygen_publishing_draft_accept` | Accepts one draft variant into the publish queue as a NEEDS-APPROVAL post. It does not publish: approve the post separately. | |
| `oxygen_publishing_draft_reject` | Rejects a post draft. The reason is filed to the Knowledge Graph, so later drafts learn what this workspace will not publish. | |
| `oxygen_publishing_draft_update` | Edit a queued publishing draft's text without publishing it. | |
| `oxygen_publishing_drafts_list` | Lists AI post drafts awaiting a human decision. Defaults to the open queue (queued + edited). | `read-only` |
| `oxygen_publishing_idea_add` | Files a content idea into the backlog — a draft with kind=idea and no publish time. | |
| `oxygen_publishing_import` | Bulk-loads scheduled posts from rows or a CSV string. dry_run=true (the DEFAULT) parses, lints, and reports invalid rows while writing NOTHING — inspect that before passing dry_run=false. | |
| `oxygen_publishing_media_upload_url` | Creates media and an upload_url. PUT byte_length with upload_headers, then mark uploaded. | |
| `oxygen_publishing_media_uploaded` | Verifies a Publishing media object exists in storage and marks the durable media asset uploaded. | |
| `oxygen_publishing_mentions_resolve` | Checks that the LinkedIn identities a post references (@handles, /in/ and /company/ URLs, provider ids, URNs) exist and returns their profiles; it never changes the post. | |
| `oxygen_publishing_mentions_search` | Find LinkedIn company or person identities for a mention; free, subject to the connected account's read quota. | `read-only` |
| `oxygen_publishing_notes` | Internal post review notes. action=list\|add\|resolve; add replies with parent_comment_id, resolve settles a note or reopens it with resolved=false. list has resolved/limit filters and a… | |
| `oxygen_publishing_posts_approve` | Approves a draft or scheduled post; drafts become scheduled for publish_at. | |
| `oxygen_publishing_posts_boost` | One-off amplification of ONE post: creates a post-scoped, already-enabled policy and plans its actions immediately. | |
| `oxygen_publishing_posts_cancel` | Cancels a draft, scheduled, queued, or failed Publishing post and revokes its approval. oxygen_publishing_posts_uncancel reopens it as an unapproved draft; approve it again before it can publish. | |
| `oxygen_publishing_posts_create` | Creates a personal post. With ugc_participation_id it saves an unapproved program draft; ordinary posts default scheduled and publish only after approval. | |
| `oxygen_publishing_posts_delete` | Deletes OXYGEN copies and settled history only; live platform posts stay intact. | |
| `oxygen_publishing_posts_draft` | Drafts post variants with AI, grounded in the workspace Knowledge Graph (voice, positioning, campaign learnings). | |
| `oxygen_publishing_posts_get` | Gets one scheduled Publishing post with its sender account, resolved media assets, preview URLs, provider result, and publish attempt history. | `read-only` |
| `oxygen_publishing_posts_list` | Lists stored Publishing posts. Continue with next_cursor and identical filters; no provider call. | `read-only` |
| `oxygen_publishing_posts_retry` | Moves a failed approved Publishing post back to scheduled so the worker can attempt it again on the next 5-minute scheduler tick. | |
| `oxygen_publishing_posts_review` | Pre-publish review of one post: deterministic channel lint (free; error findings BLOCK approval) plus an AI voice/claims check against the Knowledge Graph (PAID, max_credits required; findings… | |
| `oxygen_publishing_posts_uncancel` | Reopens a canceled post as an unapproved draft, keeping its publish time and attempt history. Approve it again to re-arm it. | |
| `oxygen_publishing_posts_update` | Updates an editable draft, scheduled, or failed post. Changing its text or content revokes approval. | |
| `oxygen_publishing_revisions` | Content history of one scheduled post. action=list reads newest-first revisions with limit and a whole-receipt window (MCP default 20 rows). action=restore rolls the post back to revision_number… | |
| `oxygen_publishing_tags` | Adds/removes unified workspace tags on a scheduled post. Tags are internal and never published. | |
| `oxygen_visual_file_download` | Download a tenant-owned visual source or rendered file as exact bytes. | `read-only` |
## workflows (`?toolset=workflows`)
| Tool | What it does | Notes |
| --- | --- | --- |
| `oxygen_observability_approvals` | Workspace-wide approvals inbox across workflow approvals, publishing posts, AI message reviews, inbox reply drafts, and collaboration approval requests (a named human's go/no-go). | `read-only` |
| `oxygen_observability_events` | Lists recent CLI/API operation events and provider request events for the active organization. Useful for debugging failed runs by trace id. | `read-only` |
| `oxygen_observability_runs` | Workspace-wide runs lens: active and failed runs across workflows and table runs (search/sourcing included), newest first. | `read-only` |
| `oxygen_runs_get` | Returns a workspace run record by id (provider call, AI column, or workflow step) including provenance and steps. | `read-only` |
| `oxygen_runs_list` | Recent workspace runs (provider calls, AI column runs, workflow steps), newest first. One run's full provenance: oxygen_runs_get. | `core` `read-only` |
| `oxygen_table_runs_effect_unknown` | Lists the items of a table action run whose external write (a custom HTTP POST) was dispatched but never confirmed — codes custom_http_effect_unknown / worker_step_outcome_unknown. | `read-only` |
| `oxygen_table_runs_get` | Read one Table run: status, counts, costs and failures. Summary omits inputs/metadata. | `read-only` |
| `oxygen_table_runs_items` | Lists per-row items for a table action run, optionally filtered by status. Use to inspect failures. | `read-only` |
| `oxygen_table_runs_provider_summary` | Summarizes provider attempts, no-results, errors, upstream request events, poll statuses, and credit capture/release for a table action run. | `read-only` |
| `oxygen_table_runs_wait` | Wait for a Table run to finish or time out; repeat to continue watching. | `core` `read-only` |
| `oxygen_tables_activity` | Returns every active background run for a table (queued, running, or canceling) with status, item counts, throughput, ETA, credits, worker claim identity, and a worker-queue health rollup. | `read-only` |
| `oxygen_worker_failures` | Lists failed background worker items — table action runs, table ingestions, and Postgres-queue jobs — with failure reasons and counts. | `read-only` |
| `oxygen_worker_queue_stats` | Returns background worker queue health for table action runs, table ingestions, and workflows, including active worker ids and worker type (Fly worker, Vercel Queue, Vercel cron, or manual). | `read-only` |
| `oxygen_workflow_observed_output` | Inspect observed output paths and bounded samples from an exact run or recent matching workflow revision. | `read-only` |
| `oxygen_workflow_resource_status_set` | Enable or disable a Workflow and record an optional reason. Enabling paid recurring execution requires standing approval and max_credits; CRM-sync workflows use their paired lifecycle instead. | |
| `oxygen_workflow_run_events` | Read the exact Workflow run's bounded event history and whether it is still active. | `read-only` |
| `oxygen_workflow_run_step_statuses` | Read the current Workflow run status and every step status for immediate execution readback. | `read-only` |
| `oxygen_workflow_templates_apply` | Deprecated alias for oxygen_blueprints_apply; creates a disabled workflow. | |
| `oxygen_workflow_templates_describe` | Deprecated alias for oxygen_blueprints_describe. | `read-only` |
| `oxygen_workflow_templates_preflight` | Deprecated alias for oxygen_blueprints_preflight. Price-aware seeds return current runtime descriptor pricing and an exact zero-credit disabled-install command. | `read-only` |
| `oxygen_workflow_templates_run` | Removed alias (HTTP 410). Use oxygen_blueprints_apply, then oxygen_workflows_call. | |
| `oxygen_workflow_templates_search` | Deprecated alias for oxygen_blueprints_list; view=summary/names enables bounded lists with next_cursor. | `read-only` |
| `oxygen_workflow_tool_output_paths` | Discover bounded workspace-observed tool output paths and run/revision provenance, without exposing provider values. | `read-only` |
| `oxygen_workflow_webhook_deliveries` | Lists webhook payloads, safe headers, auth outcomes, and started runs. rejected=auth failed; blocked=authenticated/no run; ran=run started. | `read-only` |
| `oxygen_workflow_webhook_delivery_replay` | Durable inspectable dry_run of a verified outcome=ran delivery's exact revision/payload. | |
| `oxygen_workflow_webhook_rotate` | Previews or rotates the current published webhook secret. Call without approved first; approved=true invalidates the old secret and returns the replacement once. | |
| `oxygen_workflows_apply` | Saves a draft or publishes a Workflow. Autonomous tools need standing approval and an explicit or plan-default delivery cap. | |
| `oxygen_workflows_approvals` | Lists durable mid-run approvals; defaults to pending. | `read-only` |
| `oxygen_workflows_call` | Enqueues any workflow without simulating its trigger. live needs approved=true and a positive max_credits cap. | `core` |
| `oxygen_workflows_cancel` | Cancels a queued or running workflow run. | |
| `oxygen_workflows_delete` | Previews or permanently deletes one or many workflows. | |
| `oxygen_workflows_disable` | Disables one or many workflows and their triggers. | |
| `oxygen_workflows_duplicate` | Duplicates a workflow as a disabled copy by default, with new workflow and webhook ids. | |
| `oxygen_workflows_enable` | Enables one or many workflows. | |
| `oxygen_workflows_events_emit` | Emits an event to matching workflows. Live requires approval and a positive cap per delivery. | |
| `oxygen_workflows_events_get` | Gets one curated workspace event by exact catalog id and returns a ready-to-copy workflow trigger object. | `read-only` |
| `oxygen_workflows_events_list` | Searches and filters the trigger-ready catalog before returning results: every registered app-native event (including Meeting Notetaker), plus connected integration events. | `read-only` |
| `oxygen_workflows_export` | Exports one graph-native workflow as portable editable JSON. Source account UUIDs and trigger authority are removed. | `read-only` |
| `oxygen_workflows_failures` | Lists failed workflow runs and trigger scheduler failures for the organization. Durable recipe bundles are omitted unless include_bundle is true. | `read-only` |
| `oxygen_workflows_get` | Gets a workflow automation definition and current manifest. | `read-only` |
| `oxygen_workflows_import` | Creates a new current but disabled workflow from a portable graph definition. Never overwrites or enables a workflow. | |
| `oxygen_workflows_import_preflight` | Checks create-only workflow id and exact destination account bindings without creating anything. | `read-only` |
| `oxygen_workflows_lint` | Validate draft/publish readiness without saving, running, or spending. | `read-only` |
| `oxygen_workflows_list` | Lists workflows; optionally filter by tag. Newest 200 by default; see `capped`. | `core` `read-only` |
| `oxygen_workflows_mcp_callable` | List this workspace's published MCP-callable Workflow definitions and interfaces. | `read-only` |
| `oxygen_workflows_mcp_disable` | Unpublishes a workflow's dynamic MCP tool without disabling the workflow. | |
| `oxygen_workflows_mcp_enable` | Publishes an active workflow as a dynamic MCP tool; approval and spend gates remain unchanged. | |
| `oxygen_workflows_rename` | Renames only the display label; the next apply may overwrite it from the manifest. | |
| `oxygen_workflows_resume` | Approves or rejects a paused run. Pass its plan_hash to bind the decision to the reviewed plan; the run's cap remains enforced. | |
| `oxygen_workflows_retry` | Previews a failed-run resume from its first failed step. Preserves completed work and refuses uncertain writes. approved=true executes; live needs a new positive cap. | |
| `oxygen_workflows_revisions` | Every published version of one workflow, newest first: version, source hash, compiler version, publisher, and which one runs now (`isCurrent`). | `read-only` |
| `oxygen_workflows_revisions_restore` | Republish an earlier version as a new revision. Restore stays append-only and reruns lint, effect, cadence, authority, and spend-cap gates. | |
| `oxygen_workflows_run` | Gets one workflow run with step state, outputs, events, and worker claim identity. | `read-only` |
| `oxygen_workflows_runs` | Stored runs newest first; default 50. | `read-only` |
| `oxygen_workflows_schema` | Returns the JSON schema for OXYGEN workflow manifests and API calls. | `read-only` |
| `oxygen_workflows_tag` | Replaces a workflow's tag set; [] clears it. Does not create a revision. | |
| `oxygen_workflows_tail` | Polls until completion, failure, approval, clock wait, or timeout. | `core` `read-only` |
## agents (`?toolset=agents`)
| Tool | What it does | Notes |
| --- | --- | --- |
| `oxygen_agent_approval_decide` | Approves or rejects one pending Workspace or custom Agent capability call and resumes the durable run. The approval id comes from oxygen_agent_run_get events. | |
| `oxygen_agent_create` | Creates a user-defined custom Agent and publishes its first immutable version. | |
| `oxygen_agent_custom` | Lists the org's user-defined custom agents (slug, name, status, deep-link). Distinct from oxygen_agent_list, which returns the fixed built-in roster (Workspace Agent + the three specialists). | `read-only` |
| `oxygen_agent_delete` | Archives (soft-deletes) a custom agent: its triggers stop firing and it leaves the roster, while its versions, runs, and provenance are preserved. Built-in agents cannot be archived. | |
| `oxygen_agent_disable` | Disables one workspace agent so it stops its drafts/runs next worker tick. The notetaker keeps manual scheduling by design. | |
| `oxygen_agent_enable` | Enables one workspace agent so it resumes its approval-gated drafts/runs. Writes only its enabled flag. | |
| `oxygen_agent_file_create` | Stores a tenant-owned text file for Agent context or sandbox input. Inline content is capped at 1.5 MB. | |
| `oxygen_agent_files_list` | Lists tenant-owned text files available as Agent context and sandbox inputs. File content remains tenant-scoped. | `read-only` |
| `oxygen_agent_get` | Shows one agent — the Workspace Agent, a specialist, or a custom agent — with its active version, approval boundary, and recent runs. | `read-only` |
| `oxygen_agent_list` | Lists workspace agents with enabled state, approval boundary, and recent runs. | `read-only` |
| `oxygen_agent_run` | Starts a durable run for a runtime agent (the Workspace Agent or a custom agent). Returns an inspectable run id and deep-link while Fly execution continues. | |
| `oxygen_agent_run_cancel` | Requests checkpointed cancellation of an active Workspace or custom Agent run. | |
| `oxygen_agent_run_get` | Reads one Workspace or custom Agent run plus its append-only event ledger. Use after_seq for incremental polling. | `read-only` |
| `oxygen_agent_runs` | Recent runs across built-in and custom Agents (or one via slug), newest first, with status, credits, and deep-links. | `read-only` |
| `oxygen_agent_session_activate` | Approve the exact preview revision and activate scoped standing authority. | |
| `oxygen_agent_session_archive` | Archive this ongoing session, retaining conversation and run history. | |
| `oxygen_agent_session_complete` | Complete this ongoing session, retaining conversation and run history. | |
| `oxygen_agent_session_configure` | Replace settings at the expected revision. Clears standing authority and pauses active work; review again before activation. | |
| `oxygen_agent_session_create` | Create a draft ongoing session. Explicit caps are required; review and activate separately. | |
| `oxygen_agent_session_get` | Read this session's configuration revision, conversation, memory, next check, approvals and budget reservations. | `read-only` |
| `oxygen_agent_session_list` | List independent ongoing sessions under an Agent, including status, next check and spend. | `read-only` |
| `oxygen_agent_session_message` | Queue durable human steering. Draft chat proposes settings for review; active chat resumes the same memory. A bounded run reserves the approved per-run cap. | |
| `oxygen_agent_session_pause` | Pause this ongoing session, retaining conversation and run history. | |
| `oxygen_agent_session_preview` | Preview the exact pinned Agent version, resource scope, actions, schedule and caps. Returns the revision and approval token; starts no inference. | |
| `oxygen_agent_session_resume` | Resume this ongoing session. Requires unchanged approved settings. | |
| `oxygen_agent_session_run` | Run this active session's next check now, within its approved caps. Refused while a check runs or a cap is reached. | |
| `oxygen_agent_session_templates` | Discover eight ongoing Agent job templates, reviewed actions, required resources, the full config schema and a draft example. Staff on dev only; legacy Agents remain available. | `read-only` |
| `oxygen_agent_session_webhook` | Create this session's webhook or rotate its secret (returned once); remove deletes it. A delivery wakes the active session within its caps; its external writes then ask first. | |
| `oxygen_agent_trigger_create` | Creates a cron, internal event, or signed-webhook trigger for the Workspace Agent. | |
| `oxygen_agent_trigger_set` | Activates, pauses, or archives one Workspace Agent cron, event, or webhook trigger. | |
| `oxygen_agent_triggers` | Lists Workspace Agent cron, event and webhook triggers: next cron time, plan slowdown, webhook URL and rate_limit; never secrets. | `read-only` |
| `oxygen_agent_update` | Publishes an immutable version (governed model, context, skills, tools, sandbox, limits) for a runtime agent — the Workspace Agent or a custom agent. | |
| `oxygen_copilot_approve` | Resolves one pending approval a Workspace Copilot turn is blocked on. | |
| `oxygen_copilot_attachment_complete` | Verify and describe an uploaded Copilot attachment in its session. | |
| `oxygen_copilot_attachment_delete` | Detach an unsent Copilot attachment; attachments already quoted by a turn cannot be removed. | |
| `oxygen_copilot_attachment_prepare` | Reserve a Copilot attachment and return its scoped upload URL; complete only after uploading the exact bytes. | |
| `oxygen_copilot_attachments` | Lists files attached to a Workspace Copilot session, sent and unsent, with each one's kind (tabular/document/image/other), size, and preview (a spreadsheet's columns and row count). | `read-only` |
| `oxygen_copilot_attachments_list` | List sent and unsent attachments in one Copilot session. | `read-only` |
| `oxygen_copilot_cancel` | Cancels an in-flight Workspace Copilot session: stops the current turn and marks the session cancelled so it makes no further inference calls. Cancelling an already-cancelled session is a no-op. | |
| `oxygen_copilot_feedback` | Rate one attended Copilot turn and optionally explain the rating. | |
| `oxygen_copilot_get` | Reads one Workspace Copilot session: the session, its turns, the event timeline after `after_seq`, pending approvals, and the latest sequence cursor. | `read-only` |
| `oxygen_copilot_interrupt` | Request cancellation of one Copilot turn. Read the session again to confirm it stopped. | |
| `oxygen_copilot_send` | Sends one user message to a Workspace Copilot session and starts inference for that turn. | |
| `oxygen_copilot_session_update` | Set an attended Copilot session's approval and screen-follow policies. Paid auto-approval is explicit standing authorization. | |
| `oxygen_copilot_sessions_list` | List attended Copilot sessions in this workspace. | `read-only` |
| `oxygen_copilot_start` | Starts an attended Workspace Copilot session on Oxygen Balanced by default. | |
| `oxygen_oxygents_activity` | List an Oxygent's recent work: its runs and the actions taken in its chats, as metadata only (no goals or messages). | `read-only` |
| `oxygen_oxygents_chat` | Open your ongoing private chat with an Oxygent, creating it the first time. Starts no inference. | |
| `oxygen_oxygents_create` | Add an Oxygent to the workspace, named "New Bot" unless you name it; tell it its job in your chat with it. | |
| `oxygen_oxygents_forget` | Remove one entry from an Oxygent's team memory. | |
| `oxygen_oxygents_get` | Read one Oxygent's profile and your ongoing private chat with it. | `read-only` |
| `oxygen_oxygents_group` | Read one of your group chats: its name, members and the chat's state. | `read-only` |
| `oxygen_oxygents_group_create` | Start a private group chat with 2 to 6 Oxygents (members, by slug), named name. Starts no inference: @mention a member in a message to have it answer. | |
| `oxygen_oxygents_group_end` | End a group chat: nobody answers in it again, and its messages stay readable. | |
| `oxygen_oxygents_group_message` | Send a message in a group chat. | |
| `oxygen_oxygents_group_read` | Mark a group chat read up to its newest turn, or up to turn_index. | |
| `oxygen_oxygents_group_update` | Rename a group chat, or add or remove Oxygents (by slug); it keeps 2 to 6. A removed member's earlier messages stay. | |
| `oxygen_oxygents_groups` | List your group chats with Oxygents: name, members and the chat (working or waiting for you, unread, the latest words and who said them). Private to you. | `read-only` |
| `oxygen_oxygents_handoff` | From your chat with an Oxygent, ask another Oxygent (to) to do something: an unattended run of it, as you, within max_credits. | |
| `oxygen_oxygents_hide` | Hide an Oxygent from your own sidebar, or show it again with hidden:false. Its chat is kept; only your sidebar changes. Free. The first Oxygent cannot be hidden. | |
| `oxygen_oxygents_list` | List this workspace's Oxygents, the first one (is_default) on top: name, what each does, its look and your chat with each (working or waiting for you, unread, its latest words). | `read-only` |
| `oxygen_oxygents_memory` | List what the team asked an Oxygent to remember. Every chat with it reads this; it is a Knowledge page. | `read-only` |
| `oxygen_oxygents_message` | Send a message in your ongoing private chat with an Oxygent. Starts a turn billed from workspace credits; paid or external actions still need approval. | |
| `oxygen_oxygents_notes` | Read what an Oxygent keeps about you: private to you, read only in your own chat with it. | `read-only` |
| `oxygen_oxygents_notes_set` | Replace what an Oxygent keeps about you; empty clears it. Private to you. | |
| `oxygen_oxygents_pin` | Pin an Oxygent near the top of your own sidebar, or unpin it with pinned:false. Only your sidebar changes. Free. | |
| `oxygen_oxygents_read` | Mark your chat with an Oxygent read up to its newest turn, or up to turn_index. | |
| `oxygen_oxygents_remember` | Add one thing to an Oxygent's team memory: every chat with it reads it, and the whole workspace can see it. Free. | |
| `oxygen_oxygents_routines` | List your routines with an Oxygent: schedule, status, next run and last report. Manage one with `agent session` (pause, resume). | `read-only` |
| `oxygen_oxygents_task` | Start a background task from your chat with an Oxygent: an unattended run of it, as you, within max_credits. | |
| `oxygen_oxygents_update` | Edit an Oxygent's name, what it does (description) or its look (avatar_key, avatar_color). Its instructions, tools and versions are unchanged. Free. | |
| `oxygen_visual_file_get` | Read a visual file's metadata, editable source when HTML, provenance and authenticated download URL in the current workspace. | `read-only` |
| `oxygen_visual_image_view` | Return actual PNG pixels to a vision-capable client for visual review of a rendered infographic. | `read-only` |
| `oxygen_visual_render_cancel` | Request cancellation of one render. Queued jobs stop before compute; running jobs stop at a bounded cancellation checkpoint. Read the job to verify terminal status. | |
| `oxygen_visual_render_get` | Read durable visual-render status, outputs, provenance and downloads. An effect_unknown run never automatically repeats billed compute. Read again while queued/running. | `read-only` |
| `oxygen_visual_render_preview` | Preview isolated HTML-to-PNG/PDF rendering without starting compute. source_file_ids defines page order. | |
| `oxygen_visual_render_start` | Approve one exact render preview and enqueue bounded isolated compute. | |
| `oxygen_visual_source_create` | Save editable, immutable HTML/CSS/inline SVG source for a GTM infographic or carousel page. | |
## billing (`?toolset=billing`)
| Tool | What it does | Notes |
| --- | --- | --- |
| `oxygen_billing_activate` | Activate a trial subscription now and charge its saved payment method; administrator approval is required. An optional tier reprices the active trial in the same call. | |
| `oxygen_billing_allowance` | Inspect this workspace's recurring credit allowance and period; due plan grants or credit expiry may apply. 0 credits; reserves nothing. | |
| `oxygen_billing_allowance_view` | Inspect the current-cycle allowance, billing owner and partner-bonus eligibility; due plan grants or credit expiry may apply. 0 credits; reserves nothing. | |
| `oxygen_billing_audit` | Summarizes where managed Oxygen credits were granted, reserved, captured, released, or spent for the active organization. | |
| `oxygen_billing_balance` | Due plan grants or expiry may apply. | `core` |
| `oxygen_billing_cancel` | cancel records comment and stops renewal; resume restores it. offer reads only: 30% off one monthly invoice; retain accepts offer_id. | `core` |
| `oxygen_billing_change_plan` | Preview via approval_url; confirm to apply/pay. First purchase: admin/owner; existing plan: unrestricted members. Terms: oxygen_billing_balance. | `core` |
| `oxygen_billing_checkout` | Open browser Checkout; payment approves purchase. First purchase: admin/owner. New yearly plans use interval month, term year and the current terms_version. | |
| `oxygen_billing_commitments` | Read current connected-resource commitments, or view=connection-prices for LinkedIn/WhatsApp/X/mailbox monthly prices and first billing timing before authorization. | `read-only` |
| `oxygen_billing_commitments_view` | Read the complete fixed-credit commitment view and linked billing-owner display, without enumerating a child's sibling resources. | `read-only` |
| `oxygen_billing_confirm` | Confirm a plan-change preview within 15 minutes; approved accepts payment, term and effective date. Unrestricted members allowed; restricted clients denied. | |
| `oxygen_billing_estimate` | Quote prospective enrichment, senders, X/WhatsApp, EmailGuard managed/own-key tests and an unsaved Workflow. | `read-only` |
| `oxygen_billing_invoices` | Read this workspace's billing invoices and their hosted payment links. | `read-only` |
| `oxygen_billing_invoices_view` | Read the browser invoice-history projection, including exact native timestamps, amounts and signed Stripe invoice links. | `read-only` |
| `oxygen_billing_ownership_clear` | Restore this workspace's own billing ownership after the same administrator checks as the browser. | |
| `oxygen_billing_ownership_get` | Read the active workspace's shared billing owner, candidate owners and credit cap. | `read-only` |
| `oxygen_billing_ownership_set` | Set the billing owner and optional monthly credit cap using the browser's administrator and workspace eligibility checks. | |
| `oxygen_billing_portal` | Create a Stripe billing-portal URL. Unrestricted members allowed; restricted clients denied. | |
| `oxygen_billing_seats` | Read sending seats, current billing-period end, monthly credit prices and connection affordability/sponsorship (null: unknown, with reason). | |
| `oxygen_billing_seats_set` | Set purchased legacy sending-seat quantity. Retired seats cannot increase; reducing existing seats lowers the next renewal charge. | |
| `oxygen_billing_set_plan` | Staff only. | `staff` |
| `oxygen_billing_summary` | Read wallet, plan, partner-bonus eligibility/timing and billing owner without grants. | `read-only` |
| `oxygen_billing_topup` | No amount: free quote via oxygen_capabilities_call; no checkout. credits/pack: creates Stripe Checkout/billing resources; no charge until payment. | |
| `oxygen_billing_usage` | Due grants/expiry may apply. Ledger default; steps, BYOK fees, seats, holds. Workspace splits; ledger ISO from/to. Shares: oxygen_billing_audit via oxygen_capabilities_call. | `core` |
| `oxygen_billing_usage_view` | Credit spend over 7, 30 or 90 days by category and provider, each with its share, plus permitted linked-workspace rollups. totalSpent is reserved minus released; billing usage managed_credits_used… | `read-only` |
| `oxygen_budget_delete` | Deletes a standing budget policy by id. Requires an admin or owner role. | |
| `oxygen_budget_list` | Lists the organization's standing credit caps by scope and window, plus the plan defaults that apply without one: the daily guard and per-run Agent and trigger ceilings. | `core` `read-only` |
| `oxygen_budget_set` | Sets, raises, or lowers a standing credit cap (idempotent per scope+scope_id+window). hard_block stops runs at the cap; warn annotates but proceeds. Requires an admin or owner role. | |
| `oxygen_limits_show` | Plan/storage summary: capacity=largest retained-row Table when all row counts reconciled; pricing=compare current plan prices/capacity; plan=one band. | `core` `read-only` |
| `oxygen_provider_limits_delete` | Clear one provider request-limit override; admin or owner only. | |
| `oxygen_provider_limits_list` | Read provider request limits and BYOK warning defaults. | `read-only` |
| `oxygen_provider_limits_set` | Set an enforced provider request limit; admin or owner only. Approve the exact provider, operation and window: raising a cap may permit more provider use. 0 credits. | |
| `oxygen_workspace_infrastructure_exit` | Preview all external infrastructure belonging to this workspace and, after explicit user confirmation, stop its renewals and begin teardown through already paid terms. | |
## integrations (`?toolset=integrations`)
| Tool | What it does | Notes |
| --- | --- | --- |
| `oxygen_cloudflare_connect` | Verify a Cloudflare token, choose an account when required, and save the encrypted connection. account_id is optional for initial account discovery; no credential is returned. | |
| `oxygen_custom_integration_connect` | Store an encrypted API key for an applied custom HTTP integration; the secret is never returned. | |
| `oxygen_custom_integrations_apply` | Creates or updates a custom HTTP tool integration from a manifest, registering its operations as custom_http.* tools in the catalog. | |
| `oxygen_custom_integrations_list` | Lists custom HTTP tool integrations registered for the active organization — slug, name, auth type, base URL, and the generated custom_http.* tool ids. | `read-only` |
| `oxygen_github_connection_start` | Create the authenticated GitHub authorization URL for this workspace. | |
| `oxygen_hubspot_connection_start` | Create the authenticated HubSpot authorization URL for this workspace. | |
| `oxygen_integration_connection_test` | Test one workspace integration connection and save its health without changing its default or returning credentials. | |
| `oxygen_integration_default_set` | Set the default active integration connection within this workspace. | |
| `oxygen_integration_events_deliveries` | Lists recent provider webhook deliveries (Composio triggers, HubSpot webhooks, etc.) for this organization, including the resulting workflow run ids. | `read-only` |
| `oxygen_integration_events_disable` | Disables a provider event subscription so matching provider webhooks stop triggering workflows. | |
| `oxygen_integration_events_enable` | Enables a provider event subscription so matching provider webhooks can trigger workflows. | |
| `oxygen_integration_events_list` | Lists raw provider webhook definitions and this organization's enabled subscriptions. Use oxygen_workflows_events_list for the trigger-ready workspace catalog. | `read-only` |
| `oxygen_integration_managed_endpoints` | Read a managed integration's full action catalog and parameter schemas. | `read-only` |
| `oxygen_integration_status` | Read active connection counts, sender connection state and the workspace's usable BYOK plan entitlement. | `read-only` |
| `oxygen_integrations_connect` | Connect a provider account, including X (integration_id=twitter). | |
| `oxygen_integrations_connections` | List this workspace's stored integration connections and health without credentials. | `read-only` |
| `oxygen_integrations_disconnect` | Disconnects a supported integration (Composio OAuth or native API-key/BYOK) for this organization. Pass connection_id to target a specific connected account when several exist. | |
| `oxygen_integrations_list` | Lists supported Composio-backed integrations plus this organization's stored integration connections (including native-provider connections like Salesforge and the Forge family), with… | `read-only` |
| `oxygen_integrations_list_actions` | Lists the actions available for an integration — both Composio toolkits (e.g. all Slack actions) and native-provider integrations (Salesforge and the Forge family, Instantly, …, which expose their… | `read-only` |
| `oxygen_integrations_list_destinations` | Lists where a connected integration can send, so you never ask a user to paste a raw provider id. | `read-only` |
| `oxygen_integrations_run_action` | Runs an action for a connected integration — a Composio action or a native-provider operation (Salesforge and the Forge family, Instantly, …). | |
| `oxygen_integrations_test` | Re-validates a stored integration API key against the provider (cheap read probe, zero credits) and heals the connection back to active/healthy when it passes. | |
| `oxygen_openrouter_models` | Read model and pricing metadata using this workspace's connected OpenRouter account; credentials are never returned. | `read-only` |
## admin (`?toolset=admin`)
| Tool | What it does | Notes |
| --- | --- | --- |
| `oxygen_admin_costs` | Staff-only. Returns COGS (USD) per provider, broken down by workspace for the last 30/7 days. Use to inspect margin and per-workspace spend. | `read-only` `staff` |
| `oxygen_admin_kpis` | Staff-only. | `read-only` `staff` |
| `oxygen_admin_price_book` | Staff-only. | `staff` |
| `oxygen_admin_primary_providers` | Staff-only provider board with default, conditional and legacy selection, configuration, health, balances, COGS and limits. | `read-only` `staff` |
---
# Web app
> Inspect, approve, retry, and edit workspace state at oxygen-agent.com.
Source: https://oxygen-agent.com/docs/surfaces/web
CLI and MCP execute; the web app at `https://oxygen-agent.com` shows the state they produced and lets you act on it.
| Use the web for | Use the [CLI](/docs/surfaces/cli) or [MCP](/docs/surfaces/mcp) for |
|---|---|
| Browsing tables and cells | Creating tables, importing files, adding columns |
| Inspecting run timelines, failed items, and provider summaries | Triggering runs and retries |
| Reviewing paid or external-write scope before live work | Building the dry run or preview |
| Reading and editing Knowledge Graph pages | Resolving context for an agent task |
| Managing team membership, billing, and connections | Running table, tool, and workflow commands |
## Deep-links
Inspectable CLI and MCP responses carry a `web_url`. Open it to see the same state visually.
| Resource | URL pattern |
|---|---|
| Table | `oxygen-agent.com/workspaces//tables/` |
| Table run | `oxygen-agent.com/workspaces//tables//runs/` |
| Record | `oxygen-agent.com/workspaces//tables//records/` |
| Workflow | `oxygen-agent.com/workspaces//workflows/` |
| Workflow run | `oxygen-agent.com/workspaces//workflows//runs/` |
| Knowledge Graph | `oxygen-agent.com/knowledge`, one page at `/knowledge/pages/` |
| Connections | `oxygen-agent.com/connections` |
| Billing | `oxygen-agent.com/billing` |
| Observability | `oxygen-agent.com/observability` |
`/billing` is a short URL that redirects to the Settings billing tab. `/context` redirects to `/knowledge`: the Context dashboard folded into the workspace wiki, and `oxygen context resolve` now returns a `/knowledge` link.
## Customise the sidebar
**Settings → Customise** lists every page the sidebar can show, grouped the way the sidebar groups them. Click a page's eye to hide it from your own sidebar in this workspace; your teammates keep theirs, and each workspace remembers its own choices. Hiding a section hides its sub-pages. Nothing is deleted: a hidden page leaves your sidebar and ⌘K, and still opens from its URL, a deep-link or a breadcrumb.
The same setting from the CLI and MCP, naming pages by name or path:
```sh
oxygen settings pages list --json
oxygen settings pages set --hide Unibox,Publishing
oxygen settings pages set --show Unibox
oxygen settings pages set --show-all
```
MCP: `oxygen_settings_pages_get` and `oxygen_settings_pages_update`.
**Settings → Beta features** turns on early-access features for a workspace. It does not bring back pages the sidebar leaves out on purpose, such as Agents and Approvals, whose routes and CLI/MCP paths stay reachable either way.
## Authentication and environments
The web app uses the same user identity and organizations as the CLI and the MCP connector — the ones `oxygen orgs list --json` returns.
| Environment | URL | CLI |
|---|---|---|
| Production | `https://oxygen-agent.com` | `oxygen` |
| Developer testing | `https://dev.oxygen-agent.com` | `oxygen-dev` |
`oxygen-dev` is for Oxygen developers and dev workspaces; customer work uses `oxygen`.
---
# Support
> Reach OXYGEN support through the web, CLI, MCP, or Slack in one Plain queue and avoid duplicate filings.
Source: https://oxygen-agent.com/docs/surfaces/support
Plain is OXYGEN's support system of record. In-app Chat, CLI, MCP, and connected
customer Slack channels all create or continue Plain Threads; they are not
separate ticket queues. One queue is not automatic issue-level deduplication:
**Retry** reconnects the same in-app Chat, while a distinct CLI, MCP, or feedback
filing can create another Thread.
## In the app
The support chat sits in the bottom-right corner of every page. Select it to
expand the conversation; the widget's own header collapses it again and can also
grow it to a larger reading size. It opens straight into your conversation with
its history, so there is nothing to choose or fill in before writing the first
message.
The sidebar's **Support** row and `/support` expand that same widget. There is one
support surface, in one place, on every screen, and the control carries a count
when support has replied and you have not read it yet.
Past conversations are all there: the **Back** arrow in the chat header leaves
the current conversation and lists every one you have had with us, open and
closed, newest first. Select one to reopen it, or start a new one from the same
screen.
If the secure connection fails, the corner control says so and **Retry** is the
only recovery control. It returns after each failed connection attempt and
reconnects the same conversation; it never creates a fallback ticket or sends
the request through a second system.
If Retry keeps failing, continue through the CLI section below without blindly
starting again: list open Plain Threads first, continue the same conversation
when it already exists, and start one only when no matching Thread exists. This
stays in the same Plain queue; it does not introduce a fallback support system.
Chat is bound to your signed-in user and active OXYGEN organization. Every chat
conversation reaches support as a question; the team re-classifies bugs and
feature requests during triage, and `oxygen support chat --category` sets the
type exactly when you would rather say it yourself.
## CLI
Check existing conversations so the same issue is not reported twice:
```sh
oxygen support list --status open --json
```
Start a conversation with one message. Plain still needs an internal Thread
title, but OXYGEN derives it from the first non-empty line instead of asking you
to write ticket metadata:
```sh
oxygen support chat \
--message "The dedicated IP is not being assigned. Here is what I observed…" \
--category bug \
--json
```
Continue the returned Thread without creating a separate titled filing:
```sh
oxygen support chat --message "Here is the additional evidence." --json
```
`oxygen support reply --body ...` remains an equivalent explicit
reply command. Use the structured filing command only when an explicit subject
and operation/run metadata materially help triage:
```sh
oxygen support file \
--subject "In-app support chat will not open" \
--body "What happened, what you expected, and what you already tried." \
--category bug \
--severity normal \
--json
```
Both commands are real writes to Plain immediately. They cost zero
credits but have no preview mode, so review the message or structured subject,
body, category, and severity before running one. `--category` takes `question`, `bug`,
`feature_request`, `billing`, `security_data`, `configuration`,
`agency_directory`, or `other`; `--severity` takes `low`, `normal`, or `high`.
`oxygen feedback` creates the same canonical Plain Thread — do not submit one
issue through both paths. Sharing the Plain queue does not merge different
filings automatically; continue the existing chat when the issue already has a
Thread.
Every new CLI or MCP support ticket needs an opening message. A subject alone is
rejected, so the team receives the issue description in the Plain conversation.
For a structured CLI report, you may explicitly attach a local agent transcript
with `--transcript-file `, `--session-id `, or `--include-transcript`
(most recent session). The CLI sends a bounded, best-effort redacted copy; review
the session before sharing because it may include other private context. A
selected file can be UTF-8 text or JSONL; the CLI does not validate JSONL. It
keeps up to the last 2 MB of the file, drops older content, and redacts common
credential patterns before uploading. Redaction cannot catch every secret. The
hosted MCP tools cannot read a local file. With your approval,
`oxygen_feedback` and `oxygen_support_ticket_create` can attach only a selected
conversation excerpt through `transcript_text` (up to 200,000 UTF-8 bytes).
Track or continue the returned Thread with:
```sh
oxygen support get --json
oxygen support reply --body "Additional context" --json
```
OXYGEN-created conversations are regular Plain Chat Threads, including requests
filed from the CLI or MCP. Your support team replies to that same conversation
from Plain Inbox or the staff support CLI; the reply appears in the embedded
Chat immediately. If the customer has not read it after five minutes, Plain
sends its native unread-message email to the customer's verified address. The
email's **Reply** button returns to `https://oxygen-agent.com/support`.
If a CLI/MCP attempt returns `plain_headless_portal_unavailable`, its error
includes the Plain Thread ID and reference because the shell already exists but
the message did not arrive. Do not file it again. Continue in the in-app chat or
email `priority@oxygen-agent.com` and include that Thread reference so support
can reconcile the fallback. A direct email is correlated recovery; it does not
claim to append itself to the empty Chat shell.
The shared `priority@oxygen-agent.com` Plain Email channel must also be enabled.
It is separate from Tim's `tim@oxygen-agent.com` teammate login and lets a
customer reply directly to the notification email without creating or losing a
second conversation: Plain appends that email response to the existing Thread.
OXYGEN does not send a duplicate custom email for the same Chat reply.
State-changing responses return the `oxygen-agent.com/support/` deep-link. Plain remains authoritative for status, priority, assignment, messages, notes, and resolution.
## MCP and Slack
`oxygen_support_ticket_create`, `oxygen_support_tickets_list`,
`oxygen_support_ticket_get`, and `oxygen_support_ticket_reply` call the same
contract as the CLI. An assistant must show the exact filing payload and obtain
confirmation before creating the zero-credit Thread. Connected customer Slack
channels remain native Slack conversations in Plain. A mapped channel uses its
exact OXYGEN Tenant and ingestion policy. An enabled channel that is not mapped
still reaches the support team for manual triage, but OXYGEN does not guess its
organization or run org-aware automation until the exact route is mapped.
For a product failure, include the operation or error code and any relevant run
IDs, table IDs, or OXYGEN deep-links (`--operation`, `--error-code`,
`--run-ids`, `--table-ids`, `--deep-links`). Never include API keys, secrets, or
raw credentials.
---
# Claude Code
> Run Oxygen from Claude Code — the CLI in your terminal, plus the optional hosted MCP connector.
Source: https://oxygen-agent.com/docs/surfaces/claude-code
The [`oxygen` CLI](/docs/surfaces/cli) is the primary path here: full command surface, agent skills, and `--json` envelopes. The hosted [MCP](/docs/surfaces/mcp) connector is optional and additive.
## What works here
| Capability | Claude Code |
|---|---|
| `oxygen` CLI in the terminal | Yes — the primary surface |
| Agent skills (`--agents claude-code`) | Yes — installed into `~/.claude/skills` |
| Hosted MCP connector (OAuth) | Yes — optional |
| `ui://` widgets | No — the connector detects Claude Code and strips the inline widget block automatically |
## Setup — CLI
```sh
npm install -g @oxygen-agent/cli
oxygen login
oxygen skills install --agents claude-code --json
```
Requires Node.js >=22.22.0 and npm >=10.9.0. `oxygen login` opens a browser and stores credentials for the active profile. `oxygen skills install` writes the Oxygen skills into `~/.claude/skills` (context first, table first, dry run before live, inspect runs after) and installs every skill unless you pass `--skill `.
For headless or non-interactive sessions, use a token instead of the browser login:
```sh
oxygen api-keys create --name "claude-code" --json
oxygen auth use-token --token --json
```
## Setup — hosted MCP (optional)
```sh
claude mcp add --transport http oxygen https://oxygen-agent.com/mcp
```
Claude Code uses loopback OAuth redirects, which the connector's dynamic client registration allows by default. Complete the sign-in when the OAuth flow opens, then ask Claude to call `oxygen_whoami`. Do not paste API keys into prompts — let the OAuth flow hold the credential.
A bare URL advertises the core toolset. The [MCP tool reference](/docs/surfaces/mcp-reference) lists every tool and the pack that advertises it.
## Verify your setup
These are read-only and spend no credits:
```sh
oxygen status --json
oxygen whoami --json
oxygen capabilities search "add an AI column and enrich work emails" --json
oxygen commands get "enrich-column preview" --json
```
- `oxygen status` — `data.compatible: true` means your CLI is at or above the server's enforced minimum. The envelope also carries `client_version`, `server_version`, `minimum_cli_version`, `api_url`, and a `skew` of `in_sync`, `client_ahead`, or `client_behind`.
- `oxygen whoami` — `data.user.email`, `data.organization.name`, and an `onboarding` block. If `onboarding.complete` is `false`, load [workspace context](/docs/workspace/context) before paid work.
- `oxygen capabilities search` names the owning primitive, its negative boundary, the gateway commands/tools, and the exact hydration step. `oxygen commands get` returns only the selected command's flags and safety markers. The full `oxygen commands --json` manifest is an opt-in diagnostic, not the normal discovery path.
- On MCP the same pair is `oxygen_capabilities_search` → `oxygen_capabilities_schema`. Provider operations use the separate bounded `oxygen_tools_search` → exact `oxygen_tools_get` path.
## Cost and approval posture
Dry-run and preview commands never spend credits or write externally; paid provider calls, AI/tool column runs, enrichment, and external writes execute only after you pass `--approved` with a `--max-credits` ceiling. See [Approvals](/docs/safety/approvals) and [Spend caps](/docs/safety/caps).
## Known limitations
- No `ui://` widget rendering — inspect results through the `web_url` in each JSON envelope or the [web app](/docs/surfaces/web).
- The hosted MCP connector requires OAuth (dynamic client registration); if your environment blocks the browser handshake, use the CLI with a token instead.
- Do not paste large CSV/JSON files into MCP prompts — import them with `oxygen tables import --file --background`.
---
# Claude Desktop
> Connect Claude Desktop to Oxygen's hosted MCP server — an MCP-Apps host that renders Oxygen's ui:// widgets inline.
Source: https://oxygen-agent.com/docs/surfaces/claude-desktop
Claude Desktop has no terminal, so it drives Oxygen entirely through the hosted [MCP](/docs/surfaces/mcp) connector. It is an MCP-Apps host, so it shows the Table widget: when Claude previews a table or a company search, the rows appear in the conversation as the same grid as the Oxygen web app, and **Expand** opens all of it.
## What works here
| Capability | Claude Desktop |
|---|---|
| Hosted MCP connector (OAuth) | Yes — the only surface |
| `ui://` widgets | Yes — rendered inline |
| `oxygen` CLI in a terminal | No — Claude Desktop has no shell; use [Claude Code](/docs/surfaces/claude-code) for the CLI |
| Agent skills | Not applicable — skills teach terminal CLI agents; Claude Desktop reads the MCP tool descriptors directly |
## Setup
1. Open **Settings → Connectors** and add a custom connector.
2. Point it at the hosted server. Claude Desktop lists every advertised tool inline and has no tool search, so use the core profile rather than the full registry:
```text
https://oxygen-agent.com/mcp?toolset=core
```
3. Sign in when the OAuth flow opens. Then ask Claude to call `oxygen_whoami`. If your account has more than one organization, ask it to call `oxygen_orgs_select` with the org slug.
`?toolset=core` trims what is advertised, and a bare URL selects the same core profile. Claude reaches every other tool without reconnecting: `oxygen_capabilities_search` finds it, `oxygen_capabilities_schema` returns its arguments, and `oxygen_capabilities_read` (read-only tools) or `oxygen_capabilities_call` (anything else) runs it by name with that tool's own previews, spend caps and approvals. A domain pack (`?toolset=`) still lists a pack's tools natively if you prefer. The [MCP tool reference](/docs/surfaces/mcp-reference) lists every tool, its pack, and which tools core advertises.
## Verify your setup
Ask Claude to run these read-only tool calls (they spend no credits):
- `oxygen_whoami` — returns your user email and the active `organization.name`, plus an `onboarding` block. If `onboarding.complete` is `false`, load [workspace context](/docs/workspace/context) before paid work.
- `oxygen_capabilities_search` with a query like `find company emails` — returns ranked tool matches, each flagged `read_only`, `paid`, and `in_core`. A non-empty ranked list confirms the connector is live and searchable.
To confirm widgets render, ask Claude to preview one of your tables (for example "show me a preview of my Leads table"). The Table widget appears under Claude's answer with the table's first rows, **Expand** and **Open in OXYGEN**.
## Cost and approval posture
Read and dry-run tools (`oxygen_tools_run_dry`, table/context/billing reads) never spend credits; the paid tools (`oxygen_tools_run_live`, `oxygen_columns_run` on paid columns, enrichment, external writes) run only after you approve the row scope and credit ceiling. See [Approvals](/docs/safety/approvals) and [Spend caps](/docs/safety/caps).
## Known limitations
- No terminal means no CLI, no local file imports, and no scripting. For bulk file work use `oxygen_cli_file_import_prepare`, which hands back a local `oxygen tables import ... --background` command to run on a machine that has the CLI.
- The connector requires OAuth with dynamic client registration; a first-run failure usually means the OAuth handshake did not complete.
- `?toolset=full` crowds Claude Desktop's context — prefer core or the returned domain pack.
---
# Claude Cowork
> Connect Claude Cowork to Oxygen and choose the tool scope scheduled tasks can actually dispatch.
Source: https://oxygen-agent.com/docs/surfaces/claude-cowork
Claude Cowork uses Oxygen through a hosted custom connector. Scheduled tasks reuse the connectors available to Cowork, so the connector URL determines which Oxygen tools a task can call.
## Choose the connector scope
| URL | Advertised scope | Use when |
|---|---|---|
| `https://oxygen-agent.com/mcp` | Core | The bounded golden-path toolset is enough. A bare URL means core. |
| `https://oxygen-agent.com/mcp?toolset=core` | Core | Same scope, made explicit. |
| `https://oxygen-agent.com/mcp?toolset=crm` | Core + CRM | The task needs CRM record or relationship tools. |
| `https://oxygen-agent.com/mcp?toolset=full` | Every customer tool | The task spans several domains or an existing automation requires the former full scope. |
Core stays the default because the full registry's schemas consume most of a context window before the user says anything, and tool-selection accuracy degrades as the advertised list grows. In core, every other customer tool is still reachable without reconnecting through `oxygen_capabilities_read` (read-only tools) or `oxygen_capabilities_call` (anything else), so a pack is optional. Domain packs are additive on core, and several can be combined (`?toolset=crm,tables`). The [MCP tool reference](/docs/surfaces/mcp-reference) lists every pack and the tools it advertises.
## Restore the full scope
1. Open Claude **Settings → Connectors**.
2. Remove the existing Oxygen custom connector. Changing or removing `?toolset=core` is not enough: a bare Oxygen URL still selects core.
3. Add a custom connector with this exact URL:
```text
https://oxygen-agent.com/mcp?toolset=full
```
4. Complete the Oxygen OAuth sign-in again.
5. In Cowork, ask Oxygen to run the read-only `oxygen_whoami` tool and confirm the expected organization.
6. Re-run the scheduled task. No Oxygen data or schedule definition needs to be recreated.
For a CRM-only task, use `https://oxygen-agent.com/mcp?toolset=crm` instead. That pack advertises `oxygen_crm_record_assert` and `oxygen_crm_relationship_upsert` without loading unrelated domains.
## Why capability search alone may not unblock Cowork
`oxygen_capabilities_search` and `oxygen_capabilities_schema` can discover every Oxygen tool. Their results include `toolset_pack`, the smallest connector profile that advertises the selected tool.
The Oxygen server can dispatch an exact hidden tool name, but Cowork rejects a name that was not in its connector's `tools/list` before the call reaches Oxygen. If Cowork reports **No such tool available**, run the same tool through `oxygen_capabilities_call` (or `oxygen_capabilities_read` for a read-only tool) with `{ "tool": "", "arguments": { ... } }`. Both are listed in every scope, so no reconnect is needed. Reconnect with the returned `?toolset=` only when a task should see those tools listed by name.
## Cost and approval posture
Changing the advertised tool scope does not authorize spending or external writes. Paid calls and external mutations still require their normal preview, exact scope, approval, and credit ceiling.
---
# ChatGPT
> Connect your OXYGEN workspace to ChatGPT for company research, tables, and knowledge.
Source: https://oxygen-agent.com/docs/surfaces/chatgpt
The OXYGEN ChatGPT plugin is being prepared for review. Until it is published,
you can test the connection in ChatGPT developer mode if your account supports it.
You need an existing OXYGEN account and access to the workspace you want to use.
## Connect OXYGEN
In ChatGPT, open **Settings → Apps**, enable developer mode in **Advanced settings**,
and create an app using this MCP server URL:
```text
https://oxygen-agent.com/mcp?toolset=chatgpt-v1
```
Choose OAuth and sign in to OXYGEN when prompted. Keep the `toolset=chatgpt-v1`
query parameter: it selects the reviewed ChatGPT tools. Add OXYGEN to a conversation
and start with “Which OXYGEN workspace am I using?” If you belong to more than one
workspace, choose the one you intend to use before working with its data.
For a dev workspace, use `https://dev.oxygen-agent.com/mcp?toolset=chatgpt-v1`
and a dev OXYGEN account. Dev and production accounts and data are separate.
## What you can do
Ask ChatGPT to preview an existing table, plan a company search and estimate its cost,
read workspace knowledge, or create a small table from data you provide. For example:
- “Show the first three rows of my companies table. Do not change anything.”
- “Plan a search for US software companies with 20–200 employees. Estimate costs without running it.”
- “Find our ideal customer profile in OXYGEN knowledge and summarize its source.”
Table previews and sourcing-run summaries can appear as inline cards when the host
supports them. Other results appear as text. A preview does not save leads or complete
a paid sourcing run.
The reviewed connection lists each supported operation separately. Native company
previews continue with `oxygen_companies_native_search_run`, hiring previews with
`oxygen_companies_hiring_search_run`, and local-business previews with
`oxygen_companies_maps_search_run`. Pass the preview filters as `source_filters`
and start with `mode: "dry_run"`. Native people searches use
`oxygen_people_native_search_run`; contacts at companies in an existing Table use
`oxygen_people_company_contacts_run` with that Table's company LinkedIn URL column
and typed people filters.
Public LinkedIn posts use `oxygen_signals_search_run`. Recurring posts use the
separate `oxygen_signals_linkedin_posts_feed_create` operation. Its `every`
cadence uses UTC, and `max_credits_per_cycle` limits Oxygen credits for each refresh.
A feed dry run quotes only the initial search; it creates no feed and does not
validate live provider access or cadence. Live creation requires approval for the
Table, recurring cadence and per-cycle ceiling, even when the search is free.
`oxygen_columns_run` runs AI columns. Formula recalculation uses
`oxygen_columns_formula_run`; research, enrichment, CRM binding and lookup columns
have their corresponding named operations. A free formula run still changes cells.
Saved catalog-tool, custom HTTP and workspace Function columns run through the
OXYGEN app or CLI. They cannot run through this reviewed connection. Its tool list
is an allowlist: capability dispatch and broader toolset packs cannot extend it.
## Approvals and credits
Workspace writes follow your requested scope. Before paid sourcing, lookups, or column
runs, approve the operation and a maximum number of credits. A zero ceiling permits
only free operations. Existing workspace permissions, balance, and execution limits
still apply. While ChatGPT is subscribed to OXYGEN events in a workspace, its paid calls
there also count against its daily credit ceiling (by default 10% of the plan's monthly
credits in any 24 hours); a call that would pass it is refused before anything runs.
Change the ceiling in OXYGEN on the Connected apps page, `/settings/connected-apps`. The plugin cannot buy credits, change subscriptions, send outreach,
or run arbitrary tools or workflows.
## Privacy
OXYGEN sends the requested workspace data and tool results to the connected ChatGPT
conversation. Share only the data you intend ChatGPT to process. Retrieved content
cannot authorize a write or paid run. You can disconnect OXYGEN from ChatGPT's app
settings. See the [connector privacy policy](/connector-privacy) and
[terms of service](/terms).
If ChatGPT subscribes to OXYGEN events, for example to act when a reply is classified
or a run settles, OXYGEN also sends event notices to OpenAI: one signed notice per
matching event, to the callback address ChatGPT registered for that subscription. A
notice carries ids, statuses, counts, timestamps and a link to OXYGEN. It never carries
message text, names, email addresses or other content; ChatGPT reads details back through
its OXYGEN tools under your own access. A subscription lasts at most 24 hours unless
ChatGPT renews it, and ends when you leave the workspace. See each subscription and every
delivery, and revoke them, on the [Connected apps](/settings/connected-apps) page or with
`oxygen connectors events get ChatGPT`.
## Support
Email [support@oxygen-agent.com](mailto:support@oxygen-agent.com) with the operation,
workspace name, and any returned run ID. Do not send passwords, API keys, or private
table contents. If sign-in fails, confirm you used the correct production or dev URL
and kept the `toolset=chatgpt-v1` parameter.
---
# Codex
> Run Oxygen from OpenAI Codex — the CLI in your terminal, plus the hosted MCP connector on the core toolset profile.
Source: https://oxygen-agent.com/docs/surfaces/codex
The [`oxygen` CLI](/docs/surfaces/cli) is the primary path here: full command surface, agent skills, and `--json` envelopes. The hosted [MCP](/docs/surfaces/mcp) connector is optional; Codex has no tool search, so connect it on the core profile.
## What works here
| Capability | Codex |
|---|---|
| `oxygen` CLI in the terminal | Yes — the primary surface |
| Agent skills (`--agents codex`) | Yes — installed into `~/.codex/skills` |
| Hosted MCP connector (OAuth) | Yes — use `?toolset=core` |
| `ui://` widgets | No — the connector detects Codex and strips the inline widget block automatically |
## Setup — CLI
```sh
npm install -g @oxygen-agent/cli
oxygen login
oxygen skills install --agents codex --json
```
Requires Node.js >=22.22.0 and npm >=10.9.0. `oxygen login` opens a browser and stores credentials for the active profile. `oxygen skills install` writes the Oxygen skills into `~/.codex/skills` (context first, table first, dry run before live, inspect runs after) and installs every skill unless you pass `--skill `.
For headless environments, use a token instead of the browser login:
```sh
oxygen api-keys create --name "codex" --json
oxygen auth use-token --token --json
```
## Setup — hosted MCP (optional)
Add this URL to Codex's MCP configuration:
```text
https://oxygen-agent.com/mcp?toolset=core
```
The core profile advertises a bounded golden-path set plus the `oxygen_capabilities_search` / `oxygen_capabilities_schema` discovery pair instead of the full registry. A capability search first identifies the owning primitive and its boundary, then recommends the gateway tools; every hidden tool stays callable by exact name. Complete the OAuth sign-in when it opens. The [MCP tool reference](/docs/surfaces/mcp-reference) lists every tool and the pack that advertises it.
## Verify your setup
These are read-only and spend no credits:
```sh
oxygen status --json
oxygen whoami --json
oxygen capabilities search "build a hosted workflow for new signups" --json
oxygen commands get "workflows schema" --json
```
- `oxygen status` — `data.compatible: true` means your CLI meets the server's enforced minimum. The envelope also carries `client_version`, `server_version`, `minimum_cli_version`, `api_url`, and a `skew` of `in_sync`, `client_ahead`, or `client_behind`.
- `oxygen whoami` — `data.user.email`, `data.organization.name`, and an `onboarding` block; load [workspace context](/docs/workspace/context) first if `onboarding.complete` is `false`.
- `oxygen capabilities search` returns one bounded ownership card and recommended gateways. `oxygen commands get` hydrates only the selected command's arguments, flags, and safety markers. The full `oxygen commands --json` manifest is an opt-in diagnostic.
- If you connected MCP, ask Codex to call `oxygen_whoami` and `oxygen_capabilities_search` with a query like `enroll leads in a sequence`, then hydrate one result with `oxygen_capabilities_schema`. Provider and enrichment discovery is separate: bounded `oxygen_tools_search`, then exact `oxygen_tools_get`.
## Cost and approval posture
Dry-run and preview calls never spend credits or write externally; paid provider calls, AI/tool column runs, enrichment, and external writes execute only after you pass `--approved` with a `--max-credits` ceiling (or approve the equivalent scope through MCP). See [Approvals](/docs/safety/approvals) and [Spend caps](/docs/safety/caps).
## Known limitations
- No `ui://` widget rendering — inspect results via the `web_url` in each envelope or the [web app](/docs/surfaces/web).
- Connect the MCP server with `?toolset=core`; the full advertised list will overwhelm a client without tool search.
- Do not paste large CSV/JSON files into MCP prompts — import them with `oxygen tables import --file --background`.
---
# Cursor
> Run Oxygen from Cursor — the CLI in Cursor's integrated terminal, with agent skills.
Source: https://oxygen-agent.com/docs/surfaces/cursor
The verified path is the [`oxygen` CLI](/docs/surfaces/cli) in Cursor's integrated terminal, with agent skills installed for Cursor. Cursor also supports MCP servers, but Oxygen's hosted connector has not been tested end to end with Cursor — see [Known limitations](#known-limitations) before relying on it.
## What works here
| Capability | Cursor |
|---|---|
| `oxygen` CLI in Cursor's terminal | Yes — the verified surface |
| Agent skills (`--agents cursor`) | Yes — installed into `~/.cursor/skills` |
| Hosted MCP connector (OAuth) | Untested — the endpoint exists but we have not verified Cursor's remote-OAuth flow |
| `ui://` widgets | Untested — treat as unavailable until verified |
## Setup — CLI
Run these in Cursor's integrated terminal:
```sh
npm install -g @oxygen-agent/cli
oxygen login
oxygen skills install --agents cursor --json
```
Requires Node.js >=22.22.0 and npm >=10.9.0. `oxygen login` opens a browser and stores credentials for the active profile. `oxygen skills install` writes the Oxygen skills into `~/.cursor/skills` (context first, table first, dry run before live, inspect runs after) and installs every skill unless you pass `--skill `.
For non-interactive use, authenticate with a token instead:
```sh
oxygen api-keys create --name "cursor" --json
oxygen auth use-token --token --json
```
## Verify your setup
These are read-only and spend no credits:
```sh
oxygen status --json
oxygen whoami --json
oxygen capabilities search "find public LinkedIn post engagers" --json
oxygen commands get "tools search" --json
```
- `oxygen status` — `data.compatible: true` means your CLI meets the server's enforced minimum. The envelope also carries `client_version`, `server_version`, `minimum_cli_version`, `api_url`, and a `skew` value.
- `oxygen whoami` — `data.user.email`, `data.organization.name`, and an `onboarding` block. Load [workspace context](/docs/workspace/context) first if `onboarding.complete` is `false`.
- `oxygen capabilities search` returns a bounded ownership card and gateway recommendations. `oxygen commands get` hydrates only one exact command; the full `oxygen commands --json` manifest remains an opt-in diagnostic.
## Cost and approval posture
Dry-run and preview commands never spend credits or write externally; paid provider calls, AI/tool column runs, enrichment, and external writes execute only after you pass `--approved` with a `--max-credits` ceiling. See [Approvals](/docs/safety/approvals) and [Spend caps](/docs/safety/caps).
## Known limitations
- **Hosted MCP is untested with Cursor.** The connector at `https://oxygen-agent.com/mcp` uses OAuth with dynamic client registration; that flow is verified for Claude Desktop, Claude Code, and Codex, but Cursor's MCP client sends no distinguishable user agent in Oxygen's traffic, so we have neither verified nor instrumented it. Until it is verified, drive Oxygen through the CLI.
- **If you do connect it**, use `https://oxygen-agent.com/mcp?toolset=core&widgets=off`. Cursor has no tool search, so it needs the core profile; and Oxygen auto-suppresses the inline widget block only for clients it recognizes as terminal-shaped, so an unrecognized client receives the block and pays for it in context whether or not it renders. Both parameters are documented in the [generic MCP client guide](/docs/surfaces/generic-mcp).
- **Widget rendering is unverified** — do not assume `ui://` widgets appear; rely on the `web_url` in each JSON envelope and the [web app](/docs/surfaces/web).
- Import large CSV/JSON files with `oxygen tables import --file --background` rather than pasting them into a prompt.
---
# Generic MCP client
> Connect any MCP-capable client to Oxygen's hosted server, with OAuth or a bearer token.
Source: https://oxygen-agent.com/docs/surfaces/generic-mcp
Any MCP-capable client can operate Oxygen through the hosted [MCP](/docs/surfaces/mcp) server. If your client also has a terminal, the [`oxygen` CLI](/docs/surfaces/cli) is available too.
## What works here
| Capability | Generic MCP client |
|---|---|
| Hosted MCP connector | Yes |
| OAuth (dynamic client registration) | Yes — the recommended auth path |
| Bearer token (CLI API key) | Yes — for clients that cannot do OAuth |
| `ui://` widgets | Only on MCP-Apps hosts; other clients read the JSON result |
| Core toolset profile (`?toolset=core`) | Yes — for clients without tool search |
| Full toolset profile (`?toolset=full`) | Yes — explicit opt-in |
## Endpoint
```text
https://oxygen-agent.com/mcp
```
The server speaks Streamable HTTP and publishes OAuth discovery metadata (RFC 9728 protected-resource metadata and RFC 8414 authorization-server metadata). Unauthenticated requests get a `401` with a `WWW-Authenticate` challenge pointing at the resource metadata.
## Setup — OAuth (recommended)
Add the endpoint as a custom/remote MCP connector. On first use the client registers itself through dynamic client registration and opens the OAuth sign-in. After sign-in, call `oxygen_whoami`; if the account has more than one organization, call `oxygen_orgs_select` with the org slug. OXYGEN remembers that choice for this client only; see [connected apps](/docs/workspace/orgs#connected-apps) to change it later.
## Setup — bearer token
For clients that cannot complete an OAuth flow, mint a CLI API key and configure the client to send it as an `Authorization: Bearer ` header:
```sh
oxygen api-keys create --name "mcp client" --json
```
Store the token in the client's credential or connector configuration. Do not paste it into prompts or documents.
## Toolset and widget parameters
Two query parameters shape the connection:
- **No `toolset` parameter, or `?toolset=core`** — advertises the bounded golden-path tools plus the `oxygen_capabilities_*` tools: search, schema, and the `oxygen_capabilities_read` / `oxygen_capabilities_call` runners that run any other customer tool by name. A bare URL means core; it does not restore the former full list.
- **`?toolset=`** — adds one or more focused domain packs on top of core, such as `?toolset=crm,sequences`. Capability results return `toolset_pack`, the smallest pack that advertises a selected tool. Every pack and its tools: [MCP tool reference](/docs/surfaces/mcp-reference).
- **`?toolset=full`** — explicitly advertises every customer tool. Use it when an existing automation genuinely spans the registry and the host refuses tools omitted from `tools/list`.
- **`?widgets=off|inline`** — forces the inline widget HTML block off or on, overriding client detection. See [Widgets](#widgets).
An unrecognized `toolset` token is ignored rather than rejected, so a typo silently falls back to core instead of blanking the tool list. `full` anywhere in the list wins.
The Oxygen server accepts an exact hidden tool name regardless of the advertised profile. Some hosts enforce their own `tools/list` first and reject that name client-side; run it through `oxygen_capabilities_read` or `oxygen_capabilities_call` as `{ tool, arguments }` instead, which needs no reconnect. For Claude Cowork setup, see the dedicated [Cowork guide](/docs/surfaces/claude-cowork).
## Widgets
`ui://` widgets render on MCP-Apps hosts — Claude Desktop, Claude on the web, and ChatGPT connectors. Of these, only Anthropic's connector has been observed against Oxygen's server; treat any other host as unverified until you see a widget render.
Oxygen auto-detects terminal-shaped agents (Claude Code, Codex) and strips the inline block for them. An unrecognized client — including one behind a proxy that hides its User-Agent — still receives it, so if your client does not render widgets, set `?widgets=off` rather than paying for the block in context. `?widgets=inline` forces it on for a rendering host Oxygen does not recognize.
## Verify your setup
Ask the client to run these read-only tool calls (they spend no credits):
- `oxygen_whoami` — returns your user email and the active `organization.name`, plus an `onboarding` block. If `onboarding.complete` is `false`, load [workspace context](/docs/workspace/context) before paid work.
- `oxygen_capabilities_search` with a query like `export a table to my CRM` — returns ranked tool matches, each flagged `read_only`, `paid`, `in_core`, and `toolset_pack`. A non-empty ranked list confirms the connector is live; the pack tells strict clients how to advertise the selected tool.
## Cost and approval posture
Read and dry-run tools (`oxygen_tools_run_dry`, reads) never spend credits; paid tools (`oxygen_tools_run_live`, `oxygen_columns_run` on paid columns, enrichment, external writes) run only after you approve the row scope and credit ceiling. See [Approvals](/docs/safety/approvals) and [Spend caps](/docs/safety/caps).
## Known limitations
- On a client that does not render widgets, use the `web_url` in each result and the [web app](/docs/surfaces/web) to inspect state.
- The full registry can exceed a small context budget. Prefer core or a domain pack for focused work; reserve `?toolset=full` for clients or existing automations that truly need it.
- Do not stream large CSV/JSON files through an MCP prompt; use `oxygen_cli_file_import_prepare`, which returns a local `oxygen tables import ... --background` command to run where the CLI is installed.
---
# Organizations
> An organization is one workspace boundary for data, context, integrations, runs, members, and credits.
Source: https://oxygen-agent.com/docs/workspace/orgs
Every table, row, run, integration, wiki page, member, and credit belongs to exactly one organization, and each org's data sits in its own tenant database schema. Nothing crosses that line except a billing link (below).
## Projects
Within an org, tables and workflows can be grouped into projects. The default project is `general`.
```sh
oxygen projects list --json # every folder with its tableCount
oxygen projects create "Outbound Q1" --json
oxygen tables move leads-us leads-eu leads-uk --project outbound-q1 --json # one or several tables, one call
oxygen projects rename outbound-q1 --name "Pipeline Q1" --json
oxygen projects delete pipeline-q1 --json # dry-run preview
oxygen projects delete pipeline-q1 --live --confirm --expected-table-ids "," --json
```
`projects list` reports each folder's active table count as `tableCount`, so empty and oversized folders are visible without listing every folder's tables one at a time. `tables move` takes one or several table ids or slugs and moves them into the folder in one call; with several, each table is reported separately under `results`, a bad reference fails only that one, and the response deep-links to the folder.
A project is a grouping for navigation, not a separate billing or permission boundary. Rename changes its name and slug without renaming the physical database schema. Deleting a folder also deletes its tables: they disappear from normal listings immediately and enter the standard 14-day recovery period. You do not need to move them first. Restoring a table also restores its folder. CRM-backed tables remain protected, and the default `general` project cannot be renamed or deleted.
A bare delete previews every affected table without changing anything. For a nonempty folder, copy those table IDs into `--expected-table-ids` when confirming with `--live --confirm`. Changed folder contents require a fresh preview. Empty folders need only `--live --confirm`. The web confirmation handles the table IDs for you and lists the affected tables before deletion.
Projects also carry workspace tags: `oxygen projects tag --tags `.
Each project is tinted in the Tables rail so folders are distinguishable at a glance. The colour is assigned automatically from the workspace's project order; set your own with `oxygen projects color --color ` (`gray` means no tint), and `--color auto` restores the automatic one.
## Switching orgs
```sh
oxygen orgs list --json
oxygen orgs use
oxygen whoami --json
```
`oxygen whoami` returns the active org with its `plan_tier`, `entitled`, `shared_billing`, `billing_owner_organization_id`, and `monthly_credit_cap`, plus your membership and the API key in use. `--summary-json` prints the same identity with no credential-shaped fields, for health probes and logs.
## Multi-org users
Agencies typically use one org per client. Org switching is per CLI profile or MCP session, so check the active org before importing client data or running paid work.
If an MCP client returns `organization_selection_required`, ask it to call `oxygen_orgs_list` and then `oxygen_orgs_select` for the intended workspace, or give that app a default workspace (below) so it stops asking.
## Connected apps
Each app you connect to OXYGEN with OAuth (ChatGPT, Claude, Codex or any other MCP client) keeps its own **default workspace**: the workspace it works in without asking. Changing one app never changes another app or the CLI. Choosing a workspace inside the app, where its assistant calls `oxygen_orgs_select`, changes the same setting, so the latest choice wins.
- **Web:** the [Connected apps](/settings/connected-apps) page lists every connected app, when it was last used, and a default-workspace picker for each. **Ask each time** clears the default.
- **CLI:**
```sh
oxygen connectors list --json
oxygen connectors set ChatGPT --default-workspace "Acme GTM" # use the id when two apps share a name
oxygen connectors set --clear-default-workspace # ask each time again
```
- **MCP:** `oxygen_connector_list` and `oxygen_connector_update`; `connection: "current"` is the app you are talking to.
- **ChatGPT:** the OXYGEN app's settings page in ChatGPT shows the same default-workspace picker.
An app appears after its first request to OXYGEN. Connected apps belong to you rather than to a workspace, so a workspace API key (`oxy_live_…`) cannot read or change them; use your own sign-in (`oxygen login`).
### Events an app is subscribed to
An app connected with OAuth, such as ChatGPT, can subscribe to OXYGEN events: a reply was classified, a Sequence enrollment ended, a meeting was processed, a record changed stage, a run settled, or a run is waiting for approval. OXYGEN then sends that app an id-only notice for each matching event (ids, statuses, counts and a link to OXYGEN, never message text, names or contact details). A subscription lasts at most 24 hours unless the app renews it.
You can see what each app is subscribed to, in which workspace and with which filters, and every recent delivery with its status, attempts and failure reason (never its content). Revoking a subscription stops those events at once, and the app cannot renew it.
- **Web:** the [Connected apps](/settings/connected-apps) page, the app's **Events** column.
- **CLI:**
```sh
oxygen connectors events get ChatGPT --json # subscriptions and recent deliveries
oxygen connectors events revoke ChatGPT --subscription --json
oxygen connectors events revoke ChatGPT --subscription all --workspace "Acme GTM"
```
- **MCP:** `oxygen_connector_events_get` and `oxygen_connector_events_revoke`.
`oxygen connectors list` shows how many live subscriptions each app holds (`event_subscriptions.active`). Revoking changes nothing else about the app; to disconnect the app itself, remove it in that app's own settings.
### Daily credit ceiling
An app that reacts to OXYGEN events can run with nobody watching, so while an app holds event subscriptions in a workspace, every paid call it makes there counts against its **daily credit ceiling**: the most credits it may spend in any rolling 24 hours. A call that would go past the ceiling is refused before anything runs, with how much was spent and when room opens again. The call's own `max_credits` still applies inside the ceiling. OXYGEN cannot tell a call ChatGPT makes on its own from one you watch, so the ceiling counts every paid call of a subscribed app.
The default is your plan's trigger default, 10% of the plan's monthly credits (`oxygen limits show` reports it as `connected_app_daily_credit_ceiling`). You can set a lower or higher ceiling per app; above the default also needs your explicit approval, the same as an Agent run ceiling.
- **Web:** the [Connected apps](/settings/connected-apps) page, the **Daily credit ceiling** column, with what the app spent in the last 24 hours.
- **CLI:**
```sh
oxygen connectors get ChatGPT --json # credit_ceiling: the ceiling, what it spent, what is left
oxygen connectors set ChatGPT --credit-ceiling 300
oxygen connectors set ChatGPT --credit-ceiling 5000 --approve-above-default
oxygen connectors set ChatGPT --clear-credit-ceiling # back to the plan default
```
- **MCP:** `oxygen_connector_update` with `credit_ceiling` (and `approve_above_default`).
- **ChatGPT:** the app's settings page in ChatGPT shows the ceiling read-only; it can only be changed in OXYGEN.
## Billing ownership
Each org owns its own credit balance by default. A workspace with no plan of its own can be covered by a plan you already pay for in another org instead of buying a second subscription.
```sh
oxygen orgs billing-owners --json # which of your orgs may pay, and why the rest may not
oxygen orgs billing-link --owner --json # omit --owner when exactly one is eligible
oxygen orgs billing-link --owner --monthly-credit-cap 50000 --json
oxygen orgs billing-unlink --json
```
Credit billing moves; data access does not — a billing owner gains no read of the linked workspace. It does see what each linked workspace spends: `oxygen billing usage --group-by workspace --json` from the paying org totals the credits per workspace ([usage per client workspace](/docs/safety/billing#usage-per-client-workspace)). `billing-link` targets the active org unless you pass `--organization`. Omitting `--monthly-credit-cap` leaves any existing cap untouched rather than clearing it.
Linking needs admin in both organizations, and the workspace being linked must not already have its own subscription.
The workspace uses its billing owner's credits and plan. Read `oxygen billing estimate --json`: when `sender_billing` is `credit_reservations`, the owner's credits fund connected accounts, sending and supported publishing, even if `plan_tier` is `free`, but adding a sending account needs the owner's paid plan. `oxygen billing seats --json` then reports `status: seats_retired`; adding dollar seats is refused. Your own provider keys and Instagram, TikTok, YouTube and Facebook publishing still need a paid plan. On the legacy `sending_seats` model, the owner's paid plan and purchased or grandfathered seats cover connections, and seats are managed on the owner. The response names the model in force. OAuth connections to your own tools are open on every plan.
## Members
```sh
oxygen orgs member-role --role admin|member # admin only
```
Inviting people is still done in workspace settings; this only moves an existing member between the two workspace roles. Demote an admin to `member` before granting them the restricted [client role](/docs/workspace/collaboration) — an admin's role overrides the restriction.
## Related
- [Workspace context](/docs/workspace/context) — what to put in your org once it's created.
- [Billing](/docs/safety/billing) — credit balance and subscription per org.
---
# Workspace database
> Inspect PostgreSQL hosting, read SQL and configure the active workspace database.
Source: https://oxygen-agent.com/docs/workspace/database
Database operations belong to Platform operations. They use the active workspace's authenticated identity. Through MCP, discover them with `oxygen_capabilities_search`, inspect the selected schema, then use `oxygen_capabilities_read` for reads or `oxygen_capabilities_call` for configuration.
| CLI | MCP | Behavior |
| --- | --- | --- |
| `oxygen db status` | `oxygen_workspace_database_status` | Read hosting/provisioning status. Hosting is included in the plan; region is a recorded label, not verified physical location. |
| `oxygen db cost-policy` | `oxygen_database_cost_policy` | Read retired Neon policy status. `managed` describes that retired policy, not database hosting. PostgreSQL has no per-workspace sleep control. |
| `oxygen db query` | `oxygen_database_query` | Run one read-only `SELECT`, `WITH` or `EXPLAIN` statement under the customer SQL boundary. Writes and multiple statements are refused. Request a small `max_rows` (hard cap 1000); legacy native requests default to 100. `rowCount` is returned rows, and `truncated` describes that window. There is no query continuation cursor; narrow the SQL for another read. |
| `oxygen db attach` | `oxygen_database_attach` | Immediately attach the supplied `database_url`, set up tenant isolation and apply the native migration frontier. |
| `oxygen db migrate` | `oxygen_database_migrate` | Immediately apply pending migrations. Optional `rotate_credentials` rotates role passwords; routine migration leaves it false. |
| `oxygen db provision` | `oxygen_workspace_database_provision` | Provision the active workspace database through its bounded native provisioning path. |
Attach, migrate and provision have no native preview, dry-run or `approved` input. Inspect status and the selected schema before a requested configuration change. Normal workspace identity/access rules apply. A restricted client can read status, cost-policy and SQL, but configuration writes are refused. Built-in Copilot and Agent approval policy is enforced separately; an absent HTTP approval flag does not waive that policy.
`oxygen db reconcile-cost-policy` / `oxygen_database_cost_policy_reconcile` remains a compatibility no-op for a ready tenant: `applied: false`, `suspended: false`, `reason: "provider_retired"` and no operations. Its historical `suspend_idle` input cannot restore Neon controls or change PostgreSQL. Staff-wide migrations, repair and reconciliation procedures are separate privileged operations.
---
# Workspace context
> The typed company profile and typed assets every AI action resolves against, and the purposes that require each section.
Source: https://oxygen-agent.com/docs/workspace/context
Workspace context is the typed half of the [Knowledge Graph](/docs/knowledge/knowledge-graph): a structured company profile plus typed assets. Assets and wiki pages are the same rows in the same store — `oxygen context assets upsert` and `oxygen knowledge page upsert` are two names for one write, and `/context` redirects to `/knowledge`.
## Profile sections
Sections are merged independently, so an update touching only `icp` leaves the rest alone.
| Section | Fields |
|---|---|
| `company` | name, domain, category, geography |
| `offering` | products, value propositions, use cases |
| `icp` | target accounts, personas, disqualifiers |
| `market` | competitors, alternatives, segments |
| `gtm_stack` | CRM, outbound tools, channels |
| `custom` | tone, user preferences, constraints |
## Asset types
Type defaults to `other` on create.
| Asset kind | Purpose |
|---|---|
| `playbook` | Operational guides for a GTM motion |
| `strategy` | High-level GTM approach |
| `campaign` | Campaign brief, target segment, offers, and copy direction |
| `positioning` | Messaging, differentiators, objections, and proof points |
| `brand` | Brand guidelines; the canonical one is injected into AI copy generation |
| `voice` | How you sound; the canonical one is injected into AI copy generation |
| `persona` | Buyer or user profile |
| `competitor` | Notes on a market rival |
| `message_playbook` | Outreach message patterns; the canonical one backs live outreach |
| `research_note` | Ad-hoc research output (e.g. from onboarding) |
| `other` | Flexible supporting context |
`--default` (and `oxygen context assets set-default`) pins an asset as the canonical instance of its type, and canonical `brand`, `voice`, and `positioning` are injected into AI copy generation. The canonical instance of `voice`, `brand`, `positioning`, `playbook`, or `message_playbook` is live copy, so it changes only through an approved proposal, whether the asset is a file-backed page or not. Editing, retyping or archiving it does not save — it files an approval proposal and fails with `knowledge_approval_required`. `--default` on one of those types saves the asset unpinned and returns `pin.ok: false` with the `proposal_id` to approve (`oxygen knowledge proposals approve `); `set-default` files the same pin proposal. Other types pin at once. See [the approval gate](/docs/knowledge/knowledge-graph). Unpinned drafts of those types edit freely.
## Resolving
```sh
oxygen context resolve --purpose general --require-ready --json
```
The resolver returns a task-specific, revision-pinned bundle. Each purpose requires different sections, and `--require-ready` turns a gap into a conflict error instead of a partial bundle:
| `--purpose` | Required sections |
|---|---|
| `onboarding` | none; returns available research and current context |
| `general` | company, offering, icp, market, gtm_stack |
| `lead_sourcing` | company, offering, icp, market, gtm_stack |
| `workflow_design` | company, offering, icp, gtm_stack |
| `outbound_copy` | company, offering, icp |
| `qualification` | offering, icp, market |
It also carries up to `--max-assets` assets (default 10, hard cap 50). If it returns `context_missing` or reports `missing_required_context`, fill the named sections before resuming the work that needed them.
With `--purpose onboarding`, the result also includes `workspace`, a read-only snapshot of what already runs and what is connected. `campaigns` counts sequences (and how many are active), workflows (and how many are enabled), signal sources, posts and agents; `data` counts tables, CRM records and objects, and wiki pages; `access` counts LinkedIn accounts that are not disconnected and sending mailboxes, and names connected integrations. It contains counts and integration names only and spends no credits. A count Oxygen could not read is `null` and is listed in `workspace.degraded`, so it is never shown as zero. It also includes `plays`: `workspace`, `blank` when nothing is connected or running yet (the agent then skips the warm-lead reads) and `has_sources` otherwise; `leads`, the free reads that find your warmest leads in order (open deals, unanswered interested replies, recent visitors, viewers, engagers and followers, your captured LinkedIn network, people posting about the problem, then net-new ICP matches), each with its CLI command and MCP call; the featured plays from the Recipe catalog; and the ranked catalog search.
The `onboarding` block holds the research `brief`, the GTM `hypotheses` (ICP, offers and opportunities, or `research_note` when the research page lists hypotheses without sorting them), `unknowns` and the cited `evidence`. With no hypotheses, `hypothesesReason` says why: no research yet, a later profile change took precedence, or the research stated none. A brief that is too long is shortened between words and ends by naming where the full text is: the company profile or the `company-research` Knowledge page. `context.available` gives each brand, positioning and voice page a `state` of `canonical`, `draft` or `active`; only canonical copy grounds AI-written copy, and `context.missing` names each type that has none. In the ChatGPT app, `assets` carry each page's summary instead of its body, and `plays` keeps only the hint and the featured plays.
## Bootstrapping
The company domain entered at workspace creation starts one background research pass, funded by Oxygen. A company with no website enters its LinkedIn company page instead, and the pass starts from that page. It gathers LinkedIn company and website evidence, attempts a bounded match for the signup creator, and saves company facts with a cited research note. Suggested ICPs, offers, and opportunities remain separate hypotheses. Unresolved person matches do not block company research.
Your agent uses this context like a GTM consultant and takes you to a launched campaign. It first tells you in a few lines what the research found about your company, drafts your ICP and asks what you want to build first. Then it guides the Get started steps one at a time: your first leads (from your warmest people when you have connected sources, such as customers, open deals, unanswered replies, your network and engagers, or else from free searches of your ICP or a list you already have), a first sequence, the LinkedIn account or mailbox it sends from, and the launch. In a new workspace with nothing connected it skips the warm-lead search and answers in a few lines. Plays come after, to keep your list full. You can correct its assumptions as you work; corrections update durable context and take precedence over research. The `oxygen-onboarding` skill guides this conversation, while `oxygen-knowledge` carries the deeper context-bootstrap procedure.
```sh
oxygen skills install --agents codex claude-code cursor --skill '*' --json
oxygen context resolve --purpose onboarding --json
oxygen knowledge bootstrap status --json
```
For an explicit company-research rerun, `oxygen knowledge bootstrap` previews the provider plan, costs, and writes without spending. Manual execution requires `--live --max-credits ` and uses workspace credits; an existing marker also requires `--force`. It writes company facts and separate hypotheses, preserves the offering, ICP, and market profile sections, and does not repeat the automatic creator lookup. Research does not authorize outreach or execute a suggested play.
## Working with context
```sh
oxygen context profile get --json
oxygen context profile update \
--data-json '{"icp":{"segments":["B2B SaaS at $1M-$20M ARR"],"personas":["Founder","Revenue leader"]}}' \
--summary "Refine ICP" \
--json
oxygen context assets list --type playbook --json
oxygen context assets search --query "objection handling" --json
oxygen context assets upsert --type playbook --title "Outbound Q1" --body "..." --json
oxygen context assets archive --json
```
None of these spend credits or call a provider.
## Related
- [Knowledge Graph](/docs/knowledge/knowledge-graph) — the same store as wiki pages, with revisions, search, the link graph, and the proposal queue.
- [Blueprints](/docs/authoring/templates) — a blueprint declares the context keys it expects (`required_context_keys`), reported by `blueprints preflight`.
---
# Tags
> One label vocabulary across every primitive: declare and annotate tags, attach them on each owning surface, filter by them, and rename, merge, or delete them everywhere at once.
Source: https://oxygen-agent.com/docs/workspace/tags
Tags are the campaign handle — there is no separate campaign object. Put the same label on a sequence, its lead table, the workflow feeding it, the conversations it produces, and its learnings wiki page, and `tags get` returns the whole footprint in one read. Signal types, saved Dashboards, runtime Agent definitions, and saved Ads search collections also join this index. Signal events, Agent runs, and individual ads do not carry tags.
A tag exists once it is **declared** (a registry row carrying a description, colour, and pinned flag) or **carried** (some item's tags array holds it). Either alone is enough, and drift is permanent in both directions: a declared tag nobody uses stays declared with a count of 0, and a carried tag nobody declared is fully real — it indexes, renames, merges, and deletes like any other.
Labels are lowercased, trimmed, and deduplicated, up to 50 per item. They are **not slugified**: `"Q3 Outbound"` becomes `q3 outbound`, spaces intact. Chip colour derives from the label unless someone sets an override, so the same tag looks the same everywhere by default.
## Browse
```bash
oxygen tags list # every tag with per-primitive counts, most-used first
oxygen tags get q3-outbound # everything carrying the tag, deep-linked
```
`/tags` is the same read plus editing: search across labels and descriptions, **All** / **Pinned** / **Unused** facets, **New tag**, per-row **Edit… / Rename… / Pin / Delete…**, and a selection bar with **Merge into… / Pin / Unpin / Delete**. Each tag's own page groups its items by kind. Tag chips filter the sequencer, publishing queue, and unibox lists; `?tag=` deep-links into a pre-filtered view.
## Declare and annotate
```bash
oxygen tags create q3-outbound --description "Q3 founder-led launch" --color blue --pinned
oxygen tags update q3-outbound --clear-color --unpinned
```
`create` is idempotent and never touches carriers — running it on a tag forty items already carry just annotates it. Colours are the named set (`gray`, `red`, `orange`, `amber`, `yellow`, `green`, `teal`, `blue`, `indigo`, `purple`, `pink`); omit `--color` to keep deriving it from the label. `update` changes only the flags you pass; `--clear-description` and `--clear-color` remove a value. To change the label itself use `tags rename`.
## Attach
Tags are attached on each primitive's own surface:
```bash
oxygen sequences create ... --tags q3-outbound,saas-founders
oxygen sequences update --tags q3-outbound # replaces the set; "" clears
oxygen tables tag --tags q3-outbound
oxygen workflows tag --tags q3-outbound # org metadata; no new revision
oxygen knowledge page upsert --slug --tags q3-outbound ...
oxygen publishing tags set --add q3-outbound # add/remove deltas
oxygen inbox tag --add q3-outbound # add/remove deltas; --channel linkedin/whatsapp for DMs
oxygen crm tag companies --add tier-1 # add/remove deltas (run `oxygen crm setup` once to add the attribute)
oxygen mailboxes tag --tags q3-pool # pool sending identities under a campaign
oxygen senders tag --tags q3-pool
oxygen blueprints tag --tags q3-outbound # a saved blueprint; no re-export needed
oxygen domains tag acme.com --tags q3-pool # sending domains (survives `domains sync`)
oxygen projects tag outbound --tags q3-outbound # table projects
oxygen senders profiles tag --tags q3-pool # a whole sending identity in one edit
oxygen voice numbers tag +14155550142 --tags q3-pool # dialing numbers
oxygen tags attach signal_type website_visit --tags q3-outbound
oxygen tags attach dashboard --tags q3-outbound
oxygen tags attach agent --tags q3-outbound
oxygen tags attach ad_search_collection --tags q3-outbound
```
`tags attach` replaces the complete tag set on those four definition kinds; `--tags ""` clears it. It changes metadata only: a signal type remains a code-defined type, a Dashboard keeps its widgets, an Agent keeps its immutable versions, and a saved Ads search does not run. Over MCP, use `oxygen_tags_attach`. Save and browse Ads queries with `oxygen ads searches` or `oxygen_ads_searches`; see [Ads](/docs/data/ads).
Feeds carry no tags of their own: a live table's capture is part of the table, so `oxygen tables tag` is where a feed joins a campaign.
Most list commands accept `--tag` to filter — `sequences list`, `publishing posts list`, `tables list`, `workflows list`, `messages query`, `blueprints list`, `signals registry`, `dashboards list`, `agent custom`, and `ads searches list` — each taking **one** tag.
Every sending-identity list — `mailboxes`, `domains`, `senders`, `senders profiles`, `voice numbers` — takes `--tag` as a comma-separated set instead, matching **any** of them:
```bash
oxygen mailboxes list --tag q3-pool,q4-pool
```
`oxygen inbox list --tag` is the exception: it filters on the tags of the conversation's **campaign** (its sequence), not the conversation's own tags. DMs have no campaign link, so a tag filter there returns email only.
An **archived** sequence is otherwise immutable but still accepts a tags-only update, so finished campaigns can still be filed into a learnings tag.
## In the web app
Anywhere tags appear there is an editing affordance: **Add tags** beside a tag glyph on an item with none yet, collapsing to a **+** once it has some (tight call sites show the **+** in both states). It opens a picker listing the tags your workspace already uses, pinned first, each with its carrier count; type to filter. Pick any number of them; if what you type doesn't exist yet, choose **Create "…"** and it's added on save. On list rows, clicking an existing tag chip filters the list instead; the add affordance is what edits.
Your changes save when you close the picker. If someone (or the AI Inbox Tagger) adds a tag while you have it open, that tag is kept — the picker only applies what you actually changed.
### Filtering the sending pool
On **Sequencer → Accounts**, every tab (Senders, LinkedIn, Email, WhatsApp, Phone numbers) has a **Tags** dropdown next to its search box. Pick one or more tags to narrow the list to anything carrying **any** of them; clicking a tag chip on a row does the same thing, and clicking it again removes it.
The Email tab lists inboxes under their domains, and both can be tagged. Tagging the **domain** is the shortcut: filter to that tag and the domain shows up with all of its inboxes, so you don't have to tag twenty inboxes one at a time. Combine the tag filter with another filter (say Provider) and it narrows to inboxes proper — a tagged domain with no matching inbox drops out.
## Auto-tagging inbound conversations
The **AI Inbox Tagger** (a workspace agent at `/agents/inbox-auto-tagger`; the `/agents` nav entry is beta-gated) classifies every new inbound conversation against a tag allowlist you configure and applies the matches automatically — riding the same analysis call that already categorizes replies, so it adds no model cost. It only ever adds tags, and it never re-adds a tag you removed from a conversation.
```bash
oxygen inbox auto-tagger get
oxygen inbox auto-tagger set --enabled --tags "pricing-question,partnership,support-request"
oxygen inbox auto-tagger set --channels email,linkedin # default is all three
oxygen agent get inbox-auto-tagger # state + recent tag applications
```
`--tags` replaces the whole allowlist (max 50). `--tags ""` clears it, which pauses tagging while leaving the agent enabled.
## Reshape the vocabulary
```bash
oxygen tags rename q3-outbound q3-founder-launch # preview: per-kind counts, no writes
oxygen tags rename q3-outbound q3-founder-launch --apply
oxygen tags merge q3-outbound q3-old --into q3-founder-launch --apply
oxygen tags delete q3-old q3-scratch --apply # IRREVERSIBLE
```
All three are preview-first: without `--apply` they print per-kind (and per-tag) would-change counts and mutate nothing. All three are unfiltered by liveness — archived and finished items are rewritten too, so an un-archive never resurfaces the old name. That is why a preview count can legitimately **exceed** what `tags list` shows, which hides archived carriers. All three are safe to re-run after a partial failure.
Rename onto an existing tag behaves exactly like merging into it. When a tag absorbs another, the surviving tag wins per field, but a field it left empty is filled from the first source that has one; `pinned` ORs. `delete` strips the tag from every carrier **and** removes its declaration.
## Semantics worth knowing
- Whole-set vs delta is per-surface, and the flag names it: `--tags` **replaces** every tag on the item (`--tags ""` clears them) with no preview step, so read the current tags first when you mean to edit rather than overwrite. Exactly three surfaces take `--add`/`--remove` deltas instead — publishing posts, inbox conversations, and CRM records — so the auto-tagger and your edits merge instead of clobbering each other. Every other surface is whole-set, projects, sending domains, sender profiles and phone numbers included.
- The tag index hides finished work: archived tables, wiki pages, blueprints, domains, projects, sender profiles and conversations drop out, as do canceled posts, disabled mailboxes, disconnected senders, and released phone numbers. Archived **sequences** stay in.
- The unibox's warmup/DMARC/bounced markers are **system badges** — derived state, not tags.
- Tags carry no approvals and spend no credits — they are workspace metadata.
---
# Collaboration
> Comment threads, approval requests assigned to a named person, the opt-in gate that blocks a live launch, and the restricted client role.
Source: https://oxygen-agent.com/docs/workspace/collaboration
Get a second person's documented go/no-go on the sequence about to launch or the list it sends to — and, when you want it, make that decision a precondition for the live launch. Comment threads hang off any workspace object, from a wiki page to a CRM record; approvals exist only where a gate does.
This is not the [paid-action approval](/docs/safety/approvals) gate. That one asks **you** to authorize your own spend (`--approved`, `--max-credits`). This one asks **somebody else** to decide, stores their answer, and can hold the action until it arrives. Both can apply to the same launch.
## Where it lives
Sidebar **Data → Approvals** opens `/collab`, titled "Waiting on you": approvals assigned to your login, plus comment threads that named you. Decide a card in place — **Approve**, **Request changes**, **Reject**, with an optional decision note. Withdrawing is the requester's move, not the assignee's: use `approvals cancel`, or the card's **Withdraw** button on the object's own panel. **Members and roles** in the header goes to `/collab/members`.
The sidebar entry is beta-gated — a workspace admin turns it on at `/settings#/beta-features`. The routes are not. `/collab`, `/collab/approvals/`, and `/collab/threads/` open by direct URL at either setting, deliberately: an emailed "you have been asked to approve" link must work for a client whose agency never flipped the toggle. Every `approvals` and `comments` command returns the matching URL as `web_url`.
{/* SCREENSHOT: /collab | the "Waiting on you" inbox with one pending approval card: title, who asked, the decision note field, and the Approve / Request changes / Reject buttons */}
## Ask someone to decide
Sequence detail pages no longer show the comments or **Approvals** panels, and Knowledge files no longer show their comments panel. Use the commands below to request Sequence approval, and open an existing request or thread through its direct link. Existing requests, threads, and configured gates remain in place.
Table grids no longer show a Comments button or column and cell comment actions; table comments and sign-off requests remain available through the CLI and MCP. CRM records mount the thread half only. No gate covers Knowledge pages or CRM records, so `approvals request` on either is refused with `gate_not_supported_for_subject`. Table sign-off requests apply to the whole table.
```bash
oxygen approvals request --on sequence:9f1c2b7e --gate launch \
--assignee client@acme.com --title "Q3 outbound" --expires-hours 48
oxygen approvals inbox # what is waiting on you
oxygen approvals list --on sequence:9f1c2b7e # also --status, --mine, --limit
oxygen approvals show # the id from an email or a /collab link
oxygen approvals decide --approve --note "Copy is fine"
oxygen approvals cancel
```
You cannot assign yourself, and you cannot decide your own request — withdraw it with `approvals cancel` instead. Any one assignee can answer, and so can a workspace admin. Only `--approve` opens a gate: `--changes-requested` is a real answer that leaves it shut, and an expired request never opens one.
## The gate
Asking blocks nothing on its own. A gate is workspace policy, and the owning primitive enforces it.
| Gate | Means | Set on | Refuses |
|---|---|---|---|
| `launch` | approve before a sequence sends live | sequences | `oxygen sequences start`, `oxygen sequences resume` |
| `signoff` | approve the table's rows before they are worked | tables | any enrollment from the bound source table — `oxygen sequences enroll`, a workflow's enroll step, the capture-feed sweep |
```bash
oxygen approvals gate set --default sequence --gate launch --required
oxygen approvals gate set --on sequence:9f1c2b7e --gate launch --not-required
oxygen approvals gate list --on sequence:9f1c2b7e
```
Every gate is off until an admin turns it on, and `gate set` is admin-only and CLI/MCP-only — the web app has no control for it. A gated sequence still previews, dry-runs, and shows its steps, copy, and cost to everyone; that is what the approver reads. Only the live start refuses, with `approval_required` naming the pending request and its assignees. The yes binds to what was approved: rewrite the sequence afterwards and the next live start refuses with `approval_stale`. Clearing the gate is not authorization to spend — the live start still needs its own `--approved` and caps, and a start that raises `--max-credits` or `--max-live-sends` above the approved ceiling is refused with `approval_cap_exceeded`.
## Comments
Threads hang off the object, never inside it: resolving one changes no campaign.
```bash
oxygen comments add "Second step reads as a pitch" --on sequence:9f1c2b7e
oxygen comments add "Wrong domain" --on table:2b7e --path row:8f2c1a4d#email
oxygen comments list --on table:2b7e --status all
oxygen comments resolve # --reopen flips it back
```
An `@email` in the body notifies that member. `comments edit` and `comments delete` are author-only and leave a trace.
## The client role
The agency case: a login that can read the work, comment, and decide the approvals assigned to it — nothing else. Anything that runs, launches, spends, or reconfigures refuses with `insufficient_role`.
```bash
oxygen approvals client grant client@acme.com # admin only
oxygen approvals client list # everyone, and what they may do
oxygen approvals client revoke client@acme.com
```
Invite the person in Settings → Members first; a grant on an invited-but-not-joined address applies the moment they accept. On `/collab/members`, the **Access** column shows who holds what, and an admin's **Change access** column switches a member between **Full access** and **Client (restricted)**. An admin's role overrides the restriction, so the grant is refused until you demote them with `oxygen orgs member-role --role member`.
{/* SCREENSHOT: /collab/members | the members table showing Member / Workspace role / Access / Change access columns, with one row badged "client" */}
---
# Agency directory
> Apply for, edit, publish, and pull your agency's listing in the public OXYGEN directory.
Source: https://oxygen-agent.com/docs/workspace/agency-directory
Get your agency onto [oxygen-agent.com/agencies](/agencies), then edit or unpublish that listing from the web app or the CLI.
The directory is invite-only. Until OXYGEN staff enable a listing for your organization, `oxygen directory get` returns `directory_not_enabled` and the settings screen shows an application form instead of the editor.
## Apply
Two routes:
- **Web** — open `oxygen-agent.com/settings/directory`, fill in **Your agency website** and **Tell us about your agency**, press **Submit application**.
- **CLI**:
```sh
oxygen directory apply \
--message "What we do, who we serve, and how we use OXYGEN for client work" \
--website https://your-agency.com
```
Applying files a support request with the OXYGEN team. It costs 0 credits, creates no listing, and publishes nothing. One open application per organization — apply twice and you get back `status: "already_applied"`.
There is currently no separate directory application-status read. `directory get` reports the listing, not the application review stage. Keep the application’s `ticket_id` to follow up through support; review timing is unknown and no ETA is promised.
If staff approve, they create the listing in `invited` status and seed its name and public slug. They may also prefill fields and set featured placement. That gives you an editor, not a live page; an update never publishes a draft.
## Find the editor
`/settings/directory` is a deep link only. It has no sidebar entry and is not in the **Settings** popover in the sidebar footer. CLI and MCP responses hand you the URL as `settings_url`, and the public directory's **Apply to be listed** button points at it.
Once a listing exists, an **Agency Directory** tab also appears in the settings dialog: sidebar footer **Settings** → **Organisation settings** → **Agency Directory** (`/settings#/agency-directory`). Organizations without a listing never see that tab.
{/* SCREENSHOT: /settings/directory | status badge, the Publish to directory button, and the top of the profile form */}
## Edit the profile
The editor autosaves: text fields save when you leave them, the **Services** and **Regions served** chips save shortly after you toggle them. Fields are Agency name, URL slug, Tagline, Logo (**Upload image** takes PNG, JPEG, WebP, or SVG up to 2 MB), Description, Founding team (**Add founder**), Website, Company LinkedIn, Book-a-call link, and Contact email.
The same edits from the CLI:
```sh
oxygen directory get --json
oxygen directory update --tagline "GTM systems for seed-stage B2B SaaS" --website https://your-agency.com
```
`oxygen directory update --help` prints every field flag plus the fixed Services and Regions values the form offers as chips. `--profile-json` sends a whole profile object under the API field names (`website_url`, `booking_url`, …); individual flags override it, and a `null` in that object is the only way to clear a field — an empty flag value is ignored.
On a published listing every save is public immediately — in the web editor that includes autosave. Unpublish first if you want to rework the copy.
## Publish and unpublish
Publishing requires a tagline, a description, and at least one contact method (website, booking link, contact email, or company LinkedIn). Miss any of those and the call fails with `directory_profile_incomplete`, naming what to add.
- **Web** — **Publish to directory**. Once live, that button becomes **Unpublish**.
- **CLI** — `oxygen directory publish` and `oxygen directory unpublish`.
Neither spends credits, and neither writes to any platform outside OXYGEN. Both change a public web page, so run them only when you mean to. Unpublishing returns the listing to an editable draft; it does not delete it.
| Status | Badge in the editor | What it means |
|---|---|---|
| `invited` | Draft — not public | Editable, nothing public yet |
| `published` | Published | Live at `oxygen-agent.com/agencies/` |
| `delisted` | Removed by OXYGEN | Pulled by staff, read-only — contact support |
## Once you are live
A published listing makes you an OXYGEN Certified Partner, or Featured Partner if staff pinned you. The editor then shows a **Partner program** panel with your badge in dark and light — **Download SVG** each, or **Copy embed code** for a badge that links back to your listing — the affiliate rate: 30% on the first 12 months of every customer you refer, and the partner bonus: 15% of your plan's price in bonus credits every month on Oxygen plans from $99, on top of the volume bonus. The bonus arrives as its own `partner_bonus` line with each monthly plan grant; `oxygen billing summary --json` reports eligibility, amount and timing under `partner_bonus` without applying credit grants or expiry, and [Billing](/docs/safety/billing#agency-partner-bonus) lists the amount for every plan. The **Activate your affiliate link** link appears only on deploys where the affiliate portal is configured.
The bonus follows the paying organization’s published listing and eligible plan. Publishing a client workspace’s listing adds no separate bonus to a shared pool. Application submission or approval alone earns no bonus.
First-grant timing and the next scheduled monthly grant are separate facts. Billing reports an explicit unknown reason when it cannot establish the first grant; publication does not promise an immediate credit arrival. Unpublishing stops eligibility for future bonus grants. Existing credits retain their normal paid-period, refund and rollover treatment.
Existing PARTNERS2026 discounts end on cancellation or when a plan change takes effect. The separate prospective bonus-exclusion policy must be enabled before it applies. [Billing](/docs/safety/billing#agency-partner-bonus) explains the account's conditions and dated coupon evidence. Once enabled, an active approved coupon excludes only the bonus; an unavailable discount check withholds only the unvalidated bonus. Base plan credits and historical grants remain unchanged.
---
# Knowledge Graph
> Run the workspace wiki: write wikilinked pages, pin the canonical copy that grounds AI drafts, and clear the approval queue those pins create.
Source: https://oxygen-agent.com/docs/knowledge/knowledge-graph
Each wiki page has a kebab-case slug (`founder-voice`), a type, tags, a Markdown body, and a revision number. `[[wikilinks]]` in the body become graph edges. Every create, edit, pin, and filing appends to a log. Search is full-text and accepts quoted phrases, `OR`, and `-exclude`.
Pages and [context assets](/docs/workspace/context) are the same rows in the same store: `oxygen knowledge page upsert` and `oxygen context assets upsert` write to it under two names, and `/context` redirects to `/knowledge`.
## Seed it
A new workspace self-seeds two starter pages when it is provisioned: `icp` (who you sell to) and `offers` (what you sell), linked to each other. They ship as drafts, so they never ground AI copy until you fill them and set `status: active`. Create any other page, such as positioning, voice or a competitor teardown, when you have something real to put in it. Re-run seeding any time — it never overwrites your edits.
```bash
oxygen knowledge seed
```
## In the web app
Open **Knowledge** under **Data** in the sidebar, at `/knowledge`. No beta opt-in is required.
| Route | What it is |
| ------------------------- | ------------------------------------------------------------------------------------ |
| `/knowledge` | Folder and file explorer on the left; the knowledge graph opens by default |
| `/knowledge/pages/new` | Create a knowledge file with a title, folder, and Markdown content |
| `/knowledge/pages/` | Read and edit the file with automatic saving; deleted files show their deleted state |
| `/knowledge/graph` | The force-directed graph |
| `/knowledge/log` | Activity history grouped by day, with affected files and older activity |
| `/knowledge/proposals` | The approval queue |
Expand folders with their arrows to browse nested folders and files. Select a folder to see its contents, or a file to read and edit it on the right; the graph is hidden while viewing content. Choose **Knowledge graph** in the explorer to return to the graph. **New folder** and **New file** create persistent workspace items, including empty folders. Drag files or folders onto another folder to move them; hold over a collapsed folder to expand it. Drop on **Files** to move to the root. The row menu also offers **Move to**. For keyboard drag-and-drop, focus the drag handle, press Space, choose a destination with the arrow keys, then press Space to move or Escape to cancel. Files shared by UGC programs you joined are listed under **Programs**, below **Files**: expand a program to open its files and skills read-only.
Files open in a continuous rich text editor. Select text to format it, or type `/` to insert headings, lists, tasks, tables, quotes, code, and dividers. Edit the title directly and select tags beneath it. Changes save automatically; the save status shows when they are safe. Canonical copy instead offers **Propose changes**. A failed save keeps your draft in the current browser tab for recovery. Advanced Markdown that cannot be represented safely stays available as Markdown source.
Choose **Delete file** on an open file and confirm its deletion to remove it from active browsing. Wait for edits to finish saving first; unsaved changes block deletion. Oxygen archives the file and retains its content and revision history. Deleting canonical copy files a proposal and leaves the file in place until approved. Knowledge files no longer show a comments panel; existing threads remain accessible through their direct links and the [collaboration commands](/docs/workspace/collaboration).
Slug auto-fills from the title until you type your own. The slug `new` is reserved for the creation screen; use a different slug such as `new-file`. Files are knowledge pages: folders organize them without changing stable slugs, URLs, or `[[wikilinks]]`.
Open **Activity log** from the top breadcrumb bar. Changes appear in a history grouped by UTC date, with an action, summary, recorded actor kind, timestamp, and affected file link. **Details** appears only when the entry has additional meaningful metadata. **Older activity** continues through the workspace history; **Latest activity** returns to recent changes. Proposals are not listed in the Knowledge explorer; the approval queue remains available at `/knowledge/proposals` and through approval links.
The graph starts in **2D**, with pastel colors identifying file types. Choose **3D** to rotate the same connections in space: drag to rotate and scroll to zoom. Switch back to **2D** at any time. Browsers without 3D support automatically keep the 2D view.
Use **Find a connection…** to centre either view on a file. **Filters** opens label visibility, tags, file types, and **Include unlinked files**; **Fit graph to view** resets the camera. In 3D, **On hover** shows labels for the file under your pointer and the focused file; **More labels** shows up to 50, prioritizing those files. It loads 500 pages by default and caps at 2,000; when more pages exist, a **Load up to … files** picker beside **Filters** changes that limit. Clicking a node opens its file. Missing linked files appear as dashed nodes in 2D or gray nodes in 3D; select one and choose **Create linked file** to create it.
{/* SCREENSHOT: /knowledge/graph | the knowledge graph with Filters open, showing labels, tags, file types, and Include unlinked files */}
## Read and write from the CLI
```bash
oxygen knowledge index # every slug, one-liner, tags, link degree
oxygen knowledge search "icp OR positioning" --limit 5
oxygen knowledge page get founder-voice
oxygen knowledge page list --type competitor --status active
oxygen knowledge lint # orphans, dead ends, unfilled stubs, missing canonicals
```
Plain-language search can combine keyword matches with semantic passages when semantic indexing is enabled for the workspace. The response reports `match_type` and `semantic_status`; the Knowledge index shows indexing coverage. Disabled, empty, or unavailable semantic indexing falls back to keyword search. Quoted phrases, `OR`, and exclusions retain strict keyword semantics. Results retain page revisions and relevant excerpts so you can open and verify the source.
Page writes spend no credits. In enabled workspaces they queue background embedding updates funded by OXYGEN's budgeted search infrastructure:
```bash
oxygen knowledge page upsert \
--slug founder-voice --title "Founder voice" --type voice \
--summary "How we sound" --body "Short sentences. See [[positioning]]."
```
Add `--expected-revision ` to fail the write if the page moved under you. `oxygen knowledge page revisions ` lists history; `oxygen knowledge page revision ` reads one snapshot back. Use `oxygen knowledge page get --view sources` for its evidence ledger, or `--view full` for content, links and sources together. Follow `next_cursor` for older sources. A citation in the body or structured data does not add an auto-filed source record.
`oxygen knowledge page archive --expected-revision ` archives the version you reviewed. Archived pages remain readable by slug with their revision history, but leave active browsing and search. Wikilinks to an archived page become unresolved, and lint reports them.
Restore a working page with `oxygen knowledge page upsert --slug --status draft --expected-revision `. Omit `--body` to retain its content. This adds a revision; canonical-copy changes still require proposal approval.
## Organize folders and files
```bash
oxygen knowledge folders list --json
oxygen knowledge folders create --name "Research" --json
oxygen knowledge folders create --name "Competitors" --parent --json
oxygen knowledge folders move --parent --json
oxygen knowledge folders move --parent root --json
oxygen knowledge page upsert --title "Competitor notes" --folder --create-only --json
oxygen knowledge page upsert --slug competitor-notes --folder root --json
```
Use the returned folder UUID for `--parent` and `--folder`. Omit `--folder` on an edit to preserve placement; `--folder root` moves a file out of its folder. `--create-only` prevents an existing page from being overwritten. Folder listing includes page locations and a `truncated` flag when its page limit is reached. Folders are workspace organization, not separate permissions or graph links.
Moving a page adds a revision and changes `data.knowledge_folder_id`; its slug and body are retained.
## The approval gate
Editing or pinning the **canonical** page of a sensitive type does not save your change. It files a proposal.
Sensitive types are `voice`, `brand`, `positioning`, `playbook`, and `message_playbook`. Only the pinned instance is gated — unpinned drafts of those same types edit freely, because nothing customer-facing reads them yet.
The CLI returns error code `knowledge_approval_required` carrying the proposal id. The web editor toasts "Change proposed — pending approval" and keeps your text. Clear the queue with:
```bash
oxygen knowledge proposals
oxygen knowledge proposals approve # --force if the page moved since
oxygen knowledge proposals reject
```
Or at `/knowledge/proposals`, where each card shows the target page, the reason, the changed fields, and **Approve** / **Reject**.
`--approved` on `page upsert` and `page pin` does **not** bypass this gate.
The flag is accepted for compatibility and ignored — the proposal is filed
either way.
{/* SCREENSHOT: /knowledge/proposals | one proposal card with its reason badge, the changed-field diff, and the Approve / Reject buttons */}
## What grounds your AI copy
Pinned canonical `voice`, `brand`, and `positioning` pages are injected into AI copy generation — table AI columns, message drafts, reply drafting. That is what the gate is protecting.
```bash
oxygen knowledge page pin founder-voice # sensitive type → files a proposal
```
Retrieval of the _rest_ of the wiki alongside those pins is built but switched off in production pending review, so pinning is the live path today.
## Synthesize (spends credits)
`oxygen knowledge synthesize` distills auto-filed outreach outcomes into a learnings page, or sent messages into a voice guide. It previews by default — but the preview _is_ the AI call, so it spends credits and reports `credits_used`. `--approved` on its own runs the call a _second_ time before writing; pass `--body` with the text you reviewed to save it verbatim and skip that second charge. A voice guide saved with `--approved` files a pin proposal like any other canonical pin (`pinned: false`, `pin.proposal_id`); it becomes the canonical voice when that proposal is approved. The guide is saved as a Knowledge page (slug `founder-voice`, or the next free one such as `founder-voice-2`), so `knowledge search` and the index find it.
```bash
oxygen knowledge synthesize --kind campaign_learnings # preview + cost
oxygen knowledge synthesize --kind campaign_learnings --approved --body "…" # write what you read
```
Cap a run with `--max-credits ` (MCP and API: `max_credits`). When the estimate is higher, Oxygen refuses before the AI call with `spend_cap_too_low`, charges nothing and reports `estimated_credits`. Saving a reviewed `--body` makes no AI call and needs no cap.
Unattended synthesis is off by default and spend-capped: `oxygen knowledge agent set --enabled --cadence-hours 24 --max-credits-per-day 100`. It only writes working learnings pages; canonical changes still queue as proposals.
## Local mirror
Optional, for editing in your own editor. `oxygen knowledge sync` clones the pages as Markdown under your CLI config directory, `push --dry-run` shows what would go back, `status` reports staleness and quarantined conflicts, and `purge` deletes the mirror. Pushed edits to canonical pages become proposals, same as everywhere else.
The config directory is `OXYGEN_CONFIG_DIR` when set; otherwise Oxygen uses the platform config default (`~/.config/oxygen` on macOS/Linux and the Oxygen folder under `%APPDATA%` on Windows). This mirror is a disposable, manually refreshed cache of hosted wiki pages.
## Connect an existing GitHub or Obsidian repository
The Oxygen GitHub App requests Contents read and write plus Metadata read on the repositories you select, and push events; it requests no account or organization permissions. If GitHub shows as unavailable in Connections, repository connections are not enabled on your deployment yet; ask Oxygen support to enable them for your workspace.
A repository mount is different from the local mirror. It keeps original repository-relative paths and case, retains eligible Markdown, Obsidian Bases, plugin data, and attachments as immutable file revisions, and can synchronize an exact GitHub repository, branch, and root folder automatically. The local mirror only renders hosted wiki pages into a CLI-managed editing directory and moves changes when you explicitly run `sync` or `push`.
Connect the GitHub App, discover the repository and branch, preview the exact scope, and approve that preview:
```bash
oxygen integrations connect github
oxygen integrations github repositories --connection-id --json
oxygen integrations github branches \
--connection-id --repository-id --json
oxygen knowledge repositories preview \
--connection-id --repository-id \
--branch main --root-path "" --mode two_way --json
oxygen knowledge repositories connect \
--connection-id --repository-id \
--branch main --root-path "" --mode two_way \
--preview-token --approved --json
```
Preview only reports the files, exclusions, limits, and future sync policy. It does not import or activate anything. `connect` requires the exact unexpired preview token and `--approved`. Choose `--mode import` for a one-time copy or `--mode two_way` to authorize future automatic writes to that same branch and root folder.
Import, **Sync now**, webhook deliveries, and automatic polling queue work for the background worker. They do not mean a commit has already landed. Read `oxygen knowledge repositories list --json` until the status, pending count, and `last_synced_at` advance. After a successful cycle, the next automatic poll is scheduled with jitter at roughly 4.5–5.5 minutes; a GitHub push webhook or explicit sync request can make the mount due sooner.
The web repository page lists files in pages of 500. Opening a Markdown file shows its exact source and resolves `[[wikilinks]]` against original paths inside the same mount. Opening an Obsidian `.base` file waits for every metadata page, then renders supported table, cards, and kanban views using filters, sort rules, grouped properties, Base Board column configuration, and `kanban_order`. Unknown view types or filter expressions remain preserved and are reported instead of being executed or guessed.
Original file operations are also available from the CLI:
```bash
oxygen knowledge files list --mount-id --limit 100 --json
oxygen knowledge files get --id --revision --json
oxygen knowledge files upsert --mount-id --id \
--expected-revision --properties-json '{"status":"Published"}' --json
oxygen knowledge files upsert --mount-id --path assets/diagram.png \
--expected-revision 0 --file ./diagram.png --json
oxygen knowledge files download --id --out ./diagram.png
```
Every edit and archive requires the file revision you reviewed; `0` is valid only when creating a new path. `--file` transports exact bytes, including binary attachments. `--properties-json` changes only the named Markdown frontmatter values and preserves the body and unrelated frontmatter. Downloads verify size and SHA-256 and refuse to overwrite an existing local file.
If Oxygen and GitHub change the same file, both versions and their common base are retained. Inspect the exact path with `oxygen knowledge repositories conflicts --mount-id --path --json`. Resolve only after reviewing the returned local revision and remote SHA; `knowledge repositories resolve` requires those identities, a decision (`oxygen`, `github`, or `merged`), and `--approved`. A canonical voice, brand, positioning, or pinned playbook edit still enters the normal proposal queue. GitHub synchronization never grants approval authority.
Repository limits are 25,000 eligible files, 1 GiB retained bytes per workspace, 100 MiB per attachment imported through GitHub, and 1.5 MB for editable UTF-8 Markdown. An inline `knowledge files upsert` request has a 2 MB JSON-envelope limit; base64 encoding makes the usable binary payload smaller, so move larger originals through the connected GitHub repository. Oxygen excludes credential files, machine state, symbolic links, submodules, and `.github/workflows`. Obsidian settings and plugin files can be preserved for round trips, but imported scripts and plugins are never executed. HTML and SVG are retained as downloads rather than active previews; inline previews are limited to signature-verified PNG, JPEG, and PDF files.
## For agents
`oxygen_knowledge_index`, `_search`, `_page_get`, `_page_upsert`, and `_log_append` ship in the default MCP tool set. Discover other Knowledge tools with `oxygen_capabilities_search`, inspect the selected schema, then run through `oxygen_capabilities_read` for reads or `oxygen_capabilities_call` for writes. This includes folders, revisions, proposals and repository/file tools; `?toolset=knowledge` optionally lists them directly. Use `oxygen_knowledge_repository` for repository discovery, preview, connection, status, and conflicts. Use `oxygen_knowledge_file` for metadata, bounded text ranges, and revision-checked file edits. Per-tool detail: [MCP tool reference](/docs/surfaces/mcp-reference).
GitHub previews label the size of Git blobs. Expanded Git LFS object sizes are additional and checked during import; the retained workspace quota can pause an import after some files are saved. Progress and accepted files remain available.
---
# Recipes
> Find a proven GTM play, read its prerequisites and credit cost, and install it into your workspace wiki as a page your agent follows.
Source: https://oxygen-agent.com/docs/knowledge/recipes
A recipe is a versioned GTM playbook: one motion written out with its prerequisites, credit posture, approval gates, and steps. Categories, each phrased as the question it answers: `start-here`, `pipeline-from-zero`, `catch-warm-signals`, `linkedin-engine`, `convert-faster`, `revenue-truth`, `agency-scale`.
Recipes are advisory. Reading or installing one costs 0 credits and changes nothing outside the wiki. The paid steps inside a play run through their own primitives, with their own `--approved` and `--max-credits` gates.
## Start with this one
```sh
oxygen recipes show day-1-first-win --json
```
If you have no play running yet, run that one. In one free session `day-1-first-win` writes down what you sell and who buys it, builds a table of about ten people to contact first with the reason for each, and drafts first messages for the top few. Warm contacts (customers, open deals, unanswered replies, your LinkedIn network) come first when the workspace has them; otherwise a free search finds people who match your buyers. Nothing is sent and no credits are spent.
## Find the others
```sh
oxygen recipes list --stage day-1 --json
oxygen recipes list "outbound" --category pipeline-from-zero --json
oxygen recipes list --audience agency-operator --json
```
`--stage` takes `day-1`, `day-7`, `day-30`, or `ongoing`. `--audience` takes `founder`, `gtm-operator`, or `agency-operator`. An unknown value is rejected with the allowed list.
In the browser, the catalog is **Plays** (`/plays`): open **Settings** at the foot of the sidebar and choose **Plays**, or follow **All plays** on Home. The web app calls a recipe a play, and a play is a prompt. Each card shows the play's icon, its name and one line on what it gets you, with a **Copy prompt** button: paste the prompt into the agent you connected to OXYGEN (Claude, Codex or another MCP client) and it runs the play from your workspace. The prompt is the play's request in your own words, then one line naming the play and your workspace and asking the agent to check that workspace and the folder it is working in, then show the plan and its cost first. One search box ranks plays the same way `oxygen recipes list ""` does; without a search, the page shows the featured plays first and then every other play under its category. Home shows the featured plays as the same cards. `/recipes`, `/recipes/` and `/plays/` land on Plays with that play's card highlighted.
## Read one
```sh
oxygen recipes show outbound-pilot-50 --json
```
You get the full body plus the frontmatter facts. The body has four sections, always in this order: **The Play** (what you get and when it fits), **Before You Start** (what must exist, the command that checks it and what it costs), **Steps** and **If It Goes Wrong**. The frontmatter facts are: outcome, leading metric, a labelled benchmark range, effort, pilot and full credit cost, prerequisites with the check command for each, and the approval gates. A play has no page of its own in the web app: its card is the play, and your agent reads these facts when it opens the play. `recipes list --view summary` also returns each play's `summary` (the card's line) and `prompt` (what **Copy prompt** copies).
On 2026-10-04 the catalog went from 33 plays to 13: plays that repeated another became options inside it. An old play's name still works. `oxygen recipes show competitor-post-engagers --json` opens `inbound-led-outbound` and says so first, and a play that was cut answers `recipe_retired` with what to use instead.
Every paid or external step in the body is marked `> APPROVAL GATE — ` and names what you must see before approving. A recipe marked `trial-safe` keeps its pilot path at or under 100 credits.
## Install one
```sh
oxygen recipes install outbound-pilot-50 --draft --json
```
This writes the play into your workspace wiki as a page at `playbook-` — revisioned, searchable, and readable by your agent. Automatic retrieval of wiki pages into AI columns and drafts is built but [switched off in production](/docs/knowledge/knowledge-graph), so an installed playbook is something your agent opens on purpose, not something injected into every AI call. `--draft` installs it inactive. Edit it freely afterwards; a re-install refuses to clobber your edits unless you pass `--force`, and `--slug ` installs under a different name instead. Read the result with `oxygen knowledge page get playbook-outbound-pilot-50 --json` or open the returned link at `/knowledge/pages/`.
## Three different things are called "recipe"
| Name | What it is | Command | Where |
|---|---|---|---|
| **Recipe** (this page; a **play** in the web app) | A guided GTM playbook, installed into the wiki — and, when the play needs infrastructure, the ordered kit of blueprints that builds it | `oxygen recipes list \| show \| install \| apply` | **Plays** (a prompt card each) |
| **Blueprint** (a workflow **template** in the web app) | One installable bundle: tables, columns, prompts, and one disabled workflow | `oxygen blueprints apply` | **Workflows → Templates**, `/blueprints/` |
| **Durable recipe** | The legacy TypeScript workflow format, for imperative logic the v2 graph cannot express | `oxygen workflows init --format recipe` | [Durable workflows](/docs/authoring/durable-workflows) |
## The kit: install a whole motion in one step
A play that needs several blueprints in order carries them as its **kit** — an ordered list of stages, where a later stage's table input is bound to the table an earlier stage created. `oxygen recipes apply` installs the whole thing under one approval instead of making you apply each blueprint by hand and copy table ids between them.
```sh
oxygen recipes show inbound-led-outbound --json # the kit, and which stages you already have
oxygen recipes apply inbound-led-outbound --dry-run --json # preflight every stage, one forecast
oxygen recipes apply inbound-led-outbound --json # install, 0 credits, workflows disabled
```
Applying a kit spends **0 credits**, makes **no provider calls** and writes nothing outside your workspace. Every workflow it installs arrives **disabled**. Installing is not permission to run, enable, enroll, send or spend — each of those still asks you separately, with its own preview and cap.
Re-running `apply` is safe: a stage you already have is reported as reused, and a stage whose workflow is currently **active** is skipped rather than replaced, so a reapply can never switch a live motion off. A stage that *is* republished comes back disabled and needs enabling again — workflow authority is bound to the revision you approved.
## Blueprints on their own
Some recipes name a single blueprint that builds the infrastructure the play needs. `outbound-pilot-50` names `dm-outbound-pilot`; the recipe still works without it. You can always work a blueprint directly:
```sh
oxygen blueprints list --json
oxygen blueprints describe dm-outbound-pilot --json
oxygen blueprints preflight dm-outbound-pilot --json # 0 credits, no workspace change
oxygen blueprints apply dm-outbound-pilot --json # 0 credits, creates workspace objects
```
Preflight first: it validates inputs against your workspace, reports the per-run credit ceilings you would face later, and returns the exact `apply` command that preserves the inputs you validated. `apply` spends no credits and makes no provider calls, but it does create tables, columns, prompt templates, and a workflow — left **disabled**, so nothing runs until you enable it.
To go the other direction, `oxygen blueprints export --workflow --out ./my-play.json` bundles a workflow you built, `oxygen blueprints save --file ./my-play.json` stores it in this workspace, and `oxygen blueprints share ` returns a public `oxygen-agent.com/b/` URL anyone can apply.
Blueprints has its own sidebar item under **Knowledge**, labelled **Blueprints** and pointing at `/blueprints` — separate from **Recipes**, which points at the playbook catalog above. It is beta-gated: it stays hidden until an admin turns on **Beta features** in organization settings (`/settings#/beta-features`). The route itself works by URL either way. Recipes is not gated. `/blueprints/