Tutorial: upgrade ContextRelay safely
A new ContextRelay version is out and you want it - but you have a live project with a configured coordinator, tuned permissions, and maybe an in-flight handoff between Claude and Codex. The fear is the usual one: that bumping a tool quietly resets your settings or drops you into a half-migrated state mid-work.
This tutorial removes that fear. You will upgrade in a sequence designed to be safe while a
project is active: reach a clean point, record your current policy, update the package, reconcile
with ctxrelay upgrade (previewing first), then verify the things you recorded survived. By the
end you will have a repeatable upgrade ritual and a clear rollback path.
A developer with a working ContextRelay project who wants to move to a newer release without losing config or interrupting the pair. For the conceptual reference version of these steps, see Upgrading ContextRelay in Getting Started - this page is the hands-on companion to it.
The principle: update, then reconcile
ContextRelay ships prebuilt bundles to npm as @proofofwork-agency/contextrelay, so there is no
source build on the user path. Updating the package only swaps the files on disk. It does not
touch the agent-facing surface ContextRelay manages for you:
- your project
.contextrelay/config.json(coordinator, permissions, activation, budgets…), - the managed blocks in your
CLAUDE.md/AGENTS.mdinstruction files, - the bare
/contextrelaycommand, if you installed one, - the Claude plugin that Claude Code has registered.
ctxrelay upgrade is the reconcile step that brings that surface in line with the package you just
installed. It is the third flow alongside ctxrelay init
(first-time setup) and ctxrelay dev (local source rebuild). Crucially, its config reconciliation
is additive - it adds new default keys and preserves every value you set - which is why config
loss should never be the failure mode of an upgrade.
The binaries contextrelay, ctxrelay, and context-relay are interchangeable; this page uses
ctxrelay.
Prerequisites
- An existing ContextRelay project where you have run
initat least once (a.contextrelay/directory and a managed instruction block exist). - The
ctxrelayCLI on your PATH. - Ideally, your project under version control so you can review and, if needed, revert changes.
Step 1 - Reach a clean point
Upgrade between turns, not in the middle of one. If Claude or Codex is mid-turn or there is an open handoff, finish or pause it so nothing is interrupted. Check the live state:
ctxrelay status
This prints daemon, session, connection, ledger, task, and finality state as JSON. Confirm there is no active turn or unresolved handoff in flight before you proceed.
If you are pausing real work to upgrade, drop a durable note to the shared ledger first (from inside
an agent session, the append_note tool) describing the goal, files touched, and next step. The
upgrade does not clear the ledger, but a clean handoff note makes resuming after the bump painless.
Step 2 - Record your current policy
Capture the settings you most want to confirm survive the upgrade. These are plain reads - they change nothing - so run them now and keep the output:
ctxrelay coordinator status
ctxrelay permissions status
ctxrelay status --json
ctxrelay coordinator statusprints the configuredcoordinatorandgitWritespolicy.ctxrelay permissions statusprints the full permission block (readonly, theallowedcapability list, and any per-agent overrides).ctxrelay status --jsonis your before-snapshot of daemon, session, and ledger state.
You will compare against these in Step 5. Recording them up front turns "did anything change?" into a concrete diff instead of a guess.
Step 3 - Update the package
Now update the npm package. To move to the latest release:
npm install -g @proofofwork-agency/contextrelay@latest
Or pin to a specific line when you want a controlled bump:
npm install -g @proofofwork-agency/contextrelay@3.x
Confirm the new version is on disk:
ctxrelay --version
At this point the files are updated but your project is not yet reconciled - that is the next step.
Step 4 - Reconcile (preview, then apply)
Always look before you leap. From inside your project, compute the plan without writing anything:
ctxrelay upgrade --dry-run
The dry run prints the full plan and performs zero writes and no plugin install: the version
change (from X → Y), the config keys that would be added, the instruction files that would be
refreshed and in which state (full or slim), and the bare-command and plugin actions. Read it. This
is the safest way to inspect a bump before applying it.
When the plan looks right, apply it:
ctxrelay upgrade
ctxrelay upgrade reconciles the following, in order, and prints a summary at the end:
- Records the applied version. It stamps
appliedVersioninto.contextrelay/config.jsonso the next run (andctxrelay doctor) can show thefrom → tochange. - Migrate-merges the project config. It deep-merges the current defaults into your existing
.contextrelay/config.json: new default keys are added, and every value you set is preserved - coordinator, permissions, activation (auto-connect vs dormant), autonomy, budgets, write-mode are all left exactly as they are. If no project config exists yet, it creates one with defaults, likeinit. - Refreshes the managed instruction blocks in the
CLAUDE.md/AGENTS.mdfiles that already carry a ContextRelay block (your project files plus the conventional global and ancestor copies). Each file's state is preserved: a full block re-renders as full, and a slim (dormant) block stays slim. Only the content inside the managed markers is touched - your own prose outside that region is never altered. - Refreshes the bare
/contextrelaycommand at~/.claude/commands/contextrelay.mdonly if it already exists (it exists when you have gone dormant withctxrelay standalone on). If it is absent,upgradedoes not create it. - Re-registers and reinstalls the Claude plugin so Claude Code picks up the new bundles. This
step is best-effort: if it fails (Claude Code not installed, or you are offline),
upgradeprints a clear remediation instead of failing the whole command.
Config reconciliation is purely additive. upgrade does not reset your coordinator, flip your
activation state, change your permissions, or un-slim a dormant file. It also does not run git,
npm, or release operations, and it does not force-restart the daemon. Read the printed summary so you
know exactly what it touched.
ctxrelay upgrade re-registers the plugin, but a Claude Code session that is already open keeps
the previously loaded plugin until you reload it. When the upgrade finishes, run /reload-plugins
in your active Claude Code session (or restart it). upgrade reminds you of this in its summary.
Flags you may want
| Flag | Effect |
|---|---|
--dry-run | Compute and print the plan only. Writes nothing and runs no plugin install. |
--no-plugin | Skip the Claude plugin re-register/reinstall step. Use this offline, or when Claude Code is not installed; config and instruction reconciliation still run. |
--instructions <mode> | refresh (default) updates only files that already have a block, preserving slim/full; project / global / both also install blocks where missing (like init); skip touches no instruction files. |
-h, --help | Show usage. |
# Reconcile config and plugin only; leave all instruction files alone
ctxrelay upgrade --instructions skip
If you are on a ContextRelay release that predates ctxrelay upgrade, do the same reconciliation by
hand: run ctxrelay dev (local checkout) or reinstall the shipped plugin to re-register it,
ctxrelay instructions install --scope project (or global / both) to refresh the managed blocks,
then ctxrelay doctor to confirm. Finish active work and run ctxrelay kill, then relaunch your
agents so a long-running daemon loads the new bundle. Run /reload-plugins in any open Claude
session afterward.
Step 5 - Verify
Confirm the upgrade is healthy and that the policy you recorded in Step 2 survived:
ctxrelay doctor
ctxrelay status
ctxrelay doctorchecks binaries, auth, state, plugin registration, daemon health, tokens, and stale locks. Add--no-authto skip the Claude/Codex auth probes for a quick local-only check.ctxrelay statusprints the live daemon, session, and ledger state.
Now re-run the two policy reads and compare them against what you saved in Step 2 - they should match:
ctxrelay coordinator status
ctxrelay permissions status
If the coordinator and permissions are unchanged and doctor is clean, the reconcile did its job.
Bring the pair back up and confirm both agents reconnect:
ctxrelay pair
See Daily operation for the full launch-inspect-stop loop.
ctxrelay upgrade does not force-restart the daemon, so a daemon that was already running can keep
using the previously loaded bundle. To be certain it is on the new code: finish any active turns and
handoffs, run ctxrelay kill, then relaunch your agents (ctxrelay claude / ctxrelay codex, or
ctxrelay pair).
If something regresses: rollback
Because config reconciliation preserves your explicit settings, config loss should not be the failure mode - so if a new version misbehaves, the safe move is to step back to the version that worked:
# Reinstall the prior version, then reconcile again to that version
npm install -g @proofofwork-agency/contextrelay@<previous-version>
ctxrelay upgrade
Running ctxrelay upgrade again after reinstalling re-records the applied version and re-renders the
instruction blocks for the version now on disk. Your .contextrelay/config.json keeps the values you
set across both directions; only new-default keys differ between versions. Re-run ctxrelay doctor
to confirm you are back to a clean state.
A refresh rewrites the managed block inside your committed CLAUDE.md / AGENTS.md. If those files
are version-controlled, review the diff and commit it deliberately (a fix or chore branch + PR) so
the change is reviewed rather than slipping in. ContextRelay never deletes content outside its own
managed markers.
The whole ritual, in order
| Step | Command | Why |
|---|---|---|
| 1. Clean point | ctxrelay status | No agent mid-turn; no open handoff. |
| 2. Record policy | ctxrelay coordinator status · ctxrelay permissions status · ctxrelay status --json | A before-snapshot to compare against. |
| 3. Update package | npm install -g @proofofwork-agency/contextrelay@latest → ctxrelay --version | New bundles on disk. |
| 4. Reconcile | ctxrelay upgrade --dry-run → ctxrelay upgrade | Preview, then bring the managed surface in line - settings preserved. |
| 5. Verify | ctxrelay doctor · ctxrelay status · re-read policy · ctxrelay pair | Healthy, settings intact, agents reconnect. |
Next steps
- Upgrading ContextRelay - the reference version of this flow, with every flag spelled out.
- config.json reference - every key that reconciliation preserves or adds.
- Troubleshooting and FAQ - what to do if the plugin, daemon, or config looks wrong after an upgrade.
- Frequently asked questions - quick answers to common upgrade and setup questions.