unkinben 748048be50
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
Add fail-closed author allowlist gating job dispatch
Sessions run claude with --dangerously-skip-permissions and a prompt built
from issue/PR/comment text, so only trusted authors may supply that text.
teabot now dispatches a job only when the triggering event's author login is
on an allowlist; an empty allowlist dispatches nothing (fail-closed).

Claude-Session: https://claude.ai/code/session_015ur3i7D2azsMAWTSVABApv
2026-07-27 00:33:09 +10:00
2026-07-26 23:36:21 +10:00
2026-07-26 23:36:21 +10:00
2026-07-26 23:36:21 +10:00
2026-07-26 23:36:21 +10:00
2026-07-26 23:36:21 +10:00
2026-07-26 23:36:21 +10:00
2026-07-26 23:36:21 +10:00

teabot

teabot is a Go daemon (shipped as a systemd user service) that watches Gitea repositories and dispatches one-shot Claude Code sessions in Docker containers to work issues and review pull requests.

On each poll it looks for new issues, new pull requests, and new comments across the repos it watches. For each event it launches a throwaway container that clones the repo fresh and runs claude --print with a task-specific prompt:

  • New issue → an implementer personality reviews it and, if it warrants a change, opens a PR that closes the issue (following the house PR conventions).
  • New pull request → a reviewer personality critiques the diff and posts an approving or change-requesting review.
  • New comment on a thread teabot already engaged with → a follow-up session responds or makes the requested change.

Each personality is a distinct Gitea bot account backed by its own tea config file, so an implementer bot can open PRs that a separate reviewer bot critiques. teabot never reacts to events authored by its own personalities (loop prevention) and persists processed state so restarts don't re-trigger work.

Security: sessions run claude --dangerously-skip-permissions with a prompt built from event text, so teabot only acts on events from authors on a configured allowed_authors allowlist (fail-closed — an empty list dispatches nothing). See Author allowlist.

Quick start

# 1. Create the config and edit it.
teabot config init
$EDITOR ~/.config/teabot/config.yaml

# 2. Create a tea login file per personality (a normal tea config.yml).
tea logins add --name teabot-impl   --url https://git.unkin.net --token <impl-token>
tea logins add --name teabot-review --url https://git.unkin.net --token <review-token>
# point each personality's tea_config: at the resulting config.yml

# 3. Validate, then run a single cycle to test.
teabot config show
teabot run --once

# 4. Enable the daemon.
systemctl --user enable --now teabot

Documentation

  • Architecture — how polling, dispatch, and the Docker execution model fit together.
  • Configuration — every config key, personalities, and Claude/tea credential handling.
  • teabot run — running the daemon, --once, logging, systemd.
  • teabot config — the init and show subcommands.

Build

make build      # -> dist/teabot (static, CGO disabled)
make test       # go test -race ./...
make rpm        # build + package an RPM (needs nfpm)

Requires Go 1.25+. A v* tag triggers the release pipeline: a Gitea release with cross-platform binaries plus an RPM published to the artifactapi rpm-internal repo.

License

MIT

S
Description
A Go daemon that watches Gitea repos and dispatches one-shot Claude Code sessions in Docker to work issues and review PRs.
Readme 124 KiB
v0.1.0 Latest
2026-07-27 17:10:49 +10:00
Languages
Go 96.8%
Makefile 1.8%
Shell 1.4%