v0.2.1 — Safe moves, clear status.
Maintainer v0.2.1 makes maintainer fetch keep to what you select and to the workspace it manages, makes maintainer status sum up your checkouts in one line and name what went wrong, and ships an agent skill inside the binary. Configuration, state and pins from v0.2.0 keep working, except keys outside the config schema, which are now errors.
Fetch keeps to your selection
--ownerand--profilenarrow the whole run: repositories outside the selection get no request, clone, fetch, move or new state, and the summary shows the selection, such asselected=12/40.- Owners are compared case-insensitively, as GitHub compares them.
fetch statecommands use the selection of your config, and a record that fetch could not verify is kept, not dropped.- A repository the token may not read, behind single sign-on or an IP allowlist, is a conflict of its own; the rest of the plan goes on.
- When GitHub’s rate limit runs out, fetch waits once for the reset and tries again; a wait longer than an hour or than
--timeoutstops the run with the wait named.
Checkouts keep their identity
- A checkout stays with the repository it was recorded for through renames, case-only renames and a new repository at the old name.
- Every adoption, relocation, remote update and move fetches the checkout’s refs in the same apply.
- Adopting a pinned checkout only adds the record and leaves its Git configuration alone; a stale origin is updated as a separate step.
- A clone cut short is kept for inspection, reported as an
incomplete cloneconflict and never adopted. - Linked worktrees keep working after their repository moves.
- A failed save of the state file is an error that names the repositories it leaves unrecorded.
The workspace boundary holds
- Clone and move never write through a symlink or into another checkout; apply checks every target again right before the change.
- A directory the scan cannot read, or a repository at an owner or visibility level, is a
scan obstructionrow, and the scan goes on past it. - A per-repository path is used only when every field it needs is known; otherwise fetch reports a conflict and status an
unresolved pinrow.
Configuration you can check
- A key outside the config schema stops
fetch, its subcommands andstatuswith exit2, naming the key, its table and the closest valid key. cue vet -c fetch.cue fetch.tomlchecks a config against the published schema.fetch config validaterejects a per-repositorypaththat is not a valid template; fetch and status report it on that repository and go on with the rest.
Status at a glance
Repository status · 3 checkouts · 2 uncommitted · 1 ahead · 1 behind · 1 locked · 0 orphan · 0 errors · local refs (no fetch)- The header sums up the rows; in the terminal UI the summary follows the filter.
- A failed Git command names the step and quotes Git’s message.
- Duplicates count only checkouts of the same
owner/name; two local projects with the same directory name are two ordinary rows. - Sorting keeps the highlighted row, and a row inspected again gets fresh numbers.
Clear exit codes
- Usage errors exit
2before any work starts: an unknown command or flag, a value that does not parse, a missing required flag, invalidfetchoptions, contribution arguments out of range or a missing token.
An agent skill in the binary
maintainer skill install --agent claude-codeor--agent codexteaches your coding agent to plan before--apply, read conflicts and exit codes and keep tokens out of sight. The skill is also published in theoctolab/skillscatalog.
Known limitations
- A per-repository path that uses an unknown field passes
fetch config validateand fails later, as a conflict of that repository. - When GitHub cannot confirm the repository of an explicit rule, fetch still stops the whole run.
Upgrade: with Homebrew, run brew update followed by brew upgrade --formula octolab/tap/maintainer or brew upgrade --cask octolab/tap/maintainer, whichever you installed. With the install script, pass the tag: sh -s -- -b ~/.local/bin v0.2.1. With Go, run go install go.octolab.org/toolset/maintainer@v0.2.1. For a manual installation, use a v0.2.1 release archive . Run maintainer version to check the installed version.