clawborrator-cli 0.0.23 → 0.0.24

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.
Files changed (2) hide show
  1. package/dist-bundled/claw.cjs +132 -46
  2. package/package.json +1 -1
@@ -6844,7 +6844,7 @@ var whoamiCmd = new Command("whoami").description("show the currently authentica
6844
6844
  });
6845
6845
 
6846
6846
  // src/commands/session-attach.ts
6847
- var import_node_readline = require("node:readline");
6847
+ var import_node_readline2 = require("node:readline");
6848
6848
 
6849
6849
  // ../node_modules/ws/wrapper.mjs
6850
6850
  var import_stream = __toESM(require_stream(), 1);
@@ -6857,13 +6857,65 @@ var import_websocket = __toESM(require_websocket(), 1);
6857
6857
  var import_websocket_server = __toESM(require_websocket_server(), 1);
6858
6858
  var wrapper_default = import_websocket.default;
6859
6859
 
6860
- // src/commands/session-attach.ts
6860
+ // src/util/disambiguate.ts
6861
+ var import_node_readline = require("node:readline");
6861
6862
  var RESET = "\x1B[0m";
6862
6863
  var DIM = "\x1B[2m";
6864
+ var BOLD = "\x1B[1m";
6865
+ var AmbiguousError = class extends Error {
6866
+ constructor(candidates, input) {
6867
+ super(`ambiguous reference '${input}' \u2014 multiple online sessions match`);
6868
+ this.candidates = candidates;
6869
+ this.input = input;
6870
+ }
6871
+ code = "CLW_AMBIGUOUS";
6872
+ };
6873
+ async function pickCandidate(input, candidates) {
6874
+ if (candidates.length === 1) return candidates[0];
6875
+ const live = candidates.filter((c) => c.connected);
6876
+ if (live.length <= 1) {
6877
+ return live[0] ?? candidates[0];
6878
+ }
6879
+ if (!process.stdin.isTTY || !process.stderr.isTTY) {
6880
+ throw new AmbiguousError(live, input);
6881
+ }
6882
+ process.stderr.write(`${BOLD}'${input}' is ambiguous \u2014 pick a session:${RESET}
6883
+ `);
6884
+ for (let i = 0; i < live.length; i++) {
6885
+ const c = live[i];
6886
+ const qualified = c.routingName ? `@${c.startedByLogin}/${c.routingName.replace(/^@/, "")}` : `(no routing name)`;
6887
+ const cwd = c.cwd ? ` ${DIM}${c.cwd}${RESET}` : "";
6888
+ const host = c.host ? ` ${DIM}${c.host}${RESET}` : "";
6889
+ process.stderr.write(` ${BOLD}${i + 1}${RESET}. ${qualified}${host}${cwd}
6890
+ `);
6891
+ process.stderr.write(` ${DIM}id ${c.id}${RESET}
6892
+ `);
6893
+ }
6894
+ process.stderr.write(` ${BOLD}q${RESET}. cancel
6895
+ `);
6896
+ const rl = (0, import_node_readline.createInterface)({ input: process.stdin, output: process.stderr });
6897
+ const answer = await new Promise((resolve3) => {
6898
+ rl.question(`pick [1-${live.length}]: `, resolve3);
6899
+ });
6900
+ rl.close();
6901
+ const trimmed = answer.trim().toLowerCase();
6902
+ if (trimmed === "q" || trimmed === "quit" || trimmed === "") {
6903
+ throw new Error("cancelled");
6904
+ }
6905
+ const idx = parseInt(trimmed, 10);
6906
+ if (!Number.isInteger(idx) || idx < 1 || idx > live.length) {
6907
+ throw new Error(`invalid selection '${answer}'`);
6908
+ }
6909
+ return live[idx - 1];
6910
+ }
6911
+
6912
+ // src/commands/session-attach.ts
6913
+ var RESET2 = "\x1B[0m";
6914
+ var DIM2 = "\x1B[2m";
6863
6915
  var AMBER = "\x1B[33m";
6864
6916
  var BLUE = "\x1B[36m";
6865
6917
  var RED = "\x1B[31m";
6866
- var BOLD = "\x1B[1m";
6918
+ var BOLD2 = "\x1B[1m";
6867
6919
  var GREEN = "\x1B[32m";
6868
6920
  function ts() {
6869
6921
  return (/* @__PURE__ */ new Date()).toLocaleTimeString();
@@ -6906,7 +6958,20 @@ var sessionAttach = new Command("attach").description("open a TUI on a session \
6906
6958
  console.error(`error: no session with routing name ${label} (run \`claw session list\` to see what's available)`);
6907
6959
  process.exit(2);
6908
6960
  }
6909
- sessionId = candidates[0].id;
6961
+ try {
6962
+ const picked = await pickCandidate(ref, candidates);
6963
+ sessionId = picked.id;
6964
+ } catch (e) {
6965
+ if (e instanceof AmbiguousError) {
6966
+ console.error(`error: '${ref}' is ambiguous \u2014 multiple online sessions match. Re-run with a UUID or qualified form (e.g. @owner/slug). Candidates:`);
6967
+ for (const c of e.candidates) {
6968
+ console.error(` ${c.id} @${c.startedByLogin}/${(c.routingName ?? "").replace(/^@/, "")} ${c.cwd ?? ""}`);
6969
+ }
6970
+ process.exit(2);
6971
+ }
6972
+ console.error(`error: ${e?.message ?? String(e)}`);
6973
+ process.exit(2);
6974
+ }
6910
6975
  }
6911
6976
  const wsUrl = cfg.hubUrl.replace(/^http/i, "ws") + "/cli";
6912
6977
  const ws = new wrapper_default(wsUrl, {
@@ -6915,7 +6980,7 @@ var sessionAttach = new Command("attach").description("open a TUI on a session \
6915
6980
  let mySubscription = false;
6916
6981
  const pendingPerms = [];
6917
6982
  ws.on("open", () => {
6918
- console.log(`${DIM}[${ts()}]${RESET} connected to ${cfg.hubUrl}`);
6983
+ console.log(`${DIM2}[${ts()}]${RESET2} connected to ${cfg.hubUrl}`);
6919
6984
  const sub = { type: "subscribe", sessionId };
6920
6985
  ws.send(JSON.stringify(sub));
6921
6986
  });
@@ -6935,22 +7000,22 @@ var sessionAttach = new Command("attach").description("open a TUI on a session \
6935
7000
  printInbound(msg, myLogin);
6936
7001
  if (msg.type === "subscribed") {
6937
7002
  mySubscription = true;
6938
- console.log(`${DIM}attached as ${BOLD}${msg.role}${RESET}${DIM}. type for prompt \xB7 @other <text> to route \xB7 /m <text> for op-msg \xB7 /y /n on permissions \xB7 /q to quit${RESET}`);
7003
+ console.log(`${DIM2}attached as ${BOLD2}${msg.role}${RESET2}${DIM2}. type for prompt \xB7 @other <text> to route \xB7 /m <text> for op-msg \xB7 /y /n on permissions \xB7 /q to quit${RESET2}`);
6939
7004
  }
6940
7005
  });
6941
7006
  ws.on("close", (code, reason) => {
6942
- console.log(`${DIM}[${ts()}] disconnected (${code}${reason ? ": " + reason.toString() : ""})${RESET}`);
7007
+ console.log(`${DIM2}[${ts()}] disconnected (${code}${reason ? ": " + reason.toString() : ""})${RESET2}`);
6943
7008
  process.exit(0);
6944
7009
  });
6945
7010
  ws.on("error", (err) => {
6946
- console.error(`${RED}ws error: ${err.message}${RESET}`);
7011
+ console.error(`${RED}ws error: ${err.message}${RESET2}`);
6947
7012
  });
6948
- const rl = (0, import_node_readline.createInterface)({ input: process.stdin, terminal: false });
7013
+ const rl = (0, import_node_readline2.createInterface)({ input: process.stdin, terminal: false });
6949
7014
  rl.on("line", (raw) => {
6950
7015
  const text = raw.trim();
6951
7016
  if (!text) return;
6952
7017
  if (!mySubscription) {
6953
- console.log(`${DIM}(not subscribed yet \u2014 waiting...)${RESET}`);
7018
+ console.log(`${DIM2}(not subscribed yet \u2014 waiting...)${RESET2}`);
6954
7019
  return;
6955
7020
  }
6956
7021
  if (text === "/q" || text === "/quit") {
@@ -6960,7 +7025,7 @@ var sessionAttach = new Command("attach").description("open a TUI on a session \
6960
7025
  if (text === "/y" || text === "/yes" || text === "/n" || text === "/no") {
6961
7026
  const pending = pendingPerms[pendingPerms.length - 1];
6962
7027
  if (!pending) {
6963
- console.log(`${DIM}(no pending permission to act on)${RESET}`);
7028
+ console.log(`${DIM2}(no pending permission to act on)${RESET2}`);
6964
7029
  return;
6965
7030
  }
6966
7031
  const decision = text === "/y" || text === "/yes" ? "allow" : "deny";
@@ -6977,7 +7042,7 @@ var sessionAttach = new Command("attach").description("open a TUI on a session \
6977
7042
  if (text === "/m" || text.startsWith("/m ")) {
6978
7043
  const opText = text.slice(2).trim();
6979
7044
  if (!opText) {
6980
- console.log(`${DIM}usage: /m <text> (sends as op-message; bare text is a prompt)${RESET}`);
7045
+ console.log(`${DIM2}usage: /m <text> (sends as op-message; bare text is a prompt)${RESET2}`);
6981
7046
  return;
6982
7047
  }
6983
7048
  const out2 = { type: "op_message", sessionId, text: opText };
@@ -6987,16 +7052,16 @@ var sessionAttach = new Command("attach").description("open a TUI on a session \
6987
7052
  if (text === "/p" || text.startsWith("/p ")) {
6988
7053
  const promptText = text.slice(2).trim();
6989
7054
  if (!promptText) {
6990
- console.log(`${DIM}usage: /p <text> (or just type \u2014 bare text is a prompt now)${RESET}`);
7055
+ console.log(`${DIM2}usage: /p <text> (or just type \u2014 bare text is a prompt now)${RESET2}`);
6991
7056
  return;
6992
7057
  }
6993
7058
  const out2 = { type: "prompt", sessionId, text: promptText };
6994
7059
  ws.send(JSON.stringify(out2));
6995
- console.log(`${DIM}[${ts()}]${RESET} ${AMBER}\u2192 prompt sent${RESET} ${promptText}`);
7060
+ console.log(`${DIM2}[${ts()}]${RESET2} ${AMBER}\u2192 prompt sent${RESET2} ${promptText}`);
6996
7061
  return;
6997
7062
  }
6998
7063
  if (text.startsWith("/")) {
6999
- console.log(`${DIM}unknown slash-command: ${text} (try /m /y /n /q)${RESET}`);
7064
+ console.log(`${DIM2}unknown slash-command: ${text} (try /m /y /n /q)${RESET2}`);
7000
7065
  return;
7001
7066
  }
7002
7067
  const xMatch = /^(@[A-Za-z0-9._\-/]+)\s+([\s\S]+)$/.exec(text);
@@ -7004,7 +7069,7 @@ var sessionAttach = new Command("attach").description("open a TUI on a session \
7004
7069
  const targetRef = xMatch[1];
7005
7070
  const promptText = xMatch[2].trim();
7006
7071
  if (!promptText) {
7007
- console.log(`${DIM}usage: ${targetRef} <prompt>${RESET}`);
7072
+ console.log(`${DIM2}usage: ${targetRef} <prompt>${RESET2}`);
7008
7073
  return;
7009
7074
  }
7010
7075
  (async () => {
@@ -7028,7 +7093,15 @@ var sessionAttach = new Command("attach").description("open a TUI on a session \
7028
7093
  if (mine.length > 0) candidates = mine;
7029
7094
  }
7030
7095
  if (candidates.length === 0) {
7031
- console.error(`${RED}error: no session ${targetRef} (try \`claw session list\` in another terminal)${RESET}`);
7096
+ console.error(`${RED}error: no session ${targetRef} (try \`claw session list\` in another terminal)${RESET2}`);
7097
+ return;
7098
+ }
7099
+ const liveMatches = candidates.filter((c) => c.connected);
7100
+ if (liveMatches.length > 1) {
7101
+ console.error(`${RED}error: '${targetRef}' is ambiguous \u2014 multiple online matches. Use the qualified form:${RESET2}`);
7102
+ for (const c of liveMatches) {
7103
+ console.error(` ${DIM2}${c.id.slice(0, 8)}\u2026${RESET2} @${c.startedByLogin}/${(c.routingName ?? "").replace(/^@/, "")} ${DIM2}${c.cwd ?? ""}${RESET2}`);
7104
+ }
7032
7105
  return;
7033
7106
  }
7034
7107
  const match = candidates[0];
@@ -7043,16 +7116,16 @@ var sessionAttach = new Command("attach").description("open a TUI on a session \
7043
7116
  sourceSessionId: sessionId
7044
7117
  };
7045
7118
  ws.send(JSON.stringify(out2));
7046
- console.log(`${DIM}[${ts()}]${RESET} ${AMBER}\u2192 prompt \u2192 ${targetRef}${RESET} ${promptText}`);
7119
+ console.log(`${DIM2}[${ts()}]${RESET2} ${AMBER}\u2192 prompt \u2192 ${targetRef}${RESET2} ${promptText}`);
7047
7120
  } catch (e) {
7048
- console.error(`${RED}error: ${e?.message ?? String(e)}${RESET}`);
7121
+ console.error(`${RED}error: ${e?.message ?? String(e)}${RESET2}`);
7049
7122
  }
7050
7123
  })();
7051
7124
  return;
7052
7125
  }
7053
7126
  const out = { type: "prompt", sessionId, text };
7054
7127
  ws.send(JSON.stringify(out));
7055
- console.log(`${DIM}[${ts()}]${RESET} ${AMBER}\u2192 prompt${RESET} ${text}`);
7128
+ console.log(`${DIM2}[${ts()}]${RESET2} ${AMBER}\u2192 prompt${RESET2} ${text}`);
7056
7129
  });
7057
7130
  process.on("SIGINT", () => {
7058
7131
  ws.close(1e3, "sigint");
@@ -7067,26 +7140,26 @@ function printInbound(msg, myLogin) {
7067
7140
  break;
7068
7141
  }
7069
7142
  case "op_message": {
7070
- console.log(`${DIM}[${shortTs(msg.ts)}]${RESET} ${GREEN}@${msg.authorLogin}${RESET} ${msg.text}`);
7143
+ console.log(`${DIM2}[${shortTs(msg.ts)}]${RESET2} ${GREEN}@${msg.authorLogin}${RESET2} ${msg.text}`);
7071
7144
  break;
7072
7145
  }
7073
7146
  case "permission_request": {
7074
- console.log(`${RED}[!] ${shortTs(msg.ts)}${RESET} approval needed: ${BOLD}${msg.tool}${RESET} \u2014 ${msg.inputPreview}`);
7147
+ console.log(`${RED}[!] ${shortTs(msg.ts)}${RESET2} approval needed: ${BOLD2}${msg.tool}${RESET2} \u2014 ${msg.inputPreview}`);
7075
7148
  break;
7076
7149
  }
7077
7150
  case "permission_resolved": {
7078
- const dec = msg.decision === "allow" ? `${GREEN}allowed${RESET}` : msg.decision === "deny" ? `${RED}denied${RESET}` : `${DIM}expired${RESET}`;
7079
- console.log(`${DIM}[${ts()}]${RESET} permission ${msg.requestId} ${dec} by @${msg.resolverLogin ?? "?"}`);
7151
+ const dec = msg.decision === "allow" ? `${GREEN}allowed${RESET2}` : msg.decision === "deny" ? `${RED}denied${RESET2}` : `${DIM2}expired${RESET2}`;
7152
+ console.log(`${DIM2}[${ts()}]${RESET2} permission ${msg.requestId} ${dec} by @${msg.resolverLogin ?? "?"}`);
7080
7153
  break;
7081
7154
  }
7082
7155
  case "presence": {
7083
- console.log(`${DIM}[${ts()}] presence: ${msg.attached.map((l) => "@" + l).join(", ") || "(empty)"}${RESET}`);
7156
+ console.log(`${DIM2}[${ts()}] presence: ${msg.attached.map((l) => "@" + l).join(", ") || "(empty)"}${RESET2}`);
7084
7157
  break;
7085
7158
  }
7086
7159
  case "ack":
7087
7160
  break;
7088
7161
  case "error":
7089
- console.error(`${RED}error (${msg.code}): ${msg.message}${RESET}`);
7162
+ console.error(`${RED}error (${msg.code}): ${msg.message}${RESET2}`);
7090
7163
  break;
7091
7164
  }
7092
7165
  }
@@ -7109,58 +7182,58 @@ function renderEvent(ev, myLogin) {
7109
7182
  const text = String(p.text ?? p.prompt ?? "").trim() || JSON.stringify(p).slice(0, 200);
7110
7183
  const source = String(p.source ?? "cli");
7111
7184
  if (source === "operator" && myLogin && p.authorLogin === myLogin) return;
7112
- const label = source === "operator" ? `${BOLD}@${String(p.authorLogin ?? "remote")} \u203A${RESET}` : `${BOLD}(cli) \u203A${RESET}`;
7113
- console.log(`${DIM}[${ts2}]${RESET} ${label} ${text}`);
7185
+ const label = source === "operator" ? `${BOLD2}@${String(p.authorLogin ?? "remote")} \u203A${RESET2}` : `${BOLD2}(cli) \u203A${RESET2}`;
7186
+ console.log(`${DIM2}[${ts2}]${RESET2} ${label} ${text}`);
7114
7187
  return;
7115
7188
  }
7116
7189
  if (ev.type === "assistant_text") {
7117
7190
  const text = String(p.text ?? "").trim();
7118
7191
  const isPlaceholder = !!p.placeholder;
7119
- const tag = isPlaceholder ? `${DIM}claude \xB7 thinking${RESET}` : `${AMBER}claude${RESET}`;
7120
- console.log(`${DIM}[${ts2}]${RESET} ${tag} ${isPlaceholder ? DIM + text + RESET : text}`);
7192
+ const tag = isPlaceholder ? `${DIM2}claude \xB7 thinking${RESET2}` : `${AMBER}claude${RESET2}`;
7193
+ console.log(`${DIM2}[${ts2}]${RESET2} ${tag} ${isPlaceholder ? DIM2 + text + RESET2 : text}`);
7121
7194
  return;
7122
7195
  }
7123
7196
  if (ev.type === "reply") {
7124
7197
  const text = String(p.text ?? "").trim();
7125
7198
  if (p.source === "peer-reply" && p.peerLogin) {
7126
- console.log(`${DIM}[${ts2}]${RESET} ${AMBER}${String(p.peerLogin)} answered${RESET} ${text}`);
7199
+ console.log(`${DIM2}[${ts2}]${RESET2} ${AMBER}${String(p.peerLogin)} answered${RESET2} ${text}`);
7127
7200
  return;
7128
7201
  }
7129
- const tag = p.chatId ? `${AMBER}claude${RESET} ${DIM}(reply to ${String(p.chatId).slice(0, 8)})${RESET}` : `${AMBER}claude${RESET}`;
7130
- console.log(`${DIM}[${ts2}]${RESET} ${tag} ${text}`);
7202
+ const tag = p.chatId ? `${AMBER}claude${RESET2} ${DIM2}(reply to ${String(p.chatId).slice(0, 8)})${RESET2}` : `${AMBER}claude${RESET2}`;
7203
+ console.log(`${DIM2}[${ts2}]${RESET2} ${tag} ${text}`);
7131
7204
  return;
7132
7205
  }
7133
- console.log(`${DIM}[${ts2}]${RESET} ${AMBER}[chat:${ev.type}]${RESET} ${previewPayload(p)}`);
7206
+ console.log(`${DIM2}[${ts2}]${RESET2} ${AMBER}[chat:${ev.type}]${RESET2} ${previewPayload(p)}`);
7134
7207
  return;
7135
7208
  }
7136
7209
  switch (ev.type) {
7137
7210
  case "PreToolUse": {
7138
7211
  const tool = String(p.tool_name ?? p.toolName ?? p.tool ?? "?");
7139
7212
  const input = renderToolInput(p);
7140
- console.log(`${DIM}[${ts2}]${RESET} ${BLUE}\u2192 ${tool}${RESET} ${DIM}${input}${RESET}`);
7213
+ console.log(`${DIM2}[${ts2}]${RESET2} ${BLUE}\u2192 ${tool}${RESET2} ${DIM2}${input}${RESET2}`);
7141
7214
  return;
7142
7215
  }
7143
7216
  case "PostToolUse": {
7144
7217
  const tool = String(p.tool_name ?? p.toolName ?? p.tool ?? "?");
7145
7218
  const out = stringifyToolResponse(p.tool_response ?? p.toolResponse ?? p.outputPreview ?? p.output);
7146
- const ok = p.ok === false ? `${RED}\u2717${RESET}` : `${BLUE}\u2713${RESET}`;
7147
- console.log(`${DIM}[${ts2}]${RESET} ${ok} ${tool}${out ? " " + DIM + truncate(out, 200) + RESET : ""}`);
7219
+ const ok = p.ok === false ? `${RED}\u2717${RESET2}` : `${BLUE}\u2713${RESET2}`;
7220
+ console.log(`${DIM2}[${ts2}]${RESET2} ${ok} ${tool}${out ? " " + DIM2 + truncate(out, 200) + RESET2 : ""}`);
7148
7221
  return;
7149
7222
  }
7150
7223
  case "PostToolUseFailure": {
7151
7224
  const tool = String(p.tool_name ?? p.toolName ?? p.tool ?? "?");
7152
7225
  const err = stringifyToolResponse(p.error ?? p.message ?? p.tool_response);
7153
- console.log(`${DIM}[${ts2}]${RESET} ${RED}\u2717 ${tool}${RESET} ${RED}${truncate(err, 200)}${RESET}`);
7226
+ console.log(`${DIM2}[${ts2}]${RESET2} ${RED}\u2717 ${tool}${RESET2} ${RED}${truncate(err, 200)}${RESET2}`);
7154
7227
  return;
7155
7228
  }
7156
7229
  case "Stop":
7157
- console.log(`${DIM}[${ts2}] \u2014 turn end \u2014${RESET}`);
7230
+ console.log(`${DIM2}[${ts2}] \u2014 turn end \u2014${RESET2}`);
7158
7231
  return;
7159
7232
  case "SessionStart":
7160
- console.log(`${DIM}[${ts2}] \u25B8 session start${RESET}`);
7233
+ console.log(`${DIM2}[${ts2}] \u25B8 session start${RESET2}`);
7161
7234
  return;
7162
7235
  case "SessionEnd":
7163
- console.log(`${DIM}[${ts2}] \u25C2 session end${RESET}`);
7236
+ console.log(`${DIM2}[${ts2}] \u25C2 session end${RESET2}`);
7164
7237
  return;
7165
7238
  case "TaskCreated":
7166
7239
  case "SubagentStart":
@@ -7168,16 +7241,16 @@ function renderEvent(ev, myLogin) {
7168
7241
  case "TaskCompleted": {
7169
7242
  const which = ev.type;
7170
7243
  const desc = String(p.description ?? p.agentType ?? "");
7171
- console.log(`${DIM}[${ts2}] ${BLUE}\u21AA ${which}${RESET}${desc ? " " + desc : ""}`);
7244
+ console.log(`${DIM2}[${ts2}] ${BLUE}\u21AA ${which}${RESET2}${desc ? " " + desc : ""}`);
7172
7245
  return;
7173
7246
  }
7174
7247
  case "Notification": {
7175
7248
  const msg = String(p.message ?? p.text ?? "").trim();
7176
- console.log(`${DIM}[${ts2}]${RESET} ${BOLD}\u{1F514}${RESET} ${msg || JSON.stringify(p).slice(0, 200)}`);
7249
+ console.log(`${DIM2}[${ts2}]${RESET2} ${BOLD2}\u{1F514}${RESET2} ${msg || JSON.stringify(p).slice(0, 200)}`);
7177
7250
  return;
7178
7251
  }
7179
7252
  default:
7180
- console.log(`${DIM}[${ts2}]${RESET} ${BLUE}[${ev.type}]${RESET} ${previewPayload(p)}`);
7253
+ console.log(`${DIM2}[${ts2}]${RESET2} ${BLUE}[${ev.type}]${RESET2} ${previewPayload(p)}`);
7181
7254
  }
7182
7255
  }
7183
7256
  function stringifyToolResponse(v) {
@@ -7258,7 +7331,20 @@ async function resolveSessionId(idOrName) {
7258
7331
  err.code = "CLW_NO_ROUTING_MATCH";
7259
7332
  throw err;
7260
7333
  }
7261
- return candidates[0].id;
7334
+ try {
7335
+ const picked = await pickCandidate(idOrName, candidates);
7336
+ return picked.id;
7337
+ } catch (e) {
7338
+ if (e instanceof AmbiguousError) {
7339
+ const err = new Error(
7340
+ `ambiguous reference '${idOrName}' \u2014 multiple online sessions match. Re-run with a UUID or qualified form. Candidates:
7341
+ ` + e.candidates.map((c) => ` ${c.id} @${c.startedByLogin}/${(c.routingName ?? "").replace(/^@/, "")} ${c.cwd ?? ""}`).join("\n")
7342
+ );
7343
+ err.code = "CLW_AMBIGUOUS";
7344
+ throw err;
7345
+ }
7346
+ throw e;
7347
+ }
7262
7348
  }
7263
7349
  var sessionList = new Command("list").alias("ls").description("list sessions you can see").option("--connected", "only sessions whose channel WS is currently open").option("--all", "include archived sessions").action(async (opts) => {
7264
7350
  const qs = new URLSearchParams();
@@ -7677,7 +7763,7 @@ var webhookCmd = new Command("webhook").description("manage webhook subscription
7677
7763
 
7678
7764
  // src/index.ts
7679
7765
  var program2 = new Command();
7680
- program2.name("claw").description("clawborrator CLI \u2014 control your Claude Code sessions from the terminal").version("0.0.23");
7766
+ program2.name("claw").description("clawborrator CLI \u2014 control your Claude Code sessions from the terminal").version("0.0.24");
7681
7767
  program2.addCommand(loginCmd);
7682
7768
  program2.addCommand(logoutCmd);
7683
7769
  program2.addCommand(whoamiCmd);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clawborrator-cli",
3
- "version": "0.0.23",
3
+ "version": "0.0.24",
4
4
  "type": "module",
5
5
  "description": "claw — command-line client for clawborrator hub_v1. Manages PATs, channel tokens, sessions, cross-session routing, and webhooks; ships an inline TUI for live multi-operator session attach.",
6
6
  "license": "MIT",