CLI
Look up any hcpx command with its arguments, JSON output and exit codes, plus the access commands, the store layout and environment variables.
On this page
- Conventions
- Commands
- hcpx doctor
- hcpx availability
- hcpx list
- hcpx lint
- hcpx check
- hcpx eval
- hcpx install
- hcpx uninstall
- hcpx activate
- hcpx deactivate
- hcpx connect
- hcpx commands
- hcpx exec
- hcpx search
- hcpx catalog
- hcpx init
- hcpx wrap
- hcpx share
- hcpx skill
- hcpx generate
- hcpx mcp
- hcpx adopt agent|claude|codex|cursor|opencode|mcp|grok
- Access commands
- hcpx help
- Store
- Environment
hcpx is the reference CLI and the bootstrap Invoker for the reference
runtime, described by its own pack, hcp-cli. With --json every command
prints a single JSON object, and agents should start with hcpx commands. The
binary also answers to hcp
(One binary, two names says when to use
which).
bunx @harnesscontextprotocol/cli help
# or, from a checkout of the hcp repository
bun packages/cli/src/hcp.ts helpThe package is a private preview on GitHub Packages, and Install the CLI shows how to reach it.
Conventions#
- Exit
0on success,1on any failure.hcpx checkalso exits2when it finds warnings only. - Failures print
{ "ok": false, "error": "…" }. Most also carry a stablecode, ahint, andnext, the commands to run instead. See Error codes. - Without
--json, objects are pretty-printed and strings (Skill text) print raw. - The store is
$HCP_HOME(default~/.hcp). See Store. - The bootstrap pack
hcp-cliis installed the first time a command opens the store.
Commands#
hcpx doctor#
Reports runtime health.
{ "ok": true, "cli": "hcpx", "protocol": "hcp", "version": 1, "home": "~/.hcp",
"sandbox_default": true, "installed_count": 3, "activated": ["hcp-cli", "transit"],
"connected": [], "bootstrap": "hcp-cli" }hcpx availability [pack_id]#
Prints the four availability flags for every installed pack, or for one. The
alias is avail.
{ "ok": true, "home": "~/.hcp", "sandbox_default": true,
"packs": [{ "pack_id": "transit", "status": ["activated", "executable"],
"installed": true, "activated": true, "connected": true,
"verbs": [{ "verb_key": "plan", "operation": "read", "land": "personal", "executable": true }],
"capabilities": ["verb.exec.read"] }],
"activated": ["hcp-cli", "transit"], "installed": ["hcp-cli", "transit"] }An unknown pack_id yields one row with status: ["unavailable"].
hcpx list#
Lists installed packs with their adapter kind, command count, activation and directory.
hcpx lint <pack_dir>#
Loads the directory and runs the pack lints, exiting 1 on any issue.
{ "ok": false, "pack_id": "ledger", "issues": [
{ "kind": "missing_verb", "key": "transfer", "message": "verb \"transfer\" missing from policy.json" } ] }Errors lists the issue kinds.
hcpx check <pack_dir> [--probe] [--agent|--json] [--init-evals] [--strict] [--no-eval] [--timeout ms]#
Grades structure, the quality rules, live CLI probes (--probe) and the cases
in hcp.eval.json when it exists (--no-eval skips them). --agent prints a
prioritised fix list for coding agents and --json the full report, while
--init-evals writes a starter eval file (never over an existing one) and
exits. --timeout limits each probe and eval case (default 10000 ms). It exits
0 when clean, 2 on warnings only and 1 on errors, and --strict makes
warnings exit 1. See Check and evaluate.
{ "ok": false, "pack_id": "gh", "score": 8, "grade": "F",
"summary": { "errors": 7, "warnings": 2, "info": 0 },
"findings": [ { "id": "R014", "severity": "error", "where": { "file": "surface.json", "pointer": "/verbs/list/cli" },
"message": "\"gh list\" is not a command of this CLI …", "fix": "Point \"list\".cli at a subcommand that exists …" } ] }hcpx eval <pack_dir> [--json] [--timeout ms]#
Runs the cases in hcp.eval.json through the reference runtime and prints pass
or fail per case with latency and approximate output tokens, then p50 and p95
for the run. Exit 1 when any case fails, the file is missing, or the pack
fails lint (then no case runs). --json returns { ok, pack_id, evals }, with
evals as in hcpx check --json.
hcpx install <pack_dir|github:…|npm:…>#
Lints, then copies the pack directory into $HCP_HOME/packs/<pack_id>/ and its
HARNESS.md to $HCP_HOME/skills/<pack_id>/SKILL.md. Any lint issue fails the
install, and a path without surface.json fails with code: "no_pack".
From GitHub, hcpx install github:owner/repo[@ref][//path] or a github.com
URL clones the repository, falls back to its tarball, and sends GITHUB_TOKEN
when set. From npm, hcpx install npm:@scope/name runs npm pack and installs
the directory named by "hcp": { "pack": "." } in the package's package.json,
or the package root; hcpx install npm:./path/to/pack installs a local package.
When a GitHub or npm source cannot be fetched and the catalog lists a gold
template for it, the CLI installs the template and says so in note.
{ "ok": true, "installed": "transit", "dest": "~/.hcp/packs/transit",
"verbs": ["find", "plan", "show", "status", "follow"],
"next": ["hcp activate transit", "hcp availability transit"] }hcpx uninstall <pack_id>#
Removes the pack directory, and refuses to remove hcp-cli.
hcpx activate <pack_id> [pack_id…]#
Adds packs to state.activated and copies each HARNESS.md to
$HCP_HOME/skills/<pack_id>/SKILL.md.
{ "ok": true, "activated": ["hcp-cli", "transit"], "skills": ["~/.hcp/skills/transit/SKILL.md"] }An unknown id fails with code: "not_installed", a "did you mean" when an
installed pack has a similar id, and next commands to search or install.
hcpx deactivate <pack_id> [pack_id…]#
Removes packs from activated and connected.
hcpx connect <pack_id>#
Runs the runtime's connect step for an activated pack and needs the
pack.connect grant. An inactive pack fails with not activated: <id>.
{ "ok": true, "connected": "ledger", "all": ["ledger"] }hcpx commands [pack_id]#
Lists every command of the activated packs, or of one pack, with its
description, read or write, whether it needs confirmation, what the current
access settings decide (access: allow, ask or deny), its arguments with
examples, and a line ready to run.
{ "ok": true, "packs": [ { "pack_id": "transit", "about": "Plan public-transport journeys…",
"commands": [ { "command": "plan", "description": "Route options between two places with duration, changes, and fare, fastest first.",
"operation": "read", "access": "allow",
"args": [ { "name": "from", "required": true, "description": "Origin place name or id from find", "example": "Central" } ],
"run": "hcp exec transit plan --json -- from=Central to=Harbour" } ] } ] }hcpx exec <pack_id> <verb_key> [--json] [-- k=v …] [--args '{…}']#
Runs a command through the full pipeline. Arguments after -- become args
(from=Central to=Harbour confirm=true), and --args takes a JSON object for
typed values or text with spaces.
hcpx exec transit plan --json -- from=Central to=Harbour
hcpx exec transit plan --json --args '{"from":"Central","to":"Harbour"}'
hcpx exec ledger transfer --json -- amount=2.80 payee=demo-transit confirm=trueThe runtime checks arguments first, so an unknown name or a missing required
argument fails with the valid names and a "did you mean". The command returns
the result envelope without
duplicating the raw output and exits 1 when ok is false. With no command,
hcpx exec <pack_id> returns that pack's command list.
hcpx search [query] [--class class]#
Searches the community catalog at
https://harnesscontextprotocol.io/api/v1/packs, or HCP_CATALOG_URL when set,
and caches the answer in $HCP_HOME/catalog.json for an hour. source is
remote, cache, or bundled: the snapshot shipped in the CLI, used when the
origin is unreachable (4 s timeout) and nothing is cached.
{ "ok": true, "source": "bundled", "count": 1, "packs": [{ "id": "transit", "class": "public-read" }] }hcpx catalog [pack_id]#
Lists catalog entries, or the entry for one pack_id.
hcpx init <id> [--class public-read|gated-write] [--template transit|ledger|echo] [--dir path]#
Writes a self-contained pack directory: the three files, a package.json
that depends on the CLI, and a demo bin/ for wrap templates. Gold --template
values keep their gold id. cli_bin names the CLI that starts it on this
machine (see One binary, two names).
{ "ok": true, "dir": "./weather", "pack_id": "weather", "template": "public-read",
"files": ["package.json", "surface.json", "policy.json", "HARNESS.md", "bin/cli.mjs", "README.md"],
"cli_bin": "hcpx", "next": ["hcpx check ./weather --probe --agent", "hcpx install ./weather --json", "hcpx activate weather --json"] }hcpx wrap <bin> [--id pack_id] [--class public-read|gated-write] [--dir path]#
Scaffolds a pack whose wrap.bin is an existing CLI on PATH, in packs/<id>
unless --dir says otherwise. It reads <bin> --help as an agent would (no
TTY, no colour, stdin closed) and drafts one command per usage line it can
parse: the cli[] form, the arguments, a guessed Policy row with land: local,
and confirm: true plus a suggested preview for commands that sound risky
(delete, send, publish, pay, and similar) or take the CLI's own confirmation
flag. wrap.workspace.mode is project, so the CLI runs in the caller's
project; gated-write sets Binding local and public-read sets public.
hcpx wrap mycli --class gated-write --dir ./mycli-pack --jsonThe result lists the drafted commands, candidates (subcommand names seen
when no usage line parsed), json_support, warnings, and the next steps:
review the draft against <bin> <command> --help, check each Policy row, then
hcpx check <dir> --init-evals and hcpx check <dir> --probe --agent. A CLI
not on PATH fails with code: "bin_not_found".
hcpx share [pack_dir|github:owner/repo] [--path subdir]#
Lints a directory and prints a catalog row for
hcp-docs/content/catalog/packs.json; exit 1 when lint fails. A github:
reference reads the pack from the public repository (--path for a
subdirectory) and reports the same row and issues.
Share a pack covers the catalog and the PR.
hcpx skill <pack_id>#
Prints HARNESS.md for an activated pack. With --json: { ok, pack_id, skill }.
hcpx generate#
Produces host-neutral output from activated packs (system-prompt block, tool list, Skill copies, per-host configuration) without writing files.
hcpx mcp#
Starts a stdio MCP server whose tools/list returns one tool, named hcp.
tools/call takes args (string) or argv (string array) as CLI argv, never
through a shell, and runs it inside the server process with HCP_MCP=1 set.
Every CLI a pack starts inherits that variable, so the access commands refuse.
A call starts no new hcpx, and resources/list offers only catalog, help and
skills. MCP export shows the host side.
hcpx adopt agent|claude|codex|cursor|opencode|mcp|grok [--write]#
Generates the host-neutral output and writes host configuration into the
current directory, or previews it without --write. grokbot is an alias of
grok.
| Target | Writes |
|---|---|
claude | .claude/skills/hcp/SKILL.md, one hcp server in .mcp.json, and .claude/settings.json with HCP_AGENT=1 and deny rules for the access commands |
codex | The protocol Skill and an HCP section in AGENTS.md; prints the ~/.codex/config.toml block (the server and HCP_AGENT=1 for Codex's shell) and never edits files outside the repository |
cursor | .cursor/skills/hcp/SKILL.md, .cursor/mcp.json, .cursor/rules/hcp.mdc |
opencode | One plugin tool hcp in opencode.json |
grok | .grok/config.toml, rule, Skill |
agent, mcp | The generic plugin: .hcp/plugin.json, the Skill, and .mcp.json |
HCP_HOME goes into host config only when you set it explicitly, so committed
config works on every machine. A .hcp/no-adopt file opts a workspace out of
adopt, and Adopt in hosts covers each host.
Access commands#
The commands that change access refuse with
human_only inside an agent (HCP_AGENT=1, or through hcpx mcp).
| Command | Does |
|---|---|
hcpx access | Effective mode, rules, approval authority, where each comes from, and ignored project settings |
hcpx mode [manual|auto|run] [--pack id] [--project] | Show or set the mode, globally or for one pack |
hcpx allow|ask|deny <pack.command|pack.*|*> [--op read|write] [--when k=v]… [--max k=n]… [--note text] [--project] | Add a rule. --project writes .hcp/access.json and cannot add allow rules |
hcpx rules [rm <n>] [--project] | List rules with scope and index, or remove one |
hcpx approvals | Requests waiting for a person |
hcpx preview <pack_id> <command> [-- k=v …] | The approval card a person would see, and the exact command |
hcpx approve <id> / hcpx reject <id> | Decide one request; an approval covers one run of exactly that command and those arguments for 15 minutes |
hcpx audit [--pack id] [--limit n] | Recent decisions from $HCP_HOME/audit.jsonl |
hcpx commands adds access (allow, ask, deny) to every command.
hcpx help#
Usage text. With --json, { ok: true, help: string[] }.
Store#
$HCP_HOME/ default ~/.hcp
packs/<pack_id>/ installed pack directories (verbatim copies)
skills/<pack_id>/SKILL.md
state.json { "activated": [], "connected": [], "grants"?: HcpGrant[] }
access.json user access settings (mode, packs, rules, approvals)
approvals.json pending and decided approvals
audit.jsonl one line per command decisionWithout grants in state.json, the CLI uses permissive grants (every
capability, every pack). Set grants to test denials locally, as
Testing shows.
Environment#
HCP_PROJECT_ID sets the project scope for brain-land commands. Without it,
the enclosing git repository is the project.
| Variable | Effect |
|---|---|
HCP_HOME | Store location |
HCP_CATALOG_URL | Catalog search origin (default: the docs site's /api/v1/packs) |
HCP_MCP | Set to 1 inside hcpx mcp and every CLI it starts; hcpx mcp refuses to recurse, and access commands refuse with human_only |
HCP_AGENT | 1 marks an agent's shell; access commands refuse with human_only. hcpx adopt claude sets it |
HCP_MODE | Access mode for this process: manual, auto, or run |
HCP_APPROVALS | human or agent: who can satisfy an ask |
HCP_PROJECT_DIR | Working directory for packs with wrap.workspace.mode: project |
HCP_CLI | The command the host plugins start for each call, for example hcpx or bun /path/to/packages/cli/src/hcp.ts |
GITHUB_TOKEN | Sent when hcpx install github:… falls back to downloading a tarball |
HCP_SANDBOX | Set by the runtime in the child process: sandbox or native-local. Not read by the CLI |
The CLI always runs the reference runtime in sandbox mode, with allowBins
holding every installed pack's wrap.bin, the names hcpx and hcp, and the
executable running the CLI.