# Command Reference
## Global Flags
These flags can be used with any subcommand and must appear before the subcommand name:
| `--terse` | Terse output — suppress project headers |
| `--stats` | Print match count as `N/total` after count commands |
| `--no-output` | Suppress command output (only print project names) |
| `--print-not` | Invert selection — print repos that do NOT match |
| `--git-verbose` | Pass `--verbose` to git commands |
| `--git-quiet` | Pass `--quiet` to git commands |
| `--no-sort` | Do not sort the project list |
| `--glob <PATTERN>` | Glob pattern for project discovery (default: `*/*`) |
| `--no-glob` | Disable glob — check immediate subdirectories only |
| `--folders <LIST>` | Comma-separated list of folders to operate on |
| `--no-stop` | Do not stop on errors — continue to next project |
| `--venv` | Activate each repo's local `.venv` before running tool subprocesses. On by default; honoured by `run`, `build`, and `clean make` (not by `uv`) |
| `--no-venv` | Turn `--venv` off — run tool subprocesses with the ambient environment |
| `--short-circuit` | Stop at the first negative result. Off by default; honoured by `check-same` |
| `--no-print-no-projects` | Suppress the "no projects found" message |
Example:
```bash
rsmultigit --stats --terse count-dirty # Just print "3/50"
rsmultigit --no-stop pull # Pull all, skip failures
rsmultigit --short-circuit check-same # Stop at the first broken rule
rsmultigit --glob "python-*" status # Only match python-* dirs
rsmultigit --folders a,b,c list-repos # Operate on specific folders
```
## Count Commands
These commands test each discovered repo and print matching projects.
### `rsmultigit count-dirty`
Count repositories with dirty working trees (modified, deleted, or staged files). Uses libgit2 for fast native inspection.
```bash
rsmultigit count-dirty
rsmultigit --stats count-dirty # Print count as N/total
rsmultigit --terse --stats count-dirty # Print only the count line
```
### `rsmultigit untracked`
Count repositories that have untracked files.
```bash
rsmultigit untracked
rsmultigit --stats untracked
```
### `rsmultigit synchronized`
Count repositories that are not synchronized with their upstream (ahead or behind `origin/<branch>`).
```bash
rsmultigit synchronized
rsmultigit --stats synchronized
rsmultigit --print-not synchronized # Show repos that ARE synchronized
```
## Status Commands
These commands inspect each repo and print output only for repos that have data.
### `rsmultigit status`
Show repositories that need attention, with a one-line summary of each repo's
situation: counts of conflicted, staged, modified, deleted, and untracked
files, plus ahead/behind counts when the branch has diverged from `origin`
(e.g. commits that have not been pushed yet). Clean, in-sync repos are
skipped. Pass `--verbose` for the full per-file `git status -s` output
instead of the summary.
```bash
rsmultigit status
# [~/git/myrepo]
# 2 modified, 1 untracked, ahead 1
rsmultigit --verbose status
```
### `rsmultigit dirty`
Show `git diff --stat` output for repositories with modifications.
```bash
rsmultigit dirty
```
### `rsmultigit list-repos`
List all discovered projects.
```bash
rsmultigit list-repos
```
### `rsmultigit age`
Show the age of the last commit for each repo as a human-readable relative date.
```bash
rsmultigit age
```
### `rsmultigit authors`
Show unique commit authors for each repo, sorted by number of commits.
```bash
rsmultigit authors
```
### `rsmultigit config <KEY>`
Show a git config value across all repos. Repos where the key is not set are skipped.
```bash
rsmultigit config user.email
rsmultigit config remote.origin.url
```
### `rsmultigit size`
Show the size of the `.git` directory for each repo. Useful for finding bloated repos.
```bash
rsmultigit size
```
### `rsmultigit last-tag`
Show the most recent tag for each repo. Repos without tags are skipped.
```bash
rsmultigit last-tag
```
## Action Commands
These commands run an action in each project directory.
### `rsmultigit branch-local`
Show local branches for each repo.
```bash
rsmultigit branch-local
```
### `rsmultigit branch-remote`
Show remote branches for each repo.
```bash
rsmultigit branch-remote
```
### `rsmultigit branch-github`
Show the GitHub default branch for each repo (requires `gh` CLI).
```bash
rsmultigit branch-github
```
### `rsmultigit pull`
Pull the current branch from origin.
```bash
rsmultigit pull
rsmultigit pull --quiet
```
### `rsmultigit push`
Push the current branch to origin.
```bash
rsmultigit push
```
### `rsmultigit fetch`
Fetch from origin without merging.
```bash
rsmultigit fetch
```
### `rsmultigit stash push`
Stash working-tree changes in each repo.
```bash
rsmultigit stash push
```
### `rsmultigit stash pop`
Pop the most recent stash in each repo.
```bash
rsmultigit stash pop
```
### `rsmultigit reset hard|soft|mixed`
Reset HEAD across all repos.
```bash
rsmultigit reset hard # Discard all changes
rsmultigit reset soft # Keep changes staged
rsmultigit reset mixed # Unstage changes (default git behavior)
```
### `rsmultigit log`
Show recent commits for each repo.
```bash
rsmultigit log # Show last 10 commits
rsmultigit log -n 5 # Show last 5 commits
```
### `rsmultigit tag local`
List local tags for each repo.
```bash
rsmultigit tag local
```
### `rsmultigit tag remote`
List remote tags for each repo.
```bash
rsmultigit tag remote
```
### `rsmultigit tag has-local`
Show repos that have local tags (prints only the project header).
```bash
rsmultigit tag has-local
```
### `rsmultigit tag has-remote`
Show repos that have remote tags (prints only the project header).
```bash
rsmultigit tag has-remote
```
### `rsmultigit remote`
Show remote URLs for each repo.
```bash
rsmultigit remote
```
### `rsmultigit prune`
Prune stale remote-tracking branches (`git remote prune origin`).
```bash
rsmultigit prune
```
### `rsmultigit gc`
Run git garbage collection on each repo.
```bash
rsmultigit gc
```
### `rsmultigit checkout <BRANCH>`
Checkout a branch across all repos.
```bash
rsmultigit checkout main
rsmultigit checkout develop
```
### `rsmultigit commit -m <MESSAGE>`
Stage all changes and commit across all repos with a shared message.
```bash
rsmultigit commit -m "bump version"
```
### `rsmultigit submodule-update`
Update submodules recursively (`git submodule update --init --recursive`).
```bash
rsmultigit submodule-update
```
### `rsmultigit blame <FILE>`
Run `git blame` on a specific file across all repos. Repos where the file does not exist are skipped.
```bash
rsmultigit blame README.md
rsmultigit blame Makefile
```
### `rsmultigit clean-hard`
Hard-clean each repository with `git clean -ffxd`. **Warning:** this removes all untracked and ignored files.
```bash
rsmultigit clean-hard
```
### `rsmultigit diff`
Show `git diff` for each repository.
```bash
rsmultigit diff
```
### `rsmultigit grep <REGEXP>`
Grep across all repositories. Output lines are prefixed with the project name.
```bash
rsmultigit grep "TODO"
rsmultigit grep --files "TODO" # Only show filenames
```
### `rsmultigit run <COMMAND...>` (alias: `rsmultigit exec`)
Run an arbitrary command across all repositories. By default (`--venv`), a
repo that has a local `.venv` gets it activated first — `.venv/bin` is
prepended to `PATH` and `VIRTUAL_ENV` points at `.venv` — so the command and
anything it spawns resolve from the repo's own venv. Pass `--no-venv` to run
with the ambient environment everywhere.
```bash
rsmultigit run touch marker.txt
rsmultigit run "echo hello > greeting.txt"
rsmultigit exec cargo check
rsmultigit run pytest # each repo's own pytest, via its .venv
rsmultigit --no-venv run which python # ambient python everywhere
```
## Build Commands
These commands run build tools in each project directory. Projects with a `.disable` file are skipped.
By default (the global `--venv` flag), a project that has a local `.venv` gets
it activated before the build tool runs: `.venv/bin` is prepended to `PATH`
and `VIRTUAL_ENV` points at `.venv`, so the tools the build spawns (pytest,
mypy, ruff, ...) resolve from the repo's own venv — including the build tool
itself (make, rsconstruct, ...) when the venv provides it. Projects without a
`.venv` build with the ambient environment. Pass `--no-venv` to disable the
activation everywhere.
### `rsmultigit build-bootstrap`
Run `python bootstrap.py` in each project.
### `rsmultigit build-make`
Run `make` in each project.
### `rsmultigit build-rsconstruct`
Run `rsconstruct build` on projects that have an `rsconstruct.toml` file.
Projects without `rsconstruct.toml` are skipped. As with every build command,
the project's local `.venv` is activated by default (see above); pass
`--no-venv` to build with the ambient environment only.
```bash
rsmultigit build-rsconstruct
rsmultigit --no-venv build-rsconstruct
```
## Rust Commands
These commands operate only on rust projects — repositories that have a
`Cargo.toml` file. Other repositories (and projects with a `.disable` file)
are skipped.
### `rsmultigit rust publish [--type <patch|minor|major>]`
Release a new version of each rust project by running
`cargo release <type> --execute --no-confirm`, which bumps the version in
`Cargo.toml`, commits, tags, pushes, and publishes to crates.io. The default
release type is `patch`. Requires [cargo-release](https://crates.io/crates/cargo-release)
to be installed.
```bash
rsmultigit rust publish # Patch release (default)
rsmultigit rust publish --type minor # Minor release
rsmultigit rust publish --type major # Major release
```
## uv Commands
Run [uv](https://docs.astral.sh/uv/) operations across every repository that
has a `pyproject.toml` at its root; other repositories are skipped.
### `rsmultigit uv lock [--upgrade|--check]`
Run `uv lock` in each Python project, re-resolving `uv.lock` from
`pyproject.toml`. Without `--upgrade`, versions that are already locked are
kept and only added/removed dependencies change; with `--upgrade`, locked
versions may move forward to the newest allowed releases. This is the
fleet-wide dependency-refresh step now that `rsconstruct tools install-deps`
installs the pinned closure from `uv.lock`.
With `--check`, nothing is written: `uv lock --check` only asserts that the
lockfile is up to date with `pyproject.toml`, and a stale lockfile is an
error (combine with the global `--no-stop` to survey all projects instead of
stopping at the first stale one). `--check` and `--upgrade` are mutually
exclusive.
```bash
rsmultigit uv lock # Bring every lockfile in sync with pyproject
rsmultigit uv lock --upgrade # Deliberately upgrade all locked versions
rsmultigit uv lock --check --no-stop # Report which lockfiles are stale
```
### `rsmultigit uv sync`
Run `uv sync` in each Python project, syncing its environment from the
lockfile. Projects without a `.venv` get one created.
`uv` selects its own target environment from the project directory, so
rsmultigit runs it with `VIRTUAL_ENV` (and `UV_PROJECT_ENVIRONMENT`) unset
and leaves the choice to `uv`. This matters when you invoke rsmultigit from
an activated shell: the inherited `VIRTUAL_ENV` names *your* venv, never the
repo being synced, and passing it through makes `uv sync` warn
(`does not match the project environment path` — the value is then ignored)
while the `uv pip` interface would silently target the wrong environment.
The global `--venv`/`--no-venv` flag therefore does not apply to `uv`;
`uv lock` behaves the same way.
```bash
rsmultigit uv sync
```
## GitHub Commands
These commands talk to GitHub through the [gh CLI](https://cli.github.com/)
(which must be installed and authenticated) and operate only on repositories
that have a remote on github.com. Other repositories are skipped.
### `rsmultigit gh clean-all [--keep <N>]`
Clean up GitHub deployments, releases, and workflow runs for each repository.
Keeps only the `--keep` (default 4) most recent non-failed of each and deletes
the rest; failed deployments (latest status `failure`/`error`) and failed
workflow runs (`failure`, `cancelled`, `timed_out`, `startup_failure`,
`action_required`) are always deleted, even if recent.
Note that this deletes data on GitHub permanently — releases, deployment
history, and workflow run logs are gone once removed.
```bash
rsmultigit gh clean-all # Keep the 4 most recent of each
rsmultigit gh clean-all --keep 10 # Keep the 10 most recent of each
```
## Utility Commands
### `rsmultigit version`
Print detailed version information including git commit, branch, dirty status, and Rust compiler version.
```bash
rsmultigit version
```
Short version via flag:
```bash
rsmultigit --version
```