I built a native macOS terminal so I'd stop losing track of my AI agents
Once I started running Claude Code sessions in parallel, my bottleneck moved. The agents write the code. What slows everything down is me figuring out which session is waiting for my input.
Put three or four agents in tmux panes or terminal tabs and you can't tell a stalled session from a working one. They look identical. I kept finding sessions that had been sitting on a permission prompt for ages before I noticed. The agents were fast; my dispatching was slow.
So I built a terminal. It's called viterm: a native macOS app in Swift + AppKit, with rendering handled by libghostty. MIT licensed.
What I wanted
The requirements never grew past two items:
- Spin up any number of agent sessions per git worktree
- Tell each session's state, busy / waiting / idle, at a glance in the sidebar
I also considered building this on top of an existing terminal, but knowing a session's state means reaching into the deep layers of the terminal, and a plugin can't get there. At that point it made more sense to build an app that owns the whole workflow, from creating the worktree to merging it back.
The sidebar has two levels, repository > worktree, and each worktree holds its sessions as tabs. One worktree, N sessions. My most common setup is an agent and a plain shell side by side on the same branch, so I can poke at whatever the agent just wrote.
Worktrees can be created, merged, rebased, and deleted from the sidebar, so a branch lives its whole life without me leaving the terminal. You could just cd into the worktree directory, sure. But honestly, even that cd is too much of a hassle for me, lol. Once one click switches me over, I lose all willingness to type a path.
Each session's state shows up as a dot in the sidebar: orange for busy, blue for waiting, an outline for idle. A glance down the list tells me which ones are stalled on my reply. That's the part that actually matters. โโงU jumps straight to the most recent waiting session, and I'd argue the entire parallel-agent experience comes down to that one key. (It can fire a macOS notification when a session starts waiting, too, but I end up watching the sidebar instead.)
The detection underneath is two-tiered, escape sequences plus screen text, but that's a longer story for another post.
I was using ccmanager
Tools for dispatching agents per worktree already exist. ccmanager is well made, and I used it for a while. What didn't fit me was that you can't run more than one session in a single worktree. I often want an agent and a plain shell, or two agents, side by side on the same branch. Nothing wrong with ccmanager; it just didn't match how I work.
The code is almost entirely agent-written
Confession: viterm's code is written almost 100% by Claude Code. My job is deciding what to build, running it and complaining, and choosing whether to merge or send it back. So I run Claude Code inside viterm to build viterm itself. Call it dogfooding, call it a snake eating its tail. The value of noticing an agent's waiting state fast gets tested every day by this development loop. I'm the first user, and the one with the most complaints.
What's missing
- macOS 15+ on Apple Silicon only. No Intel, no Linux, no plans for either
- The detection patterns are tuned for Claude Code and Codex; other agents will detect less reliably
Install
brew tap viteflowsystem/tap
brew install --cask viterm
There's also a direct DMG download (Developer ID signed and notarized). All the source is on GitHub.
The feedback I want most right now is about state detection. There are surely CLI agents I don't use where the waiting state gets misread, and the most useful thing you could file is an issue naming the tool and how it got it wrong.
And yeah, Claude wrote this post too.
Comments
No comments yet. Start the discussion.