Complete guide to installing and configuring PlanDrop — the Chrome extension that talks to Claude Code on remote servers.
- Prerequisites
- Step 1: Server Setup
- Step 2: Project Initialization
- Step 3: Chrome Extension Installation
- Step 4: Native Messaging Host Installation
- Step 5: Extension Configuration
- Step 6: Start the Watcher
- Verifying the Setup
- Permission Profiles
- SSH Configuration
- API Key vs Subscription Login
- Multi-Browser Setup
- Troubleshooting
| Requirement | How to Check | Install |
|---|---|---|
| Chrome, Edge, Brave, or Arc | Browser installed | Download from official site |
| Python 3 | python3 --version |
macOS: brew install python3Linux: apt install python3 |
| SSH client | ssh -V |
Pre-installed on macOS/Linux |
| SSH key | ls ~/.ssh/id_* |
ssh-keygen -t ed25519 |
| Requirement | How to Check | Install |
|---|---|---|
| Node.js 18+ | node --version |
curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash - && sudo apt install nodejsOr: nvm install --lts |
| npm | npm --version |
Comes with Node.js |
| SSH access | ssh user@server |
Contact server admin |
SSH to your server and run the automated setup script:
curl -sL https://raw.githubusercontent.com/genecell/PlanDrop/master/server/setup.sh | bash
# Reload your shell to make plandrop-watch available
source ~/.bashrcThis script:
- Checks for Node.js and npm
- Installs Claude Code globally (
npm install -g @anthropic-ai/claude-code) - Helps you authenticate with
claude loginor warns about API key usage - Installs
plandrop-watchandplandrop-historyto~/.local/bin/ - Adds
~/.local/binto your PATH if needed
If you prefer manual installation:
# Install Claude Code
npm install -g @anthropic-ai/claude-code
# Authenticate (opens browser for OAuth)
claude login
# Download and install plandrop-watch
mkdir -p ~/.local/bin
curl -sL https://raw.githubusercontent.com/genecell/PlanDrop/master/native-host/watch.sh -o ~/.local/bin/plandrop-watch
chmod +x ~/.local/bin/plandrop-watch
# Download and install plandrop-history
curl -sL https://raw.githubusercontent.com/genecell/PlanDrop/master/server/plandrop-history -o ~/.local/bin/plandrop-history
chmod +x ~/.local/bin/plandrop-history
# Add to PATH (if not already)
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
source ~/.bashrcFor each project where you want to use PlanDrop:
cd /path/to/your/project
plandrop-watch --initThis creates the .plandrop/ directory structure:
.plandrop/
├── plans/ # Incoming task requests (JSON)
├── responses/ # Claude Code output (JSONL)
└── completed/ # Processed plans (archived)
(Coming soon)
-
Clone the repository:
git clone https://github.com/genecell/PlanDrop.git
-
Open your browser's extensions page:
- Chrome:
chrome://extensions - Edge:
edge://extensions - Brave:
brave://extensions
- Chrome:
-
Enable Developer Mode (toggle in top right)
-
Click Load unpacked → select the
extension/folder -
Copy the Extension ID — you'll need this for the next step
The ID is a 32-character string like
abcdefghijklmnopqrstuvwxyzaaaaaa
The native messaging host is a Python script that handles communication between the browser and your SSH connections.
cd PlanDrop/native-host
./install.sh YOUR_EXTENSION_IDReplace YOUR_EXTENSION_ID with the ID you copied in Step 3.
Example:
./install.sh abcdefghijklmnopqrstuvwxyzaaaaaaIf using multiple browsers or Chrome profiles, pass all IDs:
./install.sh chrome_id edge_id brave_id- Verifies Python 3, ssh, and scp are available
- Makes
plandrop_host.pyexecutable - Creates a native messaging manifest at:
- Chrome (macOS):
~/Library/Application Support/Google/Chrome/NativeMessagingHosts/com.plandrop.host.json - Chrome (Linux):
~/.config/google-chrome/NativeMessagingHosts/com.plandrop.host.json - Similar paths for Edge, Brave, Chromium
- Chrome (macOS):
./install.sh --uninstall- Click the PlanDrop extension icon to open the side panel
- Click the gear icon (⚙) to open Settings
- Click Servers & Projects
| Field | Description | Example |
|---|---|---|
| Name | Friendly display name | "Lab GPU Server" |
| SSH Type | Alias (from ~/.ssh/config) or Direct | Alias |
| SSH Alias | Host name from your SSH config | labgpu |
| or Host | IP address or hostname | 192.168.1.100 |
| or Username | SSH username | jsmith |
| or SSH Key | Path to private key (optional) | ~/.ssh/id_ed25519 |
| or Port | SSH port (default: 22) | 22 |
Tip: Using an SSH alias from ~/.ssh/config is recommended. It's simpler and leverages your existing SSH configuration.
| Field | Description | Example |
|---|---|---|
| Name | Friendly display name | "RNA-seq Pipeline" |
| Path | Absolute path on the server | /home/jsmith/rnaseq |
| Interactive Mode | Enable Claude Code tab | ✓ Checked |
| Profile | Permission profile | Bioinformatics |
| Model | Claude model | Opus |
Important: The path must match where you ran plandrop-watch --init.
On your server, navigate to your project and start the watcher:
cd /path/to/your/project
# Option 1: Foreground (recommended with tmux)
tmux new -s plandrop
plandrop-watch
# Option 2: Background
plandrop-watch --daemon| Command | Description |
|---|---|
plandrop-watch |
Start watching in foreground |
plandrop-watch --init |
Initialize .plandrop/ directory |
plandrop-watch --daemon |
Start in background |
plandrop-watch --stop |
Stop background watcher |
plandrop-watch --status |
Check if watcher is running |
plandrop-watch --model sonnet |
Use Sonnet model instead of Opus |
# Start a new tmux session
tmux new -s plandrop
# Start the watcher
cd ~/your-project
plandrop-watch
# Detach: Ctrl+B, then D
# Reattach later: tmux attach -t plandrop-
Check watcher status on server:
plandrop-watch --status # ✓ Watcher running (PID: 12345, heartbeat: 2024-01-15T10:30:00Z) -
Check connection in browser:
- Open PlanDrop side panel
- Select your server and project
- Look for green status dot (●)
- Status should say "Connected"
-
Send a test task:
- Type "List the files in the current directory" in the message input
- Click Send
- Claude Code should respond in the activity feed
PlanDrop uses a deny-list approach with Claude Code's --disallowedTools CLI flag for hard security boundaries. This provides better security than allow-lists because blocked commands cannot be bypassed by prompt injection.
| Profile | Shell Access | Blocked Commands | Best For |
|---|---|---|---|
| 📋 Plan Only | None | N/A | Code review, analysis |
| 📝 Edit Files Only | None | All Bash | Safe file editing |
| ⚡ Standard | Yes | Dangerous commands | General development |
| 🔓 Full Access | Yes | None | Sandboxed environments |
| ⚙️ Custom | Yes | User-defined | Specialized workflows |
- Permission mode:
plan - Capabilities: Read files, analyze code, suggest changes
- Cannot: Write files, run any commands
- Use for: Code review, getting suggestions without any execution risk
- Permission mode:
bypassPermissions - Blocked tools:
Bash(all shell commands) - Capabilities: Read, Write, Edit, Glob, Grep
- Cannot: Run any shell commands
- Use for: Safe file modifications without command execution risk
- Permission mode:
bypassPermissions - Blocked commands:
- Privilege escalation:
sudo,su,pkexec - System control:
shutdown,reboot,halt,poweroff,init 0/6 - Destructive operations:
mkfs,dd if=,rm -rf /,rm -rf /* - Dangerous modifications:
chmod -R 777,killall,crontab
- Privilege escalation:
- Allowed: All other commands (git, npm, python, docker, etc.)
- Use for: Most development tasks with reasonable safety
- Permission mode:
bypassPermissions - Blocked commands: None
- Requires: Confirmation dialog before enabling
- Use for: Sandboxed or disposable environments only
⚠️ Warning: Full Access allows Claude to run any command, includingsudo,rm -rf, and system modifications. Only use in environments where damage is acceptable.
- Permission mode:
bypassPermissions - Blocked commands: User-defined deny list
- Templates available:
- Standard: Same blocks as Standard profile
- Restrictive: Standard + network (ssh, scp, rsync) + containers (docker) + package managers
- Minimal: Block all Bash commands
- Empty: No blocks (same as Full Access)
Creating a custom profile:
- Select "Custom" from the profile dropdown
- Choose a starting template
- Edit the blocked commands list (one per line)
- Use patterns like
Bash(sudo:*)or justBashto block all shell
Example custom deny list:
Bash(sudo:*)
Bash(rm -rf:*)
Bash(docker:*)
Bash(kubectl:*)
PlanDrop uses your existing SSH configuration. Recommended setup in ~/.ssh/config:
Host labgpu
HostName 192.168.1.100
User jsmith
IdentityFile ~/.ssh/id_ed25519
# Connection reuse (highly recommended):
ControlMaster auto
ControlPath /tmp/ssh-%r@%h:%p
ControlPersist 60PlanDrop polls your server every 3 seconds to check for responses. Without ControlMaster:
- Each poll creates a new SSH connection
- Each connection takes 1-3 seconds to establish
- Significant latency and overhead
With ControlMaster:
- First connection establishes a control socket
- Subsequent connections reuse the socket
- Near-instant response (milliseconds)
# Must work without password prompt
ssh labgpu "echo connected"If prompted for a password:
# Copy your key to the server
ssh-copy-id labgpuClaude Code uses your Anthropic subscription login by default (via claude login). However, if ANTHROPIC_API_KEY is set in your environment, Claude Code will use that instead, which costs money per token.
# On your server
claude login
# Note: if ANTHROPIC_API_KEY is set in your environment,
# Claude Code will use it instead of your subscription login.
# To use your subscription, unset it: unset ANTHROPIC_API_KEYIf ANTHROPIC_API_KEY is set in your environment, Claude Code will use it instead of your subscription login.
The watcher warns you on startup:
⚠️ WARNING: ANTHROPIC_API_KEY is set in your environment
Claude Code will use your API key (costs money per token)
# Current session
unset ANTHROPIC_API_KEY
# Permanent (check all these files)
# ~/.bashrc
# ~/.zshrc
# ~/.profile
# conda activate scripts: ~/miniconda3/envs/*/etc/conda/activate.d/PlanDrop supports Chrome, Edge, Brave, Arc, and other Chromium-based browsers.
Each browser has its own extension ID. Pass all IDs to the installer:
./install.sh chrome_id edge_id brave_id| Browser | macOS | Linux |
|---|---|---|
| Chrome | ~/Library/Application Support/Google/Chrome/NativeMessagingHosts/ |
~/.config/google-chrome/NativeMessagingHosts/ |
| Chromium | ~/Library/Application Support/Chromium/NativeMessagingHosts/ |
~/.config/chromium/NativeMessagingHosts/ |
| Brave | ~/Library/Application Support/BraveSoftware/Brave-Browser/NativeMessagingHosts/ |
~/.config/BraveSoftware/Brave-Browser/NativeMessagingHosts/ |
| Edge | ~/Library/Application Support/Microsoft Edge/NativeMessagingHosts/ |
~/.config/microsoft-edge/NativeMessagingHosts/ |
"Native host not found" error
- Re-run installer:
./install.sh YOUR_EXTENSION_ID - Verify extension ID matches (check chrome://extensions)
- Restart browser after installation
Side panel won't open
- Refresh extension (chrome://extensions → click reload icon)
- Make sure side panel is enabled (check extension permissions)
Red status dot / "Not connected"
- Check watcher is running:
plandrop-watch --status - Verify SSH works:
ssh your-alias "echo ok" - Check project path matches
"Test Connection" fails
- SSH key not added:
ssh-add ~/.ssh/id_ed25519 - On macOS:
ssh-add --apple-use-keychain ~/.ssh/id_ed25519 - Wrong SSH alias/host configuration
"Watcher not running"
# Check if running
ps aux | grep plandrop-watch
# Start manually
cd /your/project
plandrop-watch"Credit balance is too low"
- ANTHROPIC_API_KEY is set → use
unset ANTHROPIC_API_KEY - Or authenticate with your subscription:
claude login
Watcher stuck / not responding
# Check logs
tail -f .plandrop/watch.log
# Stop and restart
plandrop-watch --stop
plandrop-watch| Location | Purpose |
|---|---|
~/.plandrop/relay.log |
Native host logs (local machine) |
.plandrop/watch.log |
Watcher logs (server, if using --daemon) |
.plandrop/heartbeat |
Watcher heartbeat timestamp |
.plandrop/session_id |
Current Claude Code session ID |
# Setup (one-time)
curl -sL https://raw.githubusercontent.com/genecell/PlanDrop/master/server/setup.sh | bash
source ~/.bashrc # Reload shell to make plandrop-watch available
# Initialize project (one-time per project)
cd /your/project && plandrop-watch --init
# Start watcher
plandrop-watch # Foreground
plandrop-watch --daemon # Background
plandrop-watch --model sonnet # Use Sonnet model
# Manage watcher
plandrop-watch --status # Check status
plandrop-watch --stop # Stop background watcher
# Export history
plandrop-history # Concise summary
plandrop-history --full # With file contents# Install native host
cd PlanDrop/native-host
./install.sh YOUR_EXTENSION_ID
# Uninstall
./install.sh --uninstall- Open side panel (click extension icon)
- Select server and project
- Green dot = watcher running
- Type task → Send
- Review Claude's plan
- Click Execute, Revise, or Cancel
- Continue in Session or New Task
- GitHub Issues: github.com/genecell/PlanDrop/issues
- Documentation: plandrop.hiniki.com