GET/roostv0.2.3 · 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 ] — MITinstall:brew, from [ ikatsuba/tap ] — signed, notarised, universalstatus: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/features6 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.

06a tap on the shoulder

With the window behind something else, an agent that gets stuck becomes a notification and a count on the dock icon. The queue does not have to be watched to be answered.

/roost/shortcuts12 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
⌘Wclose the pane
⌘⇧← → ↑ ↓move between panes
⌘1…9 · ⌘⌥← →switch session
⌘⌥1…9 · ⌘⌥↑ ↓switch project
⌘B · ⌘⇧Bfold the project list · the side panel
⌘⇧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/installbrew · universal · notarised
brew tap ikatsuba/tap
brew trust ikatsuba/tap
brew install --cask roost

The middle line is not optional: Homebrew 6 refuses to load anything from a tap outside its own repositories until you say you meant that one.

By hand it is a universal zip on the releases page — unpack it, move Roost.app to /Applications. Either way it just opens: the builds carry a Developer ID signature and a stapled notarisation ticket, so Gatekeeper is satisfied without asking Apple and without being told anything by hand. You need macOS 14 or newer and Claude Code on your PATH.

POST/roost/buildsh · swift 6
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. This signature is ad-hoc, which is enough for the machine that built it and refused as damaged on any other — that is what the releases above are signed properly for.

/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.