runs/log/wait/wait-quiet/release against the Gitea API. Log fetch tries API (token) -> public web route -> ssh+zstd file storage (hex-bucket path verified against the real Pi5 layout). wait-quiet encodes the "serialize heavy builds" rule with private repos as warnings, not failures. Injectable fetchers make the wait logic testable. Spec: doc/tool-parity.md 4.1. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011KikHkfCiC3yELbsMN8fT9
giteactl — Gitea Actions, CI logs and releases for agents
Removes the biggest daily friction from
doc/tool-parity.md §4.1: CI status was
polled ad hoc, logs lived as zst files on the Pi5, and the
hard-learned rule "more than 2 heavy builds take the Pi5 down" had
no tooling. One stable command prefix for all of it.
Usage
giteactl runs <repo> [--limit 10] runs: status, branch, duration, title
giteactl log <repo> <run> [--job N] print a job log
giteactl wait <repo> [--timeout 30m] block until newest run finishes
giteactl wait-quiet [--max-active 1] block until the runner is quiet
giteactl release <repo> [<tag>] release assets + download URLs
| Exit | wait | wait-quiet |
|---|---|---|
| 0 | run finished green | runner quiet — safe to push |
| 2 | run finished red | — |
| 3 | timeout, still running | timeout, still busy |
The serialization rule as one line:
giteactl wait-quiet && git push
Log fetching
giteactl log tries three sources in order:
- API
…/actions/jobs/{id}/logs— needstokenin the config - Public web route — works anonymously for public repos
- ssh + zstd — reads Gitea's file storage
(
actions_log/<owner>/<repo>/<hex(id%256)>/<id>.log.zst) through the read-onlypi5-claudessh account and decompresses locally
So public-repo logs work with zero setup; private repos need a token (or fall back to ssh).
Config
~/.config/giteactl/config.json, created on first run
(GITEACTL_CONFIG overrides):
{
"url": "https://gitea.brasse-pc.eu",
"owner": "brasse",
"token": "",
"log_ssh_host": "pi5-claude",
"log_dir": "/srv/storage1/gitea/actions_log",
"heavy_repos": ["agent-helm", "agent-tools", "FitnessDroid", "brasse-pc.eu-v2", "Archivum", "lyssnarr", "Npm-cli"]
}
heavy_repos is what wait-quiet watches. Private repos it cannot
read become warnings, not failures — add a token to remove the
blind spots. Create one in Gitea: Settings → Applications →
Generate token (read-only scopes suffice).
Build & test
go test ./...
go build -o build/giteactl .