ctx-link
v0.4.0
Published
Connect Claude Code sessions across projects via shared context bundles
Downloads
3,191
Maintainers
Readme
ctx-link
Connect Claude Code sessions across projects via shared context bundles.
When you're building a feature that spans multiple repos (e.g., backend API + frontend), each Claude Code session only knows about its own project. ctx-link lets sessions share context through bundles — so Claude in the frontend repo knows what changed in the backend, and vice versa.
How it works
Claude Code (Project A)
|
| session_log / auto-log on commit
v
Session entries accumulated locally
|
| context_push (or ctxl push)
v
Bundle (shared context container)
|
| local mode -> ~/.ctx-link/local/<id>/
| cloud mode -> Supabase (cross-machine)
v
Claude Code (Project B)
|
| context_pull (or ctxl pull)
v
Claude sees what Project A didKey design decisions:
- Summaries are generated by Claude Code itself (the AI calling the MCP tool), not a separate API call. No Anthropic API key needed.
- Two modes: local (same machine, default), cloud (cross-machine via Supabase).
- Cloud bundles auto-sync — entries push when Claude finishes working and auto-pull on session boot.
- Cloud mode uses Supabase Auth: sign in once with email + password (or one-time email code), and access is enforced by Postgres RLS — no service-role keys, no shared secrets baked into the client.
- Cloud bundles are team-scoped. Teams are joined with a team name + join code (bcrypt-hashed server-side).
- Short join codes (
ctx-abc123) for easy bundle sharing — no UUIDs to copy. - Role-tagged notes: attach manual notes to bundles tagged with the agent role (frontend/backend/etc.) so cross-repo agents can find context relevant to their side.
- CLI is fully interactive — prompts for mode, team, strategy, etc. when flags aren't provided. Flags still work for scripting.
Quick start
1. Install
bun add -g ctx-link2. Add MCP to Claude Code
Register the MCP server with Claude Code:
macOS / Linux:
claude mcp add --scope user ctx-link "$(which ctx-link)"Windows (PowerShell):
claude mcp add --scope user ctx-link (Get-Command ctx-link).SourceThen install the session hooks:
ctxl setup # adds session hooks to global Claude Code settings
# or
ctxl setup --project # adds to current project onlyRestart Claude Code. Run /mcp to verify ctx-link is connected.
3. Initialize your project
ctxl initThis creates a bundle, connects your session, writes .ctx-link.json, and prints a short join code for teammates.
4. Sign in (only needed for cloud mode)
Local mode (same machine, default) requires no sign-in. For cloud bundles and teams, sign in once:
ctxl signin # email + password OR one-time 6-digit email code
ctxl whoami # confirm signed-in userIf the email doesn't exist yet, signin offers to create the account on the spot. To switch accounts: ctxl signout then ctxl signin again.
5. Share with teammates
# Teammate runs:
ctxl join ctx-a3f9k2 # short code from ctxl init6. Use it
Inside Claude Code, the tools are available immediately. Just ask:
- "Pull context from my bundle"
- "Push what I just did to the bundle"
- "Create a local bundle called my-feature"
- "Connect this session to bundle xyz"
Or use the CLI:
ctxl push # push session entries to connected bundles
ctxl pull # pull entries from connected bundles
ctxl create my-feature # create a bundle (prompts for mode)
ctxl connect <bundle_id> # connect your session to a bundle
ctxl note # attach a role-tagged note to a bundleCloud bundles auto-sync — entries push automatically when Claude finishes working (20s idle, 3-min minimum interval) and auto-pull on session boot.
7. Open the dashboard (optional)
ctxl uiOpens the web dashboard at http://localhost:5174 — a node graph showing teams, sessions, and bundles. The dashboard also auto-starts when the MCP server boots.
(Optional) Session logging hook
Add to ~/.claude/settings.json in the hooks object:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Bash",
"hooks": [{
"type": "command",
"command": "claude-code-hook.sh"
}]
}
]
}
}This auto-logs session entries when Claude Code runs git commit or gh pr create. Entries accumulate locally per session until you push them to a bundle.
Three modes
Mode: off (default)
Every project starts in this mode. No linking, no data stored, hooks do nothing.
Mode: local
For FE + BE on the same machine. Entries stored in ~/.ctx-link/local/<bundle_id>/. No network, no tokens, no Supabase.
# In your frontend repo:
ctxl create my-feature
# In your backend repo:
ctxl join <bundle_id>Mode: cloud
For cross-machine or team use. Entries stored in Supabase. Requires sign-in + team membership.
# Sign in once (email + password OR one-time email code):
ctxl signin
# Create a team (prompts for name + join code):
ctxl create-team
# Teammate signs in, then joins the team with the same name + join code:
ctxl signin
ctxl join-team
# Create a cloud bundle:
ctxl create my-feature # select "cloud" + pick team when prompted
# Teammate joins the bundle:
ctxl join <bundle_id>Access is enforced server-side by Postgres Row Level Security: only signed-in members of a team can read or write that team's bundles, sessions, and entries.
CLI reference
The CLI binary is ctxl. All commands with multiple options are interactive — they prompt when flags aren't provided. Flags still work for scripting.
Setup
| Command | Description |
|---------|-------------|
| ctxl setup | Add ctx-link MCP to global Claude Code settings. |
| ctxl setup --project | Add ctx-link MCP to current project's settings only. |
| ctxl init | Initialize ctx-link in a project: create bundle, connect session, get join code. |
| ctxl ui | Open the web dashboard (starts server if needed). |
| ctxl ui --no-open | Start the dashboard server without opening the browser. |
Auth (cloud mode)
| Command | Description |
|---------|-------------|
| ctxl signin | Sign in to Supabase. Choose email + password or one-time 6-digit email code. Offers to create the account if the email is unknown. |
| ctxl signout | Sign out and clear the local session token. |
| ctxl whoami | Show the currently signed-in user. |
Teams (require sign-in)
| Command | Description |
|---------|-------------|
| ctxl create-team | Create a new team. Prompts for name + join code. You become the first member. |
| ctxl join-team | Join an existing team. Prompts for name + join code. |
| ctxl my-teams | List teams you belong to. |
| ctxl team-bundles [team_id] | List bundles in a team. Prompts for team if not given. |
Session tracking
| Command | Description |
|---------|-------------|
| ctxl info | Show current project config (session, branch, bundles). |
| ctxl sessions [--limit N] | List recent Claude Code sessions across all projects. |
| ctxl session-log --message <text> | Log an entry to the current session (local, not pushed). |
| ctxl session-log --event commit --ref <sha> --diff | Log a commit entry with diff context. |
| ctxl session-entries [--all] | List accumulated session entries (un-pushed by default). |
Connect / Disconnect
| Command | Description |
|---------|-------------|
| ctxl connect <bundle_id> | Connect session to a bundle. Mode auto-detected. |
| ctxl disconnect <bundle_id> | Disconnect session from a bundle. |
Bundles
| Command | Description |
|---------|-------------|
| ctxl create <name> | Create a bundle. Prompts for mode + team. |
| ctxl create <name> --mode local | Create a local bundle (skip prompt). |
| ctxl create <name> --mode cloud --team <id> | Create a cloud bundle (skip prompts). |
| ctxl join <bundle_id> [token] | Join a bundle. Mode auto-detected. |
| ctxl join ctx-abc123 | Join a bundle using a short join code. |
| ctxl my-bundles | List all bundles this machine has joined. |
| ctxl status <bundle_id> | Show session count, entry count, last activity. |
| ctxl leave | Disconnect this project from its bundle. |
| ctxl delete-bundle [bundle_id] | Delete a bundle. Prompts for selection + confirmation. |
| ctxl regenerate-code [bundle_id] | Generate a new short join code (invalidates old one). |
Push / Pull
| Command | Description |
|---------|-------------|
| ctxl push | Push all session entries to connected bundles. |
| ctxl push --message <text> | Log a new entry, then push all to bundles. |
| ctxl push-to-bundle | Push entries to a specific bundle (interactive picker). |
| ctxl pull | Pull entries from all connected bundles (excludes own project). |
| ctxl pull <bundle_id> | Pull from one specific bundle. |
| ctxl pull --include-self | Include your own project's entries. |
| ctxl pull --since <iso> --limit <n> | Filter by time and count. |
Rewind / Restore
All commands are interactive when flags are omitted — they prompt for bundle, project, and strategy.
| Command | Description |
|---------|-------------|
| ctxl rewind | Interactive rewind: prompts for bundle, project, strategy. Dry-run first, then asks to apply. |
| ctxl rewind --bundle <id> --project <name> --last-n <n> | Dry-run preview with flags. |
| ctxl rewind ... --apply --reason "text" | Apply directly with flags (skip prompts). |
| ctxl restore | Interactive restore: prompts for bundle, project, method. |
| ctxl restore --bundle <id> --project <name> --from-log <log_id> | Restore from a specific rewind. |
| ctxl rewind-history [bundle_id] | List past rewinds. Prompts for bundle if not given. |
Notes (role-tagged manual context)
| Command | Description |
|---------|-------------|
| ctxl note | Attach a role-tagged manual note to a bundle (e.g. frontend / backend / fullstack). Notes show up alongside session entries on pull, sorted and grouped by role. |
Questions (cross-session Q&A)
| Command | Description |
|---------|-------------|
| ctxl ask | Ask a question on a bundle. Other sessions get notified. |
| ctxl answer | Answer an open question. |
| ctxl questions | List questions on a bundle. |
MCP tools
These are the tools Claude Code sees when the MCP server is connected.
| Tool | Description |
|------|-------------|
| bundle_create | Create a new bundle (local or cloud). |
| bundle_join | Join a bundle with ID + token. |
| bundle_list | List all bundles (local + cloud from joined teams). |
| bundle_status | Get entry count, last activity, linked sessions. |
| bundle_delete | Permanently delete a bundle (irreversible). |
| bundle_entries | List all entries in a bundle (unfiltered). |
| bundle_remove_entry | Remove a single entry ref from a bundle (also excludes from auto-sync). |
| bundle_include_entry | Re-include a previously excluded entry in a bundle. |
| bundle_pull_from_sessions | Pull entries from all sessions connected to a bundle. |
| bundle_push_to_cloud | Migrate a local bundle to cloud under a team. |
| bundle_add_note | Attach a role-tagged note (frontend/backend/etc.) to a bundle. |
| bundle_ask_question | Ask a question on a bundle (last resort). |
| bundle_answer_question | Answer a question in a bundle. |
| bundle_questions | List questions for a bundle. |
| context_push | Push session entries to connected bundles as refs. |
| context_pull | Pull entries from connected bundles. |
| context_rewind | Soft-delete entries by project + strategy. |
| context_restore | Undo a rewind. |
| rewind_history | List past rewinds. |
| session_start | Create or resume a session (usually auto-started). |
| session_info | Current session details (project, branch, bundles). |
| session_log | Log an entry to the session. |
| session_entries | List accumulated session entries. |
| session_connect | Connect session to a bundle. |
| session_disconnect | Disconnect session from a bundle. |
| session_push_to_cloud | Push session to cloud under a team. |
| session_push_to_bundle | Push entries to a specific bundle. |
| session_rename | Rename the current session. |
| session_delete | Delete a session and all cloud copies. |
| session_delete_entry | Delete a specific entry from the session. |
| session_list | List all active sessions on this machine. |
| team_create | Create a team (name + join code). Requires sign-in. |
| team_join | Join a team (name + join code). Requires sign-in. |
| auth_status | Show the currently signed-in Supabase user, or report not signed in. |
| auth_send_code | Send a one-time 6-digit sign-in code to an email address (auto-creates account). |
| auth_verify_code | Verify the 6-digit email code and complete sign-in. |
| auth_signout | Sign out and clear the local session token. |
Usage from Claude Code — just ask naturally:
- "Pull context from my bundle"
- "Push what I just did to the bundle"
- "Check bundle status"
- "Rewind the last 3 entries from this project"
- "Connect this session to bundle xyz"
- "Create a local bundle called auth-feature"
Web dashboard
Run ctxl ui or open http://localhost:5174. The dashboard auto-starts when the MCP server boots.
Features:
- Node graph showing teams, sessions, and bundles
- Drag sessions to bundles to connect them
- View and manage entries, rewinds, and questions
- Create teams and bundles
- Push/pull entries between sessions and bundles
- Live Feed — real-time activity panel showing pushes, connects, and bundle events across your teams
Running locally
git clone https://github.com/AHK-tech/ctx-link.git
cd ctx-link
bun installStart the dev servers
bun run dev:ui-api # API server on port 5174
bun run dev:ui # Vite dev server on port 5173Open http://localhost:5173 to see the dashboard.
Run the CLI from source
bun run cli -- init # initialize ctx-link in a project
bun run cli -- join ctx-abc123 # join a bundle with a short code
bun run cli -- regenerate-code # generate a new join code
bun run cli -- push # push entries to connected bundles
bun run cli -- pull # pull entries from connected bundles
bun run cli -- --help # see all commandsRun the MCP server (for Claude Code integration)
bun run dev:mcp # MCP server in watch modeOther commands
bun run typecheck # typecheck all packages
bun test # run all tests
bun run build # full production build -> dist/Architecture
packages/
core/ Shared business logic (bundles, entries, teams, rewind, config)
mcp-server/ MCP protocol wrapper (stdio) — Claude Code talks to this
cli/ CLI tool (ctxl) — interactive commands
ui/ React web dashboard — node graph + management
hooks/ Git post-commit + Claude Code hook scripts
supabase/
migrations/ SQL schemaSecurity model
- Cloud access is per-user. Sign in with Supabase Auth (email + password or one-time email code). The local Supabase session token is stored in
~/.ctx-link/auth.jsonand used by the CLI, MCP server, and dashboard. - Team-gated by Postgres RLS. Every cloud read/write is filtered by
auth.uid() ∈ team_members. There is no service-role key in the client and no shared secret baked into ctx-link — RLS is the access boundary. - Team join codes are bcrypt-hashed. Only the hash is stored. Joining a team goes through a
SECURITY DEFINERRPC that verifies the code server-side. - Local bundles have no auth. They're files on your machine under
~/.ctx-link/local/. - Bundle IDs are UUIDs. Not guessable. Short join codes (
ctx-abc123) are server-validated and can be regenerated to invalidate the old one. - Entries are plaintext in Supabase. E2E encryption is a future improvement.
Troubleshooting
"No bundles connected to this session"
Run ctxl connect <bundle_id> to connect to a bundle, or ctxl create <name> to create one.
"Not signed in" / "authentication required" on cloud commands
Run ctxl signin and either enter your password or request a one-time email code. Confirm with ctxl whoami. If you have stale credentials, ctxl signout clears them.
"You are not a member of this team"
Run ctxl join-team and enter the team name + join code (you must ctxl signin first).
"Invalid join code"
The team exists but the code didn't match. Ask the team owner to share the code again, or to regenerate it by recreating the team.
Claude Code doesn't see ctx-link MCP server
- Run
/mcpin Claude Code to check status. - Make sure
ctx-linkis in your PATH (which ctx-link). - Register the MCP server:
claude mcp add --scope user ctx-link "$(which ctx-link)"(macOS/Linux) orclaude mcp add --scope user ctx-link (Get-Command ctx-link).Source(PowerShell). - Run
ctxl setupto install the session hooks. - Restart Claude Code after setup.
Dashboard not loading
- Run
ctxl uito start the server manually. - Check
http://localhost:5174is accessible. - If port is in use:
lsof -ti:5174 | xargs killthen try again.
License
MIT
Built by Hassan Kourani.
