|
|
@@ -0,0 +1,425 @@
|
|
|
+# Claude Code Automation Guide
|
|
|
+
|
|
|
+## Overview
|
|
|
+
|
|
|
+This document explains how Claude Code runs automatically in response to Gogs webhook events (issues and comments).
|
|
|
+
|
|
|
+## Architecture
|
|
|
+
|
|
|
+### How It Works
|
|
|
+
|
|
|
+```
|
|
|
+1. Gogs Webhook → HTTP Server (accepts immediately, returns 200)
|
|
|
+ ↓
|
|
|
+2. Webhook Handler → Enqueues job (non-blocking)
|
|
|
+ ↓
|
|
|
+3. Job Queue → Processes ONE job at a time (FIFO)
|
|
|
+ ↓
|
|
|
+4. Command Executor → Runs handle-issue.sh (BLOCKS queue)
|
|
|
+ ↓
|
|
|
+5. Claude Code → Runs non-interactively (completes task)
|
|
|
+ ↓
|
|
|
+6. Job Complete → Next job starts
|
|
|
+```
|
|
|
+
|
|
|
+### Key Components
|
|
|
+
|
|
|
+#### 1. Webhook Server (`src/server.js`)
|
|
|
+- Listens on `http://0.0.0.0:3000/webhook`
|
|
|
+- Accepts webhooks immediately (no blocking)
|
|
|
+- Returns HTTP 200 instantly
|
|
|
+
|
|
|
+#### 2. Job Queue (`src/jobQueue.js`)
|
|
|
+- **FIFO Processing**: Jobs execute in order received
|
|
|
+- **Sequential Execution**: Only ONE job runs at a time
|
|
|
+- **Queue Blocks**: Next job waits until current one finishes
|
|
|
+- **Persistence**: Queue state saved to `queue.json`
|
|
|
+- **Crash Recovery**: Pending jobs resume after restart
|
|
|
+
|
|
|
+#### 3. Issue Handler Script (`scripts/handle-issue.sh`)
|
|
|
+- Checks if issue is assigned to `claude` user
|
|
|
+- Clones/updates repository
|
|
|
+- Builds prompt instructing Claude to fetch all comments
|
|
|
+- Runs Claude Code non-interactively
|
|
|
+
|
|
|
+#### 4. Claude Code
|
|
|
+- Runs with `--print --dangerously-skip-permissions`
|
|
|
+- **Uses Gogs MCP tools to fetch issue and all comments**
|
|
|
+- **Reads entire discussion history before starting work**
|
|
|
+- No user interaction required
|
|
|
+- Completes task and exits
|
|
|
+
|
|
|
+## Configuration
|
|
|
+
|
|
|
+### Enable Issue & Comment Webhooks
|
|
|
+
|
|
|
+**.env:**
|
|
|
+```bash
|
|
|
+# Issues Event Configuration
|
|
|
+WEBHOOK_ISSUES_ENABLED=true
|
|
|
+
|
|
|
+# Issue Comment Event Configuration
|
|
|
+WEBHOOK_ISSUE_COMMENT_ENABLED=true
|
|
|
+```
|
|
|
+
|
|
|
+### Command Configuration
|
|
|
+
|
|
|
+**commands.json:**
|
|
|
+```json
|
|
|
+{
|
|
|
+ "commands": {
|
|
|
+ "issues": [
|
|
|
+ {
|
|
|
+ "name": "claude-issue-handler",
|
|
|
+ "description": "Automatically handle issues assigned to Claude",
|
|
|
+ "type": "shell",
|
|
|
+ "command": "/home/claude/agent-manager/scripts/handle-issue.sh",
|
|
|
+ "args": [
|
|
|
+ "{{repo_owner}}",
|
|
|
+ "{{repo}}",
|
|
|
+ "{{pusher}}",
|
|
|
+ "{{issue_number}}",
|
|
|
+ "{{issue_title}}",
|
|
|
+ "{{issue_body}}",
|
|
|
+ "{{issue_action}}",
|
|
|
+ "",
|
|
|
+ "{{issue_assignee}}"
|
|
|
+ ],
|
|
|
+ "cwd": null,
|
|
|
+ "timeout": 600000,
|
|
|
+ "filterBranch": null
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ "issue_comment": [
|
|
|
+ {
|
|
|
+ "name": "claude-comment-handler",
|
|
|
+ "description": "Handle issue comments for Claude-assigned issues",
|
|
|
+ "type": "shell",
|
|
|
+ "command": "/home/claude/agent-manager/scripts/handle-issue.sh",
|
|
|
+ "args": [
|
|
|
+ "{{repo_owner}}",
|
|
|
+ "{{repo}}",
|
|
|
+ "{{pusher}}",
|
|
|
+ "{{issue_number}}",
|
|
|
+ "{{issue_title}}",
|
|
|
+ "{{issue_body}}",
|
|
|
+ "{{issue_action}}",
|
|
|
+ "{{comment_body}}",
|
|
|
+ "{{issue_assignee}}"
|
|
|
+ ],
|
|
|
+ "cwd": null,
|
|
|
+ "timeout": 600000,
|
|
|
+ "filterBranch": null
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+## Critical Flags for Non-Interactive Claude
|
|
|
+
|
|
|
+### Problem
|
|
|
+By default, Claude Code runs in **interactive mode** and expects:
|
|
|
+- Terminal (TTY) for UI
|
|
|
+- User to approve permissions
|
|
|
+- User to confirm actions
|
|
|
+
|
|
|
+When run from a script, Claude would **hang waiting for input**.
|
|
|
+
|
|
|
+### Solution
|
|
|
+Use these flags to run Claude non-interactively:
|
|
|
+
|
|
|
+```bash
|
|
|
+claude --print --dangerously-skip-permissions "$PROMPT"
|
|
|
+```
|
|
|
+
|
|
|
+**Flags explained:**
|
|
|
+- `--print`: Non-interactive mode - print output and exit
|
|
|
+- `--dangerously-skip-permissions`: Skip all permission dialogs (safe in controlled environment)
|
|
|
+
|
|
|
+**Alternative (safer in some contexts):**
|
|
|
+```bash
|
|
|
+claude --print --permission-mode bypassPermissions "$PROMPT"
|
|
|
+```
|
|
|
+
|
|
|
+## Behavior
|
|
|
+
|
|
|
+### ✅ What Happens
|
|
|
+
|
|
|
+1. **Multiple webhooks arrive quickly:**
|
|
|
+ - All are accepted immediately (HTTP 200)
|
|
|
+ - All are queued
|
|
|
+
|
|
|
+2. **Queue processes sequentially:**
|
|
|
+ - Job 1 starts → Claude runs → Claude finishes → Job 1 complete
|
|
|
+ - Job 2 starts → Claude runs → Claude finishes → Job 2 complete
|
|
|
+ - Job 3 starts → ...
|
|
|
+
|
|
|
+3. **New webhooks accepted during processing:**
|
|
|
+ - Webhook arrives while Claude is running
|
|
|
+ - Gets queued immediately
|
|
|
+ - Webhook sender gets instant 200 response
|
|
|
+ - Job will process when queue reaches it
|
|
|
+
|
|
|
+### ✅ Benefits
|
|
|
+
|
|
|
+- **No Lost Webhooks**: Even if Claude takes 30 minutes, new webhooks are queued
|
|
|
+- **No Concurrent Execution**: Only one Claude runs at a time (prevents conflicts)
|
|
|
+- **Crash Recovery**: If server crashes, pending jobs resume on restart
|
|
|
+- **No Timeouts**: Webhook sender gets instant response, doesn't timeout
|
|
|
+
|
|
|
+## How Claude Reads All Comments
|
|
|
+
|
|
|
+### Critical Feature: Mandatory Comment Reading
|
|
|
+
|
|
|
+The system **forces Claude to read all issue comments** before starting work. This is achieved through:
|
|
|
+
|
|
|
+1. **Explicit Instructions in Prompt**
|
|
|
+ - Prompt contains step-by-step mandatory instructions
|
|
|
+ - Claude MUST use MCP tools to fetch data
|
|
|
+ - Clear order: fetch → read → understand → act
|
|
|
+
|
|
|
+2. **Gogs MCP Tools Used**
|
|
|
+ - `mcp__gogs__get_issue` - Fetches complete issue details
|
|
|
+ - `mcp__gogs__list_issue_comments` - Fetches ALL comments chronologically
|
|
|
+
|
|
|
+3. **Why This Matters**
|
|
|
+ - Prevents Claude from missing context
|
|
|
+ - Ensures Claude sees user clarifications
|
|
|
+ - Avoids duplicate work or wrong assumptions
|
|
|
+ - Claude understands full conversation history
|
|
|
+
|
|
|
+### Example Prompt Structure
|
|
|
+
|
|
|
+When an issue or comment is received, Claude gets this prompt:
|
|
|
+
|
|
|
+```
|
|
|
+IMPORTANT: Issue #42 was opened in repository owner/repo.
|
|
|
+
|
|
|
+=== MANDATORY FIRST STEPS - READ ALL MESSAGES ===
|
|
|
+
|
|
|
+Before you start any work on this issue, you MUST complete these steps IN ORDER:
|
|
|
+
|
|
|
+1. Use the mcp__gogs__get_issue tool to fetch the complete issue details:
|
|
|
+ - owner: owner
|
|
|
+ - repo: repo
|
|
|
+ - number: 42
|
|
|
+
|
|
|
+2. Use the mcp__gogs__list_issue_comments tool to fetch ALL comments:
|
|
|
+ - owner: owner
|
|
|
+ - repo: repo
|
|
|
+ - number: 42
|
|
|
+
|
|
|
+3. Read and understand:
|
|
|
+ - The complete issue description
|
|
|
+ - ALL comments in the discussion thread
|
|
|
+ - The full context
|
|
|
+
|
|
|
+4. ONLY AFTER reading everything above, proceed with your work
|
|
|
+
|
|
|
+=== ISSUE CONTEXT ===
|
|
|
+[Issue details here]
|
|
|
+
|
|
|
+=== YOUR TASK ===
|
|
|
+[Instructions here]
|
|
|
+
|
|
|
+DO NOT skip reading the comments using the MCP tools. This is critical.
|
|
|
+```
|
|
|
+
|
|
|
+This ensures Claude always has the complete conversation context.
|
|
|
+
|
|
|
+## Workflow Example
|
|
|
+
|
|
|
+### Scenario: User creates issue assigned to Claude
|
|
|
+
|
|
|
+1. **User creates issue** in Gogs
|
|
|
+ - Title: "Add dark mode to settings"
|
|
|
+ - Assignee: `claude`
|
|
|
+
|
|
|
+2. **Gogs sends webhook** → `POST /webhook`
|
|
|
+ - Event: `issues`
|
|
|
+ - Action: `opened`
|
|
|
+
|
|
|
+3. **Server accepts webhook** → Returns `200 OK` (instant)
|
|
|
+
|
|
|
+4. **Job enqueued:**
|
|
|
+ ```json
|
|
|
+ {
|
|
|
+ "id": 5,
|
|
|
+ "eventType": "issues",
|
|
|
+ "status": "pending",
|
|
|
+ "config": { "command": "handle-issue.sh", ... }
|
|
|
+ }
|
|
|
+ ```
|
|
|
+
|
|
|
+5. **Queue starts processing:**
|
|
|
+ - Runs `handle-issue.sh`
|
|
|
+ - Script clones/updates repo
|
|
|
+ - Builds prompt:
|
|
|
+ ```
|
|
|
+ Issue #5 was opened in owner/repo by user.
|
|
|
+
|
|
|
+ Issue Title: Add dark mode to settings
|
|
|
+
|
|
|
+ Issue Description: [description here]
|
|
|
+
|
|
|
+ This issue is assigned to you. Please review and handle it accordingly.
|
|
|
+ ```
|
|
|
+
|
|
|
+6. **Claude Code runs:**
|
|
|
+ ```bash
|
|
|
+ claude --print --dangerously-skip-permissions "$PROMPT"
|
|
|
+ ```
|
|
|
+ - **First**: Uses `mcp__gogs__get_issue` to fetch issue details
|
|
|
+ - **Second**: Uses `mcp__gogs__list_issue_comments` to fetch ALL comments
|
|
|
+ - **Third**: Reads and understands the complete discussion thread
|
|
|
+ - **Then**: Analyzes the requirements from full context
|
|
|
+ - Reads codebase
|
|
|
+ - Implements feature
|
|
|
+ - Commits changes
|
|
|
+ - Uses `mcp__gogs__create_issue_comment` to comment on issue
|
|
|
+
|
|
|
+7. **Job completes** → Next job starts (if any)
|
|
|
+
|
|
|
+## Testing
|
|
|
+
|
|
|
+### Test Non-Interactive Mode
|
|
|
+
|
|
|
+```bash
|
|
|
+./scripts/test-claude-noninteractive.sh
|
|
|
+```
|
|
|
+
|
|
|
+Expected output:
|
|
|
+```
|
|
|
+✓ SUCCESS: Claude ran non-interactively
|
|
|
+```
|
|
|
+
|
|
|
+### Test Queue Blocking
|
|
|
+
|
|
|
+Send multiple webhooks rapidly:
|
|
|
+```bash
|
|
|
+./test-queue-blocking.sh
|
|
|
+```
|
|
|
+
|
|
|
+Monitor queue:
|
|
|
+```bash
|
|
|
+watch -n1 'cat queue.json | jq .queue'
|
|
|
+```
|
|
|
+
|
|
|
+You should see:
|
|
|
+- All jobs queued immediately
|
|
|
+- Only one job with `status: "running"`
|
|
|
+- Others with `status: "pending"`
|
|
|
+- Jobs complete one by one
|
|
|
+
|
|
|
+## Monitoring
|
|
|
+
|
|
|
+### Check Queue Status
|
|
|
+
|
|
|
+```bash
|
|
|
+cat queue.json | jq
|
|
|
+```
|
|
|
+
|
|
|
+### Watch Queue in Real-Time
|
|
|
+
|
|
|
+```bash
|
|
|
+watch -n1 'cat queue.json | jq .queue'
|
|
|
+```
|
|
|
+
|
|
|
+### View Server Logs
|
|
|
+
|
|
|
+```bash
|
|
|
+# If running with systemd
|
|
|
+journalctl -u agent-manager -f -n100
|
|
|
+
|
|
|
+# If running with npm run dev
|
|
|
+# Check terminal where server is running
|
|
|
+```
|
|
|
+
|
|
|
+## Troubleshooting
|
|
|
+
|
|
|
+### Claude hangs/does nothing
|
|
|
+
|
|
|
+**Problem:** Claude is waiting for user input
|
|
|
+
|
|
|
+**Solution:** Ensure you're using `--print` and `--dangerously-skip-permissions` flags
|
|
|
+
|
|
|
+### Jobs pile up in queue
|
|
|
+
|
|
|
+**Problem:** Jobs are being queued but not processing
|
|
|
+
|
|
|
+**Solution:**
|
|
|
+1. Check if a job is stuck running: `cat queue.json | jq '.queue[] | select(.status=="running")'`
|
|
|
+2. Check server logs for errors
|
|
|
+3. Restart server to reset stuck jobs to pending
|
|
|
+
|
|
|
+### Webhooks timing out
|
|
|
+
|
|
|
+**Problem:** Gogs webhook delivery fails with timeout
|
|
|
+
|
|
|
+**Solution:** This shouldn't happen - webhooks return immediately. Check:
|
|
|
+1. Is server running? `curl http://localhost:3000/health`
|
|
|
+2. Check firewall/network
|
|
|
+3. Verify webhook URL in Gogs settings
|
|
|
+
|
|
|
+### Claude makes no changes
|
|
|
+
|
|
|
+**Problem:** Claude runs but doesn't commit anything
|
|
|
+
|
|
|
+**Solution:**
|
|
|
+1. Check if issue is assigned to `claude` user
|
|
|
+2. Verify repository exists and Claude has access
|
|
|
+3. Check the prompt being sent to Claude
|
|
|
+4. Review Claude's output in logs
|
|
|
+
|
|
|
+## Security Considerations
|
|
|
+
|
|
|
+### `--dangerously-skip-permissions` Flag
|
|
|
+
|
|
|
+This flag bypasses all permission checks. It's **safe in this context** because:
|
|
|
+- ✅ Claude only runs on issues assigned to `claude` user
|
|
|
+- ✅ Runs in isolated environment
|
|
|
+- ✅ Repository is controlled/trusted
|
|
|
+- ✅ No external network access to malicious sites
|
|
|
+
|
|
|
+**Do NOT use** if:
|
|
|
+- ❌ Untrusted users can trigger Claude
|
|
|
+- ❌ Claude has access to production systems
|
|
|
+- ❌ Running on sensitive data
|
|
|
+
|
|
|
+### Alternative Safer Approach
|
|
|
+
|
|
|
+If you need more control, use permission modes:
|
|
|
+```bash
|
|
|
+claude --print --permission-mode acceptEdits "$PROMPT"
|
|
|
+```
|
|
|
+
|
|
|
+This auto-accepts edits but may still prompt for other actions.
|
|
|
+
|
|
|
+## Advanced: Adding Logging
|
|
|
+
|
|
|
+To track Claude's output, modify the script:
|
|
|
+
|
|
|
+```bash
|
|
|
+# Create logs directory
|
|
|
+mkdir -p "$HOME/agent-manager/logs"
|
|
|
+
|
|
|
+# Log file with timestamp
|
|
|
+LOG_FILE="$HOME/agent-manager/logs/issue${ISSUE_NUMBER}_$(date +%Y%m%d_%H%M%S).log"
|
|
|
+
|
|
|
+# Run Claude with logging
|
|
|
+claude --print --dangerously-skip-permissions "$PROMPT" 2>&1 | tee "$LOG_FILE"
|
|
|
+```
|
|
|
+
|
|
|
+## Performance
|
|
|
+
|
|
|
+Typical execution times:
|
|
|
+- Webhook acceptance: < 100ms
|
|
|
+- Simple issue (read/comment): 10-30 seconds
|
|
|
+- Complex issue (code changes): 2-5 minutes
|
|
|
+- Very complex (multiple files): 5-15 minutes
|
|
|
+
|
|
|
+Queue handles bursts:
|
|
|
+- 10 webhooks → queued in ~1 second
|
|
|
+- Processing time: 10 × average job time
|
|
|
+- No webhook delivery failures
|