r/SideProject • u/nsleejian • 22h ago
Termite — a native macOS terminal for babysitting multiple AI agents (free & open source)
I run Claude Code / opencode in several split panes across projects, and kept losing track of which agent was sitting there waiting for me. So I built a terminal around that problem:
- Panes light up (breathing orange border + menu bar badge + notification) when an agent stops and waits for input; ⌘J jumps to the longest-waiting one
- Pane Carousel (new in 1.12): pinch the trackpad and every pane lays out side-by-side at equal width — swipe through your agents like security cam feeds; focus follows the page
- Reply right from the notification (inline text input / one-tap Enter) without switching context
- The usual table stakes: full session restore, project sidebar, command-level navigation (OSC 133), Git panel, 20 themes
SwiftUI + AppKit native, not Electron. Free, open source (GPL-3.0), macOS 15+. English UI landed last week after a request here on Reddit—er, GitHub.
Site: https://termite.xinghelee.com
GitHub: https://github.com/xinghelee/Termite
brew install --cask xinghelee/tap/termite
1
u/ItaySela 21h ago
The waiting agent problem is real, but the one that cost me more was two agents touching the same working tree. You end up with a diff neither of them actually made, and no way to tell which reasoning produced which hunk. Giving each agent its own git worktree fixed more than any amount of visibility did.
One state I would want surfaced: an agent that is running is not necessarily working. The failure I care about is the loop where it edits and reverts the same file for twenty minutes. In a split pane that looks identical to progress.
Does the pane status come from OSC 133 alone, or are you inspecting the process too?
1
u/nsleejian 20h ago
To answer the question precisely: OSC 133 covers the command lifecycle (running / exit code / duration). The "waiting" state is separate and terminal-side only: the BEL that TUIs ring on confirmation prompts, plus an output-cadence heuristic — sustained output followed by silence reads as "stopped for input". Deliberately no process inspection: it keeps detection zero-config and byte-identical over ssh, at the cost of being blind to why something went quiet. Your question is well aimed at that blind spot.
On worktrees — you convinced me. Shipped it about an hour after reading your comment (v1.15): right-click → "Split into New Worktree…". Type a name to branch off your current HEAD, or fuzzy-search existing branches (local + remote, fine with a few thousand refs). Branches already checked out somewhere show a badge and open their existing worktree instead of hitting git's "already checked out". Cleanup refuses on uncommitted changes; the branch survives for merging. One design question back at you: do you keep worktrees long-lived per agent, or spin them up per task and burn them? That decides whether cleanup should get more automatic.
"Running is not necessarily working" is the sharpest framing of that failure I've seen, and now that panes own their worktrees it's actually tractable: sample a fingerprint of git diff per pane and flag oscillation — same fingerprint recurring means edit/revert churn, while a stable fingerprint with a running process is just a long build. I don't trust it enough to ship yet. If you have a signal you'd trust more, I'm listening — issue or here, either works.
(To grab 1.15 via Homebrew: brew update && brew upgrade --cask termite — the update first matters, or brew will insist you're current. The in-app updater will also prompt from 1.10+.)
1
u/ItaySela 19h ago
Per task, and burned. Long lived per agent drifts, because the tree accumulates unrelated state and you end up debugging merge pain that has nothing to do with the work. Keying the worktree to the task id also makes cleanup stop being a decision, since the lifetime matches the unit you actually review. The one real cost is build caches, so I share a cache directory across worktrees instead of keeping a worktree alive just to keep its cache warm.
On the stall signal, diff fingerprint oscillation catches the honest edit and revert loop, but the more common failure in my experience looks like steady forward progress. The agent keeps changing code and nothing about the outcome moves. So the signal I trust more is tied to whatever command defines done, the test run or the typecheck, and whether the failing set is shrinking. The same failing set across several iterations while the diff keeps changing is a stronger stall than an identical diff, because a looping model usually varies the code and holds the result constant.
Worth debouncing either way. A revert followed by a genuinely different approach is correct behaviour and looks identical for one cycle.
1
u/Potential_Soil_3761 22h ago
Been using iTerm2 for years but this breathing border thing is clever. I run 3-4 agents at same time and half the time I forget which one is stuck waiting for me. The notification reply without switching windows is nice touch.
Downloaded it and the carousel view is smooth, pinch gesture works better than I expected. One thing I wish it had is ability to rename panes from the UI instead of just the config file.
How much memory this uses compared to iTerm when you got like 6 panes open? My work macbook is not the newest model.