npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@frozencrow/monogit

v1.5.3

Published

A CLI tool to manage multiple git repositories in a parent directory.

Downloads

487

Readme

🚀 monogit

Manage multiple git repositories under a single parent folder with one command.

GitHub

monogit gives you a monorepo workflow without a monorepo. Run git operations across all your linked repositories simultaneously — branching, committing, pushing, opening PRs, and more — with a single command.


✨ Features

  • Interactive Setup — Recursively scan a directory, detect existing repos, and optionally initialize new ones
  • Unified Git Commands — Run checkout, add, commit, push, pull across all repos at once
  • Cross-Repo Commits — One shared editor message, and Monogit-Change-Id trailers that link a logical change across every repo
  • Status Dashboard — One compact table: branch, ahead/behind, dirty count, and in-progress operations per repo
  • Live Watch TUI — An auto-refreshing, interactive control center for all repos with one-key actions
  • Branch Tidy — Scan for and safely clean up orphaned branches (merged, or with a deleted upstream)
  • Pull Requests — Open PRs across every repo with one command (via the GitHub CLI)
  • Arbitrary Commandsexec any git command or run any shell command everywhere
  • Workspace Manifest — Record remotes so a teammate can clone the whole workspace in one step
  • Shared Packages 🧪 betalink shared libraries across repos, release them as one coordinated change, and correct the links for CI/deploys with ci hydrate|resolve (+ a GitHub Action)
  • Targeting — Scope any command to a subset of repos with --only, --except, or named --groups
  • Parallel & Resilient — Commands run concurrently (bounded); one repo failing won't block the others
  • Ordered Pushes — Declare dependsOn and push runs as a dependency graph, optionally waiting for each repo's CI (--wait-ci) before its dependents
  • Works Anywhere in the Tree — Like git, monogit finds your workspace from any subdirectory
  • MCP Server — Drive the whole workspace from an LLM/agent via a built-in Model Context Protocol server
  • Voice Commands — Hands-free, continuous voice control in the terminal via local, offline speech recognition
  • Shell Autocompletion — Bash, Zsh, Fish, and PowerShell

📦 Installation

npm i -g @frozencrow/monogit

Once installed, monogit is available as a global command.

Enable Tab Completion

Completion is opt-in. Install it for your shell:

monogit completion install zsh     # or: bash, fish

For PowerShell, add this to your $PROFILE:

monogit completion powershell | Out-String | Invoke-Expression

You can also print the script and source it yourself, e.g. source <(monogit completion zsh).


🛠 Getting Started

1. Initialize your workspace

Navigate to a parent directory that contains (or will contain) your git repositories, then run:

monogit init

This will scan for git repositories (recursively, up to --depth, default 3), let you select which to link, offer to git init any non-git folders, record each repo's remote/branch, and save the configuration to .monogit.json.

2. Work across repos

monogit checkout -b feature/my-feature   # branch everywhere
monogit status                           # dashboard of all repos
monogit add .                            # stage everything
monogit commit -m "implement feature"    # commit everywhere
monogit push origin feature/my-feature   # push everywhere
monogit pr --fill                        # open PRs everywhere

🎯 Targeting a subset of repos

Every multi-repo command accepts these filters:

| Option | Description | |--------|-------------| | --only <repos> | Comma-separated repos to include (by name or path) | | --except <repos> | Comma-separated repos to exclude | | --group <groups> | Comma-separated named groups (defined in .monogit.json) | | -c, --concurrency <n> | Max repos to process in parallel (default 8) |

monogit status --only api,web
monogit push --group backend
monogit pull --except docs

📖 Commands

monogit init [--depth <n>]

Interactively scan for and link repositories (recording remotes so the workspace can be re-cloned later), then set up workspace options. After picking repos, init asks:

  • Commit linking — add cross-repo Change-Id trailers by default (commit.link).
  • Untracked files — whether voice/watch commits stage new files (commit.untracked).
  • Protected branches — branches tidy will never delete (protected).
  • Advanced (opt-in) — define named repo groups for --group, and voice settings (Whisper model, mic device, spoken confirmation).

Only non-default answers are written, so .monogit.json stays minimal.

monogit status [--full] [--json]

Show a compact status dashboard across all repos:

  REPO    BRANCH        SYNC      CHANGES   STATE
  api     main          ✓         clean
  web     feature/wip   ↑2 ↓0     +1 ~3
  infra   main          ↑0 ↓4     ?2        ⚠ rebasing
  • SYNC↑ahead ↓behind vs upstream ( up to date, no upstream)
  • CHANGES+staged ~unstaged ?untracked (only non-zero parts shown; clean when none)
  • STATE — flags an in-progress rebase / merge / cherry-pick

Use --full for the original per-repo boxed git status, or --json for machine-readable output.

monogit watch

A live, interactive dashboard — the workspace control center. It auto-refreshes (every 5s by default, --interval), lets you navigate repos, and run common actions with a single keypress.

 monogit watch  3 repos · /path/to/workspace                      14:32:07
──────────────────────────────────────────────────────────────────────────
  REPO   BRANCH         SYNC     CHANGES   STATE
▸ api    main           ✓        clean
  web    feature/login  ↑2 ↓0    +1 ~3
  infra  main           ↓4       ?2        ⚠ rebasing
──────────────────────────────────────────────────────────────────────────
 1 clean · 2 dirty · 1 behind
 ↑/↓ select · enter detail · r refresh · f fetch · p pull · P push · c commit · m merge · t tidy · q quit

| Key | Action | |-----|--------| | / (j/k) | Move the selection | | enter | Toggle a detail pane (status -sb + recent commits) for the selected repo | | r | Refresh now | | f / p | Fetch / pull all repos (inline, with a summary) | | P | Push all (drops to a full view so you can watch the output) | | c | Commit all — prompts for a message | | m | Merge a branch into all repos — prompts for the branch | | t | Run monogit tidy (orphan-branch cleanup) | | q / Ctrl-C | Quit (always restores your terminal) |

monogit checkout <branch> [-b]

Switch (or, with -b, create) branches across all repos.

monogit add <paths...>

Stage files across all repos.

monogit commit [-m <message>] [-a] [paths...]

Commit staged changes everywhere. Repos with nothing to commit are reported as skipped, not failed.

If you omit -m, monogit opens your editor once (respecting core.editor/$EDITOR), captures a single message, and applies it to every repo. An empty message aborts the whole batch. Pass -m multiple times for multi-paragraph messages.

Cross-repo linking. A logical change usually spans several repos, but each repo gets its own commit with nothing tying them together. With linking enabled, every commit in the batch is stamped with a shared Monogit-Change-Id trailer plus the list of participating repos:

feat: add login

Monogit-Change-Id: 01JA2B3C4D5E6F7G8H9J0K1M2N
Monogit-Repos: api@feature/login, web@feature/login

Only repos that actually commit are listed. Enable it per-workspace with "commit": { "link": true } in .monogit.json, or per-commit with --link / --no-link. Look a change back up with monogit show.

| Option | Description | |--------|-------------| | -m, --message <msg> | Commit message (repeatable; opens an editor if omitted) | | -a | Stage all modified/deleted tracked files | | -A, --all-files | Stage everything, including untracked files (git add -A) | | --link / --no-link | Force linking on/off for this commit (overrides config) |

Voice "commit message …" uses -A (commits everything, including new files), since that's the natural spoken intent.

monogit show [change-id]

Show every commit across all repos that shares a Monogit-Change-Id — reconstructing the atomic change a monorepo would give you for free. With no id, shows the most recent linked change.

$ monogit show 01JA2B3C4D5E6F7G8H9J0K1M2N
🔗 Change 01JA2B3C4D5E6F7G8H9J0K1M2N  (2 repos)

  api  a1b2c3d  feat: add login endpoint (2 minutes ago)
  web  d4e5f6a  feat: add login form (2 minutes ago)

Accepts an id prefix, and --json for machine-readable output.

monogit push / pull / fetch [remote] [branch]

Sync with remotes. With no remote given, monogit push publishes the current branch to origin and sets up tracking (git push -u origin HEAD) — so it works even on a fresh branch with no upstream yet, instead of failing.

Ordered pushes (dependsOn). By default monogit pushes all repos in parallel — but if a repo's build depends on another (e.g. api builds against the freshly-published shared), a parallel push is a race. Declare the order in .monogit.json:

"repos": [
  { "path": "shared" },
  { "path": "api", "dependsOn": ["shared"] },
  { "path": "web", "dependsOn": ["api"] }
]

monogit push then runs as a dependency graph: independent repos still push in parallel, but a repo waits for its dependencies first. If a dependency's push fails, its dependents are skipped (never pushed into a broken state), and cycles are rejected.

By default a dependent waits for its dependency's push to complete. Add --wait-ci to instead wait for the dependency's CI to pass before pushing dependents — which actually prevents the build race (pushing only triggers CI; --wait-ci waits for it to finish). Needs the gh CLI; if a dependency's CI fails, its dependents are skipped.

monogit push               # dependency order; each dependent waits for its deps' push
monogit push --wait-ci     # each dependent waits for its deps' CI to go green first

monogit branch [branch] [-d|-D]

List branches (no args), or create / delete a branch across all repos.

monogit merge <branch>

Merge a branch into the current branch across all repos.

monogit tidy [options]

Scan every repo for orphaned branches and clean them up. By default targets two high-confidence categories:

  • gone — the upstream was deleted on the remote (PR merged, branch reaped). Force-deleted, since squash-merges leave these "unmerged" locally.
  • merged — already merged into the default branch. Safely deleted with git branch -d.

The current, default, and any protected branches are never touched. Runs git fetch --prune first (so gone is accurate) and confirms before deleting.

monogit tidy                  # scan + interactive cleanup
monogit tidy --dry-run        # report only
monogit tidy --stale 60       # also branches idle 60+ days
monogit tidy --yes            # non-interactive (CI)

| Option | Description | |--------|-------------| | --gone / --merged / --stale [days] | Choose categories (default: gone + merged) | | --no-fetch | Skip git fetch --prune | | --dry-run | Report without deleting | | -y, --yes | Delete without the prompt | | --protect <branches> | Names/globs to never delete (e.g. develop,release/*) | | --json | Machine-readable output |

monogit pr [options]

Open pull requests across all repos using the GitHub CLI (gh). Pushes the current branch, then opens a PR for each repo that has commits ahead of its base. Repos on the base branch or with no new commits are skipped.

monogit pr --fill                          # title/body from commits
monogit pr --title "Bump deps" --body "…"  # explicit
monogit pr --draft --base develop
monogit pr --web                           # finish each in the browser

| Option | Description | |--------|-------------| | --title / --body | PR title / body | | --base <branch> | Base branch (defaults to each repo's default) | | --fill | Fill from commit messages | | --draft | Create draft PRs | | --web | Open each PR in the browser | | --no-push | Don't push before creating |

monogit exec -- <git args>

Run an arbitrary git command across all repos — anything monogit doesn't wrap directly.

monogit exec -- stash list
monogit exec -- tag v1.2.0
monogit exec --only api -- reset --hard origin/main

monogit run "<command>"

Run an arbitrary shell command in each repo.

monogit run "npm test"
monogit run "rm -rf node_modules"

monogit clone

Clone any linked repo that has a recorded remote but is missing locally — reconstitutes a whole workspace from a committed .monogit.json.

monogit repos <list|add|remove>

Manage linked repositories without re-running init.

monogit repos list           # show repos, remotes, presence, and groups
monogit repos add ./api      # link a repo (records its remote)
monogit repos remove api     # unlink (files untouched)

monogit link / monogit unlink · monogit release 🧪 beta

Beta. link, unlink, and release are new. Graph discovery and the release plan/commit are covered by tests and stable; the per-package-manager link execution (npm/pnpm/yarn) and --publish are still being hardened across ecosystems. Try them on a non-critical workspace first, and please report anything odd. Each command prints a one-line beta notice — silence it with MONOGIT_NO_BETA_WARNINGS=1.

monogit link / monogit unlink

Wire shared packages to their local checkouts across repos — the monorepo "edit the lib, see it downstream instantly" workflow, without a monorepo. It links using each repo's own package manager (npm / pnpm / yarn — detected per repo from its lockfile).

Guided — introduce a package into repos (the usual starting point):

monogit link ./shared          # or a package name: monogit link @acme/shared

You point at a shared package; monogit asks which repos to link it into. For each repo you pick, it adds the dependency to that repo's package.json (if it isn't there yet) and links node_modules to the local checkout. Skip the prompt with --into:

monogit link @acme/shared --into api,web       # non-interactive
monogit link ./shared --into api --dev         # add as a devDependency

Auto — link everything already declared:

monogit link            # link every consumer that already lists a workspace package as a dep
monogit link --status   # just show the graph (who provides / consumes what)
monogit unlink          # undo and restore registry versions

Published vs unpublished packages. monogit writes a committable dependency spec, and picks the right kind automatically:

  • Published (npm or a private registry): a version range like ^1.2.3. The link is a local-only dev override in node_modules; unlink removes it and keeps the declared version. CI and teammates resolve the version from the registry.
  • Unpublished / "private": true: a path dependencyfile:../shared (npm/yarn) or link:../shared (pnpm). This is portable within a monogit workspace because every repo is a sibling, so npm install works for any teammate who has the workspace (no registry needed). Force this with --file even for non-private packages. For people who clone a single repo without the workspace, use a git dependency instead (git+ssh://…/shared.git#v1.2.3).

monogit release works either way: it bumps versions, updates consumer specs, and commits as one linked change. --publish is only for registry packages — npm blocks publishing anything marked "private": true, so for internal packages you just skip it (the version bump + git tag is your release).

monogit orchestrates the links and versions; it does not do resolution, lockfiles, or a registry — that stays with your package manager.

monogit release [--bump <level>]

Cut a coordinated release of your shared packages: bump each shared library's version, update every in-workspace consumer's dependency range, and commit it all as one linked change (a cross-repo changeset, tied together by a Monogit-Change-Id). Only packages that something in the workspace depends on are bumped — leaf apps just get their specs updated.

Deploy triggers for path-linked consumers. A consumer linked via a file:/link: path spec has no version in its package.json to bump — so a release would leave that repo with no diff, and its CI/deploy wouldn't fire even though the shared code changed. To fix that, release writes the new version into the consumer's .monogit-deps.json and commits it. That's a real change in the consumer repo, so its deploy triggers. (Version-range consumers already get a package.json diff, so they don't need this.)

monogit release --bump minor --dry-run   # preview the plan, change nothing
monogit release --bump patch             # apply + commit as one linked change
monogit release --version 2.0.0 --tag    # explicit version + git tag per package
monogit release --bump minor --publish   # also publish to each package's registry

| Option | Description | |--------|-------------| | --bump <level> | major / minor / patch (default patch) | | --version <v> | Set an explicit version instead of bumping | | --tag | Create a name@version git tag per package | | --publish | Publish each package to its registry (extra confirmation) | | --dry-run | Show the plan without changing anything | | -y, --yes | Skip confirmation prompts |

monogit ci <hydrate | resolve> — make single-repo CI & deploys work

Local links (file:../shared, link:../shared) are a workspace convenience — but a CI job or a deploy build usually checks out one repo, with no sibling to resolve them against, so npm ci breaks. monogit ci corrects that. When you link a path dependency, monogit records its git source in a committed .monogit-deps.json, which a lone checkout uses to reconstitute.

  • monogit ci hydrate — clone the sibling packages this repo links to (at their recorded refs), then run your install normally. Faithful to the workspace; good for CI test runs.
  • monogit ci resolve — rewrite file:/link: path deps into git dependencies (git+ssh://…#ref) so the repo installs with no siblings and no workspace. Ideal for deploy builds (Docker, serverless). --dry-run previews.
# GitHub Actions — deploy build
- uses: Frozen-Crow/monogit/ci@v1
  with: { mode: resolve }
- run: npm ci --omit=dev

# …or a CI test run that keeps the workspace shape
- uses: Frozen-Crow/monogit/ci@v1
  with: { mode: hydrate }
- run: npm ci && npm test
# Dockerfile — self-contained deploy image
COPY package.json .monogit-deps.json ./
RUN npx --yes @frozencrow/monogit ci resolve && npm ci --omit=dev

Works on any CI via npx @frozencrow/monogit ci <mode> — the GitHub Action is just a thin wrapper. Override the ref with --ref <tag> (e.g. pin to the release tag your monogit release created).

monogit log / monogit diff

View recent history / unstaged changes for every repo in bordered boxes.

monogit completion [shell] [--install]

Generate or install completion for bash, zsh, fish, or powershell.

monogit mcp

Start the MCP server (JSON-RPC over stdio) so an LLM/agent can drive the workspace. See below.

monogit voice [phrase...]

Speak monogit commands hands-free. monogit voice listens continuously, uses voice-activity detection to find the pause at the end of each spoken command (no keypress), transcribes it locally (audio never leaves your machine), and runs it — then keeps listening for the next one. Say "stop" (or press Ctrl-C) to end the session.

Write commands (commit, push, checkout…) ask for a spoken "yes" before running, so it stays both safe and hands-free. Reads run immediately.

monogit voice                       # 🎙️ continuous, hands-free listening
monogit voice --once                # capture a single command, then exit
monogit voice "show me the status"  # pass text directly (skips the mic)
echo "push" | monogit voice --yes   # pipe text; --yes allows the write
monogit voice "commit message fix login" --dry-run   # just show the mapping

A session looks like:

🎙️  Listening continuously. Speak a command, pause, and it runs. Say "stop" or Ctrl-C to end.

🗣  Heard: "what's the status"
→ monogit status
  ... dashboard ...
🗣  Heard: "commit message fix the login redirect"
→ monogit commit -am "fix the login redirect"
   say "yes" to run, or "no" to skip…
   🗣  "yes"
  ... commits ...
🗣  Heard: "stop"
👋 Stopped listening.

Recognized phrases:

| You say | It runs | |---------|---------| | "status" / "what's the status" | status | | "commit message <text>" | commit -am "<text>" | | "new branch <name>" ("slash" → /) | checkout -b <name> | | "checkout <name>" / "switch to <name>" | checkout <name> | | "merge <name>" | merge <name> into the current branch | | "push" / "pull" / "fetch" | sync | | "tidy" / "clean up branches" | tidy (dry-run — voice never deletes) | | "log" / "diff" / "show change" | history / changes / linked change |

First run sets itself up. Speech recognition runs locally via whisper.cpp, and monogit provisions it for you:

  • If the whisper.cpp binary is missing, monogit offers to brew install whisper-cpp (macOS).
  • The model is downloaded on first use (after a Download? [Y/n] prompt) and cached in ~/.cache/monogit/models/, then reused across every workspace. Pass --yes to skip the prompt.
  • Utterance detection uses sox's silence effect if present, otherwise ffmpeg's silencedetect — so it auto-stops at the pause after each command. No keypress.

Everything is overridable in .monogit.json if you'd rather bring your own:

"voice": {
  "model": "base.en",
  "device": ":0",
  "transcribe": "whisper-cli -m ~/models/ggml-base.en.bin -nt -f {audio}",
  "confirm": true
}
  • modeltiny.en, base.en, or small.en (auto-downloaded).
  • device — ffmpeg input device index for the mic (default :0 on macOS).
  • transcribe — your own command; {audio} is replaced with a temp WAV path (transcript via stdout or {audio}.txt).
  • record — a custom recorder. It must stop itself at the end of an utterance (e.g. include sox's silence effect), since the loop runs it once per command.
  • confirm — set false to run write commands without the spoken yes/no.
  • commitUntracked — whether "commit" stages everything incl. new files (default true). The workspace-wide commit.untracked covers both voice and watch.

🤖 Using monogit from an AI agent (MCP)

monogit ships a built-in Model Context Protocol server, so assistants like Claude can manage your repos directly. It exposes the workspace as structured tools.

Add it to your MCP client config (the server finds the workspace by walking up from cwd, just like the CLI — point cwd at your workspace or any subdirectory):

{
  "mcpServers": {
    "monogit": {
      "command": "monogit",
      "args": ["mcp"],
      "cwd": "/path/to/your/workspace"
    }
  }
}

No global install? Use "command": "npx", "args": ["-y", "@frozencrow/monogit", "mcp"]. A standalone monogit-mcp binary is also provided.

Tools exposed:

| Tool | What it does | |------|--------------| | monogit_status | Per-repo branch, ahead/behind, dirty counts, in-progress ops | | monogit_list_repos | Linked repos with remote/branch/presence | | monogit_exec | Run arbitrary git args across all repos | | monogit_commit | Commit across repos (with optional Change-Id linking) | | monogit_checkout / monogit_push / monogit_pull | Branch & sync operations | | monogit_show | Look up a cross-repo change by id | | monogit_tidy | Scan for orphaned branches (read-only unless execute: true) | | monogit_pr | Open pull requests via the GitHub CLI |

Every tool accepts only / except / group to scope which repos it touches. Destructive operations are gated: monogit_tidy is a dry run unless you pass execute: true.


⚙️ Configuration

monogit stores its configuration in a .monogit.json file, discovered by walking up from your current directory (like git's .git):

{
  "repos": [
    "shared-lib",
    { "path": "api", "remote": "[email protected]:acme/api.git", "branch": "main" },
    { "path": "web", "remote": "[email protected]:acme/web.git", "branch": "main" }
  ],
  "groups": {
    "backend": ["api", "shared-lib"],
    "frontend": ["web"]
  },
  "protected": ["develop", "release/*"],
  "commit": { "link": true },
  "voice": { "transcribe": "whisper-cli -m ~/models/ggml-base.en.bin -nt -f {audio}" }
}
  • repos — a relative path string, or an object with path plus an optional remote/branch (used by monogit clone) and dependsOn (an array of repo names, for ordered pushes — see below).
  • groups — named sets of repos for --group.
  • protected — branches monogit tidy will never delete (the current and default branches are always protected too).
  • commit.link — when true, monogit commit adds cross-repo Monogit-Change-Id trailers by default (override per-commit with --no-link).
  • commit.untracked — whether interactive commits (voice & watch) stage untracked files too. Defaults to true ("commit everything"); set false for tracked-only. (voice.commitUntracked is still honored for voice.)
  • voicerecord / transcribe commands (with {audio}) and confirm for monogit voice.

Tip: Commit .monogit.json to share the workspace with your team — they can monogit clone to get every repo.

There's also a second, per-repo file: .monogit-deps.json 🧪 beta — written into a consumer repo by monogit link when it adds a file:/link: shared dependency, recording that package's git source (remote + ref). Commit itmonogit ci hydrate/resolve read it to reconstitute the workspace in single-repo CI and deploy builds.


🏗 Project Structure

monogit/
├── index.js                    # CLI entry point & command wiring
├── src/
│   ├── commands/
│   │   ├── init.js             # Interactive (recursive) repo linking
│   │   ├── git-proxy.js        # Parallel proxy for standard git commands
│   │   ├── commit.js           # Commit with editor fallback & cross-repo linking
│   │   ├── show.js             # Look up a linked change across repos
│   │   ├── visual.js           # Boxed output for log / diff / branch
│   │   ├── dashboard.js        # Status dashboard table
│   │   ├── watch.js            # Live interactive TUI (raw ANSI, no deps)
│   │   ├── tidy.js             # Orphaned-branch scan & cleanup
│   │   ├── exec.js             # Arbitrary git / shell passthrough
│   │   ├── clone.js            # Clone missing repos from the manifest
│   │   ├── repos.js            # repos list / add / remove
│   │   ├── pr.js               # Open pull requests via gh
│   │   ├── voice.js            # Speak a command (record → transcribe → run)
│   │   ├── completion.js       # Completion scripts (bash/zsh/fish/pwsh)
│   │   └── complete.js         # Dynamic branch completion logic
│   ├── core/                   # Data-returning logic shared by CLI + MCP
│   │   ├── commit.js           # Linked commit across repos
│   │   ├── tidy.js             # Orphan scan & delete
│   │   ├── changes.js          # Change-Id lookup
│   │   ├── voice.js            # Speech-phrase → command grammar
│   │   ├── voice-setup.js      # Whisper model download / binary detection
│   │   ├── watch-render.js     # Pure TUI frame renderer
│   │   └── pr.js               # Pull-request creation
│   ├── mcp/
│   │   └── server.js           # Dependency-free MCP server (stdio)
│   └── utils/
│       ├── config.js           # Config discovery, resolution & filtering
│       ├── git.js              # Git command execution & introspection
│       ├── editor.js           # Capture a commit message via $EDITOR
│       ├── link.js             # Change-Id generation & trailers
│       ├── concurrency.js      # Bounded parallel map
│       ├── match.js            # Glob matcher for protected branches
│       └── ui.js               # Shared CLI helpers
├── test/                       # node:test suites
└── scripts/postinstall.js

🧪 Development

npm test        # node --test

CI runs the suite on Node 18, 20, and 22.


🧰 Built With


📄 License

ISC