Overview
ctx preserves Claude Code session context across compactions — automatically.
When Claude Code hits its context window limit, it compacts the conversation. This is necessary, but lossy: your current goal, technical decisions, the file you were editing, what to do next — all of it can get diluted or lost. After two or three compactions, Claude may forget what you were building, repeat work, or contradict decisions you already made together.
ctx hooks into Claude Code’s PreCompact, PostCompact, and SessionStart events to capture and restore a structured snapshot of your working context, every time. Snapshots are scoped per branch, so parallel sessions on different branches never collide.
Vision
Every Claude Code session starts exactly where you left off.
Mission
Capture the minimum context needed to resume work, automatically, at the right moment.
Philosophy
The most recent state is the only state that matters. Compaction is not loss — it’s a checkpoint. One snapshot per branch, always current, never accumulated. If it’s in the code, git has it. If it’s not, it shouldn’t survive anyway.
ctx is not a memory tool. It doesn’t accumulate knowledge across sessions, index conversations, or build a searchable history. It solves one specific problem: keeping the current session coherent when context gets compacted.
How It Works
ctx hooks into three Claude Code lifecycle events:
| Hook | When | What ctx does |
|---|---|---|
| PreCompact | Before compaction fires | Reads transcript + git state, calls claude -p, writes snapshot |
| PostCompact | After compaction completes | Re-injects the snapshot into the compacted session |
| SessionStart | Every new session | Finds snapshot for project + branch, prints it as context |
The Flow
┌──────────────────────────────────────────────────────────────┐
│ Claude Code session │
│ │
│ /compact triggered │
│ │ │
│ ▼ │
│ PreCompact hook → ctx reads transcript + git state │
│ → calls claude -p to extract semantics │
│ → writes snapshot (scoped to branch) │
│ │
│ PostCompact hook → ctx reads the snapshot just written │
│ → prints it to stdout │
│ → Claude Code re-injects it immediately │
│ │
│ New session on same branch │
│ │ │
│ ▼ │
│ SessionStart hook → ctx finds snapshot for project+branch │
│ → prints it to stdout │
│ → Claude Code injects it as context │
└──────────────────────────────────────────────────────────────┘
Why PostCompact Re-Injection Matters
After compaction, the context is summarized. PostCompact runs immediately after — ctx prints the snapshot back, so Claude re-enters the session with structured context intact. No information gap between pre-compaction and post-compaction state.
Branch Scoping
Snapshots are stored per project per branch:
~/.local/share/ctx/{sha256(project_path)}/{branch}/snapshot.md
Two sessions on different branches in the same repo never overwrite each other. Non-git directories and detached HEAD use _ as the branch name.
What ctx Does NOT Do
- Does not keep a history of previous snapshots
- Does not sync between machines
- Does not require git
- Does not auto-expire snapshots
- Does not read chop’s SQLite database
- Does not handle subagent transcripts (everything relevant is already in the orchestrator’s transcript)
Quick Start
Get ctx running in under a minute.
Install
macOS / Linux:
curl -fsSL https://raw.githubusercontent.com/AgusRdz/ctx/main/install.sh | sh
Windows (PowerShell):
irm https://raw.githubusercontent.com/AgusRdz/ctx/main/install.ps1 | iex
Register Hooks
ctx init
This registers three hooks in ~/.claude/settings.json: PreCompact, PostCompact, and SessionStart.
Verify
ctx init --status
Expected output:
hooks: installed
PreCompact · auto ✓
PreCompact · manual ✓
PostCompact · auto ✓
PostCompact · manual ✓
SessionStart ✓
Try It
- Open a Claude Code session and do some work
- Run
/compactto trigger compaction - Check the snapshot:
ctx show - Open a new session — ctx automatically injects the snapshot
That’s it. ctx works silently from this point forward.
Installation
Install Script
macOS / Linux:
curl -fsSL https://raw.githubusercontent.com/AgusRdz/ctx/main/install.sh | sh
Windows (PowerShell):
irm https://raw.githubusercontent.com/AgusRdz/ctx/main/install.ps1 | iex
Homebrew
brew install AgusRdz/tap/ctx
Go Toolchain
go install github.com/AgusRdz/ctx@latest
Binary Location
| Platform | Path |
|---|---|
| macOS / Linux | ~/.local/bin/ctx |
| Windows | %LOCALAPPDATA%\Programs\ctx\ctx.exe |
Register Hooks
After installing, register ctx with Claude Code:
ctx init
To remove hooks:
ctx init --remove
Verify Attestations
All release binaries include build provenance attestations verifiable with the GitHub CLI:
gh attestation verify <binary> --repo AgusRdz/ctx
Update
ctx updates itself automatically in the background — once every 24 hours it checks for a new release and applies it silently on the next invocation.
ctx update # update immediately
ctx changelog # see what changed
Commands
Setup
ctx init Register PreCompact, PostCompact, and SessionStart hooks
ctx init --remove Remove ctx hooks
ctx init --status Check hook installation status
ctx init --local Create local project config (.ctx/config.yml)
Session
ctx show Print snapshot for current branch
ctx show --project <path> Print snapshot for a specific project
ctx state Capture and print current project state
ctx clear Delete snapshot for current branch
ctx clear --all Delete all branch snapshots for this project
ctx list List all projects and branches with snapshots
Configuration
ctx config Show effective configuration with sources
ctx config --global Show only global config file
ctx config --local Show only local config file
ctx config --debug true Enable verbose hook logging
Diagnostics
ctx doctor Check hooks, binary path, claude availability
ctx logs Show last 20 hook log entries
ctx logs -n <N> Show last N entries
ctx logs --all Show all entries
Maintenance
ctx update Update to the latest version
ctx uninstall Remove ctx completely (hooks, data, binary)
ctx version Show version
ctx changelog Show changes in the current version
ctx changelog --full Show full changelog history
Configuration
ctx uses two config layers that merge field-by-field. Local values win over global.
Global Config
Location: ~/.config/ctx/config.yml (Windows: %APPDATA%\ctx\config.yml)
core:
debug: false
claude_timeout: 30 # seconds; default 30
Local Config
Location: {project}/.ctx/config.yml (optional, project-level overrides)
Create with:
ctx init --local
.ctx/ is automatically added to .gitignore — local config is a developer preference, not a team setting.
Project State Config
Controls what ctx captures at compaction time:
project_state:
enabled: true
git: true
typecheck:
enabled: true
timeout_seconds: 20
command: "" # custom command overrides auto-detection
tests:
enabled: false # opt-in — can be slow
timeout_seconds: 60
max_failed_names: 5
command: "" # custom command overrides auto-detection
max_dirty_files: 10
max_errors: 5
Auto-detection for typecheck covers tsc (tsconfig.json) and go build (go.mod). For everything else, set a custom command:
# dotnet build (C#)
project_state:
typecheck:
enabled: true
command: "dotnet build --no-restore -v minimal"
# mypy (Python)
project_state:
typecheck:
enabled: true
command: "mypy src --no-error-summary"
# clippy (Rust)
project_state:
typecheck:
enabled: true
command: "cargo clippy --quiet 2>&1"
View Effective Config
ctx config
Output:
effective configuration
───────────────────────────────────────
core.debug false [default]
core.claude_timeout 30 [default]
global: ~/.config/ctx/config.yml
local: /home/agus/projects/myapp/.ctx/config.yml
Docker-based projects: ctx runs typecheck commands on the host. If your build runs inside Docker, disable typecheck in your local config:
project_state:
typecheck:
enabled: false
Snapshot Format
The snapshot is a structured markdown document with four fields, capped at 300 tokens.
Structure
# Session Context
_Captured: 2026-03-09T14:32Z_
## Goal
Building the authentication middleware
## Decisions
- Using JWT with RS256 for token signing
- Middleware applied at router level, not per-handler
## In Progress
auth/middleware.go | 45 +++++++++
auth/jwt.go | 32 ++++++
2 files changed, 77 insertions(+)
## Next
Add token refresh endpoint and write integration tests
Fields
| Field | What it captures |
|---|---|
| Goal | What you’re building right now |
| Decisions | Technical choices made this session |
| In Progress | Files being modified (git diff –stat) |
| Next | What to do when context resumes |
Storage Location
| Platform | Path |
|---|---|
| Linux/macOS | ~/.local/share/ctx/{project-hash}/{branch}/snapshot.md |
| Windows | %LOCALAPPDATA%\ctx\{project-hash}\{branch}\snapshot.md |
The project hash is sha256(abs_project_path). One snapshot per project per branch. path.txt at the hash-dir level stores the original path for ctx list reverse lookup.
View Your Snapshot
ctx show
Delete Your Snapshot
ctx clear # current branch only
ctx clear --all # all branches for this project
Debugging
Doctor Command
ctx doctor
Checks hooks registration, binary path, and claude CLI availability. Run this first when something doesn’t work.
Log File
All hook executions write to a single log file:
| Platform | Path |
|---|---|
| Linux/macOS | ~/.local/share/ctx/debug.log |
| Windows | %LOCALAPPDATA%\ctx\debug.log |
Format:
[2026-03-08T14:32:00Z] precompact | trigger=auto | project=/home/agus/myapp | duration=3.2s | status=ok
[2026-03-08T14:32:00Z] session | project=/home/agus/myapp | snapshot=found | tokens=187
Errors append with full detail:
[2026-03-08T14:32:00Z] precompact | ERROR: claude -p exited with code 1: ...
Log Commands
ctx logs # last 20 entries
ctx logs -n 50 # last 50 entries
ctx logs --all # all entries
Enable Verbose Logging
ctx config --debug true
Shows context sizes, timings, and detailed error traces.
Manual Test Procedure
Step 1 — Verify the hook fires
Open a Claude Code session, run a few commands, then type /compact. Check the log:
tail -5 ~/.local/share/ctx/debug.log
# Windows: tail -5 "$LOCALAPPDATA/ctx/debug.log"
Expected: a precompact | status=ok entry.
Step 2 — Verify the snapshot
ctx show
Expected: structured snapshot with goal, decisions, in_progress, next.
Step 3 — Verify Claude receives context
Close the session and open a new one. Ask Claude:
What do you know about what we were working on?
Expected: Claude describes the snapshot content without you mentioning it.
Fallback Behavior
- No git: snapshot generates using filesystem data only
- claude unavailable: snapshot falls back to deterministic-only content, logs a warning, does not crash
Updates
Automatic Updates
ctx updates itself automatically in the background. Once every 24 hours it checks for a new release, downloads it silently, and applies it on the next invocation. You’ll see a one-line notification when it does.
Manual Update
ctx update
Changelog
ctx changelog # current version changes
ctx changelog --full # full history
Uninstall
ctx uninstall
Removes hooks from ~/.claude/settings.json, deletes all snapshot data, and removes the binary.
To only remove hooks without uninstalling:
ctx init --remove