@zeph-to/cli 2.10.0 → 2.12.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
@@ -179,10 +179,15 @@ way. `zeph install` does not wire Hermes either — add the MCP server to
179
179
  ```yaml
180
180
  mcp_servers:
181
181
  zeph:
182
- command: "npx"
183
- args: ["-y", "@zeph-to/mcp-server"]
182
+ command: "zeph"
183
+ args: ["mcp"]
184
184
  ```
185
185
 
186
+ `zeph mcp` runs the MCP server inside the CLI process. The older
187
+ `command: "npx"` / `args: ["-y", "@zeph-to/mcp-server"]` form still works,
188
+ but leaves an `npm exec` launcher resident beside the server for as long as
189
+ the session lives — `zeph verify` flags a config still on it.
190
+
186
191
  Add the entry; do not replace the file. `mcp_servers` is shared with
187
192
  every other server you have configured, and nothing under `~/.hermes` is
188
193
  in version control. Then `/reload-mcp` inside Hermes.
@@ -265,10 +270,18 @@ block here.
265
270
  same folder, run `zeph cc` again, and the wrapper auto-suffixes:
266
271
  first session is `zeph-encl`, the next attached one becomes
267
272
  `zeph-encl-2`, then `zeph-encl-3`, etc. The phone picker shows them
268
- as `encl · Claude`, `encl · Claude #2`, `encl · Claude #3`. If
269
- `zeph-encl` already exists but is **detached** (no one attached),
270
- the wrapper reattaches to it instead of spawning a new one — close
271
- the terminal, come back later, pick up where you left off.
273
+ as `encl · Claude`, `encl · Claude #2`, `encl · Claude #3`.
274
+
275
+ **Reattaching wins over spawning.** If any session of that project is
276
+ **detached** (no one attached), the wrapper reattaches instead of
277
+ spawning a new one — close the terminal, come back later, pick up
278
+ where you left off. When several are detached it takes the
279
+ highest-numbered one first, then works down on later runs, so no
280
+ session can end up out of reach. That matters because a session you
281
+ cannot reach still holds a live agent: an agent CLI plus its MCP
282
+ servers is a few hundred MB you can neither see nor reclaim. A
283
+ detached session is never killed for you — nothing here can tell
284
+ "done with this" from "closed the laptop".
272
285
 
273
286
  If you're already inside a tmux session (`$TMUX` set) the wrapper
274
287
  skips the outer tmux and runs the agent in the current pane — the
@@ -514,7 +527,8 @@ zeph notify --title "Hello" --json
514
527
  | `dismiss <id>` | Dismiss a push (or `--all`) |
515
528
  | `rename <name>` | Set the current agent session's display name in the app — run inside a `zeph cc` session (`--clear` resets). Auto-detects the tmux session + this machine's listener device id, so the alias lands on the right device |
516
529
  | `test` | Verify connection and API key |
517
- | `cc` · `codex` · `gemini` | Run the agent in a `zeph-<project>` tmux session (auto-suffixed `-2`, `-3`, on attached collisions). Auto-spawns the background listener on first invocation so the phone picker just works. Trailing args pass through to the agent (`zeph cc --resume "..."`) |
530
+ | `cc` · `codex` · `gemini` | Run the agent in a `zeph-<project>` tmux session — reattaches a detached session of that project (newest suffix first) when there is one, else auto-suffixes `-2`, `-3`, …. Auto-spawns the background listener on first invocation so the phone picker just works. Trailing args pass through to the agent (`zeph cc --resume "..."`) |
531
+ | `mcp` | Run the MCP server on stdio, in this process. What agent MCP configs launch — `zeph install` registers it and you never type it. Replaces the old `npx -y @zeph-to/mcp-server` registration, which left an `npm exec` launcher resident alongside the server for the life of the session. `@zeph-to/mcp-server` ships as a dependency now, so it updates with the CLI rather than being re-fetched by `npx` on every launch — `zeph check-update` reports the version you actually have |
518
532
  | `listener` | (Usually unnecessary — `zeph cc` autospawns it.) Resident daemon: subscribes via WebSocket, reports tmux session inventory every 5 s, injects `agent.command` pushes into the matching session. Run in the foreground for SDK development; otherwise let `zeph cc` manage it |
519
533
 
520
534
  ### Notify Options
@@ -1,4 +1,11 @@
1
1
  /** Semver-ish compare: returns true when `latest` is strictly newer than `current`. */
2
2
  export declare const isNewer: (latest: string, current: string) => boolean;
3
+ /**
4
+ * The mcp-server version this CLI will actually run. It ships as a dependency
5
+ * (see mcp.ts), so it is pinned at install time — no longer "whatever npx
6
+ * fetched last". Returns null on a broken install rather than throwing; the
7
+ * report degrades to "latest is vX" the way it always did for this package.
8
+ */
9
+ export declare const installedMcpServerVersion: () => string | null;
3
10
  export declare const handleCheckUpdate: (args: Record<string, string | boolean>) => Promise<number>;
4
11
  //# sourceMappingURL=check-update.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"check-update.d.ts","sourceRoot":"","sources":["../src/check-update.ts"],"names":[],"mappings":"AAsBA,uFAAuF;AACvF,eAAO,MAAM,OAAO,GAAI,QAAQ,MAAM,EAAE,SAAS,MAAM,KAAG,OAQzD,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAU,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,KAAG,OAAO,CAAC,MAAM,CA4C9F,CAAC"}
1
+ {"version":3,"file":"check-update.d.ts","sourceRoot":"","sources":["../src/check-update.ts"],"names":[],"mappings":"AAuBA,uFAAuF;AACvF,eAAO,MAAM,OAAO,GAAI,QAAQ,MAAM,EAAE,SAAS,MAAM,KAAG,OAQzD,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,yBAAyB,QAAO,MAAM,GAAG,IASrD,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAU,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,KAAG,OAAO,CAAC,MAAM,CA4C9F,CAAC"}
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.handleCheckUpdate = exports.isNewer = void 0;
3
+ exports.handleCheckUpdate = exports.installedMcpServerVersion = exports.isNewer = void 0;
4
+ const fs_1 = require("fs");
4
5
  const config_js_1 = require("./config.js");
5
6
  // Compares installed versions against the npm registry. Pure read-only —
6
7
  // never installs anything; just tells the user if a newer release exists.
@@ -34,19 +35,35 @@ const isNewer = (latest, current) => {
34
35
  return false;
35
36
  };
36
37
  exports.isNewer = isNewer;
38
+ /**
39
+ * The mcp-server version this CLI will actually run. It ships as a dependency
40
+ * (see mcp.ts), so it is pinned at install time — no longer "whatever npx
41
+ * fetched last". Returns null on a broken install rather than throwing; the
42
+ * report degrades to "latest is vX" the way it always did for this package.
43
+ */
44
+ const installedMcpServerVersion = () => {
45
+ try {
46
+ const pkg = JSON.parse((0, fs_1.readFileSync)(require.resolve('@zeph-to/mcp-server/package.json'), 'utf-8'));
47
+ return pkg.version ?? null;
48
+ }
49
+ catch {
50
+ return null;
51
+ }
52
+ };
53
+ exports.installedMcpServerVersion = installedMcpServerVersion;
37
54
  const handleCheckUpdate = async (args) => {
38
55
  const isJson = args.json === true;
39
- // The CLI's own installed version is known from package.json.
40
- // mcp-server's installed version isn't reliably knowable from here
41
- // (it's a separate package, often run via npx), so we only report its
42
- // latestthe user compares against whatever they have.
43
- const results = [];
44
- for (const pkg of PACKAGES) {
45
- const latest = await fetchLatest(pkg);
46
- const current = pkg === '@zeph-to/cli' ? config_js_1.VERSION : null;
47
- const outdated = !!(latest && current && (0, exports.isNewer)(latest, current));
48
- results.push({ pkg, current, latest, outdated });
49
- }
56
+ // Both installed versions are knowable: the CLI's from its own
57
+ // package.json, and mcp-server's because `zeph mcp` runs it in-process,
58
+ // which makes it a dependency rather than an npx download of unknown age.
59
+ // Two unrelated registry round-trips awaiting them one after the other
60
+ // doubled the command's wall time for nothing.
61
+ const latestVersions = await Promise.all(PACKAGES.map(fetchLatest));
62
+ const results = PACKAGES.map((pkg, i) => {
63
+ const latest = latestVersions[i];
64
+ const current = pkg === '@zeph-to/cli' ? config_js_1.VERSION : (0, exports.installedMcpServerVersion)();
65
+ return { pkg, current, latest, outdated: !!(latest && current && (0, exports.isNewer)(latest, current)) };
66
+ });
50
67
  if (isJson) {
51
68
  console.log(JSON.stringify({ results }, null, 2));
52
69
  return 0;
package/dist/cli.js CHANGED
@@ -11,6 +11,7 @@ const verify_js_1 = require("./verify.js");
11
11
  const check_update_js_1 = require("./check-update.js");
12
12
  const ask_js_1 = require("./ask.js");
13
13
  const wrapper_js_1 = require("./wrapper.js");
14
+ const mcp_js_1 = require("./mcp.js");
14
15
  const listener_js_1 = require("./listener.js");
15
16
  const config_js_1 = require("./config.js");
16
17
  const gate_js_1 = require("./gate.js");
@@ -79,10 +80,14 @@ Commands:
79
80
  (run inside a zeph cc session; --clear resets it)
80
81
  test Send a test notification to verify setup
81
82
  ${usageAgentLines()}
82
- (auto-suffixed -2/-3/… when another zeph cc is already
83
- attached to the default name; any args after the
84
- subcommand are forwarded verbatim, e.g.
85
- 'zeph cc --resume')
83
+ (reattaches a detached session of that project when
84
+ there is one, newest suffix first; auto-suffixes
85
+ -2/-3/… only when every existing one has a client
86
+ attached. Any args after the subcommand are forwarded
87
+ verbatim, e.g. 'zeph cc --resume')
88
+ mcp Run the MCP server on stdio. This is what agent MCP
89
+ configs launch — 'zeph install' registers it, you
90
+ never type it
86
91
  listener Resident daemon — receives 'agent.command' pushes from
87
92
  the phone picker and injects them into the matching
88
93
  tmux session.
@@ -490,6 +495,8 @@ const main = async () => {
490
495
  return handleRename(args);
491
496
  case 'test':
492
497
  return handleTest(args);
498
+ case 'mcp':
499
+ return (0, mcp_js_1.handleMcp)();
493
500
  case 'listener':
494
501
  return (0, listener_js_1.handleListener)(args);
495
502
  case 'remote-hook':
@@ -12,18 +12,6 @@ export declare const shouldReauth: (currentKey: string | undefined, relogin: boo
12
12
  /** Exported for tests (installGemini shells out to the real `gemini` binary,
13
13
  * so the merge semantics can't be covered through it deterministically). */
14
14
  export declare const mergeJsonFile: (filePath: string, patch: Record<string, unknown>) => void;
15
- /**
16
- * opencode.json's own MCP schema — top-level `mcp` key (not `mcpServers`),
17
- * `command` as ARRAY (binary + args), `type: "local"`. No `environment` —
18
- * opencode is a terminal app that inherits shell env, and the MCP server
19
- * falls back to ~/.zeph/config.json anyway (an unexpanded "${ZEPH_API_KEY}"
20
- * literal would shadow that fallback with junk). Exported for tests (shape pin).
21
- */
22
- export declare const OPENCODE_MCP_ENTRY: {
23
- type: string;
24
- command: string[];
25
- enabled: boolean;
26
- };
27
15
  /** Add the zeph entry under `key` in an MCP registry JSON file, preserving
28
16
  * everything else in it. Exported for tests (merge semantics). */
29
17
  export declare const injectMcpEntry: (filePath: string, key: string, entry: Record<string, unknown>) => void;
@@ -1 +1 @@
1
- {"version":3,"file":"installer.d.ts","sourceRoot":"","sources":["../src/installer.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AA+BzC;;;GAGG;AACH;;;;GAIG;AACH,eAAO,MAAM,YAAY,GAAI,YAAY,MAAM,GAAG,SAAS,EAAE,SAAS,OAAO,KAAG,OACxD,CAAC;AAoBzB;6EAC6E;AAC7E,eAAO,MAAM,aAAa,GAAI,UAAU,MAAM,EAAE,OAAO,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,IAqBhF,CAAC;AAgDF;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB;;;;CAI9B,CAAC;AAEF;mEACmE;AACnE,eAAO,MAAM,cAAc,GAAI,UAAU,MAAM,EAAE,KAAK,MAAM,EAAE,OAAO,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,IAQ9F,CAAC;AAqPF;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,GAAI,UAAU,KAAK,EAAE,EAAE,MAAM,MAAM,KAAG,KAAK,EAKxE,CAAC;AA8EF;;;;;;;;;GASG;AACH,eAAO,MAAM,oBAAoB,GAC/B,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,EACtC,gBAAgB,OAAO,KACtB,KAAK,GAAG,IAAI,GAAG,KAKjB,CAAC;AAgCF,eAAO,MAAM,aAAa,GAAU,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,KAAG,OAAO,CAAC,MAAM,CAuH1F,CAAC"}
1
+ {"version":3,"file":"installer.d.ts","sourceRoot":"","sources":["../src/installer.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AA+BzC;;;GAGG;AACH;;;;GAIG;AACH,eAAO,MAAM,YAAY,GAAI,YAAY,MAAM,GAAG,SAAS,EAAE,SAAS,OAAO,KAAG,OACxD,CAAC;AAoBzB;6EAC6E;AAC7E,eAAO,MAAM,aAAa,GAAI,UAAU,MAAM,EAAE,OAAO,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,IAqBhF,CAAC;AAsCF;mEACmE;AACnE,eAAO,MAAM,cAAc,GAAI,UAAU,MAAM,EAAE,KAAK,MAAM,EAAE,OAAO,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,IAQ9F,CAAC;AAmPF;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,GAAI,UAAU,KAAK,EAAE,EAAE,MAAM,MAAM,KAAG,KAAK,EAKxE,CAAC;AA8EF;;;;;;;;;GASG;AACH,eAAO,MAAM,oBAAoB,GAC/B,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,EACtC,gBAAgB,OAAO,KACtB,KAAK,GAAG,IAAI,GAAG,KAKjB,CAAC;AAgCF,eAAO,MAAM,aAAa,GAAU,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,KAAG,OAAO,CAAC,MAAM,CAuH1F,CAAC"}
package/dist/installer.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.handleInstall = exports.serviceInstallChoice = exports.filterAgentsByIds = exports.injectMcpEntry = exports.OPENCODE_MCP_ENTRY = exports.mergeJsonFile = exports.shouldReauth = void 0;
3
+ exports.handleInstall = exports.serviceInstallChoice = exports.filterAgentsByIds = exports.injectMcpEntry = exports.mergeJsonFile = exports.shouldReauth = void 0;
4
4
  const child_process_1 = require("child_process");
5
5
  const fs_1 = require("fs");
6
6
  const os_1 = require("os");
@@ -10,6 +10,7 @@ const zeph_hook_js_1 = require("./zeph-hook.js");
10
10
  const config_js_1 = require("./config.js");
11
11
  const login_js_1 = require("./login.js");
12
12
  const agents_js_1 = require("./agents.js");
13
+ const mcp_command_js_1 = require("./mcp-command.js");
13
14
  const listener_service_js_1 = require("./listener-service.js");
14
15
  const templates_js_1 = require("./templates.js");
15
16
  const HOME = (0, os_1.homedir)();
@@ -104,27 +105,6 @@ const addAiderReadDirective = (confPath, conventionsPath) => {
104
105
  (0, fs_1.writeFileSync)(confPath, (base ? `${base}\n\n` : '') + line);
105
106
  };
106
107
  // ── Per-Agent Installers ─────────────────────────────────────────
107
- // Pass through env explicitly so the MCP server doesn't have to rely on
108
- // process-env inheritance (which behaves differently per IDE — Cursor and
109
- // Windsurf spawn the MCP from a graphical context that may not inherit
110
- // shell env). Mirrors plugin/.mcp.json.
111
- const MCP_SERVERS_ENTRY = {
112
- command: 'npx',
113
- args: ['-y', '@zeph-to/mcp-server'],
114
- env: { ZEPH_API_KEY: '${ZEPH_API_KEY}' },
115
- };
116
- /**
117
- * opencode.json's own MCP schema — top-level `mcp` key (not `mcpServers`),
118
- * `command` as ARRAY (binary + args), `type: "local"`. No `environment` —
119
- * opencode is a terminal app that inherits shell env, and the MCP server
120
- * falls back to ~/.zeph/config.json anyway (an unexpanded "${ZEPH_API_KEY}"
121
- * literal would shadow that fallback with junk). Exported for tests (shape pin).
122
- */
123
- exports.OPENCODE_MCP_ENTRY = {
124
- type: 'local',
125
- command: ['npx', '-y', '@zeph-to/mcp-server'],
126
- enabled: true,
127
- };
128
108
  /** Add the zeph entry under `key` in an MCP registry JSON file, preserving
129
109
  * everything else in it. Exported for tests (merge semantics). */
130
110
  const injectMcpEntry = (filePath, key, entry) => {
@@ -153,7 +133,7 @@ const installClaude = () => {
153
133
  };
154
134
  const installCursor = () => {
155
135
  try {
156
- (0, exports.injectMcpEntry)((0, path_1.join)(HOME, '.cursor', 'mcp.json'), 'mcpServers', MCP_SERVERS_ENTRY);
136
+ (0, exports.injectMcpEntry)((0, path_1.join)(HOME, '.cursor', 'mcp.json'), 'mcpServers', mcp_command_js_1.MCP_SERVERS_ENTRY);
157
137
  ok('MCP server added');
158
138
  }
159
139
  catch {
@@ -176,7 +156,7 @@ const installCursor = () => {
176
156
  };
177
157
  const installWindsurf = () => {
178
158
  try {
179
- (0, exports.injectMcpEntry)((0, path_1.join)(HOME, '.codeium', 'windsurf', 'mcp_config.json'), 'mcpServers', MCP_SERVERS_ENTRY);
159
+ (0, exports.injectMcpEntry)((0, path_1.join)(HOME, '.codeium', 'windsurf', 'mcp_config.json'), 'mcpServers', mcp_command_js_1.MCP_SERVERS_ENTRY);
180
160
  ok('MCP server added');
181
161
  }
182
162
  catch {
@@ -201,20 +181,18 @@ const installWindsurf = () => {
201
181
  };
202
182
  const installGemini = () => {
203
183
  try {
204
- // gemini ≥0.26 syntax: `mcp add [-s scope] <name> <command> [args…]`
205
- // the default scope is "project" (cwd-local .gemini/), so pin user
206
- // scope for a machine-wide install. Older gemini CLIs only accept the
207
- // legacy `mcp add zeph -- npx …` form; fall back for those.
208
- (0, child_process_1.execSync)('gemini mcp add -s user zeph npx -- -y @zeph-to/mcp-server', { stdio: 'pipe' });
184
+ // Both forms are built in mcp-command.ts; older gemini CLIs only accept
185
+ // the legacy one, so try the modern form first and fall back.
186
+ (0, child_process_1.execSync)(mcp_command_js_1.GEMINI_MCP_ADD, { stdio: 'pipe' });
209
187
  ok('MCP server added');
210
188
  }
211
189
  catch {
212
190
  try {
213
- (0, child_process_1.execSync)('gemini mcp add zeph -- npx -y @zeph-to/mcp-server', { stdio: 'pipe' });
191
+ (0, child_process_1.execSync)(mcp_command_js_1.GEMINI_MCP_ADD_LEGACY, { stdio: 'pipe' });
214
192
  ok('MCP server added (legacy gemini CLI)');
215
193
  }
216
194
  catch {
217
- fail('MCP add failed. Manual: gemini mcp add -s user zeph npx -- -y @zeph-to/mcp-server');
195
+ fail(`MCP add failed. Manual: ${mcp_command_js_1.GEMINI_MCP_ADD}`);
218
196
  }
219
197
  }
220
198
  try {
@@ -320,7 +298,7 @@ const installPi = () => {
320
298
  };
321
299
  const installOpencode = () => {
322
300
  try {
323
- (0, exports.injectMcpEntry)((0, path_1.join)(HOME, '.config', 'opencode', 'opencode.json'), 'mcp', exports.OPENCODE_MCP_ENTRY);
301
+ (0, exports.injectMcpEntry)((0, path_1.join)(HOME, '.config', 'opencode', 'opencode.json'), 'mcp', mcp_command_js_1.OPENCODE_MCP_ENTRY);
324
302
  ok('MCP server added');
325
303
  }
326
304
  catch {
@@ -14,5 +14,19 @@ export interface InventoryOffload {
14
14
  * run of cycles a stuck worker would otherwise cost: the caller gates sweeps
15
15
  * one-at-a-time, so this bounds how long a hang can hold the inventory. */
16
16
  export declare const COLLECT_TIMEOUT_MS = 20000;
17
- export declare const startInventoryOffload: (inThread: () => CollectResult, log: (msg: string) => void, workerPath?: string) => InventoryOffload;
17
+ /**
18
+ * Consecutive timed-out sweeps before the offload gives up on workers.
19
+ *
20
+ * A sweep that overruns is terminated, and the next one starts a fresh worker
21
+ * from nothing — so on a host where a cold sweep cannot finish inside the
22
+ * timeout, retrying forever means the daemon never reports at all. Reporting
23
+ * slowly beats not reporting, and in-thread is exactly "slowly". Three in a row
24
+ * rather than one, so a single slow moment (a load spike, a machine waking) does
25
+ * not cost the offload for the rest of the daemon's life; the streak resets on
26
+ * any answered sweep.
27
+ */
28
+ export declare const MAX_CONSECUTIVE_TIMEOUTS = 3;
29
+ export declare const startInventoryOffload: (inThread: () => CollectResult, log: (msg: string) => void, workerPath?: string,
30
+ /** Overridable so a test can exercise the timeout path without waiting 20s. */
31
+ timeoutMs?: number) => InventoryOffload;
18
32
  //# sourceMappingURL=inventory-offload.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"inventory-offload.d.ts","sourceRoot":"","sources":["../src/inventory-offload.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEnD,MAAM,WAAW,cAAc;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC7B,kFAAkF;IAClF,OAAO,EAAE,MAAM,OAAO,CAAC,aAAa,CAAC,CAAC;IACtC,oDAAoD;IACpD,KAAK,EAAE,MAAM,IAAI,CAAC;CACrB;AAED;;4EAE4E;AAC5E,eAAO,MAAM,kBAAkB,QAAS,CAAC;AAQzC,eAAO,MAAM,qBAAqB,GAC9B,UAAU,MAAM,aAAa,EAC7B,KAAK,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,EAC1B,aAAY,MAA+C,KAC5D,gBAsFF,CAAC"}
1
+ {"version":3,"file":"inventory-offload.d.ts","sourceRoot":"","sources":["../src/inventory-offload.ts"],"names":[],"mappings":"AA+BA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEnD,MAAM,WAAW,cAAc;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC7B,kFAAkF;IAClF,OAAO,EAAE,MAAM,OAAO,CAAC,aAAa,CAAC,CAAC;IACtC,oDAAoD;IACpD,KAAK,EAAE,MAAM,IAAI,CAAC;CACrB;AAED;;4EAE4E;AAC5E,eAAO,MAAM,kBAAkB,QAAS,CAAC;AAEzC;;;;;;;;;;GAUG;AACH,eAAO,MAAM,wBAAwB,IAAI,CAAC;AAoB1C,eAAO,MAAM,qBAAqB,GAC9B,UAAU,MAAM,aAAa,EAC7B,KAAK,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,EAC1B,aAAY,MAA+C;AAC3D,+EAA+E;AAC/E,YAAW,MAA2B,KACvC,gBAoHF,CAAC"}
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.startInventoryOffload = exports.COLLECT_TIMEOUT_MS = void 0;
3
+ exports.startInventoryOffload = exports.MAX_CONSECUTIVE_TIMEOUTS = exports.COLLECT_TIMEOUT_MS = void 0;
4
4
  /**
5
5
  * Runs the tmux session inventory on a worker thread so the daemon's event
6
6
  * loop stays free while `tmux` child processes are waited on.
@@ -21,6 +21,14 @@ exports.startInventoryOffload = exports.COLLECT_TIMEOUT_MS = void 0;
21
21
  * behaviour instead of an empty session list. A worker that dies after having
22
22
  * worked is treated as transient — that sweep fails (the caller skips the
23
23
  * cycle) and the next `collect()` starts a fresh one.
24
+ *
25
+ * A worker we killed ourselves is neither. `terminate()` (on timeout, on close)
26
+ * exits with code 1, indistinguishable from a crash, so the exit code cannot be
27
+ * read — what separates the two is whether that worker still owed an answer,
28
+ * which is why `Live` carries its own `owed` ids rather than sharing `pending`.
29
+ * Getting this wrong is expensive in one direction only: a timeout misread as
30
+ * "died before ever answering" is permanent, and it fires exactly when the host
31
+ * is slow enough for a sweep to overrun, which is when the offload matters most.
24
32
  */
25
33
  const path_1 = require("path");
26
34
  const worker_threads_1 = require("worker_threads");
@@ -28,7 +36,21 @@ const worker_threads_1 = require("worker_threads");
28
36
  * run of cycles a stuck worker would otherwise cost: the caller gates sweeps
29
37
  * one-at-a-time, so this bounds how long a hang can hold the inventory. */
30
38
  exports.COLLECT_TIMEOUT_MS = 20_000;
31
- const startInventoryOffload = (inThread, log, workerPath = (0, path_1.join)(__dirname, 'inventory-worker.js')) => {
39
+ /**
40
+ * Consecutive timed-out sweeps before the offload gives up on workers.
41
+ *
42
+ * A sweep that overruns is terminated, and the next one starts a fresh worker
43
+ * from nothing — so on a host where a cold sweep cannot finish inside the
44
+ * timeout, retrying forever means the daemon never reports at all. Reporting
45
+ * slowly beats not reporting, and in-thread is exactly "slowly". Three in a row
46
+ * rather than one, so a single slow moment (a load spike, a machine waking) does
47
+ * not cost the offload for the rest of the daemon's life; the streak resets on
48
+ * any answered sweep.
49
+ */
50
+ exports.MAX_CONSECUTIVE_TIMEOUTS = 3;
51
+ const startInventoryOffload = (inThread, log, workerPath = (0, path_1.join)(__dirname, 'inventory-worker.js'),
52
+ /** Overridable so a test can exercise the timeout path without waiting 20s. */
53
+ timeoutMs = exports.COLLECT_TIMEOUT_MS) => {
32
54
  let worker = null;
33
55
  let closed = false;
34
56
  /** Set once a worker has answered; a failure before that is not transient. */
@@ -36,6 +58,8 @@ const startInventoryOffload = (inThread, log, workerPath = (0, path_1.join)(__di
36
58
  /** Set when the worker is given up on — sweeps run in-thread from then on. */
37
59
  let inThreadOnly = false;
38
60
  let nextId = 0;
61
+ /** Timed-out sweeps since the last answered one. */
62
+ let consecutiveTimeouts = 0;
39
63
  const pending = new Map();
40
64
  const settleAll = (outcome) => {
41
65
  for (const [id, p] of pending) {
@@ -65,59 +89,87 @@ const startInventoryOffload = (inThread, log, workerPath = (0, path_1.join)(__di
65
89
  // Never keep the process alive on the worker's account: the daemon's
66
90
  // own socket and timers decide when it exits.
67
91
  w.unref();
92
+ const live = { w, owed: new Set() };
68
93
  w.on('message', (msg) => {
94
+ live.owed.delete(msg.id);
69
95
  const p = pending.get(msg.id);
70
96
  if (!p)
71
97
  return;
72
98
  pending.delete(msg.id);
73
99
  clearTimeout(p.timer);
74
100
  everReplied = true;
101
+ consecutiveTimeouts = 0;
75
102
  if (msg.error !== undefined)
76
103
  p.reject(new Error(msg.error));
77
104
  else
78
105
  p.resolve(msg.result);
79
106
  });
80
107
  w.on('error', (err) => {
81
- if (worker === w)
108
+ if (worker === live)
82
109
  worker = null;
110
+ // Reported here, so the exit that follows is this same death and not
111
+ // a second one. An id leaves `owed` the moment its sweep is settled,
112
+ // whatever settled it — that is the invariant the exit handler reads.
113
+ live.owed.clear();
83
114
  onFailure(`inventory worker error (${err instanceof Error ? err.message : String(err)})`);
84
115
  });
85
116
  w.on('exit', (code) => {
86
- if (worker === w)
117
+ if (worker === live)
87
118
  worker = null;
88
- // A worker we terminated (timeout, close) has already been settled.
89
- if (pending.size > 0)
119
+ // Did THIS worker still owe an answer? `terminate()` exits with code
120
+ // 1 exactly like a crash, so the code says nothing; what separates a
121
+ // death we caused from one we did not is whether the sweep it was
122
+ // holding had already been settled. Asking the shared `pending` map
123
+ // instead judged a terminated worker against the NEXT worker's sweep
124
+ // — the timeout path nulls `worker`, so the following poll spawns a
125
+ // replacement and registers its id a second before this event lands.
126
+ // A routine timeout then read as "died before ever answering", which
127
+ // is permanent: `everReplied` is false, so the offload never
128
+ // recovers for the life of the daemon.
129
+ if (live.owed.size > 0)
90
130
  onFailure(`inventory worker exited (${code})`);
91
131
  });
92
- return w;
132
+ return live;
93
133
  };
94
134
  const collect = () => {
95
135
  if (closed || inThreadOnly)
96
136
  return Promise.resolve(inThread());
97
137
  worker ??= spawn();
98
- const w = worker;
138
+ const live = worker;
99
139
  const id = ++nextId;
100
140
  return new Promise((resolve, reject) => {
101
141
  const timer = setTimeout(() => {
102
142
  pending.delete(id);
103
- reject(new Error(`inventory sweep exceeded ${exports.COLLECT_TIMEOUT_MS / 1000}s`));
143
+ // Settled here, so the terminate below is a death we caused and
144
+ // this worker's exit must not be reported as a failure.
145
+ live.owed.delete(id);
146
+ consecutiveTimeouts += 1;
147
+ if (consecutiveTimeouts >= exports.MAX_CONSECUTIVE_TIMEOUTS && !inThreadOnly) {
148
+ inThreadOnly = true;
149
+ log(`! inventory sweep timed out ${consecutiveTimeouts}× in a row — running the inventory in-thread from now on`);
150
+ }
151
+ reject(new Error(`inventory sweep exceeded ${timeoutMs / 1000}s`));
104
152
  // A stuck worker is not coming back; the next call spawns a fresh one.
105
- if (worker === w)
153
+ if (worker === live)
106
154
  worker = null;
107
- void w.terminate();
108
- }, exports.COLLECT_TIMEOUT_MS);
155
+ void live.w.terminate();
156
+ }, timeoutMs);
109
157
  timer.unref();
110
158
  pending.set(id, { resolve, reject, timer });
111
- w.postMessage(id);
159
+ live.owed.add(id);
160
+ live.w.postMessage(id);
112
161
  });
113
162
  };
114
163
  const close = () => {
115
164
  closed = true;
116
165
  settleAll((p) => p.reject(new Error('inventory offload closed')));
117
- const w = worker;
166
+ const live = worker;
118
167
  worker = null;
119
- if (w)
120
- void w.terminate();
168
+ if (!live)
169
+ return;
170
+ // Settled above; clear what it owed for the same reason the timeout does.
171
+ live.owed.clear();
172
+ void live.w.terminate();
121
173
  };
122
174
  return { collect, close };
123
175
  };
@@ -694,6 +694,7 @@ export declare const collectSessionsVerbose: () => CollectResult;
694
694
  export declare const recordInventory: (sessions: ReadonlyArray<{
695
695
  name: string;
696
696
  }> | null) => void;
697
+ export declare const syncTmuxAgentNames: (sessions: ReadonlyArray<AgentSession>) => void;
697
698
  /**
698
699
  * Is this session in the inventory? Answered from the last sweep when it can
699
700
  * be: a full sweep is two tmux spawns per session on this thread, and it used
@@ -1 +1 @@
1
- {"version":3,"file":"listener.d.ts","sourceRoot":"","sources":["../src/listener.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"listener.d.ts","sourceRoot":"","sources":["../src/listener.ts"],"names":[],"mappings":"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"}
package/dist/listener.js CHANGED
@@ -26,7 +26,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
26
26
  };
27
27
  Object.defineProperty(exports, "__esModule", { value: true });
28
28
  exports.MAX_INPUT_BODY_CHARS = exports.MAX_INPUT_KEYS = exports.handleStreamControl = exports.buildStreamFrame = exports.isStreamCapReached = exports.stopAllStreams = exports.stopStream = exports.MAX_CONCURRENT_STREAMS = exports.STREAM_RENEW_FRESH_MS = exports.STREAM_LEASE_MS = exports.claimFrameSend = exports.hasFrameBudget = exports.streamCadence = exports.MAX_FRAMES_PER_SEC = exports.BURST_WINDOW_MS = exports.BURST_INTERVAL_MS = exports.STREAM_INTERVAL_MS = exports.STREAM_CAPTURE_LINES = exports.scheduleInjectSnapshots = exports.historyLinesIn = exports.cursorLineFor = exports.parsePaneGeometry = exports.handleScreenHistoryRequest = exports.SCREEN_HISTORY_MAX_LINES = exports.handleSessionForgetRequest = exports.handleSessionExitRequest = exports.SESSION_EXIT_STEP_MS = exports.handleSessionResumeRequest = exports.handleDiffFileRequest = exports.handleDiffFilesRequest = exports.DIFF_PAGE_MAX_BYTES = exports.handleScreenRequest = exports.collectWatchHits = exports.resetPatternWatches = exports.setPatternWatches = exports.deriveSessionState = exports.resetSessionStates = exports.detectRemoteAgent = exports.parseSessionName = exports.invalidateTmuxSocketCache = exports.resolveKeys = exports.paneCurrentCommand = exports.checkRateLimit = exports.AUTH_FAILURE_CODES = exports.sessionsReportDue = exports.sessionsFingerprint = exports.knownSessionsFingerprint = exports.knownSessionsToReport = exports.KNOWN_SESSIONS_REPORTED = exports.SESSION_REPORT_HEARTBEAT_MS = void 0;
29
- exports.handleListener = exports.resolveWsUrl = exports.computeListenerDeviceId = exports.computeBackoff = exports.handlePush = exports.gcAttachments = exports.setAttachmentContext = exports.writeRemoteMarker = exports.isInventoried = exports.recordInventory = exports.collectSessionsVerbose = exports.handleCommandInput = exports.pendingInputDecrypts = exports.MAX_PENDING_DECRYPTS = exports.MAX_INPUT_LANES = exports.validateInputMessage = void 0;
29
+ exports.handleListener = exports.resolveWsUrl = exports.computeListenerDeviceId = exports.computeBackoff = exports.handlePush = exports.gcAttachments = exports.setAttachmentContext = exports.writeRemoteMarker = exports.isInventoried = exports.syncTmuxAgentNames = exports.recordInventory = exports.collectSessionsVerbose = exports.handleCommandInput = exports.pendingInputDecrypts = exports.MAX_PENDING_DECRYPTS = exports.MAX_INPUT_LANES = exports.validateInputMessage = void 0;
30
30
  const child_process_1 = require("child_process");
31
31
  const crypto_1 = require("crypto");
32
32
  const fs_1 = require("fs");
@@ -2495,6 +2495,63 @@ exports.recordInventory = recordInventory;
2495
2495
  /** The daemon's sweep runner, set for the lifetime of `handleListener`. Null
2496
2496
  * outside the daemon (tests, one-shot commands) — sweeps then run in-thread. */
2497
2497
  let inventoryOffload = null;
2498
+ /**
2499
+ * Mirror each session's provider name onto the tmux session itself, as the
2500
+ * user option `@zeph_agent_name`.
2501
+ *
2502
+ * Why: the phone shows what the agent calls this session (`zeph-to-d0`) while
2503
+ * the user's own status bar shows the tmux name (`zeph-zeph-to-3`), and the
2504
+ * two never agree. The phone's render precedence is already decided
2505
+ * (`alias ?? "<providerSessionName> · <Agent>" ?? computed label`, see the
2506
+ * `agentSessionAliases` comment in zeph `libs/shared/src/types/device.ts`);
2507
+ * this puts the same middle tier where a tmux config can read it:
2508
+ *
2509
+ * #{?@zeph_agent_name,#{@zeph_agent_name},#S}
2510
+ *
2511
+ * A tmux option rather than a `#()` in the status line on purpose. The status
2512
+ * line re-renders per attached client on every status-interval, so a shell
2513
+ * there would walk a process tree several times a second across every session;
2514
+ * an option is written only when the name actually changes and costs the
2515
+ * renderer nothing.
2516
+ *
2517
+ * The tmux name is NOT renamed and must not be: it is the addressing key the
2518
+ * phone injects against, it has to exist before the agent it names does, and
2519
+ * the agent's own name rotates on resume. Display and address stay separate —
2520
+ * this only makes the display agree with the phone.
2521
+ *
2522
+ * Keyed by name AND `createdAt`, mirroring the alias anchor in zeph
2523
+ * `apps/server/src/lib/agent-session-alias.ts`: a tmux name is a slot, so the
2524
+ * cache must not let a new occupant inherit the previous one's write. tmux
2525
+ * drops session options with the session, so this is the belt to that braces —
2526
+ * what it actually prevents is the *skip*, where an unchanged key would leave
2527
+ * the new session with no write at all.
2528
+ */
2529
+ const publishedTmuxNames = new Map();
2530
+ const syncTmuxAgentNames = (sessions) => {
2531
+ const liveKeys = new Set();
2532
+ for (const s of sessions) {
2533
+ const key = `${s.name}\u241f${s.createdAt ?? ''}`;
2534
+ liveKeys.add(key);
2535
+ const value = s.providerSessionName ?? '';
2536
+ if (publishedTmuxNames.get(key) === value)
2537
+ continue;
2538
+ // No name to show → unset, so the format falls through to `#S` and no
2539
+ // stale value is left on a session whose agent stopped reporting one.
2540
+ const args = value
2541
+ ? ['set-option', '-t', s.name, '@zeph_agent_name', value]
2542
+ : ['set-option', '-u', '-t', s.name, '@zeph_agent_name'];
2543
+ const r = (0, child_process_1.spawnSync)('tmux', tmuxArgs(args), { stdio: ['ignore', 'ignore', 'ignore'] });
2544
+ // Only remember a write that landed; a failed one must be retried next
2545
+ // sweep rather than cached as done.
2546
+ if (r.status === 0)
2547
+ publishedTmuxNames.set(key, value);
2548
+ }
2549
+ for (const key of [...publishedTmuxNames.keys()]) {
2550
+ if (!liveKeys.has(key))
2551
+ publishedTmuxNames.delete(key);
2552
+ }
2553
+ };
2554
+ exports.syncTmuxAgentNames = syncTmuxAgentNames;
2498
2555
  /**
2499
2556
  * Is this session in the inventory? Answered from the last sweep when it can
2500
2557
  * be: a full sweep is two tmux spawns per session on this thread, and it used
@@ -2971,6 +3028,9 @@ const streamSession = (wsUrl, apiKey) => {
2971
3028
  };
2972
3029
  const publishSessions = ({ sessions, rejected }) => {
2973
3030
  (0, exports.recordInventory)(sessions);
3031
+ // Let the user's own status bar say what the phone says. Change-gated
3032
+ // internally, so an unchanged sweep spawns nothing.
3033
+ (0, exports.syncTmuxAgentNames)(sessions);
2974
3034
  // Watch hits are one-shot events — they go out on every poll,
2975
3035
  // independent of the sessions-report gate below.
2976
3036
  // (§S5 v2): probe watched panes and report hits; the server
@@ -0,0 +1,45 @@
1
+ /**
2
+ * How every agent launches the Zeph MCP server — one source, three schemas.
3
+ *
4
+ * Registrations used to say `npx -y @zeph-to/mcp-server`, which left an
5
+ * `npm exec` launcher resident beside the server for the life of the session.
6
+ * `zeph mcp` (see mcp.ts) runs the server in the CLI's own process instead.
7
+ *
8
+ * Cursor/Windsurf, Gemini and OpenCode each want that launch in a different
9
+ * shape, and the shapes drifted apart when each site spelled the command out
10
+ * itself. Everything below is derived from MCP_LAUNCH_ARGV.
11
+ */
12
+ /** What the agents run. `zeph` resolves out of the same global bin dir as `npx`. */
13
+ export declare const MCP_LAUNCH_ARGV: readonly ["zeph", "mcp"];
14
+ /**
15
+ * `mcpServers.zeph` — what the installer writes for Cursor and Windsurf.
16
+ * The env block is deliberate: both spawn the MCP server from a graphical
17
+ * context that may not inherit shell env, so the key is passed through
18
+ * explicitly rather than left to inheritance.
19
+ *
20
+ * `zeph-to/plugin`'s `.mcp.json` holds the same shape but is a HAND-KEPT COPY —
21
+ * it lives in another repo and cannot import this. Change one, change both.
22
+ */
23
+ export declare const MCP_SERVERS_ENTRY: {
24
+ command: "zeph";
25
+ args: "mcp"[];
26
+ env: {
27
+ ZEPH_API_KEY: string;
28
+ };
29
+ };
30
+ /**
31
+ * opencode.json's own MCP schema — top-level `mcp` key (not `mcpServers`),
32
+ * `command` as ARRAY (binary + args), `type: "local"`. No `environment` —
33
+ * opencode is a terminal app that inherits shell env, and the MCP server
34
+ * falls back to ~/.zeph/config.json anyway (an unexpanded "${ZEPH_API_KEY}"
35
+ * literal would shadow that fallback with junk).
36
+ */
37
+ export declare const OPENCODE_MCP_ENTRY: {
38
+ type: string;
39
+ command: ("zeph" | "mcp")[];
40
+ enabled: boolean;
41
+ };
42
+ export declare const GEMINI_MCP_ADD: string;
43
+ /** Older gemini CLIs only accept `mcp add <name> -- <command…>`, with no scope flag. */
44
+ export declare const GEMINI_MCP_ADD_LEGACY: string;
45
+ //# sourceMappingURL=mcp-command.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-command.d.ts","sourceRoot":"","sources":["../src/mcp-command.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,oFAAoF;AACpF,eAAO,MAAM,eAAe,0BAA2B,CAAC;AAIxD;;;;;;;;GAQG;AACH,eAAO,MAAM,iBAAiB;;;;;;CAI7B,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB;;;;CAI9B,CAAC;AAMF,eAAO,MAAM,cAAc,QAA0E,CAAC;AAEtG,wFAAwF;AACxF,eAAO,MAAM,qBAAqB,QAAwD,CAAC"}
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ /**
3
+ * How every agent launches the Zeph MCP server — one source, three schemas.
4
+ *
5
+ * Registrations used to say `npx -y @zeph-to/mcp-server`, which left an
6
+ * `npm exec` launcher resident beside the server for the life of the session.
7
+ * `zeph mcp` (see mcp.ts) runs the server in the CLI's own process instead.
8
+ *
9
+ * Cursor/Windsurf, Gemini and OpenCode each want that launch in a different
10
+ * shape, and the shapes drifted apart when each site spelled the command out
11
+ * itself. Everything below is derived from MCP_LAUNCH_ARGV.
12
+ */
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.GEMINI_MCP_ADD_LEGACY = exports.GEMINI_MCP_ADD = exports.OPENCODE_MCP_ENTRY = exports.MCP_SERVERS_ENTRY = exports.MCP_LAUNCH_ARGV = void 0;
15
+ /** What the agents run. `zeph` resolves out of the same global bin dir as `npx`. */
16
+ exports.MCP_LAUNCH_ARGV = ['zeph', 'mcp'];
17
+ const [MCP_BIN, ...MCP_SUBCOMMAND] = exports.MCP_LAUNCH_ARGV;
18
+ /**
19
+ * `mcpServers.zeph` — what the installer writes for Cursor and Windsurf.
20
+ * The env block is deliberate: both spawn the MCP server from a graphical
21
+ * context that may not inherit shell env, so the key is passed through
22
+ * explicitly rather than left to inheritance.
23
+ *
24
+ * `zeph-to/plugin`'s `.mcp.json` holds the same shape but is a HAND-KEPT COPY —
25
+ * it lives in another repo and cannot import this. Change one, change both.
26
+ */
27
+ exports.MCP_SERVERS_ENTRY = {
28
+ command: MCP_BIN,
29
+ args: [...MCP_SUBCOMMAND],
30
+ env: { ZEPH_API_KEY: '${ZEPH_API_KEY}' },
31
+ };
32
+ /**
33
+ * opencode.json's own MCP schema — top-level `mcp` key (not `mcpServers`),
34
+ * `command` as ARRAY (binary + args), `type: "local"`. No `environment` —
35
+ * opencode is a terminal app that inherits shell env, and the MCP server
36
+ * falls back to ~/.zeph/config.json anyway (an unexpanded "${ZEPH_API_KEY}"
37
+ * literal would shadow that fallback with junk).
38
+ */
39
+ exports.OPENCODE_MCP_ENTRY = {
40
+ type: 'local',
41
+ command: [...exports.MCP_LAUNCH_ARGV],
42
+ enabled: true,
43
+ };
44
+ // gemini ≥0.26 syntax: `mcp add [-s scope] <name> <command> [args…]`. The
45
+ // server NAME and the BINARY are both "zeph" here, so the doubled word below
46
+ // is correct, not a copy-paste slip. Default scope is "project" (cwd-local
47
+ // .gemini/), so user scope is pinned for a machine-wide install.
48
+ exports.GEMINI_MCP_ADD = `gemini mcp add -s user zeph ${MCP_BIN} -- ${MCP_SUBCOMMAND.join(' ')}`;
49
+ /** Older gemini CLIs only accept `mcp add <name> -- <command…>`, with no scope flag. */
50
+ exports.GEMINI_MCP_ADD_LEGACY = `gemini mcp add zeph -- ${exports.MCP_LAUNCH_ARGV.join(' ')}`;
package/dist/mcp.d.ts ADDED
@@ -0,0 +1,19 @@
1
+ /**
2
+ * `zeph mcp` — run the Zeph MCP server inside THIS process.
3
+ *
4
+ * Every registration used to say `npx -y @zeph-to/mcp-server`, which left an
5
+ * `npm exec` launcher resident for the whole session on top of the server it
6
+ * spawned — two node processes where one does the work. `@zeph-to/mcp-server`
7
+ * is a dependency of this package now, so agents register `zeph mcp` and get
8
+ * exactly one process.
9
+ */
10
+ /**
11
+ * Importing `@zeph-to/mcp-server` IS starting it: the package is a bin entry
12
+ * whose module body wires an McpServer to a StdioServerTransport and exports
13
+ * nothing. Verified against 2.3.0 (`dist/index.js` ends in `main().catch(…)`).
14
+ * Injectable so tests don't need the real package resolvable.
15
+ */
16
+ type McpServerLoader = () => Promise<unknown>;
17
+ export declare const handleMcp: (load?: McpServerLoader) => Promise<number>;
18
+ export {};
19
+ //# sourceMappingURL=mcp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../src/mcp.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH;;;;;GAKG;AACH,KAAK,eAAe,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;AAI9C,eAAO,MAAM,SAAS,GAAU,OAAM,eAAiC,KAAG,OAAO,CAAC,MAAM,CAcvF,CAAC"}
package/dist/mcp.js ADDED
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ /**
3
+ * `zeph mcp` — run the Zeph MCP server inside THIS process.
4
+ *
5
+ * Every registration used to say `npx -y @zeph-to/mcp-server`, which left an
6
+ * `npm exec` launcher resident for the whole session on top of the server it
7
+ * spawned — two node processes where one does the work. `@zeph-to/mcp-server`
8
+ * is a dependency of this package now, so agents register `zeph mcp` and get
9
+ * exactly one process.
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.handleMcp = void 0;
13
+ const importMcpServer = () => import('@zeph-to/mcp-server');
14
+ const handleMcp = async (load = importMcpServer) => {
15
+ try {
16
+ await load();
17
+ }
18
+ catch (err) {
19
+ const reason = err instanceof Error ? err.message : String(err);
20
+ console.error(`zeph: could not start the MCP server (@zeph-to/mcp-server): ${reason}`);
21
+ console.error('zeph: reinstall the CLI with `npm i -g @zeph-to/cli`.');
22
+ return 1;
23
+ }
24
+ // The server owns this process from here: it holds stdio open and decides
25
+ // when to exit. Resolving would hand cli.ts a code for `process.exit()`,
26
+ // killing the server the line above just started.
27
+ return new Promise(() => { });
28
+ };
29
+ exports.handleMcp = handleMcp;
package/dist/verify.d.ts CHANGED
@@ -1,2 +1,36 @@
1
+ /**
2
+ * The launch argv a registry file records for zeph, verbatim — null when the
3
+ * file is absent, unparseable, or has no zeph entry. Two schemas in the wild:
4
+ * `command` + `args` (Cursor/Windsurf/Gemini) and `command` as a whole array
5
+ * (opencode). Returned as-is on purpose: a stale entry is only detectable if
6
+ * the reader does not normalize it into the shape it expects.
7
+ */
8
+ export declare const registeredMcpArgv: (filePath: string, key: string) => string[] | null;
9
+ /**
10
+ * Can this launch binary actually be run? Registered commands come out of a
11
+ * config file, so they can be an absolute path with spaces in it — the shared
12
+ * `hasCommand` interpolates into `which ${cmd}`, where such a path splits into
13
+ * two words and reports a perfectly good binary as missing (and where any `;`
14
+ * in the file would reach the shell). Nothing here touches a shell.
15
+ */
16
+ export declare const binaryResolves: (bin: string) => boolean;
17
+ /**
18
+ * What a recorded registration is worth right now. `unresolvable` outranks
19
+ * `stale`: a stale entry still starts a server (through the npm launcher this
20
+ * release exists to delete), an unresolvable one starts nothing at all and
21
+ * takes the agent's whole zeph toolset down with it, silently — the config is
22
+ * read once at install time and never checked again.
23
+ */
24
+ export type McpRegistration = {
25
+ readonly state: 'current';
26
+ } | {
27
+ readonly state: 'stale';
28
+ readonly argv: string[];
29
+ } | {
30
+ readonly state: 'unresolvable';
31
+ readonly argv: string[];
32
+ };
33
+ /** null = this agent has no zeph registration at all, so there is nothing to report. */
34
+ export declare const classifyMcpRegistration: (argv: string[] | null, isOnPath: (bin: string) => boolean) => McpRegistration | null;
1
35
  export declare const handleVerify: (args: Record<string, string | boolean>) => Promise<number>;
2
36
  //# sourceMappingURL=verify.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../src/verify.ts"],"names":[],"mappings":"AA4CA,eAAO,MAAM,YAAY,GAAU,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,KAAG,OAAO,CAAC,MAAM,CAiFzF,CAAC"}
1
+ {"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../src/verify.ts"],"names":[],"mappings":"AA6DA;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,GAAI,UAAU,MAAM,EAAE,KAAK,MAAM,KAAG,MAAM,EAAE,GAAG,IAa5E,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,cAAc,GAAI,KAAK,MAAM,KAAG,OAQ5C,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,MAAM,eAAe,GACrB;IAAE,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAA;CAAE,GAC7B;IAAE,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,GACpD;IAAE,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC;AAElE,wFAAwF;AACxF,eAAO,MAAM,uBAAuB,GAChC,MAAM,MAAM,EAAE,GAAG,IAAI,EACrB,UAAU,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,KACnC,eAAe,GAAG,IAMpB,CAAC;AAYF,eAAO,MAAM,YAAY,GAAU,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,KAAG,OAAO,CAAC,MAAM,CA+GzF,CAAC"}
package/dist/verify.js CHANGED
@@ -1,13 +1,15 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.handleVerify = void 0;
3
+ exports.handleVerify = exports.classifyMcpRegistration = exports.binaryResolves = exports.registeredMcpArgv = void 0;
4
4
  const fs_1 = require("fs");
5
5
  const os_1 = require("os");
6
6
  const path_1 = require("path");
7
+ const child_process_1 = require("child_process");
7
8
  const agents_js_1 = require("./agents.js");
8
9
  const config_js_1 = require("./config.js");
9
10
  const listener_service_js_1 = require("./listener-service.js");
10
11
  const zeph_hook_js_1 = require("./zeph-hook.js");
12
+ const mcp_command_js_1 = require("./mcp-command.js");
11
13
  const HOME = (0, os_1.homedir)();
12
14
  const pass = (msg) => console.log(` ✓ ${msg}`);
13
15
  const warn = (msg) => console.log(` ! ${msg}`);
@@ -41,6 +43,83 @@ const AGENT_RULE_PRESENT = {
41
43
  pi: () => hasManagedBlock((0, path_1.join)(HOME, '.pi', 'agent', 'AGENTS.md')),
42
44
  opencode: () => hasManagedBlock((0, path_1.join)(HOME, '.config', 'opencode', 'AGENTS.md')),
43
45
  };
46
+ /**
47
+ * Where each agent records the MCP launch, and under which container key.
48
+ * `agent` matches the label `detectAgents` uses so one report never names the
49
+ * same agent two ways. Cursor/Windsurf/OpenCode are files the installer writes
50
+ * itself; the Gemini row is READ-ONLY — `zeph install` shells out to
51
+ * `gemini mcp add`, so this path is the gemini CLI's own storage layout,
52
+ * confirmed by reading the file it produced, not something Zeph chose.
53
+ */
54
+ const MCP_REGISTRIES = [
55
+ { agent: 'Cursor', path: (0, path_1.join)(HOME, '.cursor', 'mcp.json'), key: 'mcpServers' },
56
+ { agent: 'Windsurf', path: (0, path_1.join)(HOME, '.codeium', 'windsurf', 'mcp_config.json'), key: 'mcpServers' },
57
+ { agent: 'Gemini CLI', path: (0, path_1.join)(HOME, '.gemini', 'settings.json'), key: 'mcpServers' },
58
+ { agent: 'OpenCode', path: (0, path_1.join)(HOME, '.config', 'opencode', 'opencode.json'), key: 'mcp' },
59
+ ];
60
+ /**
61
+ * The launch argv a registry file records for zeph, verbatim — null when the
62
+ * file is absent, unparseable, or has no zeph entry. Two schemas in the wild:
63
+ * `command` + `args` (Cursor/Windsurf/Gemini) and `command` as a whole array
64
+ * (opencode). Returned as-is on purpose: a stale entry is only detectable if
65
+ * the reader does not normalize it into the shape it expects.
66
+ */
67
+ const registeredMcpArgv = (filePath, key) => {
68
+ let data;
69
+ try {
70
+ data = JSON.parse((0, fs_1.readFileSync)(filePath, 'utf-8'));
71
+ }
72
+ catch {
73
+ return null;
74
+ }
75
+ const container = data[key];
76
+ const entry = container?.zeph;
77
+ if (!entry)
78
+ return null;
79
+ if (Array.isArray(entry.command))
80
+ return entry.command.map(String);
81
+ if (typeof entry.command !== 'string')
82
+ return null;
83
+ return [entry.command, ...(Array.isArray(entry.args) ? entry.args.map(String) : [])];
84
+ };
85
+ exports.registeredMcpArgv = registeredMcpArgv;
86
+ /**
87
+ * Can this launch binary actually be run? Registered commands come out of a
88
+ * config file, so they can be an absolute path with spaces in it — the shared
89
+ * `hasCommand` interpolates into `which ${cmd}`, where such a path splits into
90
+ * two words and reports a perfectly good binary as missing (and where any `;`
91
+ * in the file would reach the shell). Nothing here touches a shell.
92
+ */
93
+ const binaryResolves = (bin) => {
94
+ try {
95
+ if (bin.includes('/'))
96
+ (0, fs_1.accessSync)(bin, fs_1.constants.X_OK);
97
+ else
98
+ (0, child_process_1.execFileSync)('which', [bin], { stdio: 'pipe' });
99
+ return true;
100
+ }
101
+ catch {
102
+ return false;
103
+ }
104
+ };
105
+ exports.binaryResolves = binaryResolves;
106
+ /** null = this agent has no zeph registration at all, so there is nothing to report. */
107
+ const classifyMcpRegistration = (argv, isOnPath) => {
108
+ if (!argv || argv.length === 0)
109
+ return null;
110
+ if (!isOnPath(argv[0]))
111
+ return { state: 'unresolvable', argv };
112
+ const isCanonical = argv.length === mcp_command_js_1.MCP_LAUNCH_ARGV.length
113
+ && argv.every((token, i) => token === mcp_command_js_1.MCP_LAUNCH_ARGV[i]);
114
+ return isCanonical ? { state: 'current' } : { state: 'stale', argv };
115
+ };
116
+ exports.classifyMcpRegistration = classifyMcpRegistration;
117
+ /** The registries that actually hold a zeph entry, classified. Agents that were
118
+ * never installed drop out here so the report has no row for them. */
119
+ const activeMcpRegistrations = (isOnPath) => MCP_REGISTRIES.flatMap((registry) => {
120
+ const result = (0, exports.classifyMcpRegistration)((0, exports.registeredMcpArgv)(registry.path, registry.key), isOnPath);
121
+ return result ? [{ agent: registry.agent, result }] : [];
122
+ });
44
123
  const handleVerify = async (args) => {
45
124
  const doPing = args.ping === true;
46
125
  const checks = [];
@@ -64,12 +143,28 @@ const handleVerify = async (args) => {
64
143
  ? 'ZEPH_HOOK_ID is set (two-way zeph_ask/prompt/input enabled)'
65
144
  : 'ZEPH_HOOK_ID not set (notify-only — set it for remote control)', hookId ? 'pass' : 'warn');
66
145
  // ── Runtime ──────────────────────────────────────────────────
146
+ // One resolution per binary: `zeph` alone was being looked up five times
147
+ // (twice here, once per registry below), and each lookup is a spawn.
148
+ const resolved = new Map();
149
+ const resolves = (bin) => {
150
+ const cached = resolved.get(bin);
151
+ if (cached !== undefined)
152
+ return cached;
153
+ const found = (0, exports.binaryResolves)(bin);
154
+ resolved.set(bin, found);
155
+ return found;
156
+ };
67
157
  console.log('\n Runtime:');
68
- record((0, agents_js_1.hasCommand)('node') ? 'node available' : 'node not found', (0, agents_js_1.hasCommand)('node') ? 'pass' : 'fail');
69
- record((0, agents_js_1.hasCommand)('npx') ? 'npx available (MCP server runs via npx)' : 'npx not found', (0, agents_js_1.hasCommand)('npx') ? 'pass' : 'fail');
70
- record((0, agents_js_1.hasCommand)('zeph')
71
- ? 'zeph CLI on PATH'
72
- : 'zeph CLI not on PATH (hooks fall back to npx slower first call)', (0, agents_js_1.hasCommand)('zeph') ? 'pass' : 'warn');
158
+ const hasNode = resolves('node');
159
+ const hasNpx = resolves('npx');
160
+ const hasZeph = resolves('zeph');
161
+ record(hasNode ? 'node available' : 'node not found', hasNode ? 'pass' : 'fail');
162
+ record(hasNpx ? 'npx available (hook fallback when zeph is off PATH)' : 'npx not found', hasNpx ? 'pass' : 'warn');
163
+ // Not a warning any more: `zeph mcp` IS the MCP server, so a zeph that
164
+ // isn't on PATH means no MCP tools at all, not just a slower first call.
165
+ record(hasZeph
166
+ ? 'zeph CLI on PATH (runs the MCP server and the hooks)'
167
+ : 'zeph CLI not on PATH — MCP tools will not start. Reinstall: npm i -g @zeph-to/cli', hasZeph ? 'pass' : 'fail');
73
168
  // ── Login-time service ───────────────────────────────────────
74
169
  // Optional, so a missing one is a warning. A broken one is not: every way
75
170
  // it breaks still looks installed from the outside.
@@ -79,6 +174,21 @@ const handleVerify = async (args) => {
79
174
  for (const row of serviceRows)
80
175
  record(row.label, row.state);
81
176
  }
177
+ // ── MCP registrations ────────────────────────────────────────
178
+ const registrations = activeMcpRegistrations(resolves);
179
+ if (registrations.length > 0) {
180
+ console.log('\n MCP registrations:');
181
+ for (const { agent, result } of registrations) {
182
+ if (result.state === 'current')
183
+ record(`${agent}: launches \`${mcp_command_js_1.MCP_LAUNCH_ARGV.join(' ')}\``, 'pass');
184
+ else if (result.state === 'stale') {
185
+ record(`${agent}: still launches \`${result.argv.join(' ')}\` — one extra resident process per session. Re-run: zeph install`, 'warn');
186
+ }
187
+ else {
188
+ record(`${agent}: launches \`${result.argv[0]}\`, which is not on PATH — zeph tools will not load. Re-run: zeph install`, 'fail');
189
+ }
190
+ }
191
+ }
82
192
  // ── Per-agent config ─────────────────────────────────────────
83
193
  console.log('\n Agents:');
84
194
  const detected = (0, agents_js_1.detectAgents)().filter((a) => a.detected);
package/dist/wrapper.d.ts CHANGED
@@ -6,15 +6,25 @@ export declare const tmuxSessionName: (project: string) => string;
6
6
  /**
7
7
  * Pick a tmux session name that won't steal focus from another live
8
8
  * `zeph cc`. Strategy:
9
- * - If `<base>` doesn't exist use it (create new).
10
- * - If `<base>` exists but is detached use it (reattach).
11
- * - If `<base>` exists *and* has a client attached → try `<base>-2`,
12
- * `<base>-3`, … so the new `zeph cc` gets an independent session
13
- * instead of joining the existing one.
14
- * Falls back to `<base>` after 20 attempts (shouldn't realistically hit).
9
+ * - Reuse the **highest-numbered detached** session in the family.
10
+ * - Otherwise take the lowest name that doesn't exist yet (create new),
11
+ * so an all-attached family gets an independent `<base>-N`.
15
12
  *
16
- * Detection uses `tmux has-session` and `tmux list-clients`; both are
17
- * dependency-free against the user's running tmux server.
13
+ * Highest-detached rather than lowest is what keeps the family reachable.
14
+ * The old scan walked the family in order and returned the first session that
15
+ * was missing *or* detached, which meant a detached `<base>` ended the scan
16
+ * every time: `<base>-2` could not be reached by any later `zeph cc`, not even
17
+ * after `<base>` was used and exited (a missing `<base>` is taken fresh). A
18
+ * session nobody can reach still holds a live agent — a Claude Code CLI plus
19
+ * its MCP fleet, 250-550MB measured — so stranding one leaks memory the user
20
+ * can neither see nor reclaim. Draining from the tail makes every suffix
21
+ * reachable again: the tail goes first, and `<base>` is picked on the run
22
+ * after that. Reuse also wins over a gap in the numbering, for the same
23
+ * reason — a free `<base>-2` must not hide a detached `<base>-3`.
24
+ *
25
+ * Reclaiming is deliberately all this does. Killing a detached session would
26
+ * take a live agent with it, and nothing here can tell "the user is done with
27
+ * this" from "the user closed the terminal and will come back".
18
28
  */
19
29
  export declare const findAvailableSession: (base: string) => string;
20
30
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"wrapper.d.ts","sourceRoot":"","sources":["../src/wrapper.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAOtD,kFAAkF;AAClF,eAAO,MAAM,iBAAiB,QAAO,MAapC,CAAC;AAEF,+DAA+D;AAC/D,eAAO,MAAM,eAAe,GAAI,SAAS,MAAM,KAAG,MAA2B,CAAC;AAI9E;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,oBAAoB,GAAI,MAAM,MAAM,KAAG,MAenD,CAAC;AAmCF;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,sBAAsB,GAAI,SAAS,MAAM,GAAG,IAAI,EAAE,WAAW,MAAM,KAAG,OAChC,CAAC;AAEpD;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,QAAa,OAAO,CAAC,IAAI,CAgC1D,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,GAAU,OAAO,WAAW,EAAE,QAAO,MAAM,EAAO,KAAG,OAAO,CAAC,MAAM,CAmCjG,CAAC"}
1
+ {"version":3,"file":"wrapper.d.ts","sourceRoot":"","sources":["../src/wrapper.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAOtD,kFAAkF;AAClF,eAAO,MAAM,iBAAiB,QAAO,MAapC,CAAC;AAEF,+DAA+D;AAC/D,eAAO,MAAM,eAAe,GAAI,SAAS,MAAM,KAAG,MAA2B,CAAC;AAkC9E;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,oBAAoB,GAAI,MAAM,MAAM,KAAG,MAOnD,CAAC;AAmCF;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,sBAAsB,GAAI,SAAS,MAAM,GAAG,IAAI,EAAE,WAAW,MAAM,KAAG,OAChC,CAAC;AAEpD;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,QAAa,OAAO,CAAC,IAAI,CAgC1D,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,GAAU,OAAO,WAAW,EAAE,QAAO,MAAM,EAAO,KAAG,OAAO,CAAC,MAAM,CAmCjG,CAAC"}
package/dist/wrapper.js CHANGED
@@ -43,37 +43,67 @@ exports.detectProjectName = detectProjectName;
43
43
  /** `zeph-<project>` — the canonical tmux session base name. */
44
44
  const tmuxSessionName = (project) => `zeph-${project}`;
45
45
  exports.tmuxSessionName = tmuxSessionName;
46
+ /**
47
+ * Every live tmux session as `name → attached`, in one spawn.
48
+ *
49
+ * `tmux list-sessions` exits non-zero when no server is running; that is the
50
+ * ordinary "first `zeph cc` after a reboot" case, not an error, and it means
51
+ * an empty family.
52
+ *
53
+ * The format puts the 0/1 flag first so the name — which carries whatever the
54
+ * project directory was called, spaces included — is everything after the
55
+ * first space and needs no quoting.
56
+ */
57
+ const liveSessions = () => {
58
+ const r = (0, child_process_1.spawnSync)('tmux', ['list-sessions', '-F', '#{session_attached} #{session_name}'], {
59
+ encoding: 'utf-8',
60
+ stdio: ['ignore', 'pipe', 'ignore'],
61
+ });
62
+ const out = new Map();
63
+ if (r.status !== 0)
64
+ return out;
65
+ for (const line of (r.stdout ?? '').split('\n')) {
66
+ const sep = line.indexOf(' ');
67
+ if (sep < 0)
68
+ continue;
69
+ out.set(line.slice(sep + 1), line.slice(0, sep) === '1');
70
+ }
71
+ return out;
72
+ };
46
73
  const MAX_SUFFIX_ATTEMPTS = 20;
74
+ /** `<base>`, `<base>-2`, `<base>-3`, … — the session family for one project. */
75
+ const familyNames = (base) => Array.from({ length: MAX_SUFFIX_ATTEMPTS }, (_, i) => (i === 0 ? base : `${base}-${i + 1}`));
47
76
  /**
48
77
  * Pick a tmux session name that won't steal focus from another live
49
78
  * `zeph cc`. Strategy:
50
- * - If `<base>` doesn't exist use it (create new).
51
- * - If `<base>` exists but is detached use it (reattach).
52
- * - If `<base>` exists *and* has a client attached → try `<base>-2`,
53
- * `<base>-3`, … so the new `zeph cc` gets an independent session
54
- * instead of joining the existing one.
55
- * Falls back to `<base>` after 20 attempts (shouldn't realistically hit).
79
+ * - Reuse the **highest-numbered detached** session in the family.
80
+ * - Otherwise take the lowest name that doesn't exist yet (create new),
81
+ * so an all-attached family gets an independent `<base>-N`.
82
+ *
83
+ * Highest-detached rather than lowest is what keeps the family reachable.
84
+ * The old scan walked the family in order and returned the first session that
85
+ * was missing *or* detached, which meant a detached `<base>` ended the scan
86
+ * every time: `<base>-2` could not be reached by any later `zeph cc`, not even
87
+ * after `<base>` was used and exited (a missing `<base>` is taken fresh). A
88
+ * session nobody can reach still holds a live agent — a Claude Code CLI plus
89
+ * its MCP fleet, 250-550MB measured — so stranding one leaks memory the user
90
+ * can neither see nor reclaim. Draining from the tail makes every suffix
91
+ * reachable again: the tail goes first, and `<base>` is picked on the run
92
+ * after that. Reuse also wins over a gap in the numbering, for the same
93
+ * reason — a free `<base>-2` must not hide a detached `<base>-3`.
56
94
  *
57
- * Detection uses `tmux has-session` and `tmux list-clients`; both are
58
- * dependency-free against the user's running tmux server.
95
+ * Reclaiming is deliberately all this does. Killing a detached session would
96
+ * take a live agent with it, and nothing here can tell "the user is done with
97
+ * this" from "the user closed the terminal and will come back".
59
98
  */
60
99
  const findAvailableSession = (base) => {
61
- for (let i = 0; i < MAX_SUFFIX_ATTEMPTS; i++) {
62
- const name = i === 0 ? base : `${base}-${i + 1}`;
63
- const has = (0, child_process_1.spawnSync)('tmux', ['has-session', '-t', name], {
64
- stdio: ['ignore', 'ignore', 'ignore'],
65
- });
66
- if (has.status !== 0)
67
- return name; // doesn't exist — fresh session
68
- const clients = (0, child_process_1.spawnSync)('tmux', ['list-clients', '-t', name, '-F', '#{client_tty}'], {
69
- encoding: 'utf-8',
70
- stdio: ['ignore', 'pipe', 'ignore'],
71
- });
72
- const attached = (clients.stdout ?? '').trim().length > 0;
73
- if (!attached)
74
- return name; // exists but detached — reattach
100
+ const live = liveSessions();
101
+ const family = familyNames(base);
102
+ for (let i = family.length - 1; i >= 0; i--) {
103
+ if (live.get(family[i]) === false)
104
+ return family[i];
75
105
  }
76
- return base;
106
+ return family.find((name) => !live.has(name)) ?? base;
77
107
  };
78
108
  exports.findAvailableSession = findAvailableSession;
79
109
  /** POSIX shell-quote so passthrough args survive being joined into a tmux shell-command string. */
@@ -87,10 +117,10 @@ const targetForAgent = (agent, extra) => {
87
117
  return { cmd: agent, args: extra };
88
118
  }
89
119
  const base = (0, exports.tmuxSessionName)((0, exports.detectProjectName)());
90
- // Auto-suffix when the default name is taken by another attached
91
- // session — lets the user keep `zeph cc` workflow simple and still
92
- // get independent sessions when opening multiple terminals in the
93
- // same project.
120
+ // Reattach a detached session of this project when there is one,
121
+ // else auto-suffix — lets the user keep `zeph cc` workflow simple and
122
+ // still get independent sessions when opening multiple terminals in
123
+ // the same project.
94
124
  const session = (0, exports.findAvailableSession)(base);
95
125
  // `tmux new -A`: attach if the named session exists, else create it.
96
126
  // tmux joins trailing argv into a single shell-command, so flags like
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zeph-to/cli",
3
- "version": "2.10.0",
3
+ "version": "2.12.0",
4
4
  "description": "Zeph CLI + push notification SDK for AI agents",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -72,6 +72,7 @@
72
72
  },
73
73
  "dependencies": {
74
74
  "@inquirer/prompts": "^8.4.3",
75
+ "@zeph-to/mcp-server": "^2.3.0",
75
76
  "ws": "^8.21.0"
76
77
  }
77
78
  }