Changelog

What changed, and when.

[Unreleased]

0.5.0 (2026-08-13)

Breaking changes

  • refactor!: minato move --json now emits a summary, {"reports": [...]}, as every other action command does, rather than the single report it emitted before. A move that succeeds while the manifest of its tree cannot be written is reported in that summary, so the answer says why the run exited non-zero. Read .reports[0] for what was previously the whole document.

Features

  • feat: add minato manifest, which records where clones sit and restores a tree from that record. The record is a .minato.toml file in the root it describes, so the file is the root reference: paths are relative to it, restoring targets that directory, and a tree carries its layout between machines without any configuration. write records every clone found and never drops one another machine may hold, apply clones what is recorded and missing here and reports a clone sitting elsewhere unless --relocate is passed, diff reports what the record and the tree disagree about, and forget stops recording one repository without touching its clone. clone and move keep an existing manifest up to date, in the browser as well as on the command line, while the commands that only read a tree leave it alone. Any command run from inside a recorded tree works on it (#99).
  • feat: lead the minato status table with PATH, followed by REPOSITORY, GROUP, STATE, and NOTES, and order rows by group, then by path, so clones sharing a directory read together. Repositories with no clone, and clones sitting directly in a root, come last rather than first. The ordering is shared, so --json and the fetch and update reports follow it too. The interactive view gains the same leading path column, and ordering it by group with s now follows the same group, then path order, leaving the ungrouped rows last as well (#98).

0.4.1 (2026-08-07)

Documentation

  • docs: clarify wording across the README, documentation site, CLI help text, and error messages.

0.4.0 (2026-08-04)

Breaking changes

  • fix!: --owner, --group, --state, and --include-external now belong to each command rather than to minato itself, so they must be written after the command: minato status --group perso, not minato --group perso status, which clap now refuses with a tip naming the right form. Every documented example already used the first form. This is what lets a command’s help and its completion script offer only the conditions it can act on; naming one it cannot is still refused with the explanation that names the command which does take it, rather than a bare “unexpected argument” (#91).

Features

  • feat: report a stale shell completion script in minato doctor, comparing each one it finds against what the binary would generate now and printing the command that rewrites it, so a script left offering the commands of an older release is noticed rather than quietly wrong (#89).
  • feat: name any completion script the shell installer has just made stale, with the command that rewrites it, since an install is the moment the command surface changes; a script still matching the installed binary is passed over in silence (#90).
  • feat: install a completion script with minato completions <shell> --install, which writes it where the shell reads it and edits the shell’s configuration only where the file alone is not enough, inside a managed block that re-running replaces and --uninstall removes. --dry-run reports every path either would touch. The shell is taken from $SHELL when it is left out, and printing the script to standard output is still what happens without a flag.
  • feat: install zsh completions to Oh My Zsh’s custom directory, or to Homebrew’s share/zsh/site-functions when the prefix has one and it is writable, before falling back to ~/.zfunc with an fpath line. The first two are on fpath already, so nothing is added to ~/.zshrc for them.
  • fix: report a stale copy that cannot be removed, rather than failing on it. One of the places swept is Homebrew’s prefix, which is outside the home directory and may belong to another user, and a file there is not reason enough to fail an install that has otherwise worked. Nothing is ever removed with elevated rights.
  • feat: keep an install where it is. A script already on disk is the one that is updated, wherever it is, even once the machine has gained Oh My Zsh, Homebrew, or bash-completion and a first install would now choose elsewhere; copies in the other known places are swept so none is left to shadow it. Moving one is --uninstall followed by a fresh install.
  • feat: leave an unchanged script alone, reporting Already current rather than rewriting a file that already matches what this binary generates.

Bug Fixes

  • fix: say where a completion script goes, printing the destination for the shell asked for on standard error alongside the script on standard output, so minato completions zsh > _minato writes the script alone and the instructions still reach the terminal; the help no longer declines to answer, and the zsh instructions name the oh-my-zsh directory that needs no further setup (#88).
  • fix: honour $XDG_DATA_HOME and $XDG_CONFIG_HOME when working out where a completion script lives. Both were hardcoded to ~/.local/share and ~/.config, so on a machine that sets either, minato doctor reported on a file nobody had, and the installer’s stale-script check looked in the wrong place.
  • fix: follow $ZSH and $ZSH_CUSTOM only when they point inside $HOME. Oh My Zsh exports both, so a run with a different $HOME would otherwise install into, and on uninstall delete from, a home nobody named.

0.3.0 (2026-08-03)

Features

  • feat: let groups nest as the directory tree does, so a clone in perso/apps is in the group perso/apps rather than reported as perso, with --group perso keeping everything filed beneath it and --to-group and --into-group accepting a nested group.
  • feat: print a shell completion script with minato completions <shell>, for bash, zsh, fish, PowerShell, and elvish, generated from the command definitions so it can never offer a command the binary does not have (#82).
  • feat: install on Windows with one line, powershell -ExecutionPolicy ByPass -c "irm https://m.canouil.dev/minato/install.ps1 | iex", verifying the download against SHA256SUMS as the shell installer does, installing into %LOCALAPPDATA%\Programs\minato without administrator rights, and adding that directory to the user PATH without expanding away a %VARIABLE% already written there (#84).
  • feat: publish a native Windows on ARM binary, minato-<version>-aarch64-pc-windows-msvc.zip, so an ARM64 machine installs it rather than running the x86-64 build under Windows’ emulation (#85).

Bug Fixes

  • fix: refuse a --into-group, or a group typed in the browser, that names its way out of a root, which --to-group already refused rather than cloning there.
  • fix: refuse --group, --state, and --include-external on the commands that never scan local clones, rather than accepting them and answering with the unnarrowed set: minato list --group perso listed every repository, including for a group that does not exist. list and sync-fork now take --owner alone, and move, refresh, doctor, auth status, and completions narrow by nothing.

0.2.0 (2026-07-22)

Performance

  • perf: shrink the repository listing query, halving the page size and no longer counting release downloads, so GitHub is less likely to answer an account with a 502; the download count is dropped from minato list as a result (#68).

Bug Fixes

  • fix: serve the last cached repositories with a warning when GitHub is briefly unavailable while listing, so a passing 502 or unreachable host no longer fails a whole run (#68).

0.1.0 (2026-07-22)

First public release of Minato.

Features

  • feat: compare every repository a GitHub account owns against the clones on disk, reporting each as not backed up, in sync, ahead, behind, diverged, or local only, with the reason it is in that state (#6, #7).
  • feat: clone missing repositories, fetch every clone, and fast-forward those that are strictly behind and clean, each with --dry-run and each reporting what it deliberately left alone (#8, #9).
  • feat: sync forks with their upstream through GitHub’s merge-upstream with minato sync-fork, fast-forward only and with --dry-run, leaving a diverged fork reported rather than merged (#36).
  • feat: report how far a fork trails the repository it was forked from (#13).
  • feat: group repositories by the directory they sit in, with --group to select and --into-group to place new clones, and minato move --to-group to move an existing one (#10, #14).
  • feat: hide forks and clones of untracked owners by default, with --include-forks and --include-external to show them (#30).
  • feat: browse the whole comparison interactively with minato tui, cloning the highlighted repository with c into a group you choose or create and refreshing the row once it lands (#11, #56, #57).
  • feat: narrow every command with repeatable --owner, --group, and --state, and emit machine-readable output with --json (#7).
  • feat: configure how long provider responses stay cached with cache.ttl, defaulting to fifteen minutes (#27).
  • feat: show the latest release’s download count in minato list, surfacing metadata already fetched (#53).
  • feat: install with one line, curl -fsSL https://m.canouil.dev/minato/install.sh | bash, with releases shipping a SHA256SUMS asset and build provenance the installer and gh attestation verify can check (#51).
  • feat: generate the command reference from the command-line definitions, gated in CI so the documented commands and flags cannot drift from the binary (#37).

Bug Fixes

  • fix: retry a transient stream or connection reset while listing, so one cancelled response no longer fails a run enumerating several accounts (#31).
  • fix: report a persistent server error or an unreachable host as such when listing gives up, instead of always calling it a rate limit (#49).
  • fix: report symlinked directories the scan does not follow, so a projects tree kept behind a symlink is explained rather than showing an empty result (#32).
  • fix: recognise a bare repository or mirror and report it rather than silently ignoring it, since it has no working tree to compare as a clone (#33).
  • fix: report a clone the scan cannot read as a failure rather than dropping it, so its remote is no longer mislabelled “not backed up” (#48).
  • fix: skip a clone with no origin remote when fetching rather than attempting it, so one never-published clone no longer fails the whole fetch (#39).
  • fix: report unreadable roots and skipped paths from clone, fetch, and update too, not only status, so a mistyped root is never silent (#42).
  • fix: escape quotes and backslashes when building the fork-comparison GraphQL query, so an unusual branch name cannot corrupt the request (#40).
  • fix: reject . or .. as a repository owner or name, so a crafted identity from cache or configuration cannot build a directory-escaping path (#41).
  • fix: reject a move --to-group name that is not a plain directory (empty, ., .., or containing a path separator), so a clone cannot be moved outside its root (#46).
  • fix: pass the clone destination to git as its real path rather than a lossy display string, so a non-UTF-8 path is not mangled (#45).
  • fix: give each process its own cache temporary file, so concurrent runs writing the same key cannot publish a torn entry (#47).
  • fix: list each account once when a login appears under both users and orgs or in a different case, so repositories are no longer fetched, reported, and cloned twice (#44).
  • fix: apply --owner on list and sync-fork, which previously ignored it (#50).
  • fix: in the TUI, clear a status message on the next key so the key hints return, refresh the table after a fetch or update, and open the screen before the first scan so it no longer appears to hang on start (#54).
Back to top