---
title: "Coding agents"
description: "The adopt command, the files and the quirks for Claude Code, Cursor, Codex, OpenCode and Grok Bot, so every activated pack reaches your agent."
canonical: https://harnesscontextprotocol.io/docs/hosts/coding-agents
---

# Coding agents

> The adopt command, the files and the quirks for Claude Code, Cursor, Codex, OpenCode and Grok Bot, so every activated pack reaches your agent.

A coding agent with a terminal adopts HCP in one step: `hcpx adopt <host>
--write` puts the protocol Skill, the `hcpx` binary and one tool named `hcp`
where that host looks for them. The agent then reaches every activated pack
through that tool or its shell, so new packs never touch the host's config. The
sections below give each host's command and files, and what sets it apart.

## What every host shares

Activate packs, then run your host's adopt target. Add `--json` and leave out
`--write` to preview the files first.

```bash
hcpx activate transit ledger
hcpx adopt <host> --write
```

Every target writes `.hcp/plugin.json`, the
[agent plugin](/docs/hosts#the-agent-plugin) manifest the other files come
from, and `.hcp/surface.json`, the catalog, which adds no tools. Claude Code,
Cursor, Codex and Grok Bot also get one MCP server, `hcp`, that wraps the same
bash (`hcpx mcp`) and starts the CLI by
[the name that works on your machine](/docs/quickstart#one-binary-two-names);
OpenCode gets one plugin tool instead. The tool and the shell reach the same
runtime with the same Policy, Binding and sandbox.

The protocol Skill teaches lint, install and exec, and points the agent at each
pack's own teaching with `hcpx skill <id>`. A session looks like this:

```bash
hcpx list --json
hcpx skill ledger --json
hcpx exec transit plan --json -- from=Central to=Harbour
hcpx exec ledger transfer --json -- amount=2.80 payee=demo-transit
# { "ok": false, "error": "confirm required" }
hcpx exec ledger transfer --json -- amount=2.80 payee=demo-transit confirm=true
```

The runtime enforces Policy before the adapter runs, and the Skill tells the
agent to ask you and retry with `confirm=true` only after you agree. The
runtime's hub mints credentials at exec time, so no token appears in the
conversation, the Skill or the MCP config. Claude Code and Codex also set
`HCP_AGENT=1` in the agent's shell, so the human-only access commands refuse
there ([Access](/docs/concepts/access#keeping-agents-out-of-access)).

## Claude Code

```bash
hcpx adopt claude --write
```

| File | What Claude Code does with it |
|------|-------------------------------|
| `.mcp.json` | Registers one MCP server, `hcp`, with one tool named `hcp`, and asks you to approve it on the next start. It carries `HCP_HOME` only if you set it, so the file works for every teammate who clones the repository |
| `.claude/skills/hcp/SKILL.md` | The protocol Skill: how to list, read, and exec packs, and when a write needs confirmation |
| `.claude/settings.json` | Sets `HCP_AGENT=1` for Claude's shell and adds deny rules for the access commands (`approve`, `reject`, `mode`, `allow`, `ask`, `deny`, `rules rm`, under both `hcp` and `hcpx`) and for edits to the HCP store. Existing settings are kept |

To register the server by hand instead of through `.mcp.json`:

```bash
claude mcp add hcp -- hcpx mcp
```

## Cursor

Cursor discovers the Skill in `.cursor/skills/hcp/` with no HCP-specific code.

```bash
hcpx adopt cursor --write
```

| Path | Content |
|------|---------|
| `.cursor/hcp.json` | Session pointer: `{ enabled, home, activated, sandbox, cli }` |
| `.cursor/skills/hcp/SKILL.md` | Protocol Skill: lint, install, exec |
| `.cursor/mcp.json` | One server, `hcp`: `command` is the CLI's name on this machine, `args: ["mcp"]` |
| `.cursor/rules/hcp.mdc` | Always-on: prefer `hcpx exec`, never hand-register tools |

```json title=".cursor/hcp.json"
{
  "hcp": {
    "enabled": true,
    "home": "/home/you/.hcp",
    "activated": ["transit", "ledger"],
    "sandbox": "sandbox",
    "cli": "hcpx"
  }
}
```

## Codex

```bash
hcpx adopt codex --write
```

This writes the protocol Skill to `.hcp/skills/hcp/SKILL.md`, adds one HCP
section to `AGENTS.md` (once, however often you run it) and prints the block for
your user config. The CLI never edits files outside the repository, so you add
the block yourself:

```toml title="~/.codex/config.toml"
[mcp_servers.hcp]
command = "hcpx"
args = ["mcp"]

[mcp_servers.hcp.env]
HCP_HOME = "/home/you/.hcp"

# Mark shell commands Codex runs, so hcpx refuses the human-only access commands.
[shell_environment_policy.set]
HCP_AGENT = "1"
```

`HCP_HOME` is your store. Because the runtime checks `confirm` before the adapter
runs, the gate holds in every Codex approval mode.

## OpenCode

OpenCode loads HCP as one plugin tool named `hcp` that runs the CLI without a
shell, so adding a pack never adds a tool file.

```bash
hcpx adopt opencode --write
```

| Path | Content |
|------|---------|
| `opencode.json` → `hcp` | `{ enabled, home, activated, sandbox, cli }` |
| `opencode.json` → `plugin` | `@harnesscontextprotocol/plugin-opencode` |
| `.opencode/skills/hcp/SKILL.md` | Protocol Skill |

```json title="opencode.json"
{
  "hcp": {
    "enabled": true,
    "home": "~/.hcp",
    "activated": ["transit", "ledger"],
    "sandbox": "sandbox",
    "cli": "hcpx"
  },
  "plugin": ["@harnesscontextprotocol/plugin-opencode"]
}
```

The plugin is a host shim over `wrapHcpArgv`. Its one tool takes `args` or
`argv` as you would type them after the binary (`exec transit plan -- from=A
to=B`) and starts the command in `hcp.cli` (`HCP_CLI` overrides it) directly,
never through a shell or as a nested `mcp`. It writes no
`.opencode/tools/<pack>__<verb>.ts` files.

To drive an OpenCode session from your own code, the [AI SDK](/docs/hosts/ai-sdk)
host's `HarnessAgent` takes `runtime: 'opencode'`. It maps grant-filtered
commands to tools in process, separate from this plugin:

```ts
import { Hcp, HarnessAgent } from '@harnesscontextprotocol/sdk'

const hcp = await Hcp.create({ packDirs, sandbox: true })
await hcp.activate(['transit', 'ledger'])

const agent = await HarnessAgent.create({
  hcp,
  runtime: 'opencode',
  cwd: process.cwd(),
  adoptOpenCode: true,
})
```

## Grok Bot

Grok Bot has a terminal on a persistent Linux computer and Grok Build has a bash
tool, so the agent runs `hcpx` like any other CLI, with MCP as the optional
fallback for hosts that only attach connectors.

```text
Grok Bot (cloud computer) / Grok Build (local TUI)
   │  terminal / bash   ← primary
   │  MCP connector     ← optional, one server named hcp
   ▼
hcpx search | install | skill | exec
   ▼
runtime (Policy · Binding · sandbox)
```

```bash
hcpx adopt grok --write      # alias: grokbot
```

| Path | Role |
|------|------|
| `.grok/hcp.json` | Session pointer (`home`, `activated`, `cli`) |
| `.grok/config.toml` | `[mcp_servers.hcp]` + allow `Bash(hcpx *)`, `Bash(hcp *)`, `Bash(bun *hcp*)`, `MCPTool(hcp__*)` (marked `BEGIN HCP` / `END HCP`) |
| `.grok/rules/hcp.md` | Prefer the terminal; MCP is one tool |
| `.grok/skills/hcp/SKILL.md` | How to drive the CLI from bash |
| `.mcp.json` | Same stdio server wrapping the CLI |

A project `.grok/config.toml` loads only MCP, plugins and permission, so other
Grok settings stay in the user config. Re-running adopt rewrites only the marked
block, which is how you change the MCP env or home.

Install the CLI on the Bot's computer, its VM, and put it on `PATH` like any
other CLI the Bot uses. The terminal and the MCP server both run there, so a Bot
working on its cloud computer never finds the CLI on your laptop. A first
session there runs:

```bash
hcpx doctor --json
hcpx search transit --json
hcpx install npm:@harnesscontextprotocol/pack-transit --json
hcpx activate transit --json
hcpx exec transit plan --json -- from=A to=B
```

Prefer bash, which keeps Policy in the runtime and the tool list the same size
as the catalog changes. Use MCP when the host will not let bash run the CLI (a
team connector allowlist, a headless attach), and point it at:

```toml
[mcp_servers.hcp]
command = "hcpx"
args = ["mcp"]
enabled = true
startup_timeout_sec = 30
env = { HCP_HOME = "~/.hcp" }
```

`tools/list` is still `[hcp]` ([MCP export](/docs/hosts/mcp)). Grok Bot also
follows Cursor MCP policy, with `.mcp.json` as the shared fragment.

## Adding packs later and what to avoid

```bash
hcpx install ./packs/weather --json
hcpx activate weather --json
```

The agent sees the new pack on its next call, through the `hcp` tool or `hcpx`
in its shell, while the MCP config, the tool list and the permission prompts
stay the same size however many packs you activate. A pack's teaching lives in
its `HARNESS.md`, which agents read with `hcpx skill <id>`, so re-run
`hcpx adopt <host> --write` only to refresh the protocol Skill and the session
or MCP pointer.

Avoid these in every host:

- Registering an MCP server or tool per pack or command. One `hcp` server
  reaches all of them.
- Treating MCP server install as pack install
  ([why](/docs/hosts#why-mcp-is-not-the-install-path)).
- Putting a token in the MCP config, `.cursor/hcp.json`, `.grok/config.toml`,
  `CLAUDE.md`, a rule, a Skill or pack files. Binding mints it.
- Exporting tokens into the agent's environment for packs to use. Binding never
  falls back to the environment.
- Copying pack setup steps into `AGENTS.md` or generating a Skill file per pack.
  `hcpx skill <id>` is the source.
- Pre-approving writes with `confirm=true` in a standing instruction, which
  defeats a gate that exists so you agree to each write.

## Sitemap

- [Documentation](https://harnesscontextprotocol.io/docs)
- [Packs](https://harnesscontextprotocol.io/packs)
- [Glossary](https://harnesscontextprotocol.io/docs/reference/glossary)
- [llms.txt](https://harnesscontextprotocol.io/llms.txt)
- [llms-full.txt](https://harnesscontextprotocol.io/llms-full.txt)
- [OpenAPI](https://harnesscontextprotocol.io/openapi.json)
- [MCP](https://harnesscontextprotocol.io/mcp)
