Skip to content

CLI Reference

Commands

git-scenarios list

Show all scenarios grouped by kind. Filterable by kind, tag, or both.

Terminal window
npx git-scenarios list # all scenarios
npx git-scenarios list --kind operation # only operation scenarios
npx git-scenarios list --tag conflict # only tagged 'conflict'
npx git-scenarios list --kind stash --tag untracked # AND filter
npx git-scenarios list --json # machine-readable

git-scenarios describe <name>

Print the full description and contract assertions for a scenario.

Terminal window
npx git-scenarios describe mid-merge-conflict
npx git-scenarios describe mid-merge-conflict --json # machine-readable

git-scenarios inspect <name>

See a scenario’s shape without keeping it on disk. inspect materializes the scenario in a throwaway temp repo, prints its commit graph, branches, and working-tree status, then cleans up. It’s the read-only counterpart to create — perfect for picking the right scenario before you wire it into a test.

Terminal window
npx git-scenarios inspect feature-pr-ready
npx git-scenarios inspect mid-merge-conflict --json # machine-readable

Example output:

feature-pr-ready · branch
---------------------------
feature branch with 4 commits, clean worktree, ready to open a PR
Commit graph:
* 0d92e8f (HEAD -> feat/widget-v2) docs: document widget-v2 API and migration path
* 7e06c32 test: cover widget-v2 happy path and edge cases
* 4a4ba62 feat: expose widget-v2 from public index
* 7ef2a30 feat: add widget-v2 entry point and types
* 8f8c1d3 (main) test: add baseline widget tests
* 3377978 feat: scaffold widget module
* 51d305e chore: initial commit
Branches:
* feat/widget-v2
main
Status (git status -sb):
## feat/widget-v2
Contracts:
- main has 3 commits
- feat/widget-v2 is checked out
- feat/widget-v2 is 4 commits ahead of main
- worktree is clean

git-scenarios create <name> [options]

Materialize a scenario on disk.

Terminal window
npx git-scenarios create feature-pr-ready
npx git-scenarios create mid-merge-conflict --run "lazygit"
npx git-scenarios create rich-history-graph --path ~/sandbox/test-repo

git-scenarios capture [path] [options]

Snapshot a real repository’s shape into a reusable scenario module. Hit a bug against a repo in some peculiar state? Instead of hand-writing a scenario to reproduce it, point capture at the repo (default: the current directory) and get a ready-to-edit defineScenario(...) module on stdout.

Terminal window
# Capture the current repo into a scenario file
npx git-scenarios capture . --name my-bug-repro > scenarios/my-bug.ts
# Capture another repo, give it a summary, write to a file
npx git-scenarios capture ~/work/widgets --name widgets-mid-feature \
--summary "widgets repo mid-feature, 3 staged files" \
--out scenarios/widgets.ts
# Structured shape instead of a module (file contents omitted)
npx git-scenarios capture . --json

capture is read-only against the target repo — it runs git plumbing and reads working-tree files, and never writes to the repo.

What it reproduces faithfully:

  • the current branch (and whether HEAD is detached)
  • the commit-graph shape — base-branch commits plus the commits your branch is ahead by (e.g. “4 commits ahead of main”), with each commit’s message and author date preserved
  • the working tree’s dirty state — which paths are staged, modified, or untracked, with their current content (size-capped at 4 KB, binary files skipped)

What it deliberately does not reproduce:

  • exact commit hashes — the library’s whole point is fresh, deterministic hashes
  • historical file contents — placeholders are emitted so each commit is non-empty and the count matches
  • merge topology and the contents of non-current branches — surfaced as a comment for you to fill in

The output is a starting point you edit, not a byte-perfect clone. Register the result with registerScenario(...) and it works everywhere the built-ins do.

The same logic is available programmatically from the @gfargo/git-scenarios/capture subpath for tool authors who want to build on it: gatherRepoState(git, cwd), renderScenarioModule(state, opts), captureToJson(state, name), deriveContracts(state), and normalizeName(raw).

git-scenarios clean [options]

Find and remove stale scenario temp directories from your system’s temp folder.

Terminal window
# Remove all stale scenario dirs
npx git-scenarios clean
# Preview what would be removed (no deletion)
npx git-scenarios clean --dry-run
# Only remove dirs older than 24 hours
npx git-scenarios clean --older-than 24

git-scenarios completions <shell>

Print a shell completion script for bash, zsh, or fish. Scenario names are completed dynamically at TAB time by calling git-scenarios list --names, so newly added scenarios complete without regenerating the script.

bash

Terminal window
# Temporary (current session):
eval "$(git-scenarios completions bash)"
# Permanent — add to ~/.bashrc or ~/.bash_profile:
echo 'eval "$(git-scenarios completions bash)"' >> ~/.bashrc
# Or save to a completions directory:
git-scenarios completions bash > ~/.bash_completion.d/git-scenarios

zsh

Terminal window
# Temporary (current session):
eval "$(git-scenarios completions zsh)"
# Permanent — add to ~/.zshrc:
echo 'eval "$(git-scenarios completions zsh)"' >> ~/.zshrc
# Or save to a directory on your $fpath:
git-scenarios completions zsh > "${fpath[1]}/_git-scenarios"

fish

# Temporary (current session):
git-scenarios completions fish | source
# Permanent — save to fish's completions directory:
git-scenarios completions fish > ~/.config/fish/completions/git-scenarios.fish

git-scenarios doctor [--json]

Check your environment for compatibility issues. Verifies git version (≥ 2.25.0), temp-dir writability, leftover scenario dirs, and optional dependencies (git-lfs). Exits non-zero on hard failures.

Terminal window
npx git-scenarios doctor
npx git-scenarios doctor --json # machine-readable

Example output:

git-scenarios doctor
────────────────────
✓ git version 2.43.0 (≥ 2.25.0)
✓ temp dir writable (/var/folders/...)
✓ no leftover scenario dirs in /var/folders/...
ⓘ git-lfs not found (optional — only needed for git-lfs-pointer scenario)
All checks passed.

git-scenarios diff <name-a> <name-b> [--json]

Compare two scenarios side by side. Materializes both in throwaway temp dirs, captures their shape (HEAD, branches, status, in-progress operation, contracts), and prints a structured comparison. SHA values and raw commit graphs are excluded from the diff.

Terminal window
npx git-scenarios diff feature-pr-ready multi-commit-branch
npx git-scenarios diff mid-merge-conflict mid-rebase-conflict --json

Flags

List flags

FlagBehavior
--kind <kind>Filter by scenario kind: branch, worktree, operation, history, stash, submodule.
--tag <tag>Filter by tag inclusion (e.g. conflict, dirty, upstream). Combine with --kind (AND semantics).
--jsonEmit machine-readable JSON. Each entry includes name, summary, kind, tags, contracts.

Describe flags

FlagBehavior
--jsonEmit machine-readable JSON. Includes description (the full multi-line text) plus everything in the list output.

Inspect flags

FlagBehavior
--jsonEmit machine-readable JSON: name, kind, graph (array of lines), branches (array), status (array of git status -sb lines), contracts.

Create flags

FlagBehavior
--path <dir>Materialize at <dir> instead of a temp directory.
--run <cmd>Launch <cmd> against the scenario dir after creation. Shell-style argument splitting.
--remote <url>Add origin pointing at <url> before launching.
--ephemeralAuto-clean the temp dir on exit. Without this, the dir persists.

Capture flags

FlagBehavior
--name <name>Scenario name (kebab-cased). Defaults to the captured repo’s directory name.
--summary <s>One-line summary for the generated scenario.
--kind <kind>Override the inferred kind (branch, worktree, etc.). Inference: dirty worktree → worktree, otherwise branch.
--out <file>Write the generated module to <file> instead of stdout.
--jsonEmit the structured capture shape instead of a TypeScript module. File contents are omitted.

Clean flags

FlagBehavior
--dry-runList stale dirs without deleting them.
--older-than <hours>Only remove dirs older than N hours (default: 0 = all).

List --names flag

FlagBehavior
--namesPrint scenario names only, one per line (no headers, no JSON). Used internally by shell completion scripts to resolve scenario names dynamically. Respects --kind and --tag filters.

Doctor flags

FlagBehavior
--jsonEmit machine-readable JSON with check results, pass/fail status, and version info.

Diff flags

FlagBehavior
--jsonEmit structured JSON: { a, b, same, differences }. SHA values are excluded.

Examples

Terminal window
# Launch lazygit against a merge conflict
npx git-scenarios create mid-merge-conflict --run "lazygit"
# Open VS Code against a dirty worktree
npx git-scenarios create dirty-many-files --run "code -n"
# Test your own tool
npx git-scenarios create feature-pr-ready --run "my-tool --debug"
# Add a remote for gh-aware tools
npx git-scenarios create feature-pr-ready \
--run "gh pr create" \
--remote git@github.com:org/repo.git
# Clean up old scenarios (older than 2 hours)
npx git-scenarios clean --older-than 2
# Pipe scenario metadata into another tool
npx git-scenarios list --json | jq '.[] | select(.kind == "operation")'
npx git-scenarios describe partial-stage --json | jq -r '.contracts[]'

JSON output schemas

list --json

[
{
"name": "feature-pr-ready",
"summary": "feature branch with 4 commits, clean worktree, ready to open a PR",
"kind": "branch",
"tags": ["feature-branch", "pr-ready", "clean", "ahead"],
"contracts": [
"main has 3 commits",
"feat/widget-v2 is checked out",
"feat/widget-v2 is 4 commits ahead of main",
"worktree is clean"
]
}
]

describe --json

{
"name": "feature-pr-ready",
"summary": "...",
"description": "A feature branch ready to be PR'd. ...",
"kind": "branch",
"tags": ["feature-branch", "pr-ready", "clean", "ahead"],
"contracts": ["..."]
}

inspect --json

{
"name": "feature-pr-ready",
"kind": "branch",
"graph": [
"* c477604 (HEAD -> feat/widget-v2) docs: document widget-v2 API and migration path",
"* 773c76b (main) test: add baseline widget tests"
],
"branches": ["* feat/widget-v2", "main"],
"status": ["## feat/widget-v2"],
"contracts": ["main has 3 commits", "..."]
}

For empty repos (no commits yet) graph is an empty array — the call still succeeds.

capture --json

{
"name": "my-bug-repro",
"currentBranch": "feat/widget-v2",
"detached": false,
"baseBranch": "main",
"baseCommits": [{ "message": "chore: initial commit", "date": "2026-05-01T12:00:00Z" }],
"branchCommits": [{ "message": "feat: add widget-v2", "date": "2026-05-02T12:00:00Z" }],
"localBranches": ["main", "feat/widget-v2"],
"remotes": [{ "name": "origin", "url": "git@github.com:org/repo.git" }],
"changes": [{ "path": "src/x.ts", "staged": true, "untracked": false }],
"clean": false,
"contracts": ["feat/widget-v2 is checked out", "main has 1 commits"]
}

File contents are intentionally omitted from JSON output (they’re only in the rendered module).

Errors come back on stderr as { "error": "..." }.

Cleanup strategies

There are three ways to handle cleanup depending on your use case:

1. Programmatic tests — automatic via cleanup()

In tests, always call repo.cleanup() in your teardown. The Jest/Vitest adapter handles this automatically:

// Manual approach
afterAll(async () => {
await repo.cleanup()
})
// Adapter — cleanup is automatic
describeWithScenario('feature-pr-ready', (getRepo) => {
// No cleanup needed — handled for you
})

2. Auto-cleanup on process exit

Pass { autoCleanup: true } to spinUpScenario (or createTempGitRepo()) for a safety net that cleans up when the process exits, even if you forget to call cleanup():

const repo = await spinUpScenario('feature-pr-ready', { autoCleanup: true })
// If the process exits without calling repo.cleanup(),
// the temp dir is removed automatically via a process exit hook.

This is a safety net, not a replacement for explicit cleanup. Always call cleanup() when you can — the exit hook uses synchronous rmSync which may not complete for very large repos.

3. CLI — --ephemeral or clean

For manual testing via the CLI:

  • --ephemeral — auto-removes the scenario dir when the launched tool exits
  • git-scenarios clean — batch-removes accumulated dirs from /tmp
Terminal window
# One-shot: auto-clean when lazygit quits
npx git-scenarios create mid-merge-conflict --run "lazygit" --ephemeral
# Periodic cleanup of accumulated dirs
npx git-scenarios clean --older-than 1

When dirs accumulate

Without --ephemeral, create persists the scenario dir so you can re-inspect after the tool quits. Over time these accumulate in your temp folder. The clean command handles this:

Terminal window
# See what's there
npx git-scenarios clean --dry-run
# Remove everything
npx git-scenarios clean
# Remove only old ones
npx git-scenarios clean --older-than 24

The CLI prints the path and a cleanup hint after every create:

✓ Scenario "feature-pr-ready" ready at:
/var/folders/.../git-scenarios-xR2qwz
When you're done, clean up with:
rm -rf /var/folders/.../git-scenarios-xR2qwz