# giteactl — Gitea Actions, CI logs and releases for agents Removes the biggest daily friction from [`doc/tool-parity.md`](../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 [--limit 10] runs: status, branch, duration, title giteactl log [--job N] print a job log giteactl wait [--timeout 30m] block until newest run finishes giteactl wait-quiet [--max-active 1] block until the runner is quiet giteactl release [] 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: ```bash giteactl wait-quiet && git push ``` ## Log fetching `giteactl log` tries three sources in order: 1. **API** `…/actions/jobs/{id}/logs` — needs `token` in the config 2. **Public web route** — works anonymously for public repos 3. **ssh + zstd** — reads Gitea's file storage (`actions_log////.log.zst`) through the read-only `pi5-claude` ssh 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): ```json { "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 ```bash go test ./... go build -o build/giteactl . ```