GET/roostv0.1 · macOS 14+ · MIT
$ open -a Roost

Several agents. One window.

A native macOS workspace for Claude Code sessions. Projects in a sidebar, sessions as tabs, panes split into a tree — and every pane reports what its agent is doing, so running five at once stops being bookkeeping.

runtime:Swift 6, SwiftUI and AppKit — no Electron, no web viewterminal:[ SwiftTerm ] — everything else is written from scratchsource:[ github.com/IKatsuba/roost ] — MITstatus:young, and used daily by its author — expect rough edges
The Roost window: two projects in the sidebar, three sessions as tabs, a split of two agent panes, and the attention queue on the right holding two questions waiting for an answer.
Two projects, four sessions. The marks say who is where — solid for the agents stuck on a question, stripes for the one at work, an outline for the one at rest — and the queue on the right says what they are stuck on.
/roost/status4 states · enum
waiting

Stuck on a question. Nothing moves without you — the only square filled solid, in the app as here.

working

Thinking or running tools. The only element of the interface allowed to move.

done

The output is written but nobody has read it. Fades to rest the moment you open the tab.

idle

Alive and waiting for its next task. Nothing owed in either direction.

Claude Code does not publish what it is doing, so Roost listens to its hooks and turns them into a square next to every pane, tab and project.

/roost/features5 items · application/json
01sessions that return

The layout survives a restart, and a claude pane comes back to its own conversation rather than a blank slate. Roost names each session itself, so it knows what to resume from the first second — not from the first hook.

02an attention queue

Every waiting agent in one list, longest wait first, with the question it is stuck on. Answer it, or mark it handled when you already dealt with it yourself.

03past sessions

Every conversation this project ever had, by name and by age, including the ones that ran in a branch. Paste a session id from another machine and it opens too.

04agents in a branch

A pane can run its agent in a git worktree created by Claude Code itself, so a risky refactor never touches the tree you are working in.

05a palette over everything

⌘K searches panes, projects, actions and past sessions at once, urgent ones first — because that is who you were looking for.

/roost/shortcuts10 bindings · bare ⌘ only
⌘T · ⌘⇧Tnew claude session · new shell
⌘N · ⌘⇧Nnew project · claude in a worktree
⌘Oopen a past session
⌘Kcommand palette
⌘D · ⌘⇧Dsplit right · down with claude
⌘E · ⌘⇧Esplit right · down with a shell
⌘⇧← → ↑ ↓move between panes
⌘1…⌘9switch session
⌘⌥← → · ⌘⌥1…9switch project
⌘⇧Ajump to an agent that is waiting

Anything beyond a bare ⌘ the system takes for itself before the app ever sees it. Hold ⌘ for a second inside Roost to get the full list — it is generated from the menu, so it cannot drift out of date.

POST/roost/buildsh · no releases yet
git clone https://github.com/IKatsuba/roost.git
cd roost
tool/bundle.sh          # -> build/Roost.app, ad-hoc signed
open build/Roost.app

Open the app, not the binary. Started from a terminal it inherits your PATH and hides the trap: under launchd the app gets a bare /usr/bin:/bin, where there is no claude. You need macOS 14 or newer, Claude Code on your PATH, and a Swift 6 toolchain.

/roost/permissionseverything stays local
writes

~/Library/Application Support/dev.katsuba.roost/

The workspace snapshot and the hook files it generates for Claude Code.

reads

~/.claude/projects/

Claude Code's own transcripts, to list and name past sessions. Read-only, and never sent anywhere.

listens

127.0.0.1:<os-assigned>

For the hook script that reports agent status. Loopback connections only; anything else is dropped.