Autonomous repo-maintenance agents backed by Claude Code. Watchers detect signals (PRs, failed builds, alerts), Pattern B Job agents act on them.
Ships today:
agent/pr-reviewer— Pattern B Job agent that reviews GitHub + Bitbucket Server pull requestswatcher/github-pr— polls open PRs and emits create-task commands for each new PRwatcher/github-build— polls GitHub Actions for failed CI runs on default branches and emits create-task commands on green→red transitions
Planned siblings: build-fixer agent (consume github-build tasks → propose fix PRs), dep-updater, sentry-triager, repo-reviewer.
Three modes:
| Mode | Entry | Use case |
|---|---|---|
| Standalone CLI | agent/pr-reviewer/cmd/cli/main.go |
Ad-hoc local review — takes a PR URL, posts a comment back |
| Local task runner | agent/pr-reviewer/cmd/run-task/main.go |
Dev loop for the agent — reads a task markdown file, writes result back |
| Kubernetes Job agent | agent/pr-reviewer/main.go |
Autonomous PR review triggered by the agent task controller; deployed to dev + prod |
Multi-module layout: root has no go.mod; each service (agent/pr-reviewer/, watcher/github-pr/) has its own.
Takes a GitHub or Bitbucket Server PR URL, runs Claude Code review in a claude-yolo container against a local checkout, and posts the review back with a verdict (approve / request-changes).
go install github.com/bborbe/maintainer/agent/pr-reviewer/cmd/cli@latest
pr-reviewer [-v] [--comment-only] <pr-url>Config ~/.config/maintainer/pr-reviewer.yaml:
github:
token: ${PR_REVIEWER_GITHUB_TOKEN} # optional; falls back to `gh` CLI auth
model: sonnet # sonnet | opus | haiku
autoApprove: false # only post comments unless true
repos:
- url: https://github.com/bborbe/maintainer
path: ~/Documents/workspaces/maintainer
reviewCommand: /code-review # optionalRequires: Go 1.26+, Claude Code CLI, gh, Docker.
Pattern B Job spawned per task by the agent task controller. Receives TASK_CONTENT via env, calls Claude Code with Bash(gh:*) access and a GH_TOKEN from teamvault, publishes the result back via Kafka.
cd agent/pr-reviewer
make buca BRANCH=dev # build + push + apply in dev
make buca BRANCH=prod # same for prodmake buca runs image build → docker push docker.quant.benjamin-borbe.de/maintainer-agent-pr-reviewer:<branch> → kubectlquant apply of rendered manifests in k8s/.
- Teamvault entries:
SENTRY_DSN_KEY— Sentry DSN (URL field)AGENT_PR_REVIEWER_GH_TOKEN_KEY— GitHub PAT (Password field) withrepo+read:orgscopes
- PVC
agent-pr-reviewerseeded with a valid.claude/config (copy fromagent-claudePVC or run one-timeclaude loginin a temp pod; see claude-oauth-setup.md). PVC name preserved across thecode-reviewer→maintainerrename to avoid OAuth re-seed. - Config CR registered with the task controller (handled by
k8s/maintainer-agent-pr-reviewer.yaml)
Create a markdown task file in the controller-watched vault with assignee: pr-reviewer-agent, status: in_progress, stage: dev|prod, and a task_identifier: <uuid>. Body is the task prompt — typically "Review the pull request at <url>". Controller publishes to Kafka, executor spawns the Job, result is written back to the task file.
See [[Agent Pipeline Debug Guide]] in the Trading vault for the full step-by-step trace. Quick checks:
kubectlquant -n dev get jobs | grep pr-reviewer
kubectlquant -n dev logs job/pr-reviewer-agent-<uuid>-<timestamp>Same binary as the k8s agent, driven from a local file instead of Kafka.
cd agent/pr-reviewer
make run-dummy-task # generates a sample task file, runs it, writes result backUseful for iterating on prompts (pkg/prompts/workflow.md, pkg/prompts/output-format.md) and allowed-tool config without a cluster round-trip.
maintainer/
├── agent/pr-reviewer/ service module (own go.mod)
│ ├── main.go k8s Job entry
│ ├── cmd/
│ │ ├── cli/ standalone pr-reviewer CLI
│ │ └── run-task/ local file-driven runner
│ ├── pkg/
│ │ ├── bitbucket/ Bitbucket Data Center REST client (CLI only)
│ │ ├── config/ YAML config
│ │ ├── factory/ DI wiring for k8s/run-task
│ │ ├── git/ worktree / clone manager (CLI only)
│ │ ├── github/ GitHub REST client via `gh`
│ │ ├── prompts/ embedded workflow.md + output-format.md
│ │ ├── prurl/ platform-agnostic PR URL parser
│ │ ├── review/ claude-yolo Docker reviewer (CLI only)
│ │ ├── verdict/ JSON verdict parser
│ │ └── version/ build-time version injection
│ ├── k8s/ Config CRD, Secret, PVC, PriorityClass, ResourceQuota, Makefile
│ ├── Dockerfile multi-stage build (Go + claude-code + gh + git)
│ └── agent/.claude/CLAUDE.md headless-review guardrails
├── watcher/github-pr/ GitHub PR watcher service (own go.mod)
│ └── pkg/ poll loop, GitHub client, cursor, Kafka publisher
├── watcher/github-build/ GitHub build-failure watcher (own go.mod)
│ ├── cmd/run-once/ one-shot CLI for ad-hoc polling
│ └── pkg/ poll loop, state machine (green→red detection), filter, Kafka publisher
├── Makefile.* shared includes (variables, env, docker, k8s, folder, precommit)
├── common.env / dev.env / prod.env
└── prompts/ specs/ dark-factory pipeline metadata
Review output must end with a JSON block:
{"verdict": "approve|request-changes", "reason": "<one-liner>"}Fallback: heuristic section-header scan (## Must Fix, ## Blocking). See pkg/verdict/.
BSD 2-Clause License. See LICENSE.