claude-garage 0.2.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -3,19 +3,20 @@
3
3
  <img src="docs/banner.png" alt="claude-garage: a pit wall for your Claude Code agents" width="100%" />
4
4
 
5
5
  **Multiple Claude agents driving you crazy? Park them all in one
6
- garage.** Every session, every project, on one live wall: no window
7
- juggling, no tab hunting, and you know the instant one needs you.
6
+ garage.** A needs-input queue that follows you across every project (`a`
7
+ jumps to whoever's waiting), file-by-file diff review, and tmux-owned
8
+ sessions that outlive the tool — reboot the Mac, `tmux attach` still works.
8
9
 
9
10
  [![npm](https://img.shields.io/npm/v/claude-garage?color=e2a75e&label=npm)](https://www.npmjs.com/package/claude-garage)
10
11
  [![license](https://img.shields.io/badge/license-MIT-79b26e)](LICENSE)
11
12
  [![node](https://img.shields.io/badge/node-%E2%89%A5%2020-6e9ecc)](package.json)
12
13
  [![local](https://img.shields.io/badge/100%25-local-c6cfdb)](#local-only-by-design)
13
14
 
14
- <img src="docs/hero.png" alt="The pit wall: two workspaces, a session asking for permission (amber), a finished worktree session, and the diff pane" width="100%" />
15
+ <img src="docs/hero.png" alt="The web wall: two workspaces, a session asking for permission (amber), a finished worktree session, and the diff pane" width="100%" />
15
16
 
16
17
  </div>
17
18
 
18
- **▶ 60-second reveal** — the wall, needs-input triage, diff review, and the pit pet, beat by beat:
19
+ **▶ 60-second reveal** — the web wall, needs-input triage, diff review, and the pit pet, beat by beat:
19
20
 
20
21
  https://github.com/user-attachments/assets/b19defa0-a60d-4082-9ca5-9b8ce9480b18
21
22
 
@@ -24,49 +25,90 @@ https://github.com/user-attachments/assets/b19defa0-a60d-4082-9ca5-9b8ce9480b18
24
25
  Running multiple Claude Code sessions across multiple projects means juggling
25
26
  terminal windows and editor windows. There is no single place to see:
26
27
 
27
- - **which sessions exist**, per project
28
- - **which one is blocked waiting for your input**. The real pain isn't window
29
- count, it's attention routing
28
+ - **which one is blocked waiting for your input** — right now, anywhere.
29
+ The real pain isn't window count, it's attention routing.
30
30
  - **what each session changed**, reviewable without hunting
31
+ - **which sessions exist**, per project, without them dying the moment you
32
+ close a terminal or reboot
31
33
 
32
34
  claude-garage is that single place: the garage your agents are parked in,
33
- one screen, built around four things that rarely coexist.
34
-
35
- 1. 🔌 **Real terminals that survive the tool.** tmux owns every session, not
36
- the app. Close the tab, kill the daemon, reboot the Mac:
37
- `tmux attach -t garage/<workspace>/<label>` still works, and dead sessions
38
- restore with their full conversation (`claude --resume`) in one click.
39
- 2. 🖥️ **Every session of a project on screen at once.** Not a switcher, a
40
- live grid of interactive terminals. Split, resize, maximize, float, or
41
- detach into standalone views, VS Code-style.
42
- 3. 🚨 **Needs-input triage as a first-class queue.** Blocked sessions sort
43
- first everywhere, light up amber, count into the header badge and the tab
44
- title; `a` jumps to whichever agent is waiting, across every project.
45
- Notifications reach you even when the wall isn't visible.
46
- 4. 📋 **File-by-file diff review with an editor jump.** Per-workspace or
47
- per-worktree changes (committed and uncommitted), a full-screen review mode
48
- with viewed-tracking, and `o` to open your editor at the exact line.
35
+ built around four things that rarely coexist.
36
+
37
+ 1. 🚨 **Needs-input triage as a first-class queue.** Blocked sessions sort
38
+ first everywhere, light up amber, and count into the header badge, the
39
+ tab title, and the TUI's status strip; `a` jumps to whichever agent is
40
+ waiting, across every project, on either surface.
41
+ 2. 🔌 **Real terminals that survive the tool.** tmux owns every session, not
42
+ the app. Close the terminal, kill the daemon, reboot the Mac:
43
+ `tmux attach -t garage/<workspace>/<label>` still works, dead sessions
44
+ restore with their full conversation (`claude --resume`) in one keypress,
45
+ and `t` pops a live session into its own OS terminal window alongside
46
+ the wall.
47
+ 3. 📋 **File-by-file diff review with an editor jump — in the web wall.**
48
+ Per-workspace or per-worktree changes (committed and uncommitted), a
49
+ full-screen review mode with viewed-tracking, and `o` to open your editor
50
+ at the exact line. (The TUI doesn't have review mode yet — it's on the
51
+ [Roadmap](#roadmap).)
52
+ 4. 🖥️ **Every session of a project visible at once.** Not a switcher: the
53
+ web wall renders every session in a workspace as a live terminal
54
+ simultaneously (split/resize/maximize/detach); the TUI groups sessions
55
+ into named views (`d`/`D`/`Tab`) with a 6-tile grid and an overflow rail
56
+ for the rest.
49
57
 
50
58
  ## Quick start
51
59
 
60
+ ```bash
61
+ npx claude-garage tui
62
+ ```
63
+
64
+ A full-screen terminal wall, right in your terminal. Starts the daemon if
65
+ one isn't already running; `1`–`9` switch workspaces, `Enter` engages the
66
+ focused terminal (keys go to the agent byte-exact — Alt+arrows, paste,
67
+ everything), `Ctrl+G` hands keys back to the garage, `a` jumps to whoever's
68
+ waited longest, `?` for the full keymap. Quitting the TUI leaves the daemon
69
+ and every tmux session running. It's also light: ~5ms input latency, ~2%
70
+ CPU, and a 2.4MB binary (measured on the ratatui port — see
71
+ [`openspec/changes/archive/2026-08-31-p9-ratatui-port/verification.md`](openspec/changes/archive/2026-08-31-p9-ratatui-port/verification.md)).
72
+
73
+ Since p10–p12, the TUI also groups sessions into views (`d` detaches the
74
+ focused one into its own view or rejoins it to the default, `D` moves it to
75
+ a chosen group, `Tab` cycles views), shows a dim auto-subtitle under each
76
+ session's label straight from Claude Code's own terminal-title updates (zero
77
+ config), and tracks context pressure: a per-tile meter plus a `5h`/`7-day`
78
+ usage chip in the strip, fed by a one-keypress `I` install of a chaining
79
+ statusline wrapper (any statusline you already have keeps running). Closing
80
+ a plain session tears it down; closing a worktree session keeps its branch
81
+ and points you at the web wall to merge or discard it.
82
+
83
+ **Prefer a browser?**
84
+
52
85
  ```bash
53
86
  npx claude-garage
54
87
  ```
55
88
 
56
- Opens the pit wall at `http://127.0.0.1:4747`. Add a workspace, spawn
57
- sessions with the `+` next to its name, and press `?` for the keys.
89
+ Opens the web wall at `http://127.0.0.1:4747` — the companion surface, with
90
+ diff review and the worktree finish flow (see [Web wall](#web-wall)). Both
91
+ commands start the same daemon and see the same tmux sessions, so you can
92
+ run either one, or both, at once.
58
93
 
59
94
  **Requirements**
60
95
 
61
- - macOS
96
+ - macOS (Linux support is on the [Roadmap](#roadmap))
97
+ - Node.js ≥ 20
62
98
  - [tmux](https://github.com/tmux/tmux) ≥ 3.2 (garage offers to `brew install` it if missing)
63
99
  - [Claude Code](https://docs.claude.com/en/docs/claude-code) CLI on `PATH`
64
- - Node.js ≥ 20
100
+ - Rust — **not required on Apple Silicon.** The TUI ships as a prebuilt
101
+ `arm64` binary in the npm package. On an Intel Mac, `claude-garage tui`
102
+ builds it once from source the first time you run it if `cargo` is on
103
+ `PATH` ([rustup.rs](https://rustup.rs)); without `cargo` you get an
104
+ actionable error naming exactly what's missing, not a crash. The web wall
105
+ never needs Rust.
65
106
 
66
107
  **Hooks (recommended):** status updates poll every 2s by default. Click
67
- **install hooks for me** in the banner for instant detection. The daemon
68
- merges Claude Code's hooks into `~/.claude/settings.json` (backup kept,
69
- idempotent).
108
+ **install hooks for me** in the web wall's banner (or press `I` in the TUI
109
+ for the statusline half of the story) for instant detection. The daemon
110
+ merges Claude Code's hooks/statusline into `~/.claude/settings.json` (backup
111
+ kept, idempotent).
70
112
 
71
113
  ## Local-only by design
72
114
 
@@ -77,8 +119,8 @@ Everything runs on your machine and stays there.
77
119
  phones home to no one.
78
120
  - All state is a single local file (`~/.garage/state.json`) plus your own
79
121
  tmux server and git repos.
80
- - Your sessions talk to Claude exactly as they would without garage. The
81
- wall is a viewer, not a middleman.
122
+ - Your sessions talk to Claude exactly as they would without garage. Both
123
+ the TUI and the web wall are viewers, not a middleman.
82
124
 
83
125
  ## Session states
84
126
 
@@ -88,12 +130,19 @@ Everything runs on your machine and stays there.
88
130
  | `◐` | working | Claude is running. |
89
131
  | `✓` | done | Finished a turn since you last looked (fades after 2 min). |
90
132
  | `○` | idle | Waiting for you to *ask*, not to *answer*. |
91
- | `⟳` | restorable | tmux died (reboot?). One click resurrects the conversation. |
133
+ | `⟳` | restorable | tmux died (reboot?). One keypress/click resurrects the conversation. |
92
134
 
93
- ## Also on the wall
135
+ ## Web wall
94
136
 
95
- - 🌳 **Worktree sessions**: spawn in an isolated git worktree on a
96
- `garage/<label>` branch; on close, **merge / discard / keep**.
137
+ The browser companion (`npx claude-garage`, `http://127.0.0.1:4747`) carries
138
+ the features the TUI doesn't have yet:
139
+
140
+ - 🎨 **Diff review**: the changes pane and full-screen review mode described
141
+ in [Why](#why) — `Tab`/`j`/`k`/`r`/`v`/`o`, see [Keybindings](#keybindings).
142
+ - 🌳 **Worktree finish flow**: spawn a worktree session from either surface
143
+ (`N` in the TUI, the worktree toggle here), but **merge / discard / keep**
144
+ on close is web-only for now — the TUI always keeps the branch and tells
145
+ you to finish it here.
97
146
  - 🎨 **Themes**: garage, claude dark, claude light, or follow the OS.
98
147
  Terminals re-skin in place, full ANSI palettes included.
99
148
  - 🔔 **Notifications**: badge + tab title in-app, opt-in browser
@@ -101,7 +150,7 @@ Everything runs on your machine and stays there.
101
150
  notification when no page is open (clickable with
102
151
  [`terminal-notifier`](https://github.com/julienXX/terminal-notifier)).
103
152
 
104
- ## The pit pet 🐈
153
+ ### The pit pet 🐈 (web wall)
105
154
 
106
155
  An optional ASCII companion on the key strip whose mood *is* the wall:
107
156
  asleep when all is quiet, watching while agents run, **sprinting toward the
@@ -130,55 +179,78 @@ state in character:
130
179
 
131
180
  ## Keybindings
132
181
 
182
+ The TUI's full keymap (`claude-garage tui`, also shown in-app with `?`).
183
+ Bindings apply at the garage layer; `Enter` hands your keystrokes to the
184
+ focused session byte-exact until `Ctrl+G` takes them back.
185
+
133
186
  | Key | Action |
134
187
  |---|---|
135
- | `1`–`9` | switch focused workspace |
136
- | `[` / `]` | cycle terminals within the workspace |
137
- | `a` | jump to a session that needs input, anywhere |
138
- | `\` | split the focused cell (new session beside it) |
139
- | `m` | maximize the focused cell ⇄ restore |
140
- | `Tab` | changes pane: toggle list ⇄ diff emphasis |
141
- | `j` / `k` | next / previous changed file |
142
- | `r` | enter full-screen review mode |
143
- | `v` | (review mode) mark file viewed, advance to next unviewed |
144
- | `o` | open the selected file, or the workspace root, in your editor |
145
- | `Shift+Enter` | newline in Claude Code's composer (no `/terminal-setup` needed) |
146
- | `Ctrl+\`` | release keys from the terminal back to garage |
147
- | `?` | keybindings + status legend |
148
-
149
- Bindings pause while a terminal has keyboard focus. The header chip always
150
- shows where your keys go.
188
+ | `1`–`9` | focus workspace |
189
+ | `[` / `]` | cycle focused tile |
190
+ | `Enter` | engage focused tile (restore it when restorable) |
191
+ | `Ctrl+G` | disengage (while engaged) |
192
+ | `m` | maximize / restore focused tile |
193
+ | `t` | open focused session in a new terminal window (macOS) |
194
+ | `a` | jump to longest-waiting blocked session |
195
+ | `A` | triage queue |
196
+ | `n` / `N` | spawn session / worktree session |
197
+ | `R` | restore all restorable sessions in workspace |
198
+ | `I` | install statusline feed for context meters |
199
+ | `x x` | close focused session (press twice) |
200
+ | `X X` | remove focused workspace (sessions keep running) |
201
+ | `X K` | remove focused workspace AND kill its sessions |
202
+ | `w` | add workspace |
203
+ | `d` | detach focused session to its own view, or rejoin main |
204
+ | `D` | move focused session to another view / new group |
205
+ | `Tab` | cycle the focused workspace's views |
206
+ | `?` | toggle this help |
207
+ | `q` | quit (tmux sessions keep running) |
208
+
209
+ The web wall has its own compact keymap for its own features (grid
210
+ navigation plus diff review) — press `?` there for the full list:
211
+ `1`–`9` workspace, `[`/`]` cycle terminal, `a` jump, `\` split cell, `m`
212
+ maximize, `Tab`/`j`/`k`/`r`/`v`/`o` for the changes pane and review mode,
213
+ `` Ctrl+` `` releases keys back to the browser wall.
151
214
 
152
215
  ## How it works
153
216
 
154
217
  ```
155
218
  tmux (persistence, source of truth)
156
- └─ small Node daemon (spawn / list / bridge / diff / hooks)
157
- └─ browser UI (React + xterm.js)
219
+ └─ small Node daemon (spawn / list / bridge / diff / hooks / statusline)
220
+ ├─ Rust terminal wall (ratatui + crossterm — `claude-garage tui`)
221
+ └─ browser web wall (React + xterm.js — `npx claude-garage`)
158
222
  ```
159
223
 
160
224
  The daemon is a thin Fastify process that shells out to `tmux`/`git`/`claude`
161
- rather than re-implementing them; diffs are computed read-only; hook events
162
- are token-authed. The UI is a viewer over SSE + WebSockets. tmux is the
163
- registry: garage can be deleted and your sessions won't notice.
225
+ rather than re-implementing them; diffs are computed read-only; hook and
226
+ statusline events are token-authed. Both UIs are viewers over the same
227
+ daemon: the web wall over SSE + WebSockets, the TUI over HTTP/SSE for state
228
+ and direct `tmux attach` PTYs for the terminals themselves — no WebSocket
229
+ terminal bridge in the TUI path. tmux is the registry: garage can be deleted
230
+ and your sessions won't notice.
164
231
 
165
232
  ## Development
166
233
 
167
234
  ```bash
168
235
  npm install
169
- npm run dev # daemon :4747 + Vite :5173
170
- npm test # node:test suite (status, poller, hooks, layout, views)
236
+ npm run dev # daemon :4747 + Vite :5173 (web wall)
237
+ npm test # node:test suite (status, poller, hooks, layout, views)
238
+ npm run build:tui # cargo build --release; copies the binary into wall/dist
171
239
  ```
172
240
 
241
+ `wall/` is a separate Rust workspace with its own unit and e2e suites
242
+ (`cd wall && cargo test`; e2e harnesses under `wall/test/e2e`).
243
+
173
244
  Built through spec-driven phases ([`openspec/`](openspec/)), each verified
174
245
  end-to-end on a real system.
175
246
 
176
247
  ## Roadmap
177
248
 
178
249
  - `claude-garage attach`: adopt an existing tmux session onto the wall
179
- - Phone push (ntfy/webhook) for when you're away from the machine
180
- - View renaming and drag-between-views
250
+ - Review mode in the TUI (the web wall's file-by-file diff review, ported)
181
251
  - Linux support
252
+ - Phone push (ntfy/webhook) for when you're away from the machine
253
+ - View renaming
182
254
 
183
255
  ## License
184
256