Good game. Every time.
gg is a terminal UI that runs multiple coding agents against the same prompt in isolated git worktrees, then lets you compare outputs, inspect diffs, and merge a winner.
Implementation now covers the full phased build from SPEC.md:
- Multi-view Ink TUI with setup/live/review/thread/leaderboard/history/profile
- Agent detection, spawning, live streaming output panes, timeout and stop handling
- Match-scoped git branches/worktrees and reusable preview worktree switching
- Post-match stats, per-agent checks, thread JSON, raw logs, and
match.jsonexport - Winner merge flow and cleanup of match branches/worktrees
- Secret and guard write-violation monitoring with risk flags
- Crash-recovery scanning for dangling branches/worktrees + unfinished DB matches
- SQLite persistence for matches, agents, and aggregated profiles
- CLI subcommands:
run,stats,leaderboard,history,profile,h2h,thread,clean,config
npm install
npm run devBuild:
npm run buildRun tests:
npm testgg
gg --repo /path/to/repo
gg run "add dark mode toggle" --agents claude codex --base new --theme dark-mode --strategy competition
gg stats
gg leaderboard
gg history
gg profile claude
gg h2h claude codex
gg thread <matchId> <agentId>
gg clean
gg config allowSecrets true
gg config leaderboard trueHeadless run flags:
--base current|new--theme <short-branch-theme>--strategy plain|competition--time-limit <seconds>--privacy public|private|anonymous
After a match completes (Post-Match view):
t: open an interactive shell in the focused agent worktreeu: run review test command in focused worktreec: run review build command in focused worktrees: run review serve command in focused worktree (Ctrl+C to stop)g: run review run command in focused worktree
Commands come from gg.config.json > review (with u falling back to the first checks entry if needed).
Setup now exposes the branch decision instead of assuming the user prepared it manually:
Current: race directly from the current branchCreate new: create a shortfeat/<theme>branch from the current branch, then fork the agent worktrees from that new base
Notes:
- The branch theme is a short fixed-width field in the setup screen.
ggkeeps the main checkout on the original branch while the match is running.- When you pick a winner,
ggmerges that agent into the chosen base branch. - Match history and recovery persist both the original source branch and the chosen base-branch mode.
Setup includes a prompt-strategy control:
plain: send the user's prompt as-iscompetition: prepend a judging-focused head-to-head instruction before the user prompt
The original prompt remains the visible match prompt in the UI and stored match metadata. The expanded prompt is what gets sent to executors and is recorded separately in match threads.
Automated smoke coverage is now available for the real headless CLI flow:
npm run test:e2eThat scenario spins up:
- a disposable git repo
- fake
claudeandcodexexecutables onPATH - a real
gg runheadless match - real worktrees, checks, logs, threads, and SQLite persistence
If you want to watch the flow outside Vitest:
npm run demo:e2eOptional:
GG_KEEP_E2E_TMP=1 npm run demo:e2eThat keeps the temporary repo/home directory on disk so you can inspect the generated artifacts afterward.
Interactive TUI smoke coverage is available separately:
npm run test:e2e:tuiThat scenario launches the built TUI in a PTY, drives a scripted setup flow, waits for the live match and post-match screens, opens the thread view, and verifies the transcript.
If you want to watch that scripted TUI flow outside Vitest:
npm run demo:e2e:tuiOptional:
GG_KEEP_E2E_TMP=1 npm run demo:e2e:tuiNotes:
npm testexcludes the TUI smoke test because PTY transcript checks are slower and more environment-sensitive than the default suite.- The TUI smoke test is a scripted automation mode intended for end-to-end verification. It is not asserting arbitrary user keystrokes one-by-one.
For a real-agent disposable demo that uses your installed claude and codex CLIs against a tiny JS repo:
npm run demo:e2e:real -- --live --scenario multiply --keepNotes:
--liveis required because this will use your real agent accounts and may incur cost.- The demo creates a throwaway repo with built-in Node tests and streams both agents' output live.
--keepleaves the temp repo and artifact directory on disk so you can inspect the resulting worktrees, logs, and threads.- You can swap scenarios with
multiply,title-case, orclamp, or pass--prompt "..."to use your own short test prompt.
- User config:
~/.config/gg/gg.tomlor local./gg.toml - Repo config:
./gg.config.json gg.tomltip: setgg.default_time_limit = 0for unlimited matches by default.gg.tomltip: setgg.default_prompt_strategy = "competition"to make competition framing the default.
Example files are included in this repository.
MIT