Never leave work unpushed again.

reposcan is a Git and jj repository scanner. It walks every root you point it at, checks each repo in parallel, and opens a terminal UI listing every one that’s ahead, behind, or sitting on uncommitted changes.

$ curl -fsSL https://raw.githubusercontent.com/mabd-dev/reposcan/main/install.sh | sh

Read the script first · download a binary instead

Go · Apache-2.0 · macOS + Linux · v1.4.1

reposcan — ~/

Built for the way you actually work.

The flows you’ll reach for every day.

Every root, in one pass.

Point it at as many roots as you keep code in. A worker pool checks them concurrently (8 at a time by default, tuned with -w), and dirIgnore globs keep node_modules and caches out of the walk.

$ reposcan -r ~/Code -r ~/work

reposcan — scan

See only what’s broken.

Default to dirty, or pass -f to slice by uncommitted, unpushed, unpulled, or stash. Inside the TUI, / narrows the list without leaving it.

$ reposcan -f unpushed

reposcan — filter

Git and jj, one report.

reposcan discovers .git directories, worktree-style .git files, and .jj repositories in the same pass. Every row carries the VCS it came from, and JSON reports carry a vcsType field so consumers can tell them apart.

[tui] showVCS = true

reposcan — vcs
reposcan's repository table with the VCS column arrowed: one row reads jj, the rest read git.

Copy the path, go fix it.

Finding the dirty repo is half the job. c copies the selected repository’s path, r refreshes the list, ? opens the full keymap.

c copy path · r refresh · ? keymap

reposcan — copy-path

Small binary, serious throughput.

Everything you’d expect from a tool you run a dozen times a day.

Parallel by default

A worker pool checks repos concurrently: 8 at a time out of the box, tune it with -w.

Catches what others miss

Scans Git worktrees as well as plain checkouts, and finds stash-only work on request: -f stash, or set countStashAsDirty to fold it into the dirty filter.

  • worktrees
  • stash
  • dirIgnore globs

Built for scripts

Emit machine-readable reports for dashboards and CI with a single flag.

-o json
--json-output-path ./out

One config, reproducible runs

Set your roots, ignore globs, and output format once and they travel with you. CLI flags still override per run.

~/.config/reposcan/
config.toml

Questions, answered.

The full flag and config reference lives in the docs.

What does reposcan check in each repository?

Uncommitted files, commits ahead of or behind the upstream, and stash entries. By default it lists only dirty repositories; -f switches to uncommitted, unpushed, unpulled, stash or all.

Does it find Git worktrees and jj repositories?

Yes. It discovers .git directories, worktree-style .git files and .jj directories in the same walk. jj support lands in the release after v1.4.1 (build from source to try it now) and reads state only; see the jj notes for its limits.

Which platforms does it run on?

The install script ships binaries for macOS (Intel and Apple silicon) and Linux amd64. Anywhere else with Go installed, build it from source.

How do I keep node_modules and caches out of the scan?

Pass -d glob patterns, or list them once under dirIgnore in ~/.config/reposcan/config.toml. Doublestar globs such as **/node_modules/** work.

Can I use it in scripts or CI?

Yes. -o json prints a JSON report to stdout, --json-output-path writes a timestamped report file, and -o none keeps stdout quiet. See the JSON schema.

Does reposcan collect telemetry?

Anonymous usage data: OS, CPU architecture, tool version, whether it runs in CI, and the flags used. No usernames, tokens or paths. Turn it off with --no-telemetry or no-telemetry = true in the config.

How do I update it?

Re-run the install script; it always fetches the latest release. Starting with the release after v1.4.1, reposcan update does the same in place.

Install in one line.

Detects your OS and architecture, drops the latest release on your $PATH.

$ curl -fsSL https://raw.githubusercontent.com/mabd-dev/reposcan/main/install.sh | sh

Read the script first · download a binary instead

or build from source with go build -o reposcan .