Skip to content

proofofwork-agency/contextrelay

Repository files navigation

ContextRelay

License

Run Claude Code and Codex as one local coding team.

ContextRelay is a local multi-agent coding orchestrator for Claude Code and Codex. It gives your repo a loopback daemon, native terminal dashboard, provider adapters, shared ledger, structured handoffs, review loops, backup-agent requests, and opt-in multi-session routing.

Use it when you want one model to plan or review while another implements, tests, debugs, or gives an independent second opinion. Everything runs around your local project: local daemon, local state, token-protected endpoints, project-scoped ports, and human-controlled autonomy defaults. ContextRelay is not a provider product, not endorsed by OpenAI or Anthropic, and not an OS sandbox.

ContextRelay native terminal dashboard

Why ContextRelay

Coding with multiple AI assistants is increasingly common, but moving between them is usually copy-paste and lost context. One assistant may be better at architecture review, another may be better at fast implementation, and the human still needs a clear control plane for what happened, who owns the next step, and when the work is actually done.

ContextRelay turns that into a local workflow instead of a copy-paste ritual:

  • Pair Claude Code and Codex in the same repo with live, token-protected relay paths.
  • Ask for structured handoffs instead of vague chat messages.
  • Run bounded deliberations when a design choice needs a second opinion.
  • Keep a durable ledger of notes, artifacts, test reports, decisions, runtime events, and finality proposals.
  • Launch separate named pairs for implementation, review, or debugging lanes from the same project daemon.
  • Inspect everything from a native terminal dashboard or a local browser Command Deck.

Agents share ledger entries and messages, not hidden reasoning.

Quickstart

Prerequisites

Dependency Version Install
Bun v1.0+ curl -fsSL https://bun.sh/install | bash
Claude Code v2.1.80+ npm install -g @anthropic-ai/claude-code
Codex CLI latest npm install -g @openai/codex

Bun is required because the ContextRelay daemon and plugin server run on Bun.

Install

npm install -g @proofofwork-agency/contextrelay
ctxrelay init --instructions project
ctxrelay codex-mcp install
contextrelay

What this does:

  • ctxrelay init --instructions project creates .contextrelay/config.json, installs the Claude Code plugin, and writes managed ContextRelay guidance into AGENTS.md and CLAUDE.md.
  • ctxrelay codex-mcp install registers the ContextRelay MCP server with Codex.
  • contextrelay opens the native ContextRelay terminal dashboard. From there you can launch the Claude+Codex pair, open the browser Command Deck, or inspect agents and session health.

Check the session:

ctxrelay status
ctxrelay instances

Stop the project daemon or a named runtime session:

ctxrelay kill
ctxrelay kill --all
ctxrelay kill --session <id>

Develop From Source

git clone https://github.com/proofofwork-agency/contextrelay.git
cd contextrelay
bun install
bun run build:cli
bun run build:plugin
bun link
bun link @proofofwork-agency/contextrelay
ctxrelay init --instructions project
ctxrelay codex-mcp install
ctxrelay pair

Common Workflows

Use ContextRelay for workflows that get awkward in one chat window:

Workflow What happens
Planner + builder Claude can shape the task, Codex can implement, and both can leave durable notes in one ledger.
Independent review One agent can make a change while the other reviews the risk, tests, or architecture with a bounded handoff.
Debug lane Keep the main pair focused while a named session investigates a failure in another checkout folder.
Release gate Record build, test, package, and finality evidence before publishing.
Human-controlled autonomy Read-only backup agents and auto-finality stay off unless explicitly enabled.

Product Surface

  • Native ContextRelay TUI for agents, session health, launch controls, and fixed hotkeys.
  • Live Claude Code <-> Codex routing in the same local repo.
  • Structured handoffs with reason, ask, context refs, next speaker, and handled state.
  • Shared JSONL ledger for messages, notes, artifacts, backup results, runtime events, and finality.
  • Codex MCP tools, Claude MCP tools, Claude slash commands, and Codex fallback markers.
  • Local browser Command Deck for status, task lanes, artifacts, policy, and timeline.
  • Project-scoped daemon instances and port groups so multiple repos can run at once.
  • Read-only backup agents gated by explicit autonomy settings.
  • Manual coordinator policy for git ownership: Claude, Codex, or human.

How It Works

Claude Code
  -> ContextRelay Claude plugin / MCP stdio
  -> ContextRelay daemon
  -> Codex app-server proxy
  -> Codex TUI

Claude gets ContextRelay MCP tools through the Claude Code plugin installed by ctxrelay init. Codex gets ContextRelay MCP tools only after ctxrelay codex-mcp install, because that command writes to Codex's MCP configuration.

Codex-to-Claude MCP messages use the daemon's live relay path and are recorded in the shared ledger. Claude-to-Codex delivery uses the Codex injection path so reply-required turns and busy-state handling are preserved. If Claude sends while Codex is already in a turn, the daemon queues up to 50 pending Claude-to-Codex injections and flushes them when the current Codex turn completes. Separately, undrained Claude-bound Codex messages use CONTEXTRELAY_MAX_BUFFERED_MESSAGES, which defaults to 100.

The daemon writes session data to:

.contextrelay/sessions.json
.contextrelay/sessions/<sessionId>.jsonl

Codex TUI flags are owned by ContextRelay when using ctxrelay codex: --remote and --enable tui_app_server. Claude channel flags are owned by ContextRelay when using ctxrelay claude: --channels and --dangerously-load-development-channels.

ctxrelay claude and ctxrelay pair use Claude's development channel path by default because ContextRelay is a custom channel during Claude Code's channel research preview. Normal local installs do not need to set any channel environment variable. Set CONTEXTRELAY_CLAUDE_DEVELOPMENT_CHANNELS=0 only if plugin:contextrelay@contextrelay is available through an approved channel allowlist in your environment.

Multi-Session Mode

Experimental named sessions let one project daemon host more than one Claude+Codex pair. Use them for a main implementation lane plus a review or debugging lane, or to point independent agent conversations at different checkout folders without starting separate ContextRelay daemons.

The default pair stays simple:

ctxrelay claude
ctxrelay codex

Additional pairs are explicit. The first --session <id> launch creates the session if it does not exist, remembers the current folder as that session's operation path, starts the daemon-side named runtime/proxy, and tells you how to start the other side.

Codex-first:

CONTEXTRELAY_ALLOW_NAMED_SESSIONS=1 ctxrelay codex --session review
CONTEXTRELAY_ALLOW_NAMED_SESSIONS=1 ctxrelay claude --session review

Claude-first:

CONTEXTRELAY_ALLOW_NAMED_SESSIONS=1 ctxrelay claude --session review
CONTEXTRELAY_ALLOW_NAMED_SESSIONS=1 ctxrelay codex --session review

Pre-create a session when you want a label or explicit folder:

ctxrelay session create review --worktree ../repo-review
CONTEXTRELAY_ALLOW_NAMED_SESSIONS=1 ctxrelay claude --session review
CONTEXTRELAY_ALLOW_NAMED_SESSIONS=1 ctxrelay codex --session review

ctxrelay status --json, the TUI Runtime Sessions panel, and ctxrelay session list show each runtime session's operation path. The stored "worktree" is that folder of operation. It is usually a git checkout or git worktree, but ContextRelay only remembers and validates the path; it does not create git worktrees. Use separate folders for sessions that can write files.

ContextRelay prevents two launched named Codex runtimes from sharing the same bound folder; the compatibility default session is not part of that guard. Named runtime sessions isolate live Claude/Codex routing when opted in, but transcript ledger, viewer, backup, and finality state remain mostly global/default-biased until the next architecture line.

Safety Model

ContextRelay is local developer tooling, not a security boundary between tools you do not trust. It defaults to loopback-only endpoints, local auth tokens, browser origin rejection, autonomy off, auto-finality off, read-only backup agents, and coordinator-owned git-write policy.

Provider-native Claude Code and Codex approval systems still apply inside those tools. ContextRelay records mediated permission decisions and runtime events, but it does not replace the provider approval model.

What's New

  • v2.2.0 adds TUI status observability for the reliability primitives shipped in v2.1.0: the daemon now precomputes cheap status.observability fields for same-project peer count, resolution-mismatch warnings, and the current active handoff state, and the native TUI renders them as quiet one-line badges.
  • The idle opportunity scanner remains evidence-gated rather than enabled by default. Current measurements lean toward dropping it unless organic v2.1 runtime usage shows persistent idle/status noise.
  • Agents are now explicitly taught to call read_context with handoff_id when reconciling a late reply after a live wait expires.
  • v2.1.0 added reliability primitives for long-running Claude + Codex work: live waits now expire as "still active" instead of implying failure, handoffs carry a derived state (pending, expired_live_wait, handoff_still_active, or matched), and late replies reconcile by handoff id through wait_for_messages, wait_for_claude, and read_context.
  • Connection and recovery status are more truthful: doctor and status expose the instance, state directory, and ports they reflect; resolution-mismatch warnings call out same-project daemons on different port groups; and disabled-bridge recovery is identity-aware with daemon-token re-read after relaunch.
  • ContextRelay now writes an advisory CoordinationCheckpoint from derived ledger, policy, runtime, and git state, then reads it fail-closed on startup so stale or dirty worktrees are summarized as advisory instead of auto-resumed.
  • The native TUI shows the ContextRelay version in the header and the current instance id in the Status panel, alongside clearer kill scope and deferred dev-bundle restart messaging.
  • v2.0.0 remains the streamlined major release baseline: a focused Claude Code + Codex coordination core with a state-scoped session registry, archived-session reactivation, plugin-status diagnostics, hardened CLI passthrough, watchdog stability, occupied-port preservation, managed-Codex descendant reaping, and guarded stale app-server cleanup.
  • ctxrelay codex-mcp install|remove|status|server manages Codex MCP registration explicitly.
  • Codex has typed MCP tools for live messages, handoffs, context reads, notes, artifacts, backup requests, status, and finality.
  • ctxrelay coordinator claude|codex|human rewrites coordinator policy in config and managed instruction blocks.
  • AGENTS.md and CLAUDE.md managed blocks are audience-specific: Codex files describe Codex tools and fallback markers; Claude files describe Claude plugin tools.
  • Claude-to-Codex messages sent while Codex is busy are queued instead of failing immediately.
  • ctxrelay status reuses the live daemon port group recorded in local state even when public health omits private daemon details.
  • v1.1.4 ships explicit first-use named runtime sessions behind CONTEXTRELAY_ALLOW_NAMED_SESSIONS=1: ctxrelay codex --session <id> or ctxrelay claude --session <id> can create a named pair inside the same daemon.
  • v1.1.4 shows each named session's operation path in status, session list, and the native TUI, and documents the Claude-first and Codex-first launch flows.
  • v1.1.3 added opt-in hook compaction controls through ctxrelay hook-compaction and the TUI Token mode toggle; verbose remains the default and preserves legacy hook output.
  • Named sessions remember their folder of operation, show that path in runtime status, can be archived, rebound, stopped with ctxrelay kill --session <id>, guarded against launching two named Codex runtimes on the same bound folder, and keep runtime identity across Codex MCP relay paths and bridge recovery.
  • Named runtime sessions isolate live Claude/Codex routing when opted in, but transcript ledger, viewer, backup, and finality state remain mostly global/default-biased until the next architecture line.

Reference

The sections below keep the full command, tool, state, and environment surface searchable from the README.

Tool Surface

All ContextRelay tool calls exposed by the current codebase are listed here.

Claude MCP Tools

Claude receives these tools from the ContextRelay Claude Code plugin.

Tool Purpose Inputs
reply Send a message to Codex as a new Codex turn. text required; optional chat_id, require_reply, handles_handoff_id, runtimeSessionId
get_messages Drain queued Codex messages in pull/fallback mode. none
wait_for_messages Long-poll for Codex messages, then return the same payload as get_messages. optional timeout_s, handoff_id; timeout clamped to 1..60 seconds
handoff Record a structured handoff to Codex and deliver it live. reason, ask required; optional context_refs, handles_handoff_id, timeout_policy, runtimeSessionId
deliberate_with_codex Run one bounded Claude-to-Codex deliberation and return Codex's reply for synthesis. question required; optional opening_position, context_refs, handles_handoff_id, timeout_s, timeout_policy, runtimeSessionId
append_note Add a durable Claude note to the shared ledger. text required; optional handles_handoff_id, runtimeSessionId
read_context Read recent ledger entries and latest active handoff for Claude. optional limit, handoff_id; limit clamped to 1..200
session_info Return session summary, runtime session inspection, ledger counts, active handoff, autonomy, finality, and backup state. none
create_session Create a registry-backed runtime session. Metadata only; runtime routing is unchanged. id required; optional label, worktreePath
select_session Select the registry-active runtime session for inspection. Runtime routing is unchanged. id required
archive_session Archive a registry-backed runtime session. Metadata only; launched runtimes must be exited first. id required
rebind_session Rebind a registry-backed runtime session to an existing worktree path. Metadata only; launched runtimes must be exited first. id required; optional worktreePath
task_state Return task lanes, policy state, artifacts, and finality blockers. none
record_artifact Store a structured patch, test, command, release-gate, or escalation artifact. kind, title, summary required; optional status, evidence, runtimeSessionId
ask_codex_backup Ask a read-only headless Codex backup agent for analysis. Requires autonomy enabled. ask required; optional reason, context_refs, runtimeSessionId
backup_status Return current backup-agent state and latest backup metadata. none
propose_final Record a finality proposal, or an auto-final decision when enabled and unblocked. summary, evidence required; optional remaining_risk, handles_handoff_id, runtimeSessionId

Codex MCP Tools

Codex receives these tools after:

ctxrelay codex-mcp install
Tool Purpose Inputs
send_to_claude Send a live message to Claude and record it in the ledger. text required; optional handles_handoff_id
handoff_to_claude Record a structured handoff to Claude and deliver it live. reason, ask required; optional context_refs, handles_handoff_id, wait_for_reply, timeout_seconds, poll_interval_ms, timeout_policy, runtimeSessionId
deliberate_with_claude Run one bounded Codex-to-Claude deliberation and return Claude's reply for synthesis. question required; optional opening_position, context_refs, handles_handoff_id, timeout_seconds, poll_interval_ms, timeout_policy, runtimeSessionId
read_context Read recent ledger entries and latest active handoff for Codex. optional limit, handoff_id; limit clamped to 1..200
wait_for_claude Wait for a Claude ledger reply, optionally scoped to a handoff. optional handoff_id, after_entry_id, timeout_seconds, poll_interval_ms, limit
append_note Add a durable Codex note to the shared ledger. text required; optional handles_handoff_id, runtimeSessionId
session_info Return session summary, runtime session inspection, active handoff, and ledger counts. none
create_session Create a registry-backed runtime session. Metadata only; runtime routing is unchanged. id required; optional label, worktreePath
select_session Select the registry-active runtime session for inspection. Runtime routing is unchanged. id required
archive_session Archive a registry-backed runtime session. Metadata only; launched runtimes must be exited first. id required
rebind_session Rebind a registry-backed runtime session to an existing worktree path. Metadata only; launched runtimes must be exited first. id required; optional worktreePath
task_state Return task lanes, policy state, artifacts, and finality blockers. none
record_artifact Store a structured patch, test, command, release-gate, or escalation artifact. kind, title, summary required; optional status, evidence, runtimeSessionId
ask_claude_backup Ask a read-only headless Claude backup agent for analysis. Requires autonomy enabled. ask required; optional reason, context_refs, handles_handoff_id, runtimeSessionId
backup_status Return current backup-agent state and latest backup metadata. none
propose_final Record a Codex finality proposal. summary, evidence required; optional remaining_risk, handles_handoff_id, runtimeSessionId

For validation handoffs, use handoff_to_claude with wait_for_reply: true; the tool waits for Claude to post a handled ledger reply before returning or timing out.

For deliberation, use deliberate_with_codex, deliberate_with_claude, or Claude's /contextrelay:deliberate <question> shortcut. Deliberation is intentionally bounded: one structured request, one peer response, then the calling agent synthesizes current consensus, remaining disagreement, and the next action. It is a coordination aid, not an automatic correctness guarantee.

When autonomy is enabled, ContextRelay's generated instructions tell Claude and Codex to ask each other for a bounded deliberation before asking the human about answerable planning, design, risk, or next-step questions. They still ask the human for authority, credentials, external business judgment, spending, destructive actions, and coordinator or git-policy changes.

Artifact kinds:

patch_summary
release_gate
test_report
command_log
escalation_suggestion

Artifact statuses:

passed
failed
blocked
unknown

Claude Slash Commands

ContextRelay also ships Claude Code slash commands. They are wrappers around the MCP tools above.

Command Purpose
/contextrelay:init Create or update project-local .contextrelay/config.json and .contextrelay/collaboration.md.
/contextrelay:status Show session, connection, ledger, handoff, autonomy, finality, and backup state.
/contextrelay:handoff <task> Ask Codex to take the next concrete task.
/contextrelay:review <focus> Ask Codex for a focused read-only review.
/contextrelay:deliberate <question> Run one bounded Claude-Codex deliberation and synthesize consensus, disagreement, and next action.
/contextrelay:finalize Prepare a finality proposal from current ledger evidence.

Codex Fallback Markers

When Codex MCP tools are unavailable, Codex can still use exact marker commands at the start of a message:

[IMPORTANT] CONTEXTRELAY_READ_CONTEXT: <optional focus>
[IMPORTANT] CONTEXTRELAY_TASK_STATE
[IMPORTANT] CONTEXTRELAY_NOTE: <note>
[IMPORTANT] CONTEXTRELAY_ARTIFACT:
kind: patch_summary|release_gate|test_report|command_log|escalation_suggestion
title: <short title>
summary: <what happened>
status: passed|failed|blocked|unknown
evidence:
- <optional evidence>
[IMPORTANT] CONTEXTRELAY_HANDOFF_TO_CLAUDE: <ask>
[IMPORTANT] CONTEXTRELAY_PROPOSE_FINAL:
summary: <what is complete>
evidence: <why it is complete>
remaining_risk: <optional risk>
handles_handoff_id: <optional handoff id or comma-separated ids>
[IMPORTANT] DONE: <summary>

Codex messages should put routing markers at the very start of the message. Use [IMPORTANT] for decisions, reviews, completions, and blockers; [STATUS] for progress updates; and [FYI] for background context. In filtered mode, [FYI] messages are dropped, [STATUS] messages may be buffered during busy turns, and [IMPORTANT] messages are forwarded.

Read-only backup triggers are explicit and separate:

[IMPORTANT] ASK_CLAUDE_BACKUP: <read-only help request>
[IMPORTANT] ASK_CODEX_BACKUP: <read-only help request>

Backup triggers only run when autonomy is enabled.

CLI Reference

Use contextrelay, context-relay, or ctxrelay; all point to the same CLI.

Command Purpose
contextrelay Open the full-screen native ContextRelay TUI with no subcommand.
ctxrelay tui [--no-start] [--force] Open the full-screen native terminal dashboard. --force renders even when stdin is not detected as an interactive TTY.
`ctxrelay init [--instructions project global
ctxrelay dev Register the local plugin marketplace and sync the local plugin for development.
ctxrelay claude [--session <id>] [args...] Start Claude Code with the ContextRelay plugin channel enabled. Explicit named sessions require CONTEXTRELAY_ALLOW_NAMED_SESSIONS=1; a missing session is created and bound to the current folder on first use.
ctxrelay codex [--session <id>] [args...] Start Codex TUI connected to the ContextRelay daemon and proxy. Explicit named sessions require CONTEXTRELAY_ALLOW_NAMED_SESSIONS=1; a missing session is created and bound to the current folder on first use.
`ctxrelay codex-mcp install remove
ctxrelay pair [--dry-run] [--no-tui] [--port-base <port>] Start Claude and Codex in separate terminal sessions, then keep the ContextRelay control TUI open. Use --no-tui when launching from an existing dashboard.
ctxrelay doctor [--no-auth] Diagnose binaries, auth, state, plugin registration, daemon health, tokens, and stale locks.
`ctxrelay instructions status install
`ctxrelay coordinator [status claude
`ctxrelay permissions status readonly on
ctxrelay detach-claude Clear the active Claude foreground connection without killing Codex or the daemon.
ctxrelay status [--json] Print daemon, session, connection, ledger, task, autonomy, finality, and backup state.
ctxrelay session list [--archived] | create <id> [--label <text>] [--worktree <path>] | select <id> | archive <id> | rebind <id> [--worktree <path>] [--json] List, create, select, archive, and rebind registry-backed runtime sessions. session create and session rebind bind named sessions to the current worktree by default; use --worktree <path> to bind a different checkout.
ctxrelay recover [--json] Summarize crash recovery context, recent failures, interrupted commands, git status, and a resume prompt.
ctxrelay instances List known project instances and assigned ports.
ctxrelay viewer [--no-open] Open the local Command Deck for status, task lanes, artifacts, policy, and timeline.
`ctxrelay autonomy on off
`ctxrelay finalize auto manual
`ctxrelay hook-compaction status verbose
ctxrelay release-gate [--json] Run build/check release readiness and record a release_gate artifact.
`ctxrelay kill [--all --session ]`

The native TUI uses the full terminal window and keeps the common control-plane actions in one place. The top header shows the ContextRelay version and bridge readiness. The Status panel shows transcript id, daemon pid, instance id, port group, ledger count, queue depth, same-project peer count, and any resolution warning surfaced by daemon status. The Runtime Sessions panel lists named runtime sessions when present. The Agents panel shows Claude and Codex connection state and role. The Controls panel shows coordinator, autonomy, finality, readonly policy state, and token mode. The Activity panel shows current handoff state, agent attachment state, the active handoff's derived state when available, and a width-aware capped strip of recent redacted handoffs and blocked or failed runtime events. The live status bar above the footer summarizes readiness, uptime, relay state, agent state, and the latest activity. The footer lists hotkeys as (r)efresh, (p)air, (v)iewer, (a)uto, (f)inal, (c)oord, (x)readonly, (t)token, and (q)uit.

Use p to launch the Claude + Codex pair, v to open the browser Command Deck, a to toggle autonomy, f to toggle auto-finality, c to cycle the coordinator, x to toggle readonly permission mode, and t to switch token mode between verbose and compact. Use v or ctxrelay viewer for the full timeline.

Hook compaction controls the pending-message context injected by the Claude UserPromptSubmit hook. The default token mode is verbose, which preserves the existing five-preview hook output. compact is opt-in and uses one preview, 200 preview characters, and a 60-second dedupe window for identical rendered hook output. Advanced users can keep a mode preset but override individual values:

ctxrelay hook-compaction status
ctxrelay hook-compaction compact
ctxrelay hook-compaction set --preview-limit 2 --preview-chars 240 --dedupe-seconds 45
ctxrelay hook-compaction verbose

The config shape is turnCoordination.hookCompaction = { mode, previewLimit, previewChars, dedupeSeconds } in .contextrelay/config.json. Precedence is environment variable, explicit config field, mode preset, then built-in default.

contextrelay and ctxrelay tui require an interactive terminal and start the project daemon unless --no-start is passed. Use ctxrelay status --json for scripts and CI. Use ctxrelay tui --force only when you intentionally want to render despite TTY detection.

By default, ContextRelay starts one Claude + Codex pair per project instance. If a pair is already active, p and ctxrelay pair skip the duplicate launch and record a pair-launch runtime event in the ledger.

Coordinator And Git Policy

The coordinator owns planning, task routing, and git-write responsibility. Default:

{
  "collaboration": {
    "coordinator": "claude",
    "gitWrites": "coordinator"
  }
}

Allowed coordinators:

  • claude: Claude coordinates planning and git; Codex handles delegated implementation, debugging, tests, and review.
  • codex: Codex coordinates planning and git when runtime permissions allow it and the human has approved that repo policy; Claude supports review, risk analysis, and delegated tasks.
  • human: the human coordinates and owns git; both agents execute delegated work and ask before git writes.

Change it manually:

ctxrelay coordinator status
ctxrelay coordinator claude
ctxrelay coordinator codex
ctxrelay coordinator human

Restart active Claude/Codex sessions after changing coordinator so startup instructions refresh.

Permission Policy

ContextRelay models mediated actions as:

read | write | shell | network | git | secrets | browser | external_api

The policy lives in .contextrelay/config.json. It applies to actions ContextRelay mediates directly; provider-native Claude Code and Codex approvals still run inside those tools. The external_api capability is reserved for future API-backed workers.

Add --agent <agentId> to apply readonly, allow, deny, or reset to one agent override instead of the global policy.

ctxrelay permissions status
ctxrelay permissions readonly on
ctxrelay permissions deny external_api
ctxrelay permissions allow external_api --agent reviewer
ctxrelay permissions reset

Permission decisions are recorded as runtime events in the shared ledger when mediated commands run.

Safety Defaults

  • Loopback-only daemon endpoints.
  • Local auth tokens for control APIs and viewer bootstrap.
  • Authenticated daemon status includes instanceId, projectRoot, stateDir, and controlPort; clients refuse to reuse a daemon when those fields do not match the current project.
  • Browser origin rejection.
  • Codex proxy auth passed through environment, not in the --remote URL.
  • Autonomy off by default.
  • Auto-finality off by default.
  • Backup agents are read-only.
  • Git writes should be performed only by the coordinator or the human.
  • Agents share ledger entries and messages, not hidden reasoning.

State And Ports

Project-local state:

.contextrelay/
├── config.json
├── sessions.json
├── state/
│   ├── daemon.pid
│   ├── daemon-identity
│   ├── codex-tui.pid
│   ├── codex-tui.json
│   ├── codex-app-server.pid
│   ├── daemon.lock
│   ├── status.json
│   ├── ports.json
│   ├── contextrelay.log
│   ├── killed
│   ├── token
│   ├── proxy-token
│   ├── viewer-token
│   ├── queue.db
│   ├── transcript.jsonl
│   └── runtime-sessions/
│       └── <runtimeSessionId>/
│           ├── codex-tui.pid
│           └── codex-tui.json
├── current
└── sessions/
    └── <sessionId>.jsonl

Global instance registry on macOS:

~/Library/Application Support/ContextRelay/instances.json

Default first port group:

4500 Codex app-server
4501 ContextRelay Codex proxy
4502 ContextRelay daemon control

Additional projects increment by 10: 4510/4511/4512, 4520/4521/4522, and so on. Use ctxrelay pair --port-base 4700 to request a specific group.

Environment Variables

Most users do not need to set these. The CLI exports project instance values automatically.

Variable Default Description
CODEX_WS_PORT auto group start 4500 Codex app-server WebSocket port.
CODEX_PROXY_PORT auto group start 4501 ContextRelay proxy port for Codex TUI.
CONTEXTRELAY_CONTROL_PORT auto group start 4502 Control port between plugin/frontend and daemon.
CONTEXTRELAY_PORT_BASE 4500 Starting point for automatic project port allocation.
CONTEXTRELAY_STATE_DIR .contextrelay/state during CLI launches Runtime state directory.
CONTEXTRELAY_REGISTRY_DIR platform app-state directory Global instance registry directory.
XDG_STATE_HOME ~/.local/state on Linux Linux base directory for the global registry and direct/internal state-dir defaults. Project CLI launches normally pass CONTEXTRELAY_STATE_DIR explicitly.
CONTEXTRELAY_INSTANCE_ID generated Stable project instance id exported by the CLI.
CONTEXTRELAY_PROJECT_ROOT current project root Project root exported by the CLI.
CONTEXTRELAY_ALLOW_NAMED_SESSIONS unset Set to 1 to enable opt-in named Codex runtime launch and non-default live routing. Session registry metadata is visible without this flag.
CONTEXTRELAY_NAMED_CODEX_RUNTIME_START_ATTEMPTS 3 Maximum daemon-side launch attempts when allocating concrete ports for a named Codex runtime.
CONTEXTRELAY_MODE push via ctxrelay claude, auto otherwise Message delivery mode: push, pull, or auto.
CONTEXTRELAY_RUNTIME_SESSION_ID unset Runtime session attached by ctxrelay claude --session <id>; replies default to this session when live multi-session is enabled.
CONTEXTRELAY_FILTER_MODE filtered Message-routing filter mode. Set to full to send full routing payloads.
CONTEXTRELAY_PAIR_BIN contextrelay CLI binary used by ctxrelay pair. Useful for local dist/cli.js testing.
CONTEXTRELAY_CLAUDE_DEVELOPMENT_CHANNELS 1 Set to 0 to use Claude's approved --channels path instead of development channel loading.
CONTEXTRELAY_MAX_BUFFERED_MESSAGES 100 Maximum undrained Claude-bound Codex messages kept per chat.
CONTEXTRELAY_MCP_TOOLS unset Optional comma/space-separated MCP tool allowlist. Unset or * exposes all tools.
CONTEXTRELAY_IDLE_SHUTDOWN_MS 30000 Idle daemon shutdown window.
CONTEXTRELAY_ATTENTION_WINDOW_MS 15000 Coordination window used while waiting for Codex turn settling.
CONTEXTRELAY_CLAUDE_PROBE_TIMEOUT_MS 3000 Liveness probe timeout before evicting a stale Claude frontend. Set 0 to disable probe eviction.
CONTEXTRELAY_CLAUDE_RESPONSE_TIMEOUT_MS 300000 Timeout before a Claude-owned active task lane is marked stale.
CONTEXTRELAY_CODEX_TURN_IDLE_TIMEOUT_MS 300000 Codex silence window before a stuck turn is force-cleared.
CONTEXTRELAY_TURN_MAX_MS 300000 Wall-clock budget for one Codex turn. Set 0 to disable.
TUI_DISCONNECT_GRACE_MS 2500 Grace period after Codex TUI disconnect before treating it as gone.
CONTEXTRELAY_MAX_DEPTH 3 Maximum relay recursion depth.
CONTEXTRELAY_BACKUP_THROTTLE_MS 60000 Minimum delay between backup starts for the same target.
CONTEXTRELAY_BACKUP_KILL_GRACE_MS 2000 Grace between backup timeout SIGTERM and SIGKILL.
CONTEXTRELAY_DAEMON_SHUTDOWN_STEP_TIMEOUT_MS 4000 Per-step daemon shutdown cleanup deadline.
CONTEXTRELAY_MAX_CONTROL_MESSAGE_BYTES 1000000 Maximum accepted control WebSocket message size.
CONTEXTRELAY_MAX_CONTROL_MESSAGES_PER_MINUTE 120 Per-control-connection rate limit.
CONTEXTRELAY_DAEMON_ENTRY bundled daemon Plugin daemon entry override. Requires CONTEXTRELAY_ALLOW_DAEMON_ENTRY_OVERRIDE=1.
CONTEXTRELAY_ALLOW_DAEMON_ENTRY_OVERRIDE unset Set to 1 only for local development/tests.
CONTEXTRELAY_HEALTH_HOOK_COOLDOWN_SECONDS 120 Cooldown for bundled Claude health-check hook reminders.
CONTEXTRELAY_HOOK_STATE_DIR ${TMPDIR:-/tmp}/contextrelay-hooks State directory for bundled hook scripts.
CONTEXTRELAY_HOOK_COMPACT unset Set to 1 to force the compact UserPromptSubmit hook preset for automation.
CONTEXTRELAY_HOOK_PREVIEW_LIMIT mode preset Override pending-message preview count for the UserPromptSubmit hook. Range: 1-20.
CONTEXTRELAY_HOOK_PREVIEW_CHARS mode preset Override pending-message preview character cap for the UserPromptSubmit hook. Range: 40-4000.
CONTEXTRELAY_HOOK_DEDUPE_SECONDS mode preset Override identical hook-output suppression window. Set 0 to disable dedupe.
CONTEXTRELAY_AUTO_REGISTER unset Set to 1 during npm install/postinstall to opt into automatic Claude plugin registration.
CONTEXTRELAY_AUTO_UNREGISTER unset Set to 1 during uninstall/preuninstall to remove Claude plugin registration.
CONTEXTRELAY_POSTINSTALL_DRY_RUN unset Set to 1 to print postinstall/preuninstall actions without changing plugin registration.
CONTEXTRELAY_POSTINSTALL_STRICT unset Set to 1 to make optional postinstall registration failures exit non-zero. Useful for CI install verification.
CONTEXTRELAY_CODEX_PROXY_TOKEN generated Internal Codex remote-auth token. The CLI sets it for Codex.
CONTEXTRELAY_CODEX_APP_SERVER_TRANSPORT auto Internal Codex app-server transport override. Used for compatibility testing and diagnostics.

Manual port override rule: set all three port variables (CODEX_WS_PORT, CODEX_PROXY_PORT, CONTEXTRELAY_CONTROL_PORT) or set none. Partial overrides are rejected.

Claude Code supplies CLAUDE_PLUGIN_ROOT for bundled hook script paths and may supply CLAUDE_PROJECT_DIR for project scoping. ContextRelay's health-check hook falls back to PWD when CLAUDE_PROJECT_DIR is unset.

Test harnesses use CONTEXTRELAY_FAKE_DAEMON_LAUNCH_LOG, CONTEXTRELAY_FAKE_DAEMON_DELAY_MS, CONTEXTRELAY_SHIM_LOG_DIR, and CONTEXTRELAY_CODEX_SHIM_HOLD_MS internally. They are not runtime configuration knobs.

Viewer And Metrics

ctxrelay viewer opens the Command Deck, a token-authenticated local browser view for the current project instance. It shows connection health, agent idle/busy/stale/offline state, task lanes, artifacts, policy, and a latest-first timeline. It cannot send messages, approve work, or mutate git state, but it can clear the current shared session history through its authenticated history endpoint.

Authenticated local endpoints:

/viewer
/api/viewer/status
/api/viewer/context
/api/viewer/history
/api/viewer/events
/metrics

Scrape metrics:

TOKEN=$(cat "$(ctxrelay status --json | jq -r .stateDir)/token")
PORT=$(ctxrelay status --json | jq -r .controlPort)
curl -H "Authorization: Bearer $TOKEN" "http://127.0.0.1:$PORT/metrics"

Examples

The examples/ directory contains small projects for local smoke tests:

  • examples/pair-counter/: minimal HTML/JS counter.
  • examples/shopping-basket/: browser shopping basket with pure ESM state and Bun tests.

Run the basket tests:

bun test ./examples/shopping-basket/basket.test.js

Run either UI with a static file server:

python3 -m http.server --bind 127.0.0.1 8765 --directory examples/pair-counter
python3 -m http.server --bind 127.0.0.1 8765 --directory examples/shopping-basket

Troubleshooting

If the npm install hook fails in a sandboxed shell, air-gapped CI runner, or container without Claude Code on the PATH, run the postinstall script in dry-run mode:

CONTEXTRELAY_POSTINSTALL_DRY_RUN=1 node node_modules/@proofofwork-agency/contextrelay/scripts/postinstall.cjs
CONTEXTRELAY_POSTINSTALL_DRY_RUN=1 CONTEXTRELAY_AUTO_REGISTER=1 node node_modules/@proofofwork-agency/contextrelay/scripts/postinstall.cjs
CONTEXTRELAY_POSTINSTALL_DRY_RUN=1 CONTEXTRELAY_AUTO_UNREGISTER=1 node node_modules/@proofofwork-agency/contextrelay/scripts/preuninstall.cjs

Common checks:

ctxrelay doctor
ctxrelay status
ctxrelay instances
ctxrelay detach-claude
ctxrelay kill
ctxrelay kill --session <id>

Development

Run the full local check:

bun run check

Run focused tests:

bun test src/unit-test/instructions.test.ts src/e2e-cli.test.ts

Build bundles:

bun run build:cli
bun run build:plugin

After changing plugin code:

ctxrelay dev
/reload-plugins

Before release:

ctxrelay release-gate --json

release-gate first runs the full check against existing artifacts so stale bundles fail before any rebuild can hide them. It then rebuilds the CLI and plugin bundles, reruns the full check, generates build metadata, runs the npm package smoke (bun run verify:package), and records a release_gate artifact in the shared ledger.

Limits

  • ContextRelay depends on Claude Code plugin/channel behavior and Codex app-server behavior.
  • One default Codex TUI and one default Claude foreground connection are expected per project instance unless named sessions are explicitly enabled.
  • Named sessions are opt-in runtime pairs, not separate transcript ledgers or multi-agent orchestration.
  • Backup agents are read-only and intended for analysis, not implementation.
  • ContextRelay is local developer tooling, not a security boundary between tools you do not trust.
  • Git writes should be handled only by the configured coordinator or the human.

Documentation

License

MIT. See LICENSE. ContextRelay preserves the original AgentBridge MIT copyright notice and adds the ProofOfWork / Danillo Felix copyright notice for this fork's changes.

Credit

ContextRelay is forked from raysonmeng/agent-bridge. AgentBridge demonstrated that Claude Code and Codex could communicate through the tool they were building together. ContextRelay keeps that foundation and adds shared context, explicit handoffs, backup agents, finality controls, setup diagnostics, and project-owned packaging.

About

ContextRelay bridge for Claude Code and Codex with a shared daemon, push channel delivery, and bidirectional reply tooling.

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors