reposcan is a simple command-line tool written in Go that scans your filesystem for Git and jj repositories and reports their status.
It helps you quickly find:
- Repositories with uncommitted files
- Repositories with unpushed commits (ahead of upstream)
- Repositories with unpulled changes (behind upstream)
It outputs results in both human-friendly tables and machine-friendly JSON, so you can use it interactively or integrate with scripts and future UIs.
🖼 Demo
Screen.Recording.2025-11-06.at.12.34.12.PM.online-video-cutter.com.mp4
- Daily cleanup: See which projects have dirty working trees before switching tasks.
- Context switch: Know which repos still have unpushed commits before you leave for the day.
- Housekeeping: Find old repos you forgot to commit/push.
- Automation: Export JSON reports to integrate with dashboards or other tools.
The easiest way to install reposcan. Detects your OS and architecture automatically and installs the latest release binary into a directory on your $PATH:
curl -fsSL https://raw.githubusercontent.com/mabd-dev/reposcan/main/install.sh | shSupports linux/amd64, darwin/amd64, and darwin/arm64.
| env vars | Required | Default | Description |
|---|---|---|---|
VERSION |
false | latest | download a specific version |
ALIAS |
false | reposcan | specify binary name |
# with version
curl -fsSL https://raw.githubusercontent.com/mabd-dev/reposcan/main/install.sh | VERSION=<x.y.x> sh
# with alias
curl -fsSL https://raw.githubusercontent.com/mabd-dev/reposcan/main/install.sh | ALIAS=reposcan sh
# with both
curl -fsSL https://raw.githubusercontent.com/mabd-dev/reposcan/main/install.sh | VERSION=<x.y.z> ALIAS=reposcan shIf you previously installed reposcan via go install, the binary lives in $GOPATH/bin (usually ~/go/bin/reposcan). The curl installer puts the binary in a different location, so both can coexist silently — meaning the old one may take precedence in your $PATH.
To avoid this, remove the old binary first:
rm "$(which reposcan)"Then install using the curl installer:
curl -fsSL https://raw.githubusercontent.com/mabd-dev/reposcan/main/install.sh | shgit clone https://github.com/mabd-dev/reposcan.git
cd reposcan
go build -o reposcan .Scan your home directory
reposcan -r $HOMEMultiple roots
reposcan -r ~/Code -r ~/workCommon flags
-d, --dirIgnore stringArray # (default [$HOME])
-f, --filter string # Repository filter: all|dirty|uncommitted|unpushed|unpulled|stash (default "dirty")
-h, --help # help for reposcan
--json-output-path string # Write scan report JSON files to this directory (optional)
-w, --max-workers int # Number of concurrent git checks (default 8)
-o, --output string # Output format: json|interactive|none (default "interactive")
-r, --root stringArray # Root directory to scan (repeatable). Defaults to $HOME if unset in config. (default [$HOME])
, --debug # Enable/Disable debug modeHelp
reposcan --helpMore details on flags and config mapping can be found in docs/cli-flags-and-configs.md.
RepoScan currently discovers and reports on:
- Git repositories with a
.gitdirectory or worktree-style.gitfile. - jj repositories with a
.jjdirectory.
Reports include a vcsType field so JSON consumers and table users can distinguish Git and jj repositories. For jj repositories, RepoScan collects read-only state: repository name, current bookmark/change display, uncommitted file summaries, outgoing commits for tracked bookmarks, and incoming/unpulled counts based on already-fetched remote bookmark state.
Current jj limitations:
- TUI fetch, push, and pull keybindings are not active.
- jj fetch has a command wrapper but is not exposed through TUI actions yet.
- jj push and pull behavior is not enabled until per-operation semantics are defined.
- jj incoming/unpulled detection depends on tracked bookmarks and fetched remote bookmark state.
- jj remote status is simplified into a single synthetic status entry.
- JSON reports do not expose incoming commit details directly.
- TUI details show shared repository status fields, with limited jj-specific metadata.
By default, reposcan looks for a config file in:
~/.config/reposcan/config.tomlExample
version = 1
debug = false
# directories to search for git repos inside
roots = ["~/Code", "~/work"]
only = "dirty"
# Count repos whose only local state is stashed work as dirty (default false).
# Only affects `only = "dirty"`; `only = "stash"` is unaffected.
countStashAsDirty = false
# Skip these directories (glob patterns)
dirIgnore = [
"/node_modules/",
"/.cache/",
"/.local/"
]
[output]
type = "interactive"
jsonPath = "/somewhere/nice"
[tui]
# Show the "VCS" column in the interactive table (default true).
# Set to false to hide it, e.g. if you only use git.
showVCS = true
You can still override everything via CLI flags.
check sample/config.toml for detailed configuration with examples
- Load default values
- Config in
~/.config/reposcan/config.toml(if exists) - Cli flags (if exists) Each step overrides the one before it
- Scan filesystem for repos
- Detect uncommitted files, unpushed commits and unpulled commits
- Detect Git and jj repositories
- Detect stashed changes
- Stdout Ouput in 3 formats: json, interactive, none
- Read user customizable
config.tomlfile - Export Report to json file
- Support dirignore
- Worker pool for speed
- Support git worktrees
- ColorScheme switcher
- Perform git push/pull/fetch on repos
- Show branches with their states on each repo
reposcan collects anonymous usage data to help understand how the tool is used and improve it over time. You'll see a one-time notice about this on first run.
What is collected:
os— operating system (linux, windows, darwin)arch— device cpu architecturetool-version— tool version being usedci— whether the tool is running in a CI environment
and other tool specific cli-flags like filter, output_format, repo_count
Nothing personal is collected — no usernames, tokens, or file paths. Events are sent to a mixpanel (a third-party analytics service) and visible only to the maintainer.
Add --no-telemetry when running the command. Or in ~/.config/reposcan/config.toml add no-telemetry = true at the top of the file (check sample.toml)
PRs, bug reports, and feature requests are welcome.
Before cutting a release, run the end-to-end smoke test and work through the checklist in docs/release-testing.md:
./scripts/smoke-test.sh