Skip to content

CO0Ki3/ccp

 
 

Repository files navigation

ccp — Codex channels peer

Languages: English (this file) · 한국어

A Codex plugin and worker runtime that lets one interactive Codex session coordinate with named headless Codex workers. The interactive session sends tasks; workers process them with codex exec, can delegate to other workers, and send replies back through the local CCP mesh.

Each peer runs a local MCP inbox server (ccp-inbox). Peers discover each other through ~/.ccp/registry/. Interactive Codex sessions fetch their messages manually. Headless workers poll their inboxes and reply automatically.

Why Workers?

The original Claude-oriented version could use Claude Code channel notifications to push a message into another interactive session and wake a new model turn automatically. Codex CLI does not currently expose an equivalent supported surface for arbitrary MCP server notifications to wake an existing interactive session.

CCP therefore uses headless workers for automation. Your interactive Codex session stays in control, while named workers run codex exec in the background, process tasks, optionally delegate to other workers, and send replies back to your inbox.

Requirements

  • macOS or Linux on darwin-arm64, darwin-x64, linux-x64, or linux-arm64
  • Codex with MCP, plugin, skill, and hook support
  • Either a prebuilt ccp-inbox binary or Bun 1.x on PATH

Install

As a Codex plugin

This repository is now a Codex plugin root:

codex plugin marketplace add /absolute/path/to/ccp

Then enable the plugin in ~/.codex/config.toml:

[plugins."ccp@ccp-local"]
enabled = true

Restart the Codex CLI session after enabling the plugin so plugin MCP servers are reloaded.

The Codex plugin files are:

  • .codex-plugin/plugin.json
  • .mcp.json
  • hooks.json
  • skills/ccp-protocol/SKILL.md

As a bare MCP server

Add this to ~/.codex/config.toml or a trusted project .codex/config.toml:

[mcp_servers.ccp-inbox]
command = "/absolute/path/to/ccp/server/start.sh"
enabled = true

Or use the CLI:

codex mcp add ccp-inbox -- /absolute/path/to/ccp/server/start.sh

In Codex CLI v0.130, plugin commands/ are not exposed as top-level slash commands. Use natural language prompts such as "list CCP peers" or "fetch CCP messages" instead of /ccp-* slash commands.

Runtime Binary

server/start.sh resolves the server binary in this order:

  1. $CCP_BIN if set
  2. server/dist/ccp-inbox-<os>-<arch>
  3. server/dist/ccp-inbox
  4. If bun is on PATH, compile server/inbox.ts once
  5. Otherwise, print a release download command

Build locally:

cd server
bun install
bun run build
bun run build:worker

Build all release targets:

cd server
bun run build:all

Interactive Session + Workers

Start your interactive Codex session as alice:

codex -C /absolute/path/to/ccp \
  -c 'mcp_servers.ccp-inbox.env.CCP_NAME="alice"'

Start any named worker you want:

cd /absolute/path/to/ccp/server

bun run worker.ts \
  --name daniel \
  --workspace /absolute/path/to/ccp \
  --role "senior engineer, concise, implementation-focused"

Add more workers with any names and roles:

bun run worker.ts --name tester --workspace /absolute/path/to/ccp --role "test engineer"
bun run worker.ts --name reviewer --workspace /absolute/path/to/ccp --role "code reviewer"

Each peer writes a registry record such as ~/.ccp/registry/daniel.json.

Note: setting CCP_NAME=alice codex in the shell may not propagate to Codex MCP servers. Prefer the -c mcp_servers.ccp-inbox.env.CCP_NAME=... override for interactive CLI testing. Workers set CCP_NAME internally from --name.

Workflow

List peers:

Use ccp-inbox list_peers and show me the CCP peer list.

Delegate work:

Use ccp-inbox send_to_peer to send daniel a task: find the 3 most recently modified files and report their names and mtimes.

The worker automatically polls its inbox, runs codex exec, and sends a reply. In the interactive alice session, fetch replies:

Use ccp-inbox fetch_messages and show me CCP replies.

Workers can also delegate to other workers. The model running inside a worker may return a structured delegation request; the worker supervisor sends that task to another peer, waits for its reply, then produces the final answer to the original sender.

Worker CLI

cd /absolute/path/to/ccp/server
bun run worker.ts --name <worker-name> --workspace <workspace> [options]

Useful options:

Option Purpose
--name <name> Required worker peer name, for example daniel or tester.
--workspace <path> Workspace passed to codex exec -C.
--role <text> Role/personality hint included in the worker prompt.
--persona <file> Extra instruction file for the worker.
--model <model> Model passed to codex exec.
--interval-ms <n> Inbox poll interval. Defaults to 2000.
--once Process one task and exit. Useful for smoke tests.
--max-delegations <n> Delegations allowed per task. Defaults to 1.
--reply-timeout-ms <n> Max wait for delegated worker replies.
--codex-cmd <cmd> Codex command to run. Defaults to codex.

Example with a persona file:

bun run worker.ts \
  --name daniel \
  --workspace /absolute/path/to/ccp \
  --persona ./workers/daniel.md

One-shot smoke test worker:

bun run worker.ts \
  --name daniel \
  --workspace /absolute/path/to/ccp \
  --once

Environment Variables

Variable Purpose
CCP_NAME Name of this instance. Defaults to <hostname>-<pid>.
CCP_PORT Inbox HTTP port. Defaults to an OS-assigned free port.
CCP_SUPERVISOR Peer name to relay Codex PermissionRequest hooks to.
CCP_NOTIFY_ON_STOP Peer name to notify when this session stops.
CCP_PERMISSION_TIMEOUT_SEC Seconds for the permission hook to wait for a supervisor verdict. Defaults to 120.
CCP_HOME Registry root. Defaults to ~/.ccp. Mostly useful for tests.

Permission Relay

Start a supervisor:

codex -C /absolute/path/to/ccp \
  -c 'mcp_servers.ccp-inbox.env.CCP_NAME="alice"'

Start a supervised session:

codex -C /absolute/path/to/ccp \
  -c 'mcp_servers.ccp-inbox.env.CCP_NAME="bob"' \
  -c 'mcp_servers.ccp-inbox.env.CCP_SUPERVISOR="alice"'

When Codex in bob raises a permission request, hooks/permission-request.sh posts a perm-request message to alice. Alice fetches messages, decides, and calls:

respond_permission({ "peer": "bob", "request_id": "...", "behavior": "allow" })

The verdict is written back for Bob's hook to consume.

MCP Tools

  • fetch_messages({ clear? })
  • send_to_peer({ to, content, kind?, task_id? })
  • respond_to_peer({ task_id, content })
  • list_peers()
  • whoami()
  • register({ name })
  • respond_permission({ peer, request_id, behavior })

Message kinds:

  • task: the peer should perform real work and answer with respond_to_peer
  • reply: answer to a delegated task
  • note: passive information
  • perm-request: permission request from a supervised peer
  • permission-verdict: visibility note for a permission verdict

HTTP Endpoints

Path Payload
POST /msg { from, content, kind, task_id? }
POST /permission/request { from, request_id, tool_name, description, input_preview }
POST /permission/verdict { from, request_id, behavior }
GET /info this instance's metadata
GET /peers discovered peers

Every POST requires from to match a currently alive registered peer, except loopback from the same instance.

Tests

cd server
bun test

The tests cover peer discovery, sender gating, queued inbox delivery, register renames, worker replies, and the permission relay path.

Limitations

  • Same machine only. Discovery is filesystem-based and HTTP binds to 127.0.0.1.
  • Codex does not receive arbitrary MCP server notifications as new model turns. Peers must fetch messages with fetch_messages.
  • Headless workers automate task processing, but the interactive alice session still fetches replies manually.
  • Permission relay depends on Codex hook support and a waiting hook process.

About

Codex Channels Peer

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages

  • TypeScript 87.4%
  • Shell 12.6%