Terminal multiplexer with dependency orchestration. Written in TypeScript, runs on Bun.
bun test # Run tests
bun run dev # Run in dev mode
bun run typecheck # TypeScript check (bunx tsc --noEmit)
bun run lint # Lint with Biome
bun run fix # Auto-fix lint/format issues- Formatter: Biome (tabs, single quotes, no semicolons, no trailing commas)
- Tests:
*.test.tsfiles next to source, using Bun's built-in test runner - Package manager: Bun (not npm/npx/yarn)
src/
├── index.ts # CLI entry point
├── cli.ts # CLI parser
├── config.ts # Config export
├── types.ts # Core types
├── config/ # Config loading, validation, dependency resolution
├── process/ # Process spawning, lifecycle, readiness detection
├── ui/ # TUI layer (OpenTUI) - tabs, panes, status bar
└── utils/ # Logger, file watcher, color, env-file, shutdown
- Panes are readonly by default — keyboard input is not forwarded to processes. Press
Enterto enter input mode (forwards keystrokes to the process for y/n prompts etc.),Escapeto exit - Left/Right arrows cycle tabs, Up/Down arrows scroll by line, Shift+Up/Down scroll to top/bottom, PageUp/PageDown scroll by page, Home/End to top/bottom
- Mouse drag selects text and auto-copies to clipboard (OSC 52);
Ykey also copies selection Ttoggles anHH:mm:ss.SSStimestamp gutter in TUI mode; also enabled viatimestamps: trueconfig or--timestampsflag. Accepts a format string (e.g.timestamps: "HH:mm:ss") with tokens:YYYY,MM,DD,HH,hh,mm,ss,SSS,A- Compact keybinding hints in the status bar;
Hor?opens a full help overlay. Config lives insrc/ui/keybindings.ts - Set
interactive: trueon processes that need stdin (REPLs, shells) - Non-interactive panes hide the terminal cursor (shown during input mode)
- Set
errorMatcher: trueto detect ANSI red output, or a regex string to match custom patterns — shows a red indicator on the tab while the process keeps running readyPatternacceptsstring(simple match) orRegExp(match + capture groups). RegExp captures are expanded into dependentcommandandenvvalues via$dep.groupsyntax (e.g.$odoo.url)optional: truemakes a process visible as a tab but not auto-started (starts instoppedstate). Alt+S starts it manually. Unlikecondition, optional does not cascade to dependentsplatformrestricts a process to specific OS(es) (e.g.'darwin','linux'). Non-matching processes are removed; their dependents still start with the dependency stripped (unlikeconditionwhich cascades)
Commit messages must follow Conventional Commits format: type(scope): subject. Enforced by commitlint via a git hook (.githooks/commit-msg) and in CI.
Runs on PRs: commitlint, typecheck, lint, test.
- Bash matcher: Runs
save-learnings-reminder.shbefore any Bash tool call. Ongit commitcommands, injects a reminder to save session learnings to memory files or CLAUDE.md.
- Auto-fix: Runs
bun run fixwhen a Claude session ends, ensuring code is always formatted.
| Rule | Action | Pattern | Purpose |
|---|---|---|---|
block-force-delete |
block | rm\s+.*-[^\s]*f |
Prevents rm -f; use rm without force flag |
block-npx |
block | \bnpx\s+ |
Prevents npx; use bun/bunx instead |
no-git-c-flag |
block | git\s+-C\s+ |
Prevents git -C; already in correct directory |
save-learnings-on-commit |
warn | git\s+commit |
Reminds to save learnings before committing |
Infinite-loop script for unattended Claude sessions. Runs with restricted tool access and a default prompt to implement next steps from .claude/plans/.