A composable shim architecture for extending Claude Code with multiple tool integrations (CCR, Serena, etc.) through transparent PATH interception.
# Install (assumes you have claude, ccr, and uvx installed)
./install.sh
# Use normally - shims are transparent (CCR skipped by default)
claude -p "Hello world"
# β¨ Claude Code shims active: serena, ccr (skipping, use --ccr to enable)
# Enable CCR with --ccr flag
claude --ccr --add-dir ~/project
# β¨ Claude Code shims active: ccr, serena
The shim pipeline implements a staged interception pattern where each tool gets its chance to process Claude commands before passing control to the next stage.
flowchart TD
A[User runs: claude -p "hello"]
B[PATH finds: ~/.config/claude/shims/claude]
C[Shim forwards to: ~/.config/claude/libexec/claude-dispatcher]
D[Dispatcher determines active wrappers]
E[Stage 0: CCR Wrapper]
F[Stage 1: Serena Wrapper]
G[Real Claude Binary]
A --> B --> C --> D
D --> E --> F --> G
style A fill:#e1f5fe
style G fill:#f3e5f5
style D fill:#fff3e0
- Zero Configuration: Works automatically once installed - no per-project setup needed
- Transparent Operation: User runs
claude
normally, shims work invisibly - Composable Pipeline: Easy to add/remove/reorder tools through wrapper system
- Safe Fallbacks: Missing tools are skipped gracefully, always reaches real Claude
- Mode Support:
--ccr
flag enables CCR wrapper (skipped by default)
~/.config/claude/
βββ README.md # This file
βββ install.sh # Installation script
βββ shims/
β βββ claude # PATH interception point
βββ libexec/
β βββ claude-shim # Generic shim template
β βββ claude-dispatcher # Central pipeline orchestrator
βββ wrappers.d/ # Wrapper implementations
βββ ccr/
β βββ claude # Claude Code Router integration
βββ serena/
βββ claude # Serena MCP server integration
- PATH Resolution: System finds
~/.config/claude/shims/claude
first - Shim Forwarding: Shim calls
~/.config/claude/libexec/claude-dispatcher "claude" -p "hello"
- Pipeline Orchestration: Dispatcher manages staged execution:
- Stage 0: CCR is skipped by default
- Stage 1: Serena wrapper starts MCP server, calls real Claude binary
- Final Execution: Real Claude runs with Serena integration active
- FLAG Detection: Dispatcher detects
--ccr
flag, removes from args - Wrapper Selection: Full pipeline runs (CCR + Serena)
- Execution: CCR β Serena β Real Claude
The CLAUDE_PIPELINE_STAGE
environment variable tracks progression:
- Stage 0: CCR wrapper runs, sets
CLAUDE_PIPELINE_STAGE=1
- Stage 1: Serena wrapper runs, calls real Claude
- Stage 2+: Pipeline complete, execute real binary
Purpose: Intercept all claude
commands through PATH manipulation
Key Features:
- Generic design: can be symlinked for other commands (future:
cursor
, etc.) - Absolute path forwarding prevents recursion
- Preserves all arguments and environment
Purpose: Orchestrate the wrapper pipeline and manage execution flow
Key Features:
- Mode Detection: Handles
--ccr
flag for selective wrapper enablement - Stage Management: Tracks pipeline progression through environment variables
- Wrapper Discovery: Dynamically finds available wrappers in order
- Clean Summary: Shows single line of active shims instead of verbose debug
- Fallback Safety: Always reaches real Claude binary even if wrappers fail
Purpose: Integrate Claude Code Router for model routing and request manipulation
Key Features:
- Service Management: Auto-starts CCR service if needed
- Path Handling: Pipeline vs standalone mode path management
- Graceful Fallback: Passes through if CCR unavailable
Purpose: Auto-manage Serena MCP servers per project
Key Features:
- Project Detection: Uses git root or current directory
- Automatic Startup: Launches Serena MCP server on unique ports (9000-9999)
- Process Management: Uses uvx + nohup for reliable backgrounding
- Health Checking: Fast
/dev/tcp
port connectivity tests (avoids SSE hangs) - File Locking: Prevents race conditions with concurrent
claude
calls - Cache System: Reuses existing healthy servers per project
- Create Wrapper: Add executable script at
wrappers.d/TOOLNAME/claude
- Update Order: Add tool name to
WRAPPER_ORDER
array in dispatcher - Handle Modes: Add native mode logic if tool should be skipped
- Follow Pattern: Use
CLAUDE_REAL_BINARY
for next execution
Example wrapper template:
#!/bin/bash
# Find next claude in chain
next_claude="${CLAUDE_REAL_BINARY:-$(PATH="filtered_path" command -v claude)}"
# Do your tool-specific work here
your_tool_setup
# Execute next in chain
exec "$next_claude" "$@"
- IDE Integration: Works with any IDE that calls
claude
- Terminal Usage: Transparent in all terminal sessions
- Project Switching: Automatic per-project Serena instances
- Model Selection: Route requests to different models/providers
- Request Modification: Transform prompts, add context, etc.
- Cost Optimization: Intelligent model selection based on request type
- Semantic Search: Understanding code structure and relationships
- Memory System: Project-specific knowledge graphs
- IDE Context: Rich codebase analysis for better responses
Temporarily enable debug output by editing dispatcher:
# Add this after line 14 in claude-dispatcher:
echo "π DISPATCHER: $CMD_NAME called with args: $*" >&2
claude --version # Should show the summary line
# Clear any stuck pipeline stages
unset CLAUDE_PIPELINE_STAGE
# Test CCR
ccr status
# Test Serena
ls ~/.cache/serena/*/port # Check for running instances
Aliases: Only work in interactive shells, don't affect IDE/script usage
Shell Scripts: Limited by shell-specific features, PATH complexities
Shims: Universal interception, work everywhere claude
is called
Direct Chaining: wrapper1
β wrapper2
β real_claude
- Problem: Each wrapper needs to know about next wrapper
- Problem: Complex PATH manipulation to avoid recursion
- Problem: Adding/removing wrappers requires updating all
Pipeline Stages: dispatcher
β stage0
β dispatcher
β stage1
β real_claude
- β Clean separation: each wrapper only knows about dispatcher
- β
Easy composition: just modify
WRAPPER_ORDER
array - β Graceful degradation: missing wrappers are auto-skipped
Process inheritance ensures stage information survives across exec
calls, enabling stateless wrappers that don't need complex state management.
- GraphQL Integration: Add
graphiti
wrapper for advanced memory - More Commands: Extend to
cursor
,code
, etc. - Configuration: YAML config for wrapper order/settings
- Logging: Optional structured logging for debugging
- Health Dashboard: Web UI for monitoring wrapper status
- Fork the repository
- Create your wrapper in
wrappers.d/toolname/
- Update
WRAPPER_ORDER
in dispatcher - Test with both standard and native modes
- Submit pull request with clear description
This shim pipeline enables powerful Claude Code extensibility while maintaining the simple claude
command interface developers expect.