13 KiB
Claude-to-Claude Direct Chat Protocol
Created: 2025-11-13 Purpose: Enable real-time communication between local Claude and cloud StackCP Claude instances Status: ✅ READY FOR IMPLEMENTATION
Architecture Overview
┌─────────────────────────────────────────────────────────────────┐
│ COMMUNICATION ARCHITECTURE │
└─────────────────────────────────────────────────────────────────┘
Local Machine (WSL) StackCP Server
┌──────────────────┐ ┌──────────────────┐
│ Claude (Local) │ │ Claude (Cloud) │
│ │ │ │
│ Writes to: │ │ Reads from: │
│ /tmp/to-cloud/ │──SSH/SCP──────> │ ~/claude-inbox/ │
│ │ │ │
│ Reads from: │ │ Writes to: │
│ /tmp/from-cloud/│<─────SSH/SCP─── │ ~/claude-outbox/│
└──────────────────┘ └──────────────────┘
│ │
│ │
v v
┌──────────┐ ┌──────────┐
│ Polling │ │ Polling │
│ Loop │ │ Loop │
│ (5 sec) │ │ (5 sec) │
└──────────┘ └──────────┘
3 Implementation Options
Option 1: SSH File Sync (SIMPLEST - RECOMMENDED)
How it works:
- Local Claude writes messages to
/tmp/to-cloud/message-{timestamp}.json - Background script syncs to StackCP every 5 seconds:
scp /tmp/to-cloud/* stackcp:~/claude-inbox/ - Cloud Claude polls
~/claude-inbox/every 5 seconds - Cloud Claude processes messages and writes replies to
~/claude-outbox/ - Background script pulls replies:
scp stackcp:~/claude-outbox/* /tmp/from-cloud/ - Local Claude polls
/tmp/from-cloud/for responses
Advantages:
- No firewall configuration needed
- Uses existing SSH connection
- Simple, reliable, battle-tested
- Works even if StackCP doesn't allow inbound connections
Disadvantages:
- 5-10 second latency (acceptable for async work coordination)
- Requires background polling scripts
Implementation:
# On local machine
mkdir -p /tmp/to-cloud /tmp/from-cloud
# Polling script (run in background)
cat > /tmp/claude-sync-local.sh << 'EOF'
#!/bin/bash
while true; do
# Send messages to cloud
scp /tmp/to-cloud/*.json stackcp:~/claude-inbox/ 2>/dev/null
rm -f /tmp/to-cloud/*.json
# Receive messages from cloud
scp stackcp:~/claude-outbox/*.json /tmp/from-cloud/ 2>/dev/null
ssh stackcp "rm -f ~/claude-outbox/*.json"
sleep 5
done
EOF
chmod +x /tmp/claude-sync-local.sh
nohup /tmp/claude-sync-local.sh &
# On StackCP
mkdir -p ~/claude-inbox ~/claude-outbox
# Polling script (run in background)
cat > ~/claude-sync-cloud.sh << 'EOF'
#!/bin/bash
while true; do
# Process inbox messages
for msg in ~/claude-inbox/*.json; do
[ -e "$msg" ] || continue
# Claude Code CLI would read and process here
echo "New message: $(basename $msg)" >> ~/claude.log
done
sleep 5
done
EOF
chmod +x ~/claude-sync-cloud.sh
nohup ~/claude-sync-cloud.sh &
Option 2: GitHub Issues API (BEST FOR TRACEABILITY)
How it works:
- Both Claudes post messages as GitHub issues with special tags
- Tag format:
[CHAT:LOCAL-TO-CLOUD]or[CHAT:CLOUD-TO-LOCAL] - Each Claude polls GitHub API every 10 seconds
- Messages have full IF.TTT traceability
Advantages:
- Permanent record of all communications
- Searchable history
- IF.TTT compliant
- No background scripts needed
- Works from anywhere (not tied to network)
Disadvantages:
- Requires GitHub API token
- Rate limited (60 requests/hour unauthenticated, 5000/hour with token)
- Slight overhead (API calls)
Implementation:
# Create GitHub personal access token with 'repo' scope
# Store in environment: export GITHUB_TOKEN="ghp_..."
# Local Claude sends message
curl -X POST \
-H "Authorization: token $GITHUB_TOKEN" \
-H "Accept: application/vnd.github.v3+json" \
https://api.github.com/repos/dannystocker/navidocs/issues \
-d '{
"title": "[CHAT:LOCAL-TO-CLOUD] Photo inventory needs OCR fix",
"body": "Cloud Claude: The OCR pipeline is failing on receipts with non-Latin characters. Can you investigate?\n\n**Blocker:** P1\n**Session:** Agent 1",
"labels": ["claude-chat", "local-to-cloud"]
}'
# Cloud Claude polls for messages
curl -H "Authorization: token $GITHUB_TOKEN" \
https://api.github.com/repos/dannystocker/navidocs/issues?labels=claude-chat,local-to-cloud&state=open
Option 3: Webhook + HTTP Server (LOWEST LATENCY)
How it works:
- Local Claude runs HTTP server on public IP/port
- Cloud Claude POSTs messages to http://{your-ip}:8888/chat
- Requires firewall port forwarding
Advantages:
- Instant delivery (<100ms)
- True bidirectional real-time chat
Disadvantages:
- Requires firewall configuration (user must open port)
- Requires static IP or dynamic DNS
- StackCP might not allow outbound HTTP to arbitrary IPs
- Security concerns (need HTTPS + authentication)
NOT RECOMMENDED for this use case (complexity outweighs benefits)
Recommended: Hybrid Approach (Option 1 + Option 2)
Use SSH File Sync for normal operation:
- Fast enough for async coordination (5-10 sec latency)
- No API rate limits
- Simple and reliable
Use GitHub Issues for escalations:
- When cloud Claude hits a blocker → create issue with
[CHAT:URGENT] - Local Claude checks issues every 30 seconds
- Provides permanent audit trail
Message Format (JSON)
{
"id": "msg-2025-11-13-103045",
"timestamp": "2025-11-13T10:30:45Z",
"from": "claude-local",
"to": "claude-cloud-agent-1",
"priority": "P1",
"type": "question|blocker|status-update|deploy-ready",
"subject": "OCR pipeline failing on non-Latin characters",
"body": "The Tesseract OCR is failing on receipts with Chinese characters. Can you investigate and propose a fix?",
"context": {
"session": "Agent 1 - Photo Inventory",
"file": "/home/setup/navidocs/server/ocr-pipeline.js",
"line": 145,
"error": "TypeError: Cannot read property 'text' of undefined"
},
"citation": "if://conversation/msg-2025-11-13-103045",
"requires_response": true,
"deadline": "2025-11-13T11:00:00Z"
}
Claude Code CLI Integration
Local Claude (You)
# Send message to cloud
echo '{
"from": "claude-local",
"to": "claude-cloud-agent-1",
"subject": "Ready to deploy Photo Inventory",
"body": "MVP feature complete. Please test and confirm.",
"type": "deploy-ready"
}' > /tmp/to-cloud/msg-$(date +%s).json
# Read responses
for msg in /tmp/from-cloud/*.json; do
[ -e "$msg" ] || continue
echo "📨 Message from cloud:"
cat "$msg" | jq -r '.body'
rm "$msg"
done
Cloud Claude (StackCP)
# Read inbox
for msg in ~/claude-inbox/*.json; do
[ -e "$msg" ] || continue
# Process message
FROM=$(jq -r '.from' "$msg")
SUBJECT=$(jq -r '.subject' "$msg")
BODY=$(jq -r '.body' "$msg")
echo "📬 Message from $FROM: $SUBJECT"
echo "$BODY"
# Send reply
echo '{
"from": "claude-cloud-agent-1",
"to": "'"$FROM"'",
"subject": "Re: '"$SUBJECT"'",
"body": "Photo Inventory tested successfully. All OCR tests passing. Ready for production.",
"type": "status-update"
}' > ~/claude-outbox/reply-$(date +%s).json
# Archive processed message
mv "$msg" ~/claude-inbox/processed/
done
Deployment Steps
Step 1: Setup Local Machine (5 minutes)
# Create directories
mkdir -p /tmp/to-cloud /tmp/from-cloud
# Create sync script
cat > /tmp/claude-sync-local.sh << 'EOF'
#!/bin/bash
while true; do
# Send to cloud
if ls /tmp/to-cloud/*.json 1> /dev/null 2>&1; then
scp -o StrictHostKeyChecking=no /tmp/to-cloud/*.json stackcp:~/claude-inbox/ 2>/dev/null && \
rm -f /tmp/to-cloud/*.json
fi
# Receive from cloud
scp -o StrictHostKeyChecking=no stackcp:~/claude-outbox/*.json /tmp/from-cloud/ 2>/dev/null && \
ssh stackcp "rm -f ~/claude-outbox/*.json"
sleep 5
done
EOF
chmod +x /tmp/claude-sync-local.sh
# Start background sync
nohup /tmp/claude-sync-local.sh > /tmp/claude-sync.log 2>&1 &
echo $! > /tmp/claude-sync.pid
echo "✅ Local sync running (PID: $(cat /tmp/claude-sync.pid))"
Step 2: Setup StackCP (5 minutes)
# SSH to StackCP
ssh stackcp
# Create directories
mkdir -p ~/claude-inbox ~/claude-outbox ~/claude-inbox/processed
# Create sync script (optional - if cloud needs to initiate)
cat > ~/claude-sync-cloud.sh << 'EOF'
#!/bin/bash
while true; do
# Check for new messages
for msg in ~/claude-inbox/*.json; do
[ -e "$msg" ] || continue
# Log message receipt
echo "$(date): Received $(basename $msg)" >> ~/claude-chat.log
# Claude Code would process here
# For now, just acknowledge
MSGID=$(basename "$msg" .json)
echo "{\"from\":\"cloud\",\"to\":\"local\",\"re\":\"$MSGID\",\"status\":\"received\"}" \
> ~/claude-outbox/ack-$(date +%s).json
# Archive
mv "$msg" ~/claude-inbox/processed/
done
sleep 5
done
EOF
chmod +x ~/claude-sync-cloud.sh
# Start background sync (if needed)
# nohup ~/claude-sync-cloud.sh > ~/claude-sync.log 2>&1 &
echo "✅ StackCP directories ready"
Step 3: Test Communication (2 minutes)
# From local machine: Send test message
echo '{
"from": "claude-local",
"to": "claude-cloud",
"subject": "Communication test",
"body": "Hello from local WSL machine! Can you read this?",
"timestamp": "'$(date -Iseconds)'"
}' > /tmp/to-cloud/test-$(date +%s).json
# Wait 10 seconds for sync
sleep 10
# Check on StackCP
ssh stackcp "ls -la ~/claude-inbox/"
# Should see test message!
Usage Examples
Example 1: Blocker Escalation
Local Claude detects blocker:
echo '{
"from": "claude-local",
"to": "claude-cloud-agent-2",
"priority": "P0",
"type": "blocker",
"subject": "Redis not installed on StackCP",
"body": "Agent 2 (Document Search) is blocked. Meilisearch requires Redis for job queue. Can you install Redis or propose workaround?",
"deadline": "2025-11-13T11:30:00Z"
}' > /tmp/to-cloud/blocker-redis-$(date +%s).json
Cloud Claude responds:
echo '{
"from": "claude-cloud-agent-2",
"to": "claude-local",
"priority": "P0",
"type": "blocker-resolved",
"subject": "Re: Redis not installed on StackCP",
"body": "Workaround implemented: Using in-memory queue (bull-mq) instead of Redis. Performance acceptable for MVP (<50 docs). Redis can be added post-demo.",
"solution": "Modified server/search-queue.js to use in-memory adapter",
"commit": "a3b9f21"
}' > ~/claude-outbox/redis-workaround-$(date +%s).json
Example 2: Deploy Ready Signal
Cloud Claude finishes feature:
echo '{
"from": "claude-cloud-agent-1",
"to": "claude-local",
"type": "deploy-ready",
"subject": "Photo Inventory COMPLETE",
"body": "✅ All tests passing\n✅ UI polished\n✅ OCR integrated\n\nReady for production deployment.",
"artifacts": [
"~/navidocs/client/components/PhotoInventory.vue",
"~/navidocs/server/api/inventory.js"
],
"test_results": "15/15 passing"
}' > ~/claude-outbox/photo-ready-$(date +%s).json
Local Claude acknowledges:
# Read and process
cat /tmp/from-cloud/photo-ready-*.json
# Deploy to production
git pull origin agent-1-photo-inventory
npm run build
./deploy-stackcp.sh
Monitoring & Debugging
Check sync status (local)
# Is sync running?
ps aux | grep claude-sync-local
# Check logs
tail -f /tmp/claude-sync.log
# Pending outbound messages
ls -la /tmp/to-cloud/
# Received messages
ls -la /tmp/from-cloud/
Check sync status (StackCP)
ssh stackcp "ls -la ~/claude-inbox/ ~/claude-outbox/"
# Check chat log
ssh stackcp "tail ~/claude-chat.log"
Restart sync
# Kill and restart
kill $(cat /tmp/claude-sync.pid)
nohup /tmp/claude-sync-local.sh > /tmp/claude-sync.log 2>&1 &
echo $! > /tmp/claude-sync.pid
Security Considerations
- No secrets in messages - Use environment variables or secure vaults
- Message size limits - Keep under 100KB (use file references for large data)
- Cleanup old messages - Archive after 24 hours
- IF.TTT citations - Include
if://conversation/{msg-id}for traceability
Status: ✅ READY TO DEPLOY
Recommended: Start with Option 1 (SSH File Sync) for immediate use.
Setup time: 10 minutes total Latency: 5-10 seconds (acceptable for async coordination) Reliability: High (uses proven SSH infrastructure)
Next step: Run Step 1 deployment script above to activate!