Skip to Content
Changelogv0.2.xv0.2.0 β€” Fetch & Status.

v0.2.0 β€” Fetch & Status.

Refresh your repository collection and see where local work needs attention. Maintainer v0.2.0 adds two commands for the GitHub checkouts on your disk: maintainer status lists uncommitted work, branches ahead or behind and push locks across all of them, offline; maintainer fetch plans how to bring the collection in line with GitHub β€” new repositories, renames and transfers, fresh refs β€” and changes it only with --apply, retaining existing checkouts and local work.

A weekly loop

maintainer status # where local work needs attention, offline maintainer fetch # review the plan: clones, moves, remote updates, fetches maintainer fetch --apply # apply it; branches and working files stay as they are maintainer status # ahead and behind against the refreshed refs
  • status needs Git, but no token or network: it reads local refs and performs no fetch.
  • fetch needs a GitHub token, also for public repositories. Without --apply it only prints the plan. With it, it clones missing repositories, adopts checkouts already on disk, moves renamed or transferred ones, updates their origin URL and fetches refs; branches and working files are not pulled, merged or reset.
  • On 2026-10-19, on one collection of 164 checkouts from 8 owners, status showed 82 checkouts with uncommitted work, 2 with a push lock and 4 inactive duplicates; the fetch plan discovered 160 repositories and proposed 155 fetches, 4 adoptions and 1 move.

Renames and transfers become moves

fetch remembers each repository by its stable GitHub id, so a renamed or transferred repository is moved to its new path instead of cloned again. A transfer from octolab to octopot in the plan:

↻ move octolab/cdn.octolab.org β†’ renamed on GitHub: octopot/cdn.octolab.org from <root>/public/octolab/cdn.octolab.org to <root>/public/octopot/cdn.octolab.org + update remote.origin.url
  • A move renames the checkout on the same filesystem and changes only remote.origin.url: other remotes, push locks and the rest of the Git configuration stay as written.
  • A move or a clone into a path taken by something else is a conflict: apply skips it, runs the other actions and exits with 3.

Bring existing checkouts under management

  • The first --apply adopts the checkouts already in the workspace layout, matched to a GitHub id by their origin, and clones the missing repositories; a later --apply fetches the refs of the adopted ones.
  • A per-repository path keeps an active checkout outside the tree, such as ~/.dotfiles, in place. An older copy in the tree is reported as orphan and is never fetched, moved or deleted.
  • A fetch.toml and state file from a source build of fetch load as they are. Onboard an existing tree step by step.

Keep names and paths in step

  • JSON lists each move with from_path and to_path, so you can update what points at the old path, such as the repository index of your notes vault, bookmarks or scripts:

    maintainer fetch --format=json | jq -r '.actions[]? | select(.kind == "move") | "\(.from_path) -> \(.to_path)"'
  • fetch refreshes remote-tracking refs and tags, never your branches. Keep your own routine for them, such as a git sync script that runs git pull --rebase in each checkout or a git refresh alias that rebases onto the default branch, and let status show which checkouts need it.

Focused lists with JSON

maintainer status --format=json | jq -r '.[] | select(.changed_files > 0 or .untracked > 0) | .path' maintainer status --format=json | jq -r '.[] | select(.push_locked) | .repository' maintainer fetch --format=json | jq '.actions[]? | select(.kind == "conflict" or .kind == "orphan")'
  • status keeps every row it could read and exits with 1 when a checkout could not be inspected; fetch --apply exits with 3 when an action failed or a conflict remains.

Inspect your checkouts β†’

Clearer answers from suggest

  • suggest marks the suggested day with brackets, such as [20], and keeps its count visible.
  • When there is nothing to suggest, it says why β€” every day since the anchor already has what its week requires, or the day’s schedule is over or not open yet β€” when the next gap opens and, where it helps, which higher --target has a moment; then it exits with 4.
  • Input errors, such as an unknown flag, a malformed date, a zero target or a missing token, exit with 2.

Known limitations

  • fetch updates remote-tracking refs and tags only: it does not pull, merge or rebase branches, and it fetches no submodules or LFS content. One workspace per configuration.
  • A personal access token is the only supported credential, and HTTPS with it is the supported way to clone private repositories; SSH works best-effort through a running ssh-agent.
  • --owner and --profile narrow only the discovery of new repositories: tracked checkouts and pins of other owners are still confirmed, fetched, moved and have their origin updated.
  • [filters] skip clones only: a fork, archived or template repository that is already on disk is adopted and fetched.
  • Refs are not fetched in the run that adopts, moves or updates a checkout, only by a later --apply.
  • A move leaves the checkout’s linked worktrees disconnected: run git worktree repair in the moved checkout.

Upgrade: with Homebrew, run brew update followed by brew upgrade --cask octolab/tap/maintainer; if you still have the Formula, switch to the Cask. With the install script, pass the tag: sh -s -- -b ~/.local/bin v0.2.0. With Go, run go install go.octolab.org/toolset/maintainer@v0.2.0. For a manual installation, use a v0.2.0 release archiveΒ . Run maintainer version to check the installed version.