Custom wrapper for Claude Code CLI with identity management and 1Password secrets integration.
- Git Identity Management: Separate git identity for Claude Code operations
- SSH Key Isolation: Dedicated SSH key for Claude git operations
- GitHub Token Management: Separate GitHub CLI token
- 1Password Integration: Secure secrets management with minimal TouchID prompts
- Multi-Level Secrets: Global, project, and local secrets support
- Debug Mode: Comprehensive logging for troubleshooting
- Graceful Degradation: Works with or without 1Password
- Modular Architecture: Clean separation of concerns for maintainability
-
Clone this repository:
git clone https://github.com/smartwatermelon/claude-wrapper.git ~/.claude-wrapper -
Symlink the wrapper to your local bin:
mkdir -p ~/.local/bin ln -sf ~/.claude-wrapper/bin/claude-wrapper ~/.local/bin/claude
-
Ensure
~/.local/binis in your PATH:echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc # or ~/.zshrc
-
Verify installation:
which claude # Should show ~/.local/bin/claude claude --version
The wrapper automatically sets up a dedicated git identity for Claude Code:
- Name:
Claude Code Bot - Email:
claude-code@smartwatermelon.github
Create a dedicated SSH key for Claude git operations:
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_claude_code -C "claude-code@smartwatermelon.github"
# Add to GitHub
cat ~/.ssh/id_ed25519_claude_code.pub
# Copy and add to https://github.com/settings/keysCreate a GitHub fine-grained PAT for Claude CLI operations:
# Create token at: https://github.com/settings/personal-access-tokens/new
# Required permissions: Contents (R/W), Pull requests (R/W), Actions (R)
# Save token (single account)
mkdir -p ~/.config/claude-code
echo "your_github_token_here" > ~/.config/claude-code/gh-token
chmod 600 ~/.config/claude-code/gh-tokenFine-grained PATs are scoped to a single owner (user or organization). To work with repos across multiple owners, create one token per owner:
# Personal repos (resource owner: your username)
echo "github_pat_personal..." > ~/.config/claude-code/gh-token.smartwatermelon
chmod 600 ~/.config/claude-code/gh-token.smartwatermelon
# Organization repos (resource owner: the org)
echo "github_pat_org..." > ~/.config/claude-code/gh-token.nightowlstudiollc
chmod 600 ~/.config/claude-code/gh-token.nightowlstudiollc
# Keep a default fallback (or copy one of the above)
cp ~/.config/claude-code/gh-token.smartwatermelon ~/.config/claude-code/gh-tokenThe wrapper detects the target repo owner from gh CLI arguments (e.g.,
--repo owner/repo, API paths like repos/owner/...) or the git remote of
the current directory, then loads the matching gh-token.<owner> file. If no
owner-specific file exists, it falls back to gh-token.
See SECRETS.md for comprehensive 1Password setup guide.
Quick setup:
# 1. Install 1Password CLI
brew install --cask 1password-cli
# 2. Enable app integration in 1Password settings
# 3. Create secrets file
mkdir -p ~/.config/claude-code
cat > ~/.config/claude-code/secrets.op <<EOF
ANTHROPIC_API_KEY=op://Personal/Claude-API/credential
GITHUB_TOKEN=op://Personal/GitHub/token
EOFUse claude command as normal:
# Normal usage
claude
# With debug output
CLAUDE_DEBUG=true claude
# Pass arguments
claude -c "your command here"
claude --versionThe wrapper:
- Sets git identity
- Authenticates with 1Password (once per session)
- Loads secrets from multi-level files
- Passes through to real Claude CLI
-
SECRETS.md: Comprehensive 1Password integration guide
- Setup and configuration
- Secret reference syntax
- Multi-level secrets
- Team workflows
- Troubleshooting
-
SECURITY.md: Security hardening documentation
- Permission validation
- Path security
- Binary validation
-
tests/README.md: Test suite documentation
- Running tests
- Manual testing scenarios
- Adding new tests
# Run all automated tests
./tests/test-wrapper.sh
# Run with verbose output
VERBOSE=true ./tests/test-wrapper.shclaude-wrapper/
├── bin/
│ └── claude-wrapper # Main entry point (orchestrates modules)
├── lib/
│ ├── logging.sh # Debug/error/warning logging
│ ├── permissions.sh # File permission validation
│ ├── path-security.sh # Path canonicalization and traversal protection
│ ├── git-identity.sh # Git author/committer identity
│ ├── github-token.sh # GitHub CLI token loading + multi-org routing setup
│ ├── gh-token-router.sh # Per-invocation token selection (sourced by gh wrapper)
│ ├── secrets-loader.sh # 1Password integration
│ ├── binary-discovery.sh # Claude binary search/validation
│ └── pre-launch.sh # Project-specific pre-launch hooks
├── docs/
│ ├── SECRETS.md # 1Password documentation
│ └── SECURITY.md # Security hardening documentation
├── tests/
│ ├── test-wrapper.sh # Test suite
│ └── README.md # Test documentation
├── .claude/ # Project-specific Claude config
├── .gitignore
└── README.md # This file
This is security-critical infrastructure code. All changes require:
- ShellCheck compliance: Zero warnings or errors
- Test coverage: All new features must have tests
- Code review: AI-assisted review before commit
- Security review: Adversarial review for security changes
# Run ShellCheck on all modules
shellcheck bin/claude-wrapper lib/*.sh
# Run tests
./tests/test-wrapper.sh
# Run code review (requires Claude Code)
claude --agent code-reviewer bin/claude-wrapper lib/- Claude CLI process: Yes
- Git hooks: Yes (subprocesses inherit environment)
- Spawned agents: Yes (subprocesses inherit environment)
- Other terminal windows: No
- After Claude exits: No (environment cleared)
- 1Password vault: ✓ Encrypted, secure
- secrets.op files: ✓ Only references, not actual secrets
- Process environment: ✓ Temporary, cleared on exit
- Shell history: ✓ Not stored (not exported to shell)
- Never commit
.claude/secrets.local.op - Use separate vaults for different security levels
- Review secrets file permissions:
chmod 600 ~/.config/claude-code/secrets.op - Use service accounts for CI/CD
- Enable TouchID for 1Password app
# Check symlink
ls -la ~/.local/bin/claude
# Verify PATH
echo $PATH | grep -o "\.local/bin"
# Recreate symlink
ln -sf ~/.claude-wrapper/bin/claude-wrapper ~/.local/bin/claude# Check git log shows bot identity
git log -1 --format='%an <%ae>'
# Should show: Claude Code Bot <claude-code@smartwatermelon.github>
# Debug wrapper
CLAUDE_DEBUG=true claude -c "git log -1"# Verify app integration
op account get
# Check 1Password app settings:
# - Settings → Security → Touch ID: ON
# - Settings → Developer → Integrate with CLI: ON# Enable debug mode
CLAUDE_DEBUG=true claude -c "printenv | grep API_KEY"
# Verify secret reference
op read "op://Personal/Claude-API/credential"
# Check secrets files exist
ls -la ~/.config/claude-code/secrets.opSee SECRETS.md for comprehensive troubleshooting.
- Fork the repository
- Create a feature branch
- Make your changes
- Run tests:
./tests/test-wrapper.sh - Run ShellCheck:
shellcheck bin/claude-wrapper lib/*.sh - Submit a pull request
MIT License - see LICENSE file for details
- Claude Code - Official Claude Code CLI
- 1Password CLI - 1Password command-line tool
- GitHub CLI - GitHub command-line tool
- Renamed from
claude-customtoclaude-wrapper - Modularized architecture: split into 8 focused modules in
lib/ - Each module is independently testable
- Improved test suite with TDD approach
- Full ShellCheck compliance across all modules
- Added 1Password secrets integration
- Multi-level secrets support (global, project, local)
- Enhanced error handling
- Debug mode
- Comprehensive test suite
- Full documentation
- Git identity management
- SSH key isolation
- GitHub token support
- Binary discovery logic