Skip to main content

gitomb

Turn forgotten Git branches and stashes into a cleanup list you can review.

gitomb scans local repositories, combines Git evidence with optional TypeSafe Jev assessments, and helps you decide what to keep. You select the items to remove. gitomb backs them up before deletion and can restore them by batch.

No API key is required for Git-only scans.

Command Purpose Changes Git refs?
gitomb scan Scan repositories and save a report No
gitomb show Inspect a saved report or a local diff No
gitomb clean Select, confirm, back up, and remove items Yes, unless --dry-run
gitomb batches List cleanup batches No
gitomb restore Restore a cleanup batch Yes

Quick start

Requires Python 3.11+, Git, uv, and macOS or Linux. Windows is not supported yet because cleanup uses POSIX file locks.

1. Install

uv tool install gitomb
gitomb --help
gitomb scan /path/to/your/repo --no-ai

Replace /path/to/your/repo with a repository you want to inspect. If your shell cannot find gitomb, run uv tool update-shell and restart the terminal.

To upgrade, run uv tool upgrade gitomb. To uninstall, run uv tool uninstall gitomb.

Scanning does not delete, fetch, or check out anything. It saves a report for subsequent show and clean commands.

2. Enable Jev assessments (optional)

Get an API key from TypeSafe. Create or edit .env in the directory where you will run gitomb:

TYPESAFE_API_KEY=your-api-key

Then scan with Jev:

gitomb scan /path/to/your/repo --ai

An existing TYPESAFE_API_KEY environment variable takes precedence over .env. The default .env is read from the directory where you run the command, not from each scanned repository. Use --env-file /path/to/.env for a different location.

Keep .env out of version control. The gitomb source repository already ignores it; configure your own repository accordingly. Do not commit your key. Jev calls use your own TypeSafe account quota.

Mode Behavior
Default Use Jev when a key is available; otherwise use Git rules
--no-ai Use local Git evidence only; make no Jev requests
--ai Require a key; individual API failures still fall back to Git rules

Install from source instead

git clone https://github.com/PaulChen79/gitomb.git
cd gitomb
uv sync --locked
uv tool install .
gitomb scan /path/to/your/repo --env-file /path/to/gitomb/.env

After updating the source checkout, reinstall with uv tool install --reinstall .. The examples below use the standalone gitomb command.

Usage

Scan one or more repositories

gitomb scan ~/projects ~/work --no-ai
gitomb scan /path/to/repo --base develop
gitomb scan /path/to/repo --ai --include-diff

Without a path, gitomb scans the current directory. Discovery searches six directory levels by default, deduplicates linked worktrees, skips directories such as .git, .venv, and node_modules, and does not follow directory symlinks.

Example report, simplified for readability. IDs and data are illustrative:

#  ID            Repository / item           Age   Action             Evidence / Jev
1  a1b2c3d4e5f6  billing / branch: fix/log    90d   cleanup-candidate  merged; no unique commits
2  b2c3d4e5f6a1  portal / branch: experiment  120d  review             3 unique commits
3  c3d4e5f6a1b2  infra / stash: stash@{0}     45d   review             stash contents require review

Scan: 20260923T080000Z-abcd1234
Saved: .../gitomb/scans/20260923T080000Z-abcd1234.json

Review the report and diffs

gitomb show
gitomb show ITEM_ID --diff
gitomb show ITEM_ID --scan SCAN_ID --diff

Replace ITEM_ID with an ID from the report; unique prefixes are accepted. show --diff displays the full diff locally without sending it to Jev.

show and clean use the latest saved scan, not a fresh scan of the current directory. Specify --scan SCAN_ID to use a particular report.

Select and confirm cleanup

gitomb clean

Enter comma-separated row numbers, such as 1,3. Review the selected items, then type clean 2 to confirm two deletions. An empty selection cancels. Protected branches and branches in use by a worktree cannot be removed.

For explicit selection, use item IDs. Preview the operation first:

gitomb clean --ids ITEM_ID ANOTHER_ID --dry-run
gitomb clean --ids ITEM_ID ANOTHER_ID

Branches with commits not reachable from the comparison branch require an additional flag:

gitomb clean --ids ITEM_ID --allow-unmerged

--allow-unmerged does not bypass branch protection, worktree checks, or confirmation. Stashes always require your review, but do not use the branch-specific --allow-unmerged flag.

--dry-run validates eligibility without creating backups or deleting anything. Actual cleanup checks the state again. Noninteractive cleanup requires both explicit --ids and --yes.

Restore a batch

gitomb batches
gitomb restore BATCH_ID

Use the batch ID printed by clean. Restoration recreates branches and adds stashes back to the stash list. It does not apply stashes to your working tree.

Interrupted or partially successful operations also appear in batches. Use the same batch ID to restore any items with valid backups.

How it works

Local repositories
        |
        v
Git evidence + optional Jev assessments
        |
        v
Saved report -> Your selection -> State checks -> Backup -> Cleanup
                                                    |
                                                    v
                                              Batch restoration

Git provides facts: commit age, ancestry, unique commits, upstream refs, worktree usage, file names, and diff statistics. Jev handles narrower semantic questions about the changes:

Question Primitive Result
What is the purpose of this work? Choice temporary-debug, experiment, feature-or-fix, maintenance, or unknown
Does the evidence show unfinished work? Noul Probability from 0 to 1
Is the context insufficient to determine the purpose? Noul Probability from 0 to 1

The application combines these answers with Git rules. Jev can influence review order and suggest keeping unfinished work; it never authorizes deletion.

Recommendation Meaning
cleanup-candidate Git confirms the branch is merged into the comparison branch with no unique commits; selection is still manual
review Unique work, a stash, or evidence that needs your judgment
keep Protected or checked-out branch, or model evidence of unfinished work

Percentages describe model probabilities about purpose, not deletion safety or the author's intent to abandon work. Confidence is stored separately in the report JSON. Thresholds are initial policy choices, not a calibration established on your repositories.

The comparison branch defaults to the locally recorded origin/HEAD, then local main, master, or develop. Override it with --base. Missing comparison branches are not treated as proof of a merge. Remote-tracking refs may be stale because gitomb does not fetch.

Squash merges are not considered proven ancestry merges. Age is time since the last commit, not the last checkout, edit, or review.

Data sent to Jev

When enabled, gitomb assesses items that are not protected, checked out, or already proven merged. Each item gets one request containing all three questions. Requests run with bounded concurrency, four at a time by default.

By default, requests contain names, commit messages, age, Git evidence, file names, and diff statistics. gitomb does not add the repository's absolute path or patch bodies to the request.

--include-diff additionally sends filtered excerpts from up to 20 files, capped at 12,000 characters. Common sensitive paths are excluded and recognizable credential patterns are redacted. This is best-effort filtering, not a guarantee that all secrets are detected. Names, messages, paths, and source code can contain private information; choose the appropriate mode for your repositories.

Untracked stash files are listed, but their contents are not currently included in Jev patch excerpts. show --diff is local only.

Assessments are cached by model name and input. Use --refresh to bypass the cache, including after the jev-latest alias changes, or use --model to select a specific version. Reports record the actual model returned by the API. API failures appear beside the affected item, with Git rules still available.

Configuration

gitomb scan --config gitomb.example.toml
gitomb scan ~/projects --no-ai --json > scan.json
gitomb --state-dir .gitomb scan /path/to/repo --no-ai
gitomb --state-dir .gitomb clean

Configuration files are loaded only when supplied through --config. See gitomb.example.toml.

Setting / flag Default Meaning
roots / positional paths Current directory Discovery roots
base / --base Automatic Comparison branch for this scan
protect / --protect Built-in patterns Additional protected globs; quote *; the flag can be repeated
stale_days / --stale-days 90 Age annotation threshold, not a deletion threshold
max_depth / --max-depth 6 Discovery depth; 0 checks only the roots
model / --model jev-latest Model name or version
--workers 4 Concurrent Jev requests, from 1 to 16; CLI only
--refresh Off Bypass the Jev cache; CLI only
--env-file .env in the current directory Key file; the environment variable takes precedence
--include-diff Off Send filtered patch excerpts; requires Jev and a key
--json Off Report JSON on stdout; progress on stderr
--state-dir See below Global option; place it before the subcommand

CLI arguments override configuration values; protected patterns are combined. Use separate scans and scan IDs when repositories need different comparison branches.

State lives in $XDG_STATE_HOME/gitomb, or ~/.local/state/gitomb when unset:

Directory Contents
scans/ Saved evidence and assessments
cache/ Reusable Jev assessments
batches/ Cleanup and recovery journals

Data files are created with owner-only read/write permissions. Keep both the journals and the original repositories' .git directories for recovery.

Recovery behavior and limitations

  • main, master, develop, development, release, and release/* are protected, along with a scan's local comparison branch and symbolic branch refs. Add patterns with --protect.
  • Cleanup rechecks branch tips, comparison refs, and worktrees. Branch deletion compares the expected object ID before removing the ref.
  • Before deleting each item, gitomb creates refs/gitomb/<batch>/<item> and persists a journal. These refs keep reachable Git objects alive through garbage collection, including stash index and untracked-file parents.
  • Each stash is located again by object ID before deletion. Ambiguous duplicate object IDs are rejected.
  • gitomb operations on the same repository are locked against each other. External Git commands do not share this lock. Avoid concurrent checkouts, worktree changes, or stash push/drop operations during cleanup.
  • Batches can partially succeed. Failures are reported per item; operations across repositories are not atomic.
  • Restoration will not overwrite a branch name now pointing to a different commit. Restored stash positions can change. Retrying a restored batch does not duplicate its stashes.
  • Branch tips and reachable contents are retained; old branch reflog history is not. Local branch configuration is left in place for restoration.
  • Backup refs remain after restoration. There is no automatic backup pruning, so cleanup may not reclaim disk space.
  • gitomb does not delete remote branches, push changes, or discover bare repositories.

Troubleshooting

Symptom What to do
Key not found Check the current directory or use --env-file; use --no-ai for local-only operation
Jev unavailable Check the reported error class, key, network, or quota, then rescan with --refresh
No comparison branch Set scan --base develop or another explicit branch
Branch or comparison branch changed Scan again and review the new result before cleaning
Branch checked out in a worktree Keep it; gitomb will not switch or remove worktrees for you
Squash-merged branch remains review Inspect its diff; ancestry alone does not prove the merge
Restore reports a conflicting branch name Resolve the name conflict, then retry the same batch

Development

Clone the repository and run these commands from the checkout. To run source changes without reinstalling the standalone tool, use uv run gitomb ....

uv sync --locked
uv run pytest -q
uv run ruff check src tests
uv run ruff format --check src tests
uv build

Tests use temporary Git repositories for cleanup, restoration, untracked stash contents, garbage collection, worktrees, changed state, interrupted operations, and name conflicts. SDK contract tests use the real TypeSafe SDK with a mock HTTP transport. They do not require an API key or spend API credits.

Contributing

Contributions are welcome! Bug reports, feature ideas, documentation fixes, usability feedback, and pull requests all help.

Use Issues to report a problem or discuss an idea. Include your OS, Python/Git/gitomb versions, reproduction steps, expected behavior, and sanitized output.

For a pull request, fork the repository, create a focused branch from main, make your change, and run the checks above. Small fixes can go straight to a PR; discuss larger behavior or design changes in an issue first. Explain the problem, resulting behavior, and validation in the PR description.

Useful areas to contribute include terminal interaction, squash-merge evidence, Jev assessment quality, platform support, and examples. Please keep each PR focused and include behavior tests for changes to cleanup or recovery.

License

Licensed under the MIT License.

Metadata

Release files for gitomb 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for gitomb 0.1.0
File Size Uploaded
gitomb-0.1.0.tar.gz 39.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for gitomb 0.1.0
File Interpreter ABI Platform
gitomb-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 62.1 kB

Release files / gitomb-0.1.0.tar.gz

Download URL gitomb-0.1.0.tar.gz
Size 39.8 kB
Tags Source
SHA-256 checksum
How to use checksums
0e1a76b21de6bad958b8b18d92a859c0168e4a0ca0eaa1820df90355867d4bf6
BLAKE2b-256 checksum
How to use checksums
410b50b59ed975c65790b2a3d177919f1aee5732e402e0c79c2a8337a8dd0ae5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.10 {"installer":{"name":"uv","version":"0.12.10","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / gitomb-0.1.0-py3-none-any.whl

Download URL gitomb-0.1.0-py3-none-any.whl
Size 22.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
7d3cba2ba218b9db53fee04c244c30e74bfaa335aef1cfc967ddb0ef14372f3a
BLAKE2b-256 checksum
How to use checksums
c8c9006a4f71d614fd7fa8b89103143d4ad14952f4fc0aed637fb992a07abedb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.10 {"installer":{"name":"uv","version":"0.12.10","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page