Skip to main content

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.

Who this is for

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.md instruction files,
  • the bare /contextrelay command, 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 init at least once (a .contextrelay/ directory and a managed instruction block exist).
  • The ctxrelay CLI 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.

Leave yourself a breadcrumb

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 status prints the configured coordinator and gitWrites policy.
  • ctxrelay permissions status prints the full permission block (readonly, the allowed capability list, and any per-agent overrides).
  • ctxrelay status --json is 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:

  1. Records the applied version. It stamps appliedVersion into .contextrelay/config.json so the next run (and ctxrelay doctor) can show the from → to change.
  2. 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, like init.
  3. Refreshes the managed instruction blocks in the CLAUDE.md / AGENTS.md files 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.
  4. Refreshes the bare /contextrelay command at ~/.claude/commands/contextrelay.md only if it already exists (it exists when you have gone dormant with ctxrelay standalone on). If it is absent, upgrade does not create it.
  5. 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), upgrade prints a clear remediation instead of failing the whole command.
Your settings are preserved, not reset

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.

Reload the plugin in a running session

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

FlagEffect
--dry-runCompute and print the plan only. Writes nothing and runs no plugin install.
--no-pluginSkip 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, --helpShow usage.
# Reconcile config and plugin only; leave all instruction files alone
ctxrelay upgrade --instructions skip
Older releases - manual fallback

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 doctor checks binaries, auth, state, plugin registration, daemon health, tokens, and stale locks. Add --no-auth to skip the Claude/Codex auth probes for a quick local-only check.
  • ctxrelay status prints 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.

Pick up new bundles in a long-running daemon

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.

Review committed instruction changes

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

StepCommandWhy
1. Clean pointctxrelay statusNo agent mid-turn; no open handoff.
2. Record policyctxrelay coordinator status · ctxrelay permissions status · ctxrelay status --jsonA before-snapshot to compare against.
3. Update packagenpm install -g @proofofwork-agency/contextrelay@latestctxrelay --versionNew bundles on disk.
4. Reconcilectxrelay upgrade --dry-runctxrelay upgradePreview, then bring the managed surface in line - settings preserved.
5. Verifyctxrelay doctor · ctxrelay status · re-read policy · ctxrelay pairHealthy, settings intact, agents reconnect.

Next steps