Tutorial: go dormant, then opt a session back in
ContextRelay ships auto-connect on: every Claude Code session in a project with a managed instruction block engages the collaboration loop. That is the right default when you pair Claude and Codex regularly. But plenty of developers run Claude Code solo most of the time and only want ContextRelay for a handful of specific sessions.
This tutorial walks the full dormancy lifecycle: make ContextRelay quiet by default for your user, confirm nothing surfaces in a fresh session, opt one workspace back in on demand, verify it is active, then leave again - all without touching the project's committed config or your peer's setup.
A developer who wants ContextRelay off unless asked for. If you instead want it on everywhere (the shipped behavior), you do not need any of this - just start your pair. See Activation: auto-connect vs dormant for the full model.
The principle: an explicit precedence chain
Everything below is governed by one deterministic resolver (resolveActivation in
src/activation.ts). When a hook or the CLI asks "is ContextRelay active for this session?",
the answer is decided top-down by the first rule that matches:
- Env override -
CONTEXTRELAY_AUTO_CONNECT=1/0wins over everything, for that one invocation. - Per-session attach marker - a marker file for this workspace forces active.
- Project flag -
activation.autoConnectin the project's.contextrelay/config.json, if set. - Global flag -
autoConnectin~/.contextrelay/activation.json, if set. - Shipped default -
active(auto-connect on). This is why doing nothing keeps it on.
Going dormant means writing rule 4 (global flag = off). Opting a session back in means writing
rule 2 (the attach marker), which beats the global flag. Keep that order in mind - every step is
just nudging one tier of this chain.
Prerequisites
- ContextRelay installed (
@proofofwork-agency/contextrelay) andinitalready run at least once, so a managed instruction block exists. See Install and first run. - The
ctxrelayCLI on your PATH. The binariescontextrelay,ctxrelay, andcontext-relayare interchangeable - this page usesctxrelay.
Step 1 - go dormant
From any shell, make ContextRelay dormant for your whole user account:
ctxrelay standalone on
The default scope is global, so this is equivalent to ctxrelay standalone on --scope global.
Three things change:
- Activation flag. Writes
~/.contextrelay/activation.jsonwithautoConnectset tofalse(tier 4 of the precedence chain). - Slimmed instructions. Replaces the full collaboration ruleset with a short dormant block in
the always-on
CLAUDE.md/AGENTS.mdcopies in your home and conventional global locations, so fresh sessions no longer load the full ContextRelay protocol. Only files that already carry a managed block are touched. - Bare command installed. Drops a
/contextrelayuser command at~/.claude/commands/contextrelay.mdso you can opt a session back in from inside Claude.
The command prints a summary of which instruction files it slimmed and confirms the bare command is installed.
standalone on never slims the current repo's committed CLAUDE.md/AGENTS.md - those stay
full so the repo's own verify:instructions check keeps passing. To slim a specific parent-folder
copy, pass it explicitly with --path <file> (repeatable). A warning fires if the file you
target is inside a git repo, since committing that change could affect that repo's CI.
Use --scope project to write the flag into that project's .contextrelay/config.json (tier 3)
instead of your global account, or --scope both for both. Project scope leaves your other
projects on the shipped default.
Step 2 - confirm it is quiet
Ask the activation gate directly what it resolves to here:
ctxrelay gate-check --status
When dormant, this prints dormant and exits with code 1. (gate-check is the cheap,
daemon-free resolver the SessionStart and per-prompt hooks consult - pure file, env, and marker
reads.) For the human-readable reasoning, add --why:
ctxrelay gate-check --why
# dormant - global config autoConnect=false
The --why reason tells you which tier decided the outcome, which is the fastest way to debug
an unexpected result later. You can also see the whole picture at once:
ctxrelay standalone status
That reports the resolved state here, the project and global flag values, whether the bare command is installed, and which home/ancestor instruction files carry slim or full blocks.
Now open a fresh Claude Code session in this workspace. The SessionStart and UserPromptSubmit hooks consult the gate, see dormant, and no longer surface ContextRelay - no ruleset, no peer nudges. Claude runs solo.
If gate-check ever hits an unexpected error, it exits 0 (active) on purpose. A bug in the
gate must never silently suppress the collaboration loop - so the failure mode is "stays on," not
"goes dark." A clean exit 1 always means a genuine dormant resolution.
Step 3 - opt one session back in
When you do want Claude and Codex paired for a specific piece of work, opt this workspace back in from its directory:
ctxrelay attach
attach is the deterministic counterpart of standalone on, and it does not care how Claude was
launched. It:
- Ensures the daemon is running so the bridge and registry are reachable.
- Writes the per-workspace activation marker at
<stateDir>/activation/<key>.on, where<key>is derived from the resolved project directory. This marker is tier 2 - it beats the dormant global flag from Step 1. - Prints the full collaboration ruleset to stdout. Because the always-on block was slimmed in
Step 1,
attachre-delivers the complete protocol in-session so this Claude has it. - Prints the peer on-ramp - how to start Codex.
You can attach from inside a running Claude session instead, using the bare command that
standalone on installed:
/contextrelay
That runs ctxrelay attach and injects its output (the full ruleset) back into the conversation.
The equivalent plugin command is /contextrelay:on, which also maps to attach and accepts an
optional session name.
Pass a session name to bind a named session in the registry: ctxrelay attach feature-x (or
/contextrelay feature-x). This is registry-only - it never spawns a Codex TUI. For fully
isolated routing on both sides, the command reminds you to relaunch with
ctxrelay claude --session feature-x instead.
Step 4 - verify it is active
Re-run the gate. The marker now short-circuits the chain at tier 2:
ctxrelay gate-check --why
# active - session attached (marker present)
The status flag agrees and exits 0:
ctxrelay gate-check --status
# active
The reason string session attached (marker present) is the proof that the marker won - not
the global flag. ContextRelay is active for this workspace; your next prompt re-engages the hooks.
Bring up the pair as usual (for example with ctxrelay codex in another terminal, or
ctxrelay pair from a fresh shell). See Daily operation.
Step 5 - leave again
When the paired work is done and you want this workspace quiet again, drop the marker:
ctxrelay detach
detach removes only this workspace's activation marker. It is idempotent (safe to run when no
marker exists) and intentionally narrow:
detach does not stop the daemon or Codex - it only clears the per-session opt-in. To actually
shut the runtime down, use ctxrelay kill. Leaving the daemon running is usually what you want; it
idles cheaply and the next attach reuses it.
You can also detach from inside Claude with /contextrelay:off, which runs ctxrelay detach.
Confirm you are back to dormant - with the marker gone, the chain falls through to the global flag again:
ctxrelay gate-check --status
# dormant
Precedence in practice: the env override
For a one-off, you do not need to touch any flag or marker at all. The env override is tier 1 and wins for that single invocation:
# Force ACTIVE for one launch, even while dormant-by-default:
CONTEXTRELAY_AUTO_CONNECT=1 ctxrelay gate-check --why
# active - env CONTEXTRELAY_AUTO_CONNECT (on)
# Force DORMANT for one launch, even where it would otherwise be active:
CONTEXTRELAY_AUTO_CONNECT=0 ctxrelay gate-check --why
# dormant - env CONTEXTRELAY_AUTO_CONNECT (off)
This is handy for scripts and CI, or to sanity-check the gate without changing persistent state.
Reverting fully
To undo Step 1 and return to the shipped auto-connect-on behavior for your whole account:
ctxrelay standalone off
This restores autoConnect to true (or restores the full instruction blocks where they were
slimmed) and removes the bare /contextrelay command. Pass --scope project or --scope both to
mirror whatever scope you used when going dormant.
What changed where
| Action | Tier touched | On disk |
|---|---|---|
standalone on | Global flag (tier 4) | ~/.contextrelay/activation.json → autoConnect:false; slimmed CLAUDE.md/AGENTS.md; bare command at ~/.claude/commands/contextrelay.md |
attach | Session marker (tier 2) | <stateDir>/activation/<key>.on |
detach | Session marker (tier 2) | marker removed |
standalone off | Global flag (tier 4) | autoConnect:true; full blocks restored; bare command removed |
CONTEXTRELAY_AUTO_CONNECT | Env override (tier 1) | nothing (per-invocation only) |
Next steps
- Activation: auto-connect vs dormant (standalone) - the full precedence model behind this lifecycle.
- CLI command reference - every flag for
standalone,attach,detach, andgate-check. - Install and first run - get the managed block and CLI in place before going dormant.
- Daily operation: launch, inspect, stop - bring the pair up once a session is active.