CLI Reference
The oacp CLI provides commands for workspace management, inbox messaging, monitor-friendly inbox watching, agent profiles, memory archiving and opt-in cross-machine memory git sync, and environment health checks.
Version: This reference reflects the latest published release. See the Changelog for what’s new in each version.
oacp init
Section titled “oacp init”Create a new project workspace under $OACP_HOME/projects/.
oacp init <project-name> [--agents <list>]Description
Section titled “Description”Scaffolds a complete OACP workspace with agent directories, shared memory files, and packet storage. The project name must be a valid directory name (lowercase alphanumeric and hyphens). --agents is a comma-separated list of runtimes to create — it defaults to claude,codex,cursor (since v0.3.2). Gemini remains supported: pass --agents claude,codex,gemini or add it later with oacp setup gemini.
Created Structure
Section titled “Created Structure”$OACP_HOME/projects/<project-name>/├── agents/│ ├── claude/│ │ ├── inbox/│ │ │ └── archive/│ │ ├── outbox/│ │ └── dead_letter/│ ├── codex/│ │ └── ...│ └── cursor/│ └── ...├── memory/│ ├── project_facts.md│ ├── decision_log.md│ ├── open_threads.md│ ├── known_debt.md│ └── archive/├── packets/│ ├── review/│ └── findings/├── merges/└── workspace.json
oacp add-agent --runtimecreates bothstatus.yamlandagent_card.yamlfor the new agent.oacp doctor --fixcreates or refreshesstatus.yamlonly.
Environment
Section titled “Environment”| Variable | Description | Default |
|---|---|---|
OACP_HOME | Root directory for all OACP projects | ~/oacp |
If OACP_HOME is not set, it defaults to ~/oacp. The directory is created automatically if it does not exist.
Example
Section titled “Example”export OACP_HOME=~/oacpoacp init billing-service# Created workspace at ~/oacp/projects/billing-service/oacp send
Section titled “oacp send”Send a protocol-compliant inbox message to another agent.
oacp send <project> --to <recipient> --type <type> \ --subject <subject> --body <body> [--from <sender>]Description
Section titled “Description”Composes a YAML message file and writes it to the recipient’s inbox/ directory. A copy is saved in the sender’s outbox/. The message is assigned a unique ID and timestamp automatically.
| Flag | Required | Description |
|---|---|---|
--from | No | Sender agent name. Optional when sender can be inferred (see below) |
--to | Yes | Recipient agent name |
--type | Yes | Message type (see Message Types) |
--subject | Yes | Short subject line |
--body | Yes* | Message body (inline). Required unless --body-file is used. |
--body-file | No | Read message body from a file instead of --body |
--priority | No | Priority level: P0, P1, P2, P3 (default: P2) |
--parent-message-id | No | ID of the message being replied to, for threading |
--conversation-id | No | Conversation thread ID |
--related-pr | No | Related pull request number |
--dry-run | No | Print the YAML message without writing files |
--json | No | Output result as JSON |
--quiet | No | Suppress success output |
Sender Inference
Section titled “Sender Inference”When --from is omitted, OACP resolves the sender using this precedence chain:
--fromflag (explicit)OACP_AGENTenvironment variableAGENT_NAMEenvironment variable- Agent card runtime match — if exactly one agent in the project has an
agent_card.yamlwhoseruntimefield matches the detected runtime, that agent is used
If none of these resolve to a sender, the command exits with an error.
Message Types
Section titled “Message Types”The --type flag accepts any of the 12 defined message types: task_request, question, notification, follow_up, handoff, handoff_complete, review_request, review_feedback, review_addressed, review_lgtm, brainstorm_request, brainstorm_followup.
See Message Types for details on each type.
Example
Section titled “Example”# Explicit senderoacp send my-project \ --from claude \ --to codex \ --type review_request \ --priority P1 \ --subject "Review auth middleware PR" \ --body "PR #42 adds JWT validation to the API gateway."
# Inferred sender (inside a configured agent runtime)oacp send my-project \ --to codex \ --type notification \ --subject "Done" --body "Task completed."This writes a YAML file to the recipient’s inbox and saves a copy to the sender’s outbox. The message gets a unique ID in the format msg-<YYYYMMDDHHmmss>-<sender>-<rand>.
oacp doctor
Section titled “oacp doctor”Check environment and workspace health.
# Global health checkoacp doctor
# Project-specific checkoacp doctor --project <name>
# Auto-fix common issuesoacp doctor --project <name> --fixDescription
Section titled “Description”Runs a series of diagnostic checks and reports pass/fail status for each, similar to flutter doctor. Use the global form to verify your environment is set up correctly. Use --project to validate a specific workspace’s structure and configuration.
| Flag | Description |
|---|---|
--project | Check a specific project workspace |
--fix | Auto-fix missing inbox directories and regenerate missing or stale status files |
--memory | Run advisory checks for $OACP_HOME memory git sync (since v0.3.0) |
--json | Output a machine-readable JSON report |
--output | Save the report to a file (in addition to stdout) |
--oacp-dir | Override $OACP_HOME directory |
Checks Performed
Section titled “Checks Performed”Global checks (always run):
| Check | What It Verifies |
|---|---|
| Python version | Python 3.9+ is installed and on PATH |
| Required packages | pyyaml is importable |
OACP_HOME | Environment variable is set and the directory exists |
Project checks (with --project):
| Check | What It Verifies |
|---|---|
| Workspace structure | agents/, memory/, packets/ directories exist |
| Agent directories | Each agent has inbox/ and outbox/ subdirectories |
| Memory files | project_facts.md, decision_log.md, open_threads.md, known_debt.md are present |
workspace.json | File exists and contains valid JSON |
| Trust root (since v0.4.0) | Receiver pins and the project catalog load and pass integrity checks; pinned-but-not-cataloged identities warn; cataloged-but-unpinned identities surface as the catalog-not-pinned advisory, escalating to warn when the identity is live |
| Signing readiness (since v0.4.1) | Trust-pin completeness per receiver — every catalog identity must carry an active pin before a receiver flips signing.verify_mode to enforce, with gaps broken down per receiver |
| Policy-file authorization (since v0.4.2) | Per-receiver signature status of config.yaml and trust/allowed_signers.yaml, loaded through the authorized policy loader — signed, unsigned, or invalid (an enrolled target without a verifiable signature reports invalid, never unsigned) |
Example Output
Section titled “Example Output”$ oacp doctor[ok] Python 3.12.4[ok] pyyaml 6.0.2[ok] OACP_HOME=/Users/you/oacp[ok] 2 projects found
$ oacp doctor --project billing-service[ok] workspace.json valid[ok] agents/ — 3 agents configured (claude, codex, cursor)[ok] memory/ — all required files present[ok] packets/ — review/ and findings/ exist
$ oacp doctor --project billing-service --fix[fix] Created missing inbox/ for agent cursor[fix] Regenerated stale status.yaml for agent codex
$ oacp doctor --memory[ok] memory marker present: ~/oacp/.oacp-memory-repo[ok] allowlist matches canonical .gitignore[ok] working tree clean, in sync with origin/main[warn] last commit was 14 days ago — consider running `oacp memory push`oacp validate
Section titled “oacp validate”Validate an inbox or outbox YAML message against the protocol schema.
oacp validate <path-to-message.yaml>Description
Section titled “Description”Parses a YAML message file and checks it against the OACP message schema. Reports any missing required fields, invalid values, or format violations. Exits with code 0 on success, code 1 on validation failure.
What It Checks
Section titled “What It Checks”| Validation | Description |
|---|---|
| Required fields | id, from, to, type, priority, created_at_utc, subject, body are present |
| Type validity | type is one of the 12 defined message types |
| Timestamp format | created_at_utc is valid ISO 8601 UTC (e.g., 2026-03-13T14:30:00Z) |
| Priority values | priority is P0, P1, P2, or P3 |
| ID format | id follows msg-<timestamp>-<sender>-<rand> convention |
Example
Section titled “Example”$ oacp validate ~/oacp/projects/my-project/agents/codex/inbox/20260313T1430Z_claude_task_request.yaml[ok] Message is valid.
$ oacp validate bad-message.yaml[error] Missing required field: subject[error] Invalid type: "request" (expected one of: task_request, question, ...)oacp inbox
Section titled “oacp inbox”List pending inbox messages for one or all agents in a project.
oacp inbox <project> --agent <name>oacp inbox <project> --alloacp inbox <project> --agent <name> --jsonDescription
Section titled “Description”Scans an agent’s inbox directory for YAML message files and displays a summary table with sender, type, priority, subject, and age. Use --all to see inboxes for every agent in the project. Use --json for machine-readable output.
Since v0.4.2, the lister reads each message through the shared receive boundary — one verified bounded snapshot per file. Under signing.verify_mode: enforce, an unverified message surfaces as a held row built from filesystem metadata only (no message field is parsed or displayed); under warn, rows carry the verification status. See Message Signing.
| Flag | Description |
|---|---|
--agent | List messages for a specific agent (mutually exclusive with --all) |
--all | List messages for all agents in the project |
--json | Emit JSON output instead of a table |
--oacp-dir | Override $OACP_HOME directory |
Example
Section titled “Example”$ oacp inbox my-project --agent claudeINBOX: claude (my-project) — 2 messages
| # | From | Type | Priority | Subject | Age ||---|-------|--------------|----------|-----------------------------|-----|| 1 | iris | task_request | P1 | Update docs for v0.2.0 | 3h || 2 | codex | review_lgtm | P2 | Re: Review auth middleware | 1d |$ oacp inbox my-project --all --json{ "project": "my-project", "mode": "all", "agents": [ { "agent": "claude", "message_count": 2, "messages": [...] }, { "agent": "codex", "message_count": 0, "messages": [] } ]}oacp watch
Section titled “oacp watch”Emit inbox delta events for one agent — designed for Claude Monitor or shell loops that re-run the command.
oacp watch --agent <name> --project <project> [--project <project> ...]oacp watch --agent <name> --all-projectsoacp watch --agent <name> --project <project> --jsonDescription
Section titled “Description”oacp watch scans an agent’s inbox(es), persists state between runs, and prints one structured line per new event since the last run. Each invocation is short-lived: emit, persist, exit. Run it under a process supervisor or a shell loop to keep watching.
By default — since v0.2.3 — the first run for a target uses --since=now, so existing inbox messages are not replayed as NEW_MESSAGE events. message_archived events are also suppressed unless --show-archived is passed.
For concurrent watchers of the same inbox — for example, several Claude sessions each running their own oacp watch — pass a stable per-subscriber --state-id (since v0.3.3). Each --state-id gets an independent cursor file, so every watcher receives every new-message event instead of sharing one cursor and swallowing each other’s events.
Since v0.4.2, the emitter reads each message through the shared receive boundary. Under signing.verify_mode: enforce, an unverified message emits a held event built from filesystem metadata only; under warn, events carry the verification status. See Message Signing.
| Flag | Description |
|---|---|
--agent | Required. Agent inbox name to watch |
--project | Project to scan (repeatable for multi-project watch) |
--all-projects | Auto-discover all projects that contain this agent’s inbox |
--state-id | Per-subscriber cursor file (state/watch/<agent>.<id>.json). Lets concurrent watchers of the same inbox each receive every event instead of sharing a cursor. Omit for the legacy shared cursor. Since v0.3.3 |
--since | First-run baseline cutoff. now (default), epoch, relative (30s, 5m, 2h, 7d), or ISO 8601 (2026-04-26T00:00:00Z). Only applies on the first run for a target |
--show-archived | Emit message_archived events when messages disappear from the inbox. Off by default — when the watching agent is the inbox owner, deletes are self-loops |
--json | Emit JSON Lines instead of plain NEW_MESSAGE lines |
--oacp-dir | Override $OACP_HOME directory |
--project and --all-projects are mutually exclusive — pass one or the other.
Output
Section titled “Output”Plain mode (default) emits one line per event:
NEW_MESSAGE project=my-project type=task_request priority=P1 Update docs for v0.3.0message_archived project=my-project id=msg-20260427T1430Z-claude-a8f3JSON mode (--json) emits one JSON object per line with full message metadata.
Example
Section titled “Example”# Continuous watch under a shell loop — replay existing messages first timewhile true; do oacp watch --agent claude --all-projects --since=epoch || true sleep 120done
# Notification-friendly default — no replay, no archive noiseoacp watch --agent claude --all-projects
# Observer agent watching another agent's deletesoacp watch --agent claude --project audit --show-archivedoacp retention
Section titled “oacp retention”Prune message history across a project (since v0.4.3).
oacp retention <project> [--oacp-dir <dir>] [--dry-run] [--json]Description
Section titled “Description”Prunes outbox/, dead_letter/, and processed inbox/archive/ files when a target exceeds either an age or a count bound — defaults 30 days and 1,000 files per target, with validated partial overrides in workspace.json. --dry-run reports the eligible files without deleting them (add --json for deterministic JSON output; both flags apply to real runs too). Before each removal, the pruner re-checks the file’s identity (inode, size, and modification time) and skips any file that changed or disappeared since the scan.
Inside dead_letter/, quarantine evidence is protected from automatic pruning by its durable filename format, and a manually managed dead-letter fixture can be kept with an adjacent .retain marker. Processed inbound messages have one cross-runtime archive destination, inbox/archive/, preserving the original filename and bytes — see Inbox / Outbox.
oacp agent
Section titled “oacp agent”Manage global agent profiles. Subcommands: init, show, list.
oacp agent init
Section titled “oacp agent init”oacp agent init <name> --runtime <runtime>Scaffold a global agent profile at $OACP_HOME/agents/<name>/profile.yaml. Valid runtimes: claude, codex, cursor, gemini, human.
oacp agent show
Section titled “oacp agent show”oacp agent show <name> [--project <project>]Print the merged agent profile as YAML. Without --project, shows the global profile only. With --project, merges the global profile with the project-level agent_card.yaml — project fields override global fields (shallow dict merge, list replacement).
oacp agent list
Section titled “oacp agent list”oacp agent list [--project <project>]List known agents with their scope tags (global, project, or both).
Example
Section titled “Example”$ oacp agent init alice --runtime claudeCreated global profile: ~/oacp/agents/alice/profile.yaml
$ oacp agent list --project billing-service alice (global, project) codex (project)
$ oacp agent show alice --project billing-servicename: aliceruntime: claudecapabilities: tools: [shell_access, git_ops, github_cli] ...oacp memory
Section titled “oacp memory”Archive, restore, and git-sync project and org memory files.
Subcommands fall into two groups:
- Archive layer (since v0.1.9):
archive,restore— manage the per-project active vs. archived memory split. - Git sync (since v0.3.0):
init,clone,pull,push,disable— opt-in cross-machine sync of$OACP_HOMEmemory via a plain git repo.
For the protocol-level overview of how memory works across agents, projects, and machines, see Shared Memory.
Memory Sync Activation Model
Section titled “Memory Sync Activation Model”Memory sync uses three states, gated by the presence of $OACP_HOME/.oacp-memory-repo:
| State | Trigger | Behavior |
|---|---|---|
| Disabled | No marker | Lifecycle hooks no-op silently. oacp doctor --memory reports not configured. |
| Local-only | oacp memory init (no --remote) | Wrap-up commits memory locally for audit history. No remote, no push. |
| Synced | oacp memory init --remote <URL> or oacp memory clone <URL> | Session start pulls fast-forward updates. Wrap-up commits and pushes. |
The git repo at $OACP_HOME tracks only:
$OACP_HOME/org-memory/**$OACP_HOME/projects/*/memory/**
agents/ runtime state, inbox messages, and status.yaml are not synced — see the SPEC for the full rationale and .gitignore allowlist.
oacp memory archive
Section titled “oacp memory archive”oacp memory archive <project> <memory-file> [--dry-run] [--json]Move a memory file from the active working set (memory/) into memory/archive/. Useful for decluttering the active memory directory without deleting historical context.
oacp memory restore
Section titled “oacp memory restore”oacp memory restore <project> <archived-file> [--dry-run] [--json]Restore an archived memory file back to the active working set. The <archived-file> argument must be the timestamp-prefixed filename (e.g., 20260320T143000Z_research_notes.md), not the original basename.
oacp memory init
Section titled “oacp memory init”oacp memory init [--remote <url>] [--oacp-dir <dir>]Initialize the $OACP_HOME memory git repo: writes the canonical .gitignore allowlist, creates the .oacp-memory-repo marker, configures the optional remote, and makes the initial commit. Local-only without --remote; Synced with --remote <url>.
oacp memory clone
Section titled “oacp memory clone”oacp memory clone <url> [--force] [--oacp-dir <dir>]Clone an existing memory repo into $OACP_HOME. Refuses to clone into a non-empty target unless --force is passed, in which case the existing directory is moved aside (not deleted).
oacp memory pull
Section titled “oacp memory pull”oacp memory pull [--oacp-dir <dir>]Advisory fetch + fast-forward-only pull. Warns loudly — but exits successfully — on dirty, ahead, behind, diverged, or fetch-failed states. Never auto-merges. Designed to run as a session-init hook.
oacp memory push
Section titled “oacp memory push”oacp memory push [--oacp-dir <dir>]Stages only the memory allowlist (.gitignore, .oacp-memory-repo, org-memory/**, projects/*/memory/**), commits as memory: <agent>@<host> <date> (N files), and pushes when a remote is configured. Warns loudly — but exits successfully — on dirty, behind, diverged, or push-failed states. Designed to run as a wrap-up / session-end hook.
oacp memory disable
Section titled “oacp memory disable”oacp memory disable [--oacp-dir <dir>]Removes the .oacp-memory-repo marker locally while leaving .git/ intact. Lifecycle hooks become no-ops; the local commit history is preserved and can be re-activated later by re-creating the marker.
| Flag | Description |
|---|---|
--dry-run | Archive/restore only — report what would happen without moving files |
--json | Archive/restore only — emit JSON output |
--remote | init only — git remote URL for cross-machine sync |
--force | clone only — move a non-empty OACP_HOME aside before cloning |
--oacp-dir | All subcommands — override $OACP_HOME directory |
Example
Section titled “Example”# Archive layer$ oacp memory archive billing-service research_notes.mdArchived memory/research_notes.md -> memory/archive/20260320T143000Z_research_notes.md
$ oacp memory restore billing-service 20260320T143000Z_research_notes.mdRestored memory/archive/20260320T143000Z_research_notes.md -> memory/research_notes.md
# Git sync — local-only$ oacp memory initInitialized memory repo at /home/you/oacp (local-only)
# Git sync — with remote$ oacp memory init --remote git@github.com:your-org/oacp-memory.gitInitialized memory repo at /home/you/oacp (synced)
# Pull at session start, push at wrap-up$ oacp memory pull$ oacp memory pushoacp add-agent
Section titled “oacp add-agent”Add an agent to an existing project workspace.
oacp add-agent <project> <agent-name> [--runtime <runtime>]Description
Section titled “Description”Creates the agent’s directory structure (inbox/ with its archive/, outbox/, dead_letter/) within an existing project. When --runtime is provided, also generates status.yaml and agent_card.yaml with runtime-specific defaults. Use this to add agents after initial oacp init without re-initializing the workspace.
| Flag | Required | Description |
|---|---|---|
--runtime | No | Agent runtime (claude, codex, cursor, gemini). Generates status and card files when set. |
--oacp-dir | No | Override $OACP_HOME directory |
Example
Section titled “Example”$ oacp add-agent billing-service alice --runtime claudeAdded agent 'alice' to project 'billing-service'oacp setup
Section titled “oacp setup”Generate runtime-specific configuration files in a repository.
oacp setup <runtime> [--project <project>] [--repo-dir <dir>]<runtime> is one of claude, codex, cursor, gemini. --project is auto-detected from .oacp if not given. --repo-dir is auto-detected from .git if not given.
Description
Section titled “Description”Creates boilerplate config files that connect a repo to an OACP workspace. For Claude Code, this generates a CLAUDE.md snippet with the workspace path and inbox check instructions. For Codex, it generates an AGENTS.md snippet.
Cursor runtime (since v0.3.2). oacp setup cursor --project <project> provisions the project-side Cursor agent directory and writes a repo-local .cursor/rules/oacp.todo.mdc placeholder. Cursor-owned rules and memory lifecycle hooks remain deferred.
Memory lifecycle hooks (Claude, since v0.3.0). oacp setup claude also writes .claude/hooks/oacp-memory-pull.sh and registers it under SessionStart in .claude/settings.json. The hook checks for $OACP_HOME/.oacp-memory-repo first and exits silently when memory sync is not enabled — so existing workflows are unaffected on machines that have not opted in via oacp memory init. Since v0.4.3, setup no longer creates or registers an automatic SessionEnd push — explicit wrap-up is the single push path; rerunning setup removes only the exact historical generated registration and leaves any existing script or custom hooks untouched.
Codex startup hook (since v0.4.3). oacp setup codex safely merges one startup-only handler into .codex/hooks.json, wiring oacp session-init to Codex SessionStart — a bounded, truthful ordered-read manifest with optional pull-before-verify memory sync, taking the active model and cwd from the hook payload. Users review and trust the definition with /hooks. Startup file states report verified, meaning the command confirmed readability and updated status.yaml; the hook context tells Codex which files still require ordered reads.
Example
Section titled “Example”$ oacp setup claude --project billing-serviceGenerated CLAUDE.md snippet for project 'billing-service'Wrote .claude/hooks/oacp-memory-pull.shRegistered hook under SessionStart in .claude/settings.jsonoacp org-memory
Section titled “oacp org-memory”Initialize org-level shared memory.
oacp org-memory initDescription
Section titled “Description”Creates the $OACP_HOME/org-memory/ directory structure for cross-project knowledge sharing. Org memory holds decisions, rules, and events that span multiple projects. Used with oacp write-event to publish events.
Created Structure
Section titled “Created Structure”$OACP_HOME/org-memory/├── events/├── decisions.md├── rules.md└── recent.mdoacp write-event
Section titled “oacp write-event”Write an event to org-level memory.
oacp write-event --agent <name> --project <project> \ --type <type> --slug <slug> --body <description>Description
Section titled “Description”Appends an event entry to $OACP_HOME/org-memory/events/. Events capture cross-project decisions, deployments, rule changes, and other significant outcomes that other agents should know about.
| Flag | Required | Description |
|---|---|---|
--agent | Yes | Agent that produced the event |
--project | Yes | Source project |
--type | Yes | Event type: decision, event, or rule |
--slug | Yes | Short identifier (used in filename) |
--body | Yes | One-line description of the event |
--related | No | Comma-separated cross-references (e.g., PR #42,issue #15) |
--oacp-dir | No | Override $OACP_HOME directory |
Example
Section titled “Example”$ oacp write-event --agent claude --project billing-service \ --type decision --slug rest-api-convention \ --body "Standardized on REST for all public APIs" \ --related "PR #15"oacp envelope
Section titled “oacp envelope”Compile, show, or clear the runtime envelope for an admitted task (since v0.3.5).
oacp envelope compile <message.yaml> --receiver <agent>oacp envelope show --project <project>oacp envelope clear --project <project> --receiver <agent>Description
Section titled “Description”Turns an admitted message’s declared task_profile plus the receiver’s autonomy config into a runtime envelope at agents/<receiver>/state/active_envelope.json, enforced at the tool-call layer by a static runtime shim (for Claude Code, the oacp-envelope-hook PreToolUse hook registered once by oacp setup claude). Compile at task pickup; clear at completion. Compilation is fail-closed — a missing, unparsable, or invalid profile pauses the task with envelope_compile_error instead of executing unenforced. After a threshold-checkpoint re-authorization, recompile with --extend — it preserves the active envelope’s runtime counters; --force is the different-message restart and resets them. See Receiver Autonomy → Envelope compilation.
Since v0.4.0, oacp envelope clear executes from inside the enforced session: the hook validates the clear against the task’s newest audit record (matched by content, never by filename) and sanctions it only when the record carries a terminal result.final_state (done/error) — completed envelopes no longer strand until a human clears them. Protocol-mandated bookkeeping (audit records, the receiver’s own inbox/outbox, the runtime scratchpad) does not consume the declared expected_files_touched budget. Since v0.4.1, enforcement is session-scoped: the compiled envelope records the harness session that compiled it and no-ops for tool calls from any other session, so a concurrent interactive session in the same repository neither inherits the task’s constraints nor consumes its budget.
Since v0.4.2, the compiler refuses to compile from a message that is not signed-verified when the receiver’s signing.verify_mode is enforce, and the envelope’s message_sha256 names the verified snapshot. --audit <admission-record> handles the one deliberate non-compile: an admitted public_visibility: true task with a recorded human admission approval is stamped envelope_enforcement: none (reason public_visibility_admission_approved) instead of compiling — see Receiver Autonomy → Envelope compilation.
| Flag | Required | Description |
|---|---|---|
--receiver | No | Receiver agent the envelope constrains (default: claude) |
--project | Yes (show/clear) | show/clear cannot infer the project and exit 3 without it; compile infers it only from a message path inside $OACP_HOME/projects/<project>/ — otherwise required there too |
--config | No | compile only — receiver config path (default: agents/<receiver>/config.yaml) |
--audit | No | compile only — admission audit record for this message; on an admitted public-visibility task with recorded human approval, the envelope is deliberately not compiled and the record is stamped envelope_enforcement: none by rule (since v0.4.2) |
--extend | No | compile only — recompile over an existing envelope, preserving its counters (re-authorization flow) |
--force | No | compile only — overwrite an existing envelope for a different message, resetting counters |
--json | No | compile only — machine-readable output |
--oacp-dir | No | Override $OACP_HOME directory |
Example
Section titled “Example”$ oacp envelope compile agents/claude/inbox/20260712_iris_task_request.yaml --receiver claude# ... execute the task under hook enforcement ...$ oacp envelope clear --project my-project --receiver claudeoacp autonomy-outcome
Section titled “oacp autonomy-outcome”Record a human approval, modification, or decline on a paused autonomy audit (since v0.3.5).
oacp autonomy-outcome <audit.yaml> --decision <approved|modified|declined>Description
Section titled “Description”Writes the structured result.human_outcome block into a schema-v2 autonomy audit: the decision, actor, timestamp, decision latency computed from the audit’s created_at_utc, and the copied pause reason codes. The write is flock-guarded and atomic, and refuses to overwrite a recorded outcome unless --replace is explicit. Grant handling is separate from task approval — a task approval never silently creates a standing continuation grant. See Receiver Autonomy → Human approval and decline outcomes.
Since v0.4.0, checkpoint-paused records are accepted too — for an auto-accepted admission whose in-place threshold checkpoint breached, latency is measured from the checkpoint’s paused_at_utc rather than admission time. The actor convention is pinned: one canonical, whitespace-free handle per human, fleet-wide (the anonymous default human warns), so cross-receiver outcome analytics can attribute decisions.
| Flag | Required | Description |
|---|---|---|
--decision | Yes | approved, modified, or declined |
--grant-decision | No | not_requested (default), approved, modified, or denied |
--grant-scope-file | No | Explicit replacement scope (required for --grant-decision modified) |
--decided-at | No | Override the decision timestamp (ISO-8601 UTC) |
--actor | No | Actor recorded in the outcome block (default: human) |
--replace | No | Overwrite a previously recorded outcome |
--dry-run | No | Compute and print the outcome without writing the audit file |
--json | No | Machine-readable output |
Example
Section titled “Example”$ oacp autonomy-outcome agents/claude/audit/autonomy_decisions/20260713T191200Z_msg-....yaml \ --decision approvedoacp key
Section titled “oacp key”Generate and inspect Ed25519 message-signing keys (since v0.4.0).
oacp key gen [--agent <name>]oacp key listDescription
Section titled “Description”oacp key gen creates a dedicated Ed25519 signing key under $OACP_HOME/keys/ (directory 0700, key files 0600 — the directory is excluded from memory sync by construction) plus a public <kid>.pub.json catalog stub for the trust-import flow. The kid is the key’s RFC 7638 JWK thumbprint. oacp key list shows local keys. Requires the optional crypto extra. Key-management and rotation semantics: Message Signing.
| Flag | Description |
|---|---|
--agent | Agent name the key belongs to (inferred if omitted) |
--oacp-dir | Override $OACP_HOME directory |
--json | Machine-readable output |
Example
Section titled “Example”$ oacp key gen --agent claude$ oacp key listoacp trust
Section titled “oacp trust”Import, inspect, and revoke trust-root entries (since v0.4.0); sign receiver policy files (since v0.4.2).
oacp trust import <stub.pub.json> --project <name> --agent <receiver>oacp trust list --project <name>oacp trust revoke <kid> --project <name> (--agent <receiver> | --all-receivers)oacp trust sign-policy --project <name> --agent <receiver>Description
Section titled “Description”oacp trust import records a <kid>.pub.json stub from oacp key gen in the project’s zero-authority distribution catalog (projects/<name>/trust/catalog.yaml — identity recorded, nothing granted) and pins it active in the receiver’s own allowed_signers.yaml, the only file consulted at verify time. Import is integrity-checked: the kid must be the RFC 7638 thumbprint of its JWK, private key components are refused, same-kid conflicts are refused, and a revoked pin is never silently reactivated. The whole catalog-then-pins transaction is serialized on a project trust lock.
oacp trust revoke handles compromise response without hand-editing trust files — it validates the canonical kid spelling, flips the pin to status: revoked while keeping key material in place, and is safely re-runnable (re-revoking reports unchanged). --all-receivers is all-or-nothing: every target is validated before any pin is written. The trust-root model behind these commands: Message Signing.
oacp trust sign-policy (since v0.4.2) signs the receiver’s config.yaml and trust/allowed_signers.yaml with the receiver’s own local key, under the distinct oacp-policy+yaml JOSE profile with {project, receiver, kind} context binding, and enrolls each target in the machine-local policy-enrollment registry — after which an unsigned policy file is invalid, never unsigned. Trust mutations on an enrolled trust root atomically re-sign it or refuse the write. See Message Signing → Policy-file signing.
| Flag | Description |
|---|---|
--project | Project workspace name (required) |
--agent | Receiver whose pins gain or lose the entry; for sign-policy, the receiver whose policy files are signed |
--catalog-only | import only — record the identity in the catalog, grant no authority |
--all-receivers | revoke only — revoke the kid for every receiver in the project that pins it |
--kid | sign-policy only — sign with this specific key only |
--oacp-dir | Override $OACP_HOME directory |
--json | Machine-readable output |
Example
Section titled “Example”$ oacp trust import ~/oacp/keys/8eVCNRv7uT62….pub.json --project my-project --agent claude$ oacp trust list --project my-projectoacp verify
Section titled “oacp verify”Verify a message’s auth trailer against receiver-local pins (since v0.4.0).
oacp verify <message.yaml> --project <name> --receiver <agent>Description
Section titled “Description”Implements verify-before-parse: strict last-line trailer extraction from the raw bytes, bounded structural checks, EdDSA verification over the exact raw prefix against receiver-local pins only (no network at verify time), then an identity cross-check on the verified prefix. In warn mode each message is annotated as unsigned, signed-unknown-kid, signed-verified, or signed-INVALID — recorded, never rejected. Since v0.4.2, enforce has a real caller: the autonomy gate invokes this verification at message intake, where only a signed-verified message proceeds — every other outcome quarantines an evidence copy into dead_letter/ and exits 3 with an intake_rejected decision. Byte-tampered messages can be set aside with a no-clobber evidence copy in dead_letter/ via --quarantine, without touching the original. --attach-audit records the canonical result.message_auth block into an autonomy audit record — the one supported path for audit stamping. Full protocol semantics: Message Signing.
| Flag | Description |
|---|---|
--project | Project name (with --receiver) |
--receiver | Receiver agent whose pins are consulted |
--pins | Explicit path to an allowed_signers.yaml (instead of project/receiver resolution) |
--quarantine | Write an evidence copy to dead_letter/ when the result is INVALID |
--attach-audit | Record the message_auth block into the given autonomy audit YAML |
--oacp-dir | Override $OACP_HOME directory |
--json | Machine-readable output |
Example
Section titled “Example”$ oacp verify agents/claude/inbox/20260804_iris_task_request.yaml \ --project my-project --receiver claude[oacp-auth] signed-verified signer=urn:oacp:agent:…:iris kid=8eVCNRv7uT62…