From 2c8ec3e53a0f4c6f2d16e94a95fcdce706717091 Mon Sep 17 00:00:00 2001 From: Peter Stone Date: Sun, 22 Mar 2026 23:48:03 +0000 Subject: chore: unify and centralize agent configuration in .agent/ --- CLAUDE.md | 231 +++----------------------------------------------------------- 1 file changed, 8 insertions(+), 223 deletions(-) (limited to 'CLAUDE.md') diff --git a/CLAUDE.md b/CLAUDE.md index 7ef8d63..5b01d7b 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,227 +1,12 @@ -# CLAUDE.md +# Claudomator — Agent Instructions -This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. +This repository uses a centralized agent configuration. -Also check `~/.claude/CLAUDE.md` for user-level development standards (TDD workflow, git practices, session state management, etc.) that apply globally across all projects. +**Primary Source of Truth:** ".agent/config.md" -## Canonical Repository +## Quick Reference +- **Worklog:** ".agent/worklog.md" +- **Design:** ".agent/design.md" +- **Coding Standards:** ".agent/coding_standards.md" -**The canonical source of truth is `/workspace/claudomator`.** All development must happen here. -Do not work in any other directory unless explicitly instructed. Do not explore `/site/doot.terst.org/` for source files. - -## Build & Test Commands - -```bash -# Build -go build ./... - -# Run all tests -go test ./... - -# Run a single package's tests -go test ./internal/executor/... - -# Run a single test by name -go test ./internal/api/ -run TestServer_CreateTask_MissingName - -# Run with race detector (important for executor/pool tests) -go test -race ./... - -# Build the binary -go build -o claudomator ./cmd/claudomator/ -``` - -> **Note:** `go-sqlite3` uses CGo. A C compiler (`gcc`) must be present for builds and tests. - -## Running the Server - -```bash -# Initialize data directory -./claudomator init - -# Start API server (default :8484) -./claudomator serve - -# Run a task file directly (bypasses server) -./claudomator run ./test/fixtures/tasks/simple-task.yaml - -# List tasks via CLI -./claudomator list -``` - -Config defaults to `~/.claudomator/config.toml`. Data is stored in `~/.claudomator/` (SQLite DB + execution logs). - -## Architecture - -**Pipeline:** CLI/API → `executor.Pool` → `executor.ContainerRunner` → Docker container → SQLite + log files - -### Packages - -| Package | Role | -|---|---| -| `internal/task` | `Task` struct, YAML parsing, state machine, validation | -| `internal/executor` | `Pool` (bounded goroutine pool) + `ContainerRunner` (Docker-based executor) | -| `internal/storage` | SQLite wrapper; stores tasks and execution records | -| `internal/api` | HTTP server (REST + WebSocket via `internal/api.Hub`) | -| `internal/reporter` | Formats and emits execution results | -| `internal/config` | TOML config + data dir layout | -| `internal/cli` | Cobra CLI commands (`run`, `serve`, `list`, `status`, `init`) | - -### Key Data Flows - -**Task execution:** -1. Task created via `POST /api/tasks` or YAML file (`task.ParseFile`) -2. `POST /api/tasks/{id}/run` → `executor.Pool.Submit()` → goroutine in pool -3. `ContainerRunner.Run()` clones `repository_url`, runs `docker run claudomator-agent:latest` -4. Agent runs `claude -p` inside the container; stdout streamed to `executions//stdout.log` -5. On success, runner pushes commits back to the remote; execution result written to SQLite + WebSocket broadcast - -**State machine** (`task.ValidTransition`): -`PENDING` → `QUEUED` → `RUNNING` → `COMPLETED | FAILED | TIMED_OUT | CANCELLED | BUDGET_EXCEEDED` -Failed tasks can retry: `FAILED` → `QUEUED` - -**WebSocket:** `Hub` fans out task completion events to all connected clients. `Server.StartHub()` must be called after creating the server. - -### Task YAML Format - -```yaml -name: "My Task" -claude: - model: "sonnet" - instructions: | - Do something useful. - working_dir: "/path/to/project" - max_budget_usd: 1.00 - permission_mode: "default" - allowed_tools: ["Bash", "Read"] -timeout: "15m" -priority: "normal" # high | normal | low -tags: ["ci"] -``` - -Batch files wrap multiple tasks under a `tasks:` key. - -### Storage Schema - -Two tables: `tasks` (with `config_json`, `retry_json`, `tags_json`, `depends_on_json` as JSON blobs) and `executions` (with paths to log files). Schema is auto-migrated on `storage.Open()`. - -## Features - -### Changestats - -After each task execution, Claudomator extracts git diff statistics from the execution's stdout log. If the log contains a git `diff --stat` summary line (e.g. `5 files changed, 127 insertions(+), 43 deletions(-)`), the stats are parsed and stored in the `executions.changestats_json` column via `storage.DB.UpdateExecutionChangestats`. - -**Extraction points:** -- `internal/executor.Pool.handleRunResult` — calls `task.ParseChangestatFromFile(exec.StdoutPath)` after every execution; stores via `Store.UpdateExecutionChangestats`. -- `internal/api.Server.processResult` — also extracts changestats when the API server processes a result (same file, idempotent second write). - -**Parser location:** `internal/task/changestats.go` — exported functions `ParseChangestatFromOutput` and `ParseChangestatFromFile` usable by any package without creating circular imports. - -**Frontend display:** `web/app.js` renders a `.changestats-badge` on COMPLETED/READY task cards and in execution history rows. - -## GitHub Webhook Integration - -Claudomator can automatically create tasks when CI builds fail on GitHub. - -### Endpoint - -`POST /api/webhooks/github` - -Accepts `check_run` and `workflow_run` events from GitHub. Returns `{"task_id": "..."}` (200) when a task is created, or 204 when the event is ignored. - -### Config (`~/.claudomator/config.toml`) - -```toml -# Optional: HMAC-SHA256 secret set in the GitHub webhook settings. -# If omitted, signature validation is skipped. -webhook_secret = "your-github-webhook-secret" - -# Projects for matching incoming webhook repository names to local directories. -[[projects]] -name = "myrepo" -dir = "/workspace/myrepo" - -[[projects]] -name = "other-service" -dir = "/workspace/other-service" -``` - -### Matching logic - -The handler matches the webhook's `repository.name` against each project's `name` and the basename of its `dir` (case-insensitive substring). If no match is found and only one project is configured, that project is used as a fallback. - -### GitHub webhook setup - -In your GitHub repository → Settings → Webhooks → Add webhook: -- **Payload URL:** `https:///api/webhooks/github` -- **Content type:** `application/json` -- **Secret:** value of `webhook_secret` in config (or leave blank if not configured) -- **Events:** select *Workflow runs* and *Check runs* - -### Task creation - -A task is created for: -- `check_run` events with `action: completed` and `conclusion: failure` -- `workflow_run` events with `action: completed` and `conclusion: failure` or `timed_out` - -Tasks are tagged `["ci", "auto"]`, capped at $3 USD, and use tools: Read, Edit, Bash, Glob, Grep. - -## System Maintenance (Cron) - -The following crontab entries are required for system operation and must be maintained for the root user: - -```crontab -# Sync Claude and Gemini credentials every 10 minutes -*/10 * * * * /workspace/claudomator/scripts/sync-credentials - -# Start the next queued task every 20 minutes -*/20 * * * * /workspace/claudomator/scripts/start-next-task >> /var/log/claudomator-cron.log 2>&1 -``` - -> **Note:** These requirements are critical for agent authentication and automated task progression. - -## Agent Tooling (`ct` CLI) - -Agents running inside containers have access to `ct`, a pre-built CLI for interacting with the Claudomator API. It is installed at `/usr/local/bin/ct` in the container image. **Use `ct` to create and manage subtasks — do not attempt raw `curl` API calls.** - -### Environment (injected automatically) - -| Variable | Purpose | -|---|---| -| `CLAUDOMATOR_API_URL` | Base URL of the Claudomator API (e.g. `http://host.docker.internal:8484`) | -| `CLAUDOMATOR_TASK_ID` | ID of the currently-running task; used as the default `parent_task_id` for new subtasks | - -### Commands - -```bash -# Create a subtask and immediately queue it (returns task ID) -ct task submit --name "Fix tests" --instructions "Run tests and fix any failures." [--model sonnet] [--budget 3.0] - -# Create, queue, and wait for completion (exits 0=COMPLETED, 1=FAILED, 2=BLOCKED) -ct task submit --name "Fix tests" --instructions "..." --wait - -# Read instructions from a file instead of inline -ct task submit --name "Fix tests" --file /workspace/subtask-instructions.txt --wait - -# Lower-level: create only (returns task ID), then run separately -TASK_ID=$(ct task create --name "..." --instructions "...") -ct task run "$TASK_ID" -ct task wait "$TASK_ID" --timeout 600 - -# Check status of any task -ct task status - -# List recent tasks -ct task list -``` - -### Notes - -- Default model is `sonnet`; default budget is `$3.00 USD`. Override with `--model` / `--budget`. -- `ct task wait` polls every 5 seconds and exits with the task's terminal state on stdout. -- Subtasks inherit the current task as their parent automatically (via `$CLAUDOMATOR_TASK_ID`). -- Override parent with `--parent ` if needed. - -## ADRs - -See `docs/adr/001-language-and-architecture.md` for the Go + SQLite + WebSocket rationale. +Refer to ".agent/config.md" before performing any tasks. -- cgit v1.2.3