A companion tool for Claude Code that watches external file changes and injects diffs into Claude's context, preventing sync issues between your editor and Claude.
When using Claude Code alongside an external editor (VS Code, Neovim, etc.), Claude can lose track of changes you make outside its context. This leads to:
- Claude overwriting your changes
- Merge conflicts in Claude's mental model
- Wasted context re-reading files Claude already knew about
pair runs a background watcher that:
- Detects file changes made outside Claude Code
- Generates diffs and queues them
- Injects those diffs into Claude's context on your next prompt
- Provides an MCP tool (
pair_edit) for synchronized writes
Claude stays in sync with your editor without manual intervention.
brew install fcjr/fcjr/pairscoop bucket add fcjr https://github.com/fcjr/scoop-fcjr
scoop install pairgo install github.com/fcjr/pair@latestgit clone https://github.com/fcjr/pair
cd pair
go build -o pairDownload pre-built binaries from the releases page.
# Install hooks into Claude Code
pair install
# That's it. Start a new Claude Code session and pair runs automatically.The install command:
- Adds lifecycle hooks to
~/.claude/settings.json - Creates
.mcp.jsonin your current directory with thepair_edittool
Claude Code Session
|
+-- SessionStart hook
| |
| +-> Spawns: pair watch --session-id <id> --dir <project>
| (background process monitoring filesystem)
|
+-- You edit files in VS Code / Neovim / etc.
| |
| +-> pair detects changes, generates diffs, queues them
|
+-- UserPromptSubmit hook
| |
| +-> pair hook prompt
| | |
| | +-> Reads queued diffs
| | +-> Outputs to stdout (injected into Claude's context)
| | +-> Clears queue
| |
| +-> Claude sees: "External File Changes Detected: <diffs>"
|
+-- Claude writes files using pair_edit MCP tool
| |
| +-> File written + watcher state updated atomically
| +-> No spurious "external change" diffs
|
+-- SessionEnd hook
|
+-> Stops watcher, cleans up temp files
Each Claude session maintains isolated state:
/tmp/pair/<session-id>/
pending-changes.md # Queued diffs waiting for next prompt
watcher.pid # Background process ID
queue.lock # File lock for concurrent access
Create ~/.pair/config.yaml to customize behavior:
# Additional patterns to ignore (merged with defaults)
ignore:
- "*.log"
- "tmp/"
- "coverage/"
# Debounce delay in milliseconds (default: 100)
debounce_ms: 150
# Maximum lines per diff output (default: 500)
max_diff_lines: 1000.git/ node_modules/ __pycache__/ .venv/ venv/
*.pyc *.pyo .DS_Store .pair/ vendor/
*.swp *.swo *~
Installs hooks into Claude Code settings and creates MCP configuration.
pair install # Install hooks + MCP config
pair install --mcp-only # Only install MCP config (skip hooks)Removes pair hooks from Claude Code settings.
pair uninstallShows watcher status for a session.
pair status --session-id <id>Clears pending changes without outputting them.
pair clear --session-id <id>Starts the file watcher (called automatically by hooks).
pair watch --session-id <id> --dir <path>Hook commands called by Claude Code lifecycle events.
pair hook start # SessionStart: spawns watcher
pair hook prompt # UserPromptSubmit: outputs diffs
pair hook stop # SessionEnd: stops watcherRuns the MCP server (called automatically via .mcp.json).
pair mcpPrints version information.
pair versionWrites content to a file while keeping the watcher's state synchronized. Use this when Claude needs to write to files that have pending external changes.
{
"file_path": "/absolute/path/to/file",
"new_content": "file contents here"
}This prevents the watcher from generating a spurious diff for Claude's own writes.
- Claude Code CLI
- Go 1.23+ (for building from source)
# Build
go build -o pair
# Format
go fmt ./...
# Test locally
./pair install
./pair status --session-id test-123
# Cross-compile
GOOS=darwin GOARCH=arm64 go build -o pair-darwin-arm64
GOOS=linux GOARCH=amd64 go build -o pair-linux-amd64
GOOS=windows GOARCH=amd64 go build -o pair-windows-amd64.exeMIT