claude-garage 0.3.2 → 0.3.3

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.
@@ -17,6 +17,7 @@ import { attachTermServer } from "./term.js";
17
17
  import { rejectForeignOrigins } from "./security.js";
18
18
  import { startPoller } from "./poller.js";
19
19
  import { healthPayload } from "./health.js";
20
+ import { ensureExtendedKeys } from "./tmux.js";
20
21
 
21
22
  const HOST = "127.0.0.1";
22
23
  const PORT = Number(process.env.GARAGE_PORT ?? 4747);
@@ -63,6 +64,9 @@ if (process.env.GARAGE_SERVE_UI === "1") {
63
64
  // Poller feeds StatusStore (busy/idle baseline); hooks.js and notify.js
64
65
  // subscribe to the same store — see status.js for the single write path.
65
66
  const stopPoller = startPoller(app);
67
+ // p14: Shift+Enter needs the tmux server's extended-keys config — apply it
68
+ // to an already-running server at boot (createSession re-applies later).
69
+ ensureExtendedKeys();
66
70
  app.addHook("onClose", async () => {
67
71
  stopPoller();
68
72
  });
@@ -164,6 +164,9 @@ export async function hasSession(id) {
164
164
  // must not pre-join them into a single string.
165
165
  export async function createSession(id, dir, command, extraArgs = []) {
166
166
  await run("tmux", ["new-session", "-d", "-s", id, "-c", dir, command, ...extraArgs]);
167
+ // The new-session call may have just started the server — (re)apply the
168
+ // extended-keys server config so Shift+Enter works in this pane (p14).
169
+ await ensureExtendedKeys();
167
170
  // The pit wall renders its own session title bars, so tmux's status line
168
171
  // is visual noise in every grid cell. Per-session option — a plain
169
172
  // `tmux attach` escape-hatch user can restore it with `set status on`.
@@ -172,6 +175,28 @@ export async function createSession(id, dir, command, extraArgs = []) {
172
175
  await run("tmux", ["set-option", "-t", id, "status", "off"]).catch(() => {});
173
176
  }
174
177
 
178
+ // p14: Claude Code's Shift+Enter (kitty protocol, ESC[13;2u) only reaches a
179
+ // pane if the tmux server has extended keys on and advertises them —
180
+ // exactly the tmux config Claude Code's own terminal docs prescribe. Server
181
+ // options survive until the tmux server exits, so this runs at daemon boot
182
+ // AND on every createSession (the server may have been started later by a
183
+ // plain `tmux` user). Idempotent: `set -as terminal-features` appends
184
+ // duplicates, so the extkeys feature is only appended when missing.
185
+ export async function ensureExtendedKeys() {
186
+ try {
187
+ await run("tmux", ["set-option", "-s", "extended-keys", "on"]);
188
+ const { stdout } = await run("tmux", ["show-options", "-s", "terminal-features"]).catch(
189
+ () => ({ stdout: "" })
190
+ );
191
+ if (!/xterm\*?[^\n]*extkeys/.test(stdout)) {
192
+ await run("tmux", ["set-option", "-as", "terminal-features", "xterm*:extkeys"]);
193
+ }
194
+ } catch {
195
+ // No server running (or ancient tmux) — nothing to configure; the
196
+ // createSession call path retries once a server exists.
197
+ }
198
+ }
199
+
175
200
  export async function killSession(id) {
176
201
  await run("tmux", ["kill-session", "-t", exact(id)]);
177
202
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-garage",
3
- "version": "0.3.2",
3
+ "version": "0.3.3",
4
4
  "description": "Multiple Claude agents driving you crazy? Park them all in one garage: a needs-input queue that follows you across projects, a full-screen terminal TUI, and a browser wall with diff review. tmux owns the sessions; close the app and nothing dies.",
5
5
  "license": "MIT",
6
6
  "author": "Saiful Islam <saifulislamadar@gmail.com>",
Binary file