Connect agents to Company OS
How to connect coding agents and terminals (Claude Code, Codex, OMP, Cursor, Windsurf, Gemini CLI, other MCP clients, the Tern terminal plugin, and remote clients such as Grok) to Company OS, and how each connection is governed.
Company OS owns company identity, policy, approvals, and the ledger. The agent brings its own model. Connecting an agent never gives it approval authority.
Commands use companyos (the package also installs company-os; same CLI). In a source checkout, ./company-os runs the same verbs.
1. Connection or governed run
These are three different things.
| Companion MCP connection | OMP read-only profile | Governed run (AgentChat) | |
|---|---|---|---|
| Clients | Claude Code, Codex, Cursor, Windsurf, Gemini CLI, generic MCP | OMP, opened by hand | OMP TUI opened by companyos chat |
| Command | companyos connect <client> | companyos connect omp | companyos chat |
| Identity | Host principal commissioned by the Company Passport; credential in HSMII_HOME | Your CLI session (companyos login), bound to one company | A run admitted by the Company OS host |
| Tools | Company OS MCP catalog, limited by the host principal's scopes | 7 read tools | Run-grant-limited MCP profile plus a native action guard |
| Mutations | Allowed per tool; each needs confirm=true by default; the host still enforces policy and approvals | None | Each tool call is authorized by the host before it runs and settled after |
| Receipts | Ordinary ledger records for calls the host accepts | None; not an accountable run | Host authorization and settlement receipts, plus the run execution ledger |
What connecting gives an agent:
- Governed Company OS tools: tasks, memory, the tool catalog workflow, run events, trace queries, approval and HITL endpoints, and the Gestion Velora customer-intake and email handoff.
tool-definitions.tsdefines 75 tools (my count); 47 are classed read-only.HSM_COMPANY_OS_MCP_TOOLS(comma-separated names, at most 40) narrows what a server registers. - Company context: the server publishes an operator contract at MCP initialization (identify, understand, govern, simulate, authorize, execute, verify, record). Read-only work stops after grounded understanding; mutations must leave independently verified task-trail evidence.
- Results in a
hsm.company_os.result.v1envelope with a Markdown fallback. A successful call is not treated as verification. - Approvals stay human (section 4).
What connecting does not give an agent: a run grant, per-action receipts, or any way to decide an approval. A manual OMP session from connect omp "remains read only and does not create an accountable run."
A governed run: companyos chat admits a terminal run through the host, then opens the installed OMP TUI in the current directory. Each governed MCP callback sends its signed run grant to the host's capability-actions/authorize route before the tool handler runs, and the host settles the exact action afterward. It checks scope, expiry, company, run status, grant issuance, revocation, and a matching unsettled action receipt before dispatch.
Known limit (docs/company-os/OMP_GOVERNED_DRIVER.md, evidence from 2026-10-03): the host action boundary was shown (an authorized and settled read; a native shell write denied before the effect, with a pending approval), but model-step receipts and turn receipt parity were not. The terminal client "must not advertise a complete governed receipt until a fresh installed run returns one from the host."
Runtimes Company OS can drive
The reverse direction: Company OS launching a vendor CLI. These adapter manifests exist in src/company_os/adapter_protocol.rs; the external runner contract is in docs/company-os/EXTERNAL_ADAPTER_LANE.md.
Vendor CLI adapters: vendor_cli:codex (Codex CLI), vendor_cli:claude_code (Claude Code CLI), vendor_cli:gemini (Gemini CLI), vendor_cli:opencode (OpenCode adapter), and vendor_cli:openclaw (OpenClaw 2.0 Agent CLI).
An external worker (webhook or bridged) lets any runner compute and report back through Company OS APIs. OMP is driven through companyos chat.
2. Quick start per client
Prerequisites: Node 20 or later. For OMP and Tern, a CLI session:
companyos login --company COMPANY_ID
companyos login --device # headless: open the shown Console URL, enter the codelogin runs an Authorization Code + PKCE request in the Console and creates a separate scoped CLI worker: a one-hour access credential and a rotating refresh credential, of which only the refresh envelope is stored.
Claude Code, Codex, Cursor, Windsurf, Gemini, generic
npx --yes @hsm/company-os-mcp-server connect codex
npx --yes @hsm/company-os-mcp-server connect claude
# or, with the CLI installed:
companyos connect claude|codex|cursor|windsurf|gemini|generic \
[--project-dir PATH] [--install-dir PATH] [--api-base URL] [--open] [--no-start]The README describes the npx form as available "after the package is published". connect:
- Runs the installer and Compose definition embedded in that exact npm release, pulls the matching versioned Company OS image, starts Postgres and
hsm_consoleincompanionmode, and verifies ledger health (/api/company/healthmust report Postgres ok). It fetches nothing mutable from the source repository. - Writes
companyos.integration.jsonin the project directory, then merges acompany-osentry into the client's MCP configuration, keeping other servers.
No provider key or model setting is requested; the host supplies its own model.
| Flag | Effect |
|---|---|
--no-start | Do not start the stack; only regenerate host configuration. Use when the stack already exists. |
--project-dir PATH | Directory to write configuration into. Default: current directory. Windsurf's file is global, so it is not affected. |
--api-base URL | Company OS API origin written to the config. Default http://127.0.0.1:3847. |
--install-dir PATH | Install and auth directory (becomes HSMII_HOME in the generated config). |
--installer PATH | Use a specific installer script instead of the packaged one. |
--open | Open the optional Console afterward. By default the command stays in the terminal. --no-open wins over --open. |
COMPANY_OS_IMAGE remains an explicit operator override for prerelease or private-registry testing.
| Client | File written | Next step printed |
|---|---|---|
claude | <project>/.mcp.json (entry has "type": "stdio") | Reload Claude Code in this project |
codex | <project>/.codex/config.toml, between # BEGIN COMPANY OS MANAGED and # END COMPANY OS MANAGED | Reload Codex in this project |
cursor | <project>/.cursor/mcp.json | Reload Cursor (Settings, MCP shows company-os) |
gemini | <project>/.gemini/settings.json | Restart Gemini CLI in this project |
windsurf | ~/.codeium/windsurf/mcp_config.json | Reload Windsurf (Cascade, MCP servers shows company-os) |
generic | Nothing; prints the mcpServers entry | Paste it into your MCP host's configuration |
Every entry is a stdio server running npx --yes --package @hsm/company-os-mcp-server@<version> company-os-mcp-server, with HSM_COMPANY_API_BASE (and HSMII_HOME when set) in env. After reload, ask the client to start the Company Passport. Re-running connect reuses an existing companyos.integration.json; flags override its values.
OMP
companyos login --company COMPANY_ID
companyos connect omp [--agent-dir PATH]
companyos mcp doctor --client ompconnect omp verifies the selected company through the host, starts the CLI-bound MCP server for a live company_os_health and company_os_get_company call, refreshes ~/.omp/agent/mcp.json (or --agent-dir PATH, or PI_CODING_AGENT_DIR), and runs omp plugin doctor. A failed host, CLI, or MCP probe leaves the profile untouched; a doctor failure reports an error after the profile is written.
The profile runs companyos mcp serve --stdio and holds no bearer, principal token, or refresh token. The server refreshes the CLI session on each call and refuses further calls if the session expires, is revoked, or changes company. Its 7 tools (src/cli-mcp-scope.ts): company_os_health, company_os_get_company, company_os_list_tasks, company_os_get_task, company_os_list_receipts, company_os_show_receipt, company_os_verify_receipt. Rerun companyos mcp connect omp to refresh an older profile.
For governed OMP work use companyos chat, not this profile:
companyos chat # admitted run, opens the OMP TUI here
companyos chat --prompt "TEXT" # one noninteractive turn
companyos chat --start "TEXT" # TUI opens with TEXT as the first message
companyos chat --thread-id UUID # resume a host threadOn another machine, log in remotely: ./company-os login --console-url https://<company-os-host> --device. That login needs the company_os:tools scope and a non-loopback HTTPS endpoint.
companyos connect or companyos mcp connect
Same code path. companyos mcp connect CLIENT re-parses its arguments as companyos connect CLIENT ..., and its help says "Other clients use the existing companyos connect path." Both accept omp, codex, claude, cursor, windsurf, gemini, generic; mcp connect always prints JSON.
Source states no preference. Suggested convention: companyos connect in setup instructions (the README leads with it), companyos mcp ... for status, doctor, and tools afterward. The Tern palette runs mcp connect.
--agent-dir is OMP only. The other flags apply to the non-OMP clients, and connect omp rejects boolean options.
3. First use: the Company Passport
On first use, the MCP tools run the durable Company Passport flow. The operating contract tells the agent to call company_os_list_companies first and to offer the Passport only if no commissioned company exists. In order:
| Step | Tool | Purpose |
|---|---|---|
| 1 | company_passport_start | Start a durable session before a company exists |
| 2 | company_passport_answer | Save the reviewed session, with optimistic versioning |
| 3 | company_passport_prepare | Store the server-normalized draft for human review. It "does not commission a company or mint authority." |
| 4 | company_passport_answer | Record the human's explicit authority and change-set confirmation |
| 5 | company_passport_commission | Commission the exact stored, reviewed version. Needs confirm. |
Helpers: company_passport_get re-reads a session and version; company_passport_industry_packs lists the industry packs.
"Authority and change-set confirmations must reflect explicit human answers, never model inference." The agent must never request, repeat, or display credential material.
What commissioning creates
- A distinct host agent:
claude-code-host(adapterclaude-code) orcodex-host(adaptercodex), roleworker. - Eight delegated scopes, each expiring in 720 hours (30 days):
company_os:tasks,company_os:memory,company_os:customers,company_os:connectors,company_os:tools,company_os:workspace_files,company_os:validation,work_packages:workflow. - A host principal credential, also 720 hours, and an owner credential whose expiry the server sets.
company_passport_commission takes host of claude or codex only. Source does not describe commissioning for Cursor, Windsurf, Gemini CLI, or generic clients.
Credentials and where they live
- Commissioning writes
company-os-owner.binding.jsonandcompany-os-host.binding.jsonunderHSMII_HOME(default~/.hsm-ii), each private with mode 0600. Credentials are never written to.mcp.json,.codex/config.toml, command arguments, or MCP results. - The server refuses a credential file that is not a regular non-symlink file, has any group or other permission bit, or belongs to another user.
- Auth home lookup when reading:
HSM_COMPANY_OS_AUTH_HOME, thenHSMII_HOME, thenCOMPANY_OS_INSTALL_DIR, then~/.hsm-ii. - The CLI login session is separate. On macOS its refresh envelope is a 0600 file under
~/Library/Application Support/Company OS/; Linux and Windows use the OS credential store. It does not create~/.hsm-ii.companyos logoutrevokes every credential for that CLI worker, then deletes the envelope.
4. Approval model for agents
HSM_COMPANY_MCP_APPROVAL_MODE | Behavior |
|---|---|
| unset | strict (default). Mutating and approval-sensitive tools return approval_required unless called with confirm=true. |
permissive | Skips the check. README: only for trusted local automation. |
bound | In the client code, not the README. A mutation must cite an approval_id that is approved, decided by someone other than its requester, unconsumed, and unexpired. The binding is consumed whether or not it verifies. |
confirm=true is an intent check, not authority. src/client.ts says it is "asserted by whoever calls the tool, which may be a model, so strict is an intent check, not an authority boundary." Authority is enforced by Company OS: it refuses approval decisions for model-driven principals, and external effects need a consumed human grant. The README states for the remote bridge: "A model-supplied confirm=true is not human approval." The operating contract adds: "Never treat the assistant's own proposal as approval." A CLI --confirm is not approval either ("A CLI confirmation never grants authority").
Other rules:
company_os_call_tooldefaults todry_run=true; the flow iscompany_os_discover_tools,company_os_describe_tool,company_os_call_tool. A real call needsconfirm=truein strict mode.- Direct mutations without dry-run support need a bounded change presented and current state read first (operating contract, step 4).
- The phone-call handoff tools need confirmation and reject raw transcript and recording parameters.
company_os_propose_email_replyleaves the replypending_approval; Company OS does not send it.
Who decides. A person, in the Console (Approvals inbox, /workspace/approvals) or at a terminal:
companyos approvals --status pending
companyos approval show APPROVAL_ID
companyos approval approve|reject APPROVAL_ID [--reason TEXT] --confirm
companyos approval decide APPROVAL_ID --decision approved|rejected --confirmThe decision refreshes the authoritative inbox and binds your choice to the server-stored presentation, subject, and request digests. Afterward: companyos receipt list|show|verify ID, companyos verify task|run ID.
5. Check a connection
companyos mcp checks the selected CLI company's host, connector projection, and a read-only stdio MCP handshake. It needs a CLI session. --help on any command does not contact the host.
companyos mcp status # company, host, connectors, MCP handshake
companyos mcp doctor # each check, PASS or FAIL; nonzero exit on failure
companyos mcp doctor --client omp # adds OMP version, plugin doctor, profile checks
companyos mcp tools --search task # tools the CLI-bound session actually exposes
companyos mcp tools --quiet # names only (also --json, --table)
companyos mcp connectors list # host-owned connectors and OAuth state
companyos mcp connectors show|resources|prompts ID
companyos mcp serve --stdio # the read-only server the OMP profile runs--company-id UUIDselects the company bound to the CLI grant;--jsonprints the typed report.doctorcheck ids:omp_version,omp_plugin_doctor,omp_profile(OMP only), thencli_grant,company,host,connectors,mcp_handshake. The OMP checks run even if the host is down; the rest need a valid CLI session.mcp statusandmcp toolsinspect the CLI-bound read-only server (the OMP profile), not the companion server that Claude Code or Codex launch withnpx. Check those in the client's own MCP view.companyos mcp connectors enable|disable ID --confirm(optional--idempotency-key KEY) asks the host, which rechecks authority and returns a receipt or a typed refusal. OAuth and reconnect are not in this CLI.- Also:
companyos doctor(client preflight plus server checks). - After an OMP upgrade, run the offline smoke
node services/company-os-mcp-server/scripts/omp-compatibility-smoke.mjs(afternpm --prefix services/company-os-mcp-server run build). It uses a temporary profile and a dummy model credential and does not verify the live host.
6. Tern terminal plugin
integrations/tern-companyos makes governed AgentChat the main entry point and adds a cockpit, palette actions, and read-only tools for Tern's assistant, Carly.
tern plugin link ./integrations/tern-companyos # from the repository root
tern plugin list
tern plugin unlink companyosTern reloads linked plugins when files change. Every action runs the Company OS command resolved in this order: HSM_COMPANY_OS_CLI; the checkout's scripts/company-os through /bin/bash (HSM_COMPANY_OS_REPO or the checkout the plugin is linked from); $HOME/.local/bin/companyos. Several actions run the built operator CLI (services/company-os-mcp-server/dist/company-os-cli.js); build it once with npm --prefix services/company-os-mcp-server run build.
Palette actions (search for Company OS). Each opens a new tab and leaves a shell open so output stays visible.
| Action | Runs |
|---|---|
| Company OS AgentChat: Start governed chat | companyos chat |
| Connect Claude Code to Company OS | companyos mcp connect claude |
| Connect Codex to Company OS | companyos mcp connect codex |
| Connect OMP to Company OS (read-only) | companyos mcp connect omp |
| Check OMP connection | companyos mcp doctor --client omp |
| Log this computer in to Company OS | companyos login |
| Start Company OS | companyos up (starts or reuses local services, opens the Console) |
| Open Company OS approvals waiting on you | approvals --status pending --table |
| Open Company OS tasks, recent agent runs, receipts | task list --table (25), ps --table (20), receipt list --table |
| Open Company OS usage and cost; Run Company OS doctor | cost; doctor |
| Check Company OS readiness | companyos status |
| Open Company OS Console | /workspace/start on 127.0.0.1, port HSM_COMPANY_CONSOLE_PORT or 3050; does not start services |
| Open Company OS cockpit | Native block: workspace health and Beads queue. Enter on a bead runs companyos chat --start "Work on Beads issue ..." |
The OMP profile stays read-only. Use Start governed chat when a turn needs the host-admitted run and its receipts. Approvals are listed by the palette but decided in the Console or with companyos approval approve|reject ID --confirm. Optional key binding: "cmd+shift+g": "plugin.companyos.agentchat" under keybinds in Tern's settings.json (pick a free chord).
Carly. Every Carly request carries one context line (Company OS installed, last known status, read the guide first). The plugin exports 16 tools under plugins.companyos, the Tern maximum: 15 read-only tools and open.
guide(topic?): the plugin guide,GUIDE.md.status(): API host (127.0.0.1:3847/api/company/health) and Console (/api/agent-chat-runtime), checked separately.tasks,task,approvals,runs,run(viewswhat,why,timeline,inspect,events),receipts,verify(task, run, or receipt).memory(memory search),usage(cost,usage,stats,operator-status),beads(br ready|blocked|stats|show),tools(mcp tools),connectors(mcp connectors list),doctor.open(target, page?): opens a palette view or Console page for the person.
Each live read runs one command and returns {ok, command, output, truncated, stderr, hint}, with output cut at about 9 KB. Arguments go to argv, never a shell, and a value starting with - is refused, so Carly cannot add --confirm. Carly never approves, sends, creates, or runs anything; for a change it opens the matching view and a person acts. The plugin does not read or store Company OS credentials.
7. Remote MCP bridge (Grok and other remote clients)
The package includes a stateful Streamable HTTP MCP server for a remote MCP connector such as xAI/Grok. It reuses the stdio handlers and operator contract; it is not a second agent runtime or policy engine. Start it after the API is up:
cd services/company-os-mcp-server
npm run build
HSM_COMPANY_API_BASE=https://company-os.internal \
HSM_COMPANY_ID=<company-uuid> \
HSM_COMPANY_PRINCIPAL_TOKEN=<server-held-principal-token> \
HSM_COMPANY_PRINCIPAL_COMPANY_ID=<company-uuid> \
HSM_COMPANY_OS_REMOTE_MCP_TOKEN=<strong-random-grok-token> \
npm run start:httpcompany-os-mcp-http is the installed bin for the same server.
| Setting | Default and rule |
|---|---|
| Endpoint | http://127.0.0.1:3850/mcp. Change with HSM_COMPANY_OS_REMOTE_MCP_HOST, ..._PORT, ..._PATH. |
| Inbound auth | HSM_COMPANY_OS_REMOTE_MCP_TOKEN, required. Accepted only as a bearer header, never forwarded to Company OS. A bad token gets HTTP 401 with WWW-Authenticate: Bearer. |
| Server-held credentials | HSM_COMPANY_ID, HSM_COMPANY_PRINCIPAL_TOKEN, and a matching HSM_COMPANY_PRINCIPAL_COMPANY_ID are required even for read-only. They can load from the private binding files. |
| Health | GET /healthz, unauthenticated. |
| Company binding | Each session is bound to the configured company; a request naming another company_id is refused. |
| Non-loopback bind | Also set HSM_COMPANY_OS_REMOTE_MCP_ALLOWED_HOSTS, or startup fails. ..._ALLOWED_ORIGINS is optional. |
| Limits | ..._MAX_BODY_BYTES (1048576); ..._MAX_REQUESTS_PER_MINUTE (120 per source); session cap and idle timeout. |
| Approval mode | Always bound. Every mutation must cite an approval_id a human already decided; the model's confirm=true is not accepted. |
Put the bridge behind an HTTPS reverse proxy before giving the URL to Grok.
Default allowlist, read-only (16 tools, from src/remote-mcp-config.ts):
company_os_health, company_os_list_companies, company_os_get_company,
company_os_get_document_profile, company_os_dashboard, company_os_list_tasks,
company_os_get_task, company_os_list_agent_runs, company_os_run_story,
company_os_list_run_surfaces, company_os_trace_query, company_os_search_memory,
company_os_list_approvals, company_os_show_approval, company_os_verify_task,
company_os_verify_runOverride with HSM_COMPANY_OS_REMOTE_MCP_TOOLS (comma-separated). A tool outside the read-only set also needs HSM_COMPANY_OS_REMOTE_MCP_ALLOW_MUTATIONS=1, or startup fails. Company OS confirmation, governance, approval, execution, verification, and receipt checks still apply.
For the xAI Remote MCP connector, give it the HTTPS server_url, a list of allowed_tools, and the same token as HSM_COMPANY_OS_REMOTE_MCP_TOKEN in authorization (conceptual configuration in the package README).
Set HSM_COMPANY_OS_CONSOLE_ORIGIN (absolute HTTPS origin) to add Console links to results; links are navigation only and grant no authority.
8. Troubleshooting
Messages are quoted from the source. Run companyos mcp doctor first; its Next: line names the action.
| Symptom | Fix |
|---|---|
connect host must be one of claude, codex, cursor, windsurf, gemini, generic | Use one of those, or omp (companyos connect omp). |
Company OS companion bootstrap failed: ... | The embedded installer failed; the tail of its stderr is included. If the stack already exists, rerun with --no-start. |
Company OS health verification failed: HTTP <n> or ... did not confirm Postgres | The stack started but the ledger is not healthy. Check GET /api/company/health on the API base, then rerun connect. |
invalid Claude MCP config <path> or invalid mcpServers object in <path> | The existing client config is invalid JSON or mcpServers is not an object. Fix the file; connect will not overwrite it. |
unsupported Company OS integration manifest: <path> | companyos.integration.json does not match schema hsm.company_os.integration.v1. Fix or remove it, then rerun. |
Client does not show company-os | Reload or restart the client as connect printed. Windsurf's file is global. |
| Agent says the Passport must start | No commissioned company exists. See section 3. |
Company OS credential file must have mode 0600: <path> | chmod 600 the file; it must be a regular file you own. |
Tool returns approval_required | Expected in strict mode. A person approves, then the agent retries with confirm=true. In bound mode, pass an approval_id a human already decided. |
| Agent wants to approve its own request | Not possible. Decide in the Console or with companyos approval approve|reject ID --confirm. |
Company OS host is unreachable. Start or reconnect the host, then retry companyos connect omp. | Start the host (companyos up), then retry. |
An authorized Company OS CLI session is required for OMP connection | companyos login --company COMPANY_ID. |
Doctor cli_grant fails | "Resolve the CLI session error, then run companyos mcp doctor." Log in again; a session can expire or be revoked. |
Doctor company fails | "Reauthorize the selected company with companyos login --company ID." |
Doctor host fails | "Start or reconnect the Company OS host, then retry companyos mcp doctor." |
OMP company-os profile is missing or stale at <path>; run companyos mcp connect omp | Rerun companyos mcp connect omp. |
OMP version check failed: ... or OMP plugin doctor failed: ... | Fix the OMP installation (is omp on PATH?), then companyos mcp doctor --client omp. |
Company OS CLI session changed; restart OMP to bind the new session | Login or company changed under a running OMP. Restart OMP. |
MCP tool outside the CLI read-only scope: <names> | Rerun companyos mcp connect omp to refresh the profile. |
| Governed chat refuses to start | "Governed terminal chat requires a loopback Company OS CLI session. Run companyos login against the local Company OS host." |
Company OS remote MCP configuration is missing <NAME> | Set the named variable (HSM_COMPANY_OS_REMOTE_MCP_TOKEN, HSM_COMPANY_ID, HSM_COMPANY_PRINCIPAL_TOKEN, or HSM_COMPANY_PRINCIPAL_COMPANY_ID). |
Company OS remote MCP non-loopback binding requires HSM_COMPANY_OS_REMOTE_MCP_ALLOWED_HOSTS | Set the allowlist, or bind to loopback behind a proxy. |
Remote MCP mutation tools require HSM_COMPANY_OS_REMOTE_MCP_ALLOW_MUTATIONS=1: <names> | Remove those tools from the allowlist, or set the variable deliberately. |
Tern: workspace is not ready | Run Start Company OS, then Check Company OS readiness. |
Tern: operator CLI is not built | npm --prefix services/company-os-mcp-server run build. |
| Tern: Node not found | Set HSM_COMPANY_OS_NODE. |
| Tern: login or grant errors | Run Log this computer in to Company OS. |
Tern: tools fail with fetch failed while the API answers | The Console is down or hung. Restart it, then Start Company OS. |
| Anything else | companyos doctor, or Run Company OS doctor in Tern. |