Custom wrapper for Claude Code CLI with identity management and 1Password secrets integration.
- Auto Remote Control: Every interactive session is automatically named and accessible from claude.ai/code and the Claude mobile app
- 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/keysThe wrapper fetches GH_TOKEN itself at launch, via lib/credentials.sh. It
reads OP_SERVICE_ACCOUNT_TOKEN from the macOS Keychain, then resolves a token
from the 1Password Automation vault. No shell-startup setup is required — if
GH_TOKEN is already set in your environment, the wrapper leaves it alone and
skips the vault lookup.
Which token it resolves depends on the GitHub owner of the launch directory's
origin remote, because a fine-grained PAT is bound to a single resource owner
and cannot cover a personal account and two orgs at once:
| Owner | Vault item |
|---|---|
smartwatermelon |
op://Automation/CCCLI-SWM/token |
nightowlstudiollc |
op://Automation/CCCLI-NOS/token |
| anything else, or not derivable | op://Automation/GitHub - CCCLI/Token |
Only one item is read per launch. A directory that is not a git repo, has no
origin, or has a non-GitHub remote falls back to the personal token. Run with
CLAUDE_DEBUG=true to see which owner and vault item were selected.
The wrapper does not load flat token files.
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 — automatically starts a named remote session
claude
# With debug output
CLAUDE_DEBUG=true claude
# Pass arguments
claude -c "your command here"
claude --version
# Opt out of remote control for one session
CLAUDE_NO_REMOTE_CONTROL=true claude
# Already has --remote-control? Wrapper skips injection
claude --remote-control "Custom Name"The wrapper:
- Sets git identity
- Authenticates with 1Password (once per session)
- Loads secrets from multi-level files
- Injects
--remote-control <session-name>for interactive sessions - Passes through to real Claude CLI
Every interactive claude invocation automatically registers a remote session named after the current git repository (or directory when outside a git repo). This lets you pick up any session from claude.ai/code or the Claude mobile app.
~/Developer/my-app $ claude
# → equivalent to: claude --remote-control "my-app"
Session naming priority (per Claude docs):
- Name injected by the wrapper (repo or directory name)
/renameinside the session- Last meaningful message in conversation history
- Your first prompt
Opt-out options:
| Method | Scope |
|---|---|
CLAUDE_NO_REMOTE_CONTROL=true claude |
Single session |
export CLAUDE_NO_REMOTE_CONTROL=true |
Shell session |
/config → "Enable Remote Control for all sessions" → false |
Persisted in Claude config |
Remote control is skipped automatically for non-interactive invocations: --print/-p, --version, --help, subcommands (remote-control, mcp, etc.), and script automation (--no-session-persistence).
Requirements: Claude Code v2.1.51+, claude.ai authentication (not API key), Pro/Max/Team/Enterprise plan.
-
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
./tests/test-remote-session.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
│ ├── secrets-loader.sh # 1Password integration
│ ├── binary-discovery.sh # Claude binary search/validation
│ ├── pre-launch.sh # Project-specific pre-launch hooks
│ └── remote-session.sh # Automatic remote control session naming
├── docs/
│ ├── SECRETS.md # 1Password documentation
│ └── SECURITY.md # Security hardening documentation
├── tests/
│ ├── test-wrapper.sh # Test suite
│ ├── test-remote-session.sh # Remote session module tests
│ └── 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
# Verify Claude Code version (requires v2.1.51+)
claude --version
# Check you're using claude.ai auth (not API key)
# API keys do not support Remote Control
# Disable and re-enable for one session
CLAUDE_NO_REMOTE_CONTROL=true claude
# Debug injection
CLAUDE_DEBUG=true claude --version 2>&1 | grep -i remoteIf you're on a Team or Enterprise plan, an admin must enable the Remote Control toggle in Claude Code admin settings.
# 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
- Auto Remote Control: Every interactive
claudeinvocation now automatically registers a named remote session- Session named after the git repository root (or current directory outside a repo)
- Skipped automatically for non-interactive uses (
--print,--version, subcommands,--no-session-persistence) - Opt-out via
CLAUDE_NO_REMOTE_CONTROL=true
- New module:
lib/remote-session.sh - New test suite:
tests/test-remote-session.sh(22 tests)
- 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