ci-shepherd

CI-shepherd watches your open change requests — GitHub PRs, GitLab MRs, Bitbucket PRs — and whenever one picks up failing CI , a changes-requested review , or a branch that has fallen behind its target (needs rebase) , dispatches a worker session to address it: the worker checks out the request branch, fixes the feedback (or rebases onto the base and force-pushes), pushes to the same branch (so the request updates), and leaves a comment — then pings the shepherd so the next one dispatches. It turns review round-trips into background work.

Experimental. ci-shepherd is new and under active testing — its behavior spec, scripts, and manifest may change between releases.

Overview #

A shepherd session sweeps your watched repos on a shepherd-tick automation (every 15 min). Fixers are Thurbox tasks ( fix #<n>: … ): each runs in an isolated worktree on the request branch and self-reports via the same ===RESULT=== sentinel as flow. The monitor and fixer are plain agents.toml aliases ( shepherd , shepherd-worker ), so each can be any CLI.

A fixer is dispatched for any of three signals on a watched request: failing CI, a changes-requested review, or a branch that is behind its target and needs a rebase — the normalized rebase signal surfaced as the REBASE action flag by scripts/classify.sh . dispatch-fix.sh --rebase makes the worker rebase onto the base and force-push before fixing.

Forges: any git host #

The only thing baked in is githow to talk to a repo's host is decided by the shepherd agent, fresh each tick. There are two paths, picked per repo automatically:

Path Forges How
Built-in fast path GitHub ( gh ), GitLab ( glab ), Bitbucket ( curl + token) provider.sh lists requests and supplies the branch/checkout/comment commands; the agent just dispatches by number.
Agent-driven any other git forge — Gitea/Forgejo/Codeberg, Azure DevOps, Sourcehut, self-hosted GitHub/GitLab, … provider.sh describe hands the agent the remote + installed clients; it lists the requests itself and passes the commands it chose to dispatch-fix.sh .

So there is no forge allow-list — anything reachable by a git remote and a CLI/REST API works, because the agent reasons about it at runtime. The three built-ins are an optimization (cheap, deterministic) for the common hosts.

Verification status: the GitHub fast path is verified end-to-end; the GitLab and Bitbucket fast paths are implemented against their documented APIs but not yet run live; the agent-driven path depends on the agent and the forge's own CLI/API.

Requirements #

  • git , jq , and thurbox-cli on PATH .
  • The client for each forge you watch, authenticated: gh auth login / glab auth login , or BB_TOKEN (or BB_USER + BB_APP_PASSWORD ) for Bitbucket.

Install #

ci-shepherd is a Thurbox extension (a declarative extension.toml manifest):

bash
thurbox-cli extension install ci-shepherd    # or ./extensions/ci-shepherd
thurbox-cli extension uninstall ci-shepherd  # --purge also deletes ~/.config/thurbox/extensions/ci-shepherd

Installing lays down the shepherd home ( ~/.config/thurbox/extensions/ci-shepherd ; override with --home ), registers the shepherd / shepherd-worker agents, and activates the shepherd session plus the shepherd-tick automation — both self-healed by Thurbox.

Use #

  • Add the repos to watch to ~/.config/thurbox/extensions/ci-shepherd/repos.md (one row each; author defaults to @me , provider to auto ).
  • The shepherd sweeps on its schedule; trigger one now by sending tick to the shepherd session.
  • status for a one-screen report; clean to prune merged/closed worktrees.

How the fixer gets the branch #

Thurbox's own --worktree always runs git worktree add -b , which fails on a branch that already exists — and a request's head branch always does. So dispatch-fix.sh adopts the branch itself into a shepherd-owned worktree under ~/.config/thurbox/extensions/ci-shepherd/worktrees/<repo>-<provider>-<n> , then spawns the fixer there. The checkout is git-universal: a built-in forge uses the provider's checkout ( gh pr checkout / glab mr checkout / git fetch ), any other forge uses the agent-supplied --checkout-cmd (or a plain git fetch origin <branch> fallback). The worker pushes straight to the request branch; clean removes the worktree once the request is no longer actionable (refusing if it has uncommitted work).

Files #

See extensions/ci-shepherd for the SHEPHERD.md behavior spec, the extension.toml manifest, and the helper scripts ( provider.sh — the forge adapter layer, shepherd-snapshot.sh , dispatch-fix.sh , parse-result.sh ).