AI-powered multi-agent CLI (gitgang / gg). TypeScript ESM, bundled to a single dist/cli.js via esbuild. Published to npm as gitgang. See README.md for user-facing docs.
npm install # Install deps (postinstall runs ensure-clis.mjs)
npm run build # esbuild → dist/cli.js (single bundled file, deps external, node18 target)
npm test # vitest run — ~500+ tests across src/*.test.ts
node dist/cli.js --version # Verify a build locally before releasing
./release.sh # Bump patch, update VERSION in src/cli.ts, build, test, commit, npm publish, git push- Entry point:
src/cli.ts→ bundled intodist/cli.js(the only file shipped to npm besidesscripts/ensure-clis.mjs). - Core modules in
src/:pair.ts— AI pair programming mode (one agent codes, another reviews, they negotiate)orchestrator.ts— multi-agent-imode (Gemini + Claude + Codex in parallel, synthesized result)turn.ts— per-turn agent dispatch and prompt building (includesbuildTurnPrompt())session.ts,repl.ts— interactive session state and REPL looprenderer.ts,sidebar.ts,persistent-sidebar.ts,theme.ts,styles.ts— Dracula-themed TUI layerconfig.ts— per-repo config system (gg initcommand)doctor.ts— environment health check (gg doctor,--jsonflag)completions.ts— shell completion generator (gg completions)non-git.ts— read-only Q&A mode for running outside git repos (v1.8.1+)markdown.ts,confirm.ts,slash.ts— TUI/input helpers
- Tests:
src/*.test.ts(vitest, vanilla — no test framework config file beyonddevDependencies). - Backend abstraction: the "agent" interface is designed to be extended; current backends are
claude,codex,geminiCLIs discovered onPATH.
- npm 2FA is required for publish — the release script will prompt for the OTP; it cannot run fully unattended.
VERSIONconstant insrc/cli.tsmust stay in sync withpackage.json.release.shusessedto update it — don't rename theconst VERSION = "x.y.z";pattern or the regex breaks silently.packages: "external"inscripts/build.mjsmeans runtime deps (boxen,chalk,ora, etc.) are not bundled — they must stay independencies(notdevDependencies) or the published CLI breaks for users.filesinpackage.jsonis explicit (dist/cli.js+scripts/ensure-clis.mjs) — anything else added to the project won't ship unless listed there.
ggalias can be shadowed by oh-my-zsh's git plugin (which definesggasgit gui citool). After installing, users may needunalias ggor the explicit override placed later in.zshrc. Thegg doctorcommand should help diagnose this.- Non-git mode requires
findRepoRoot()— notrepoRoot().repoRoot()throws when outside a git repo;findRepoRoot()returns null gracefully. When adding features that use repo context, always check for the no-git case (seerunInteractive()insrc/cli.tsfor the pattern). - Working tree must be clean for interactive sessions in git mode — otherwise startup aborts. Untracked
.claude/directories are a common culprit; keep them in.gitignore. - Dependent CLIs must be on
PATH. Pair mode needs ≥2 of {claude, codex}; interactive mode needs all of {claude, codex, gemini}. Missing CLIs fail fast but with a helpful message fromdoctor.
release.sh does the full flow in one shot:
- Reads current version from
package.json, bumps the patch number only (manual edit for minor/major) - Writes new version to
package.json,package-lock.json, andsrc/cli.ts - Runs
npm run build+npm test— refuses to publish if either fails - Verifies
dist/cli.js --versionmatches the new version - Commits with message
v${NEW_VERSION}(plain, no conventional-commit scope) npm publish(prompts for 2FA OTP) →git push origin HEAD
For minor/major bumps: edit package.json version first, then let the script handle the rest — or run the steps manually. Always update CHANGELOG.md before a release; it's not automated.