clawborrator-cli 0.0.8 → 0.0.10

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 +48 -169
  2. package/package.json +1 -1
@@ -6874,12 +6874,26 @@ var sessionAttach = new Command("attach").description("open a TUI on a session \
6874
6874
  console.error("error: not logged in. run `claw login`.");
6875
6875
  process.exit(2);
6876
6876
  }
6877
+ const UUID_RE2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
6877
6878
  let sessionId = ref;
6878
- if (sessionId.startsWith("@")) {
6879
+ if (!UUID_RE2.test(sessionId)) {
6880
+ const needle = sessionId.startsWith("@") ? sessionId : "@" + sessionId;
6881
+ const slash = needle.indexOf("/");
6882
+ let ownerLogin = null;
6883
+ let slug;
6884
+ if (slash > 0) {
6885
+ ownerLogin = needle.slice(1, slash);
6886
+ slug = "@" + needle.slice(slash + 1).replace(/^@/, "");
6887
+ } else {
6888
+ slug = needle;
6889
+ }
6879
6890
  const data = await api.get("/api/v1/sessions");
6880
- const match = data.items.find((s) => s.routingName === sessionId);
6891
+ const match = data.items.find(
6892
+ (s) => s.routingName === slug && (ownerLogin === null || s.startedByLogin === ownerLogin)
6893
+ );
6881
6894
  if (!match) {
6882
- console.error(`error: no session with routing name ${sessionId} (run \`claw session list\` to see what's available)`);
6895
+ const label = ownerLogin ? `@${ownerLogin}/${slug.slice(1)}` : slug;
6896
+ console.error(`error: no session with routing name ${label} (run \`claw session list\` to see what's available)`);
6883
6897
  process.exit(2);
6884
6898
  }
6885
6899
  sessionId = match.id;
@@ -7111,158 +7125,6 @@ function truncate(s, max) {
7111
7125
  return s.slice(0, max - 1) + "\u2026";
7112
7126
  }
7113
7127
 
7114
- // src/commands/session-init.ts
7115
- var import_node_path2 = require("node:path");
7116
- var import_node_fs2 = require("node:fs");
7117
- var import_node_child_process = require("node:child_process");
7118
- var HOOK_NAMES = [
7119
- "SessionStart",
7120
- "SessionEnd",
7121
- "UserPromptSubmit",
7122
- "PreToolUse",
7123
- "PostToolUse",
7124
- "PostToolUseFailure",
7125
- "TaskCreated",
7126
- "SubagentStart",
7127
- "SubagentStop",
7128
- "TaskCompleted",
7129
- "Stop",
7130
- "Notification"
7131
- ];
7132
- var TAG = "clawborrator-hook";
7133
- function hookCommand(name) {
7134
- return `node ".claude/hooks/clawborrator-tail.mjs" ${name} #${TAG}`;
7135
- }
7136
- function isOurHook(h) {
7137
- return h.type === "command" && h.command.includes(`#${TAG}`);
7138
- }
7139
- function fetchHookBundle() {
7140
- try {
7141
- const stdout = (0, import_node_child_process.execFileSync)("npx", ["-y", "clawborrator-mcp", "--print-hook-file"], {
7142
- stdio: ["ignore", "pipe", "inherit"],
7143
- encoding: "utf8",
7144
- // npx may take a while if the cache is cold (download + extract).
7145
- timeout: 12e4,
7146
- shell: true
7147
- // cross-platform PATH resolution on Windows
7148
- });
7149
- if (!stdout || !stdout.trim()) {
7150
- throw new Error("--print-hook-file returned empty output");
7151
- }
7152
- return stdout;
7153
- } catch (e) {
7154
- throw new Error(`failed to fetch hook bundle via npx: ${e?.message ?? String(e)}`);
7155
- }
7156
- }
7157
- var sessionInit = new Command("init").description("install clawborrator hooks into <cwd>/.claude/settings.json + .claude/hooks/").option("--cwd <dir>", "project directory (defaults to current cwd)").option("--remove", "remove the clawborrator hooks (and the bundled .mjs)").option("--refresh-hook", "re-fetch the bundled hook file even if it already exists").action(async (opts) => {
7158
- const root = (0, import_node_path2.resolve)(opts.cwd ?? process.cwd());
7159
- const claudeDir = (0, import_node_path2.resolve)(root, ".claude");
7160
- const hooksDir = (0, import_node_path2.resolve)(claudeDir, "hooks");
7161
- const hookFile = (0, import_node_path2.resolve)(hooksDir, "clawborrator-tail.mjs");
7162
- const settings = (0, import_node_path2.resolve)(claudeDir, "settings.json");
7163
- if (opts.remove) {
7164
- removeHooks(settings, hookFile);
7165
- return;
7166
- }
7167
- if (!(0, import_node_fs2.existsSync)(hooksDir)) (0, import_node_fs2.mkdirSync)(hooksDir, { recursive: true });
7168
- if (!(0, import_node_fs2.existsSync)(hookFile) || opts.refreshHook) {
7169
- console.log("fetching bundled hook from npm via `npx -y clawborrator-mcp --print-hook-file`...");
7170
- const bundle = fetchHookBundle();
7171
- (0, import_node_fs2.writeFileSync)(hookFile, bundle, "utf8");
7172
- try {
7173
- (0, import_node_fs2.chmodSync)(hookFile, 493);
7174
- } catch {
7175
- }
7176
- console.log(`\u2713 wrote ${hookFile} (${bundle.length} bytes)`);
7177
- } else {
7178
- console.log(`(${hookFile} already present \u2014 pass --refresh-hook to overwrite)`);
7179
- }
7180
- if (!(0, import_node_fs2.existsSync)(claudeDir)) (0, import_node_fs2.mkdirSync)(claudeDir, { recursive: true });
7181
- let s = {};
7182
- if ((0, import_node_fs2.existsSync)(settings)) {
7183
- try {
7184
- const raw = (0, import_node_fs2.readFileSync)(settings, "utf8");
7185
- if (raw.trim()) s = JSON.parse(raw);
7186
- } catch (e) {
7187
- console.error(`error: could not parse existing ${settings}: ${e?.message ?? e}`);
7188
- console.error(" fix the JSON and re-run `claw session init`");
7189
- process.exit(2);
7190
- }
7191
- }
7192
- if (!s.hooks) s.hooks = {};
7193
- let added = 0, alreadyPresent = 0, refreshed = 0;
7194
- for (const name of HOOK_NAMES) {
7195
- const arr = s.hooks[name] ??= [];
7196
- let entry = arr.find((e) => (e.matcher ?? ".*") === ".*");
7197
- if (!entry) {
7198
- entry = { matcher: ".*", hooks: [] };
7199
- arr.push(entry);
7200
- }
7201
- const existingIdx = entry.hooks.findIndex(isOurHook);
7202
- const desiredCmd = hookCommand(name);
7203
- if (existingIdx >= 0) {
7204
- if (entry.hooks[existingIdx].command !== desiredCmd) {
7205
- entry.hooks[existingIdx] = { type: "command", command: desiredCmd };
7206
- refreshed++;
7207
- } else {
7208
- alreadyPresent++;
7209
- }
7210
- continue;
7211
- }
7212
- entry.hooks.push({ type: "command", command: desiredCmd });
7213
- added++;
7214
- }
7215
- (0, import_node_fs2.writeFileSync)(settings, JSON.stringify(s, null, 2) + "\n");
7216
- if (added > 0) console.log(`\u2713 installed ${added} clawborrator hook${added === 1 ? "" : "s"} \u2192 ${settings}`);
7217
- if (refreshed > 0) console.log(`\u2713 refreshed ${refreshed} command line${refreshed === 1 ? "" : "s"} (e.g. updated to call the local file)`);
7218
- if (alreadyPresent > 0) console.log(` (${alreadyPresent} already up-to-date, untouched)`);
7219
- console.log("");
7220
- console.log("next: drop a .mcp.json with your channel token (`claw token mint --kind=channel");
7221
- console.log(" --name=<label> --mcp-snippet --out=.mcp.json`), then start CC with:");
7222
- console.log(" claude --dangerously-load-development-channels server:clawborrator");
7223
- console.log(" events will flow as you prompt; watch via `claw session attach <id>`.");
7224
- });
7225
- function removeHooks(settingsPath, hookFile) {
7226
- if ((0, import_node_fs2.existsSync)(hookFile)) {
7227
- try {
7228
- (0, import_node_fs2.unlinkSync)(hookFile);
7229
- console.log(`\u2713 removed ${hookFile}`);
7230
- } catch (e) {
7231
- console.warn(`warning: could not delete ${hookFile}: ${e?.message ?? e}`);
7232
- }
7233
- }
7234
- if (!(0, import_node_fs2.existsSync)(settingsPath)) {
7235
- console.log("(no settings.json to clean up)");
7236
- return;
7237
- }
7238
- let s;
7239
- try {
7240
- const raw = (0, import_node_fs2.readFileSync)(settingsPath, "utf8");
7241
- s = raw.trim() ? JSON.parse(raw) : {};
7242
- } catch (e) {
7243
- console.error(`error: could not parse ${settingsPath}: ${e?.message ?? e}`);
7244
- process.exit(2);
7245
- }
7246
- if (!s.hooks) {
7247
- console.log("(no hooks block in settings.json)");
7248
- return;
7249
- }
7250
- let touched = 0;
7251
- for (const name of HOOK_NAMES) {
7252
- const arr = s.hooks[name];
7253
- if (!arr) continue;
7254
- for (const entry of arr) {
7255
- const before = entry.hooks.length;
7256
- entry.hooks = entry.hooks.filter((h) => !isOurHook(h));
7257
- if (entry.hooks.length !== before) touched++;
7258
- }
7259
- s.hooks[name] = arr.filter((e) => e.hooks.length > 0);
7260
- if (s.hooks[name].length === 0) delete s.hooks[name];
7261
- }
7262
- (0, import_node_fs2.writeFileSync)(settingsPath, JSON.stringify(s, null, 2) + "\n");
7263
- console.log(`\u2713 removed ${touched} clawborrator hook entr${touched === 1 ? "y" : "ies"} from ${settingsPath}`);
7264
- }
7265
-
7266
7128
  // src/commands/session.ts
7267
7129
  function fmtDuration(ms) {
7268
7130
  if (!Number.isFinite(ms) || ms < 0) return "\u2014";
@@ -7277,12 +7139,27 @@ function fmtDuration(ms) {
7277
7139
  function fmtAgo(iso) {
7278
7140
  return fmtDuration(Date.now() - new Date(iso).getTime());
7279
7141
  }
7142
+ var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
7280
7143
  async function resolveSessionId(idOrName) {
7281
- if (!idOrName.startsWith("@")) return idOrName;
7144
+ if (UUID_RE.test(idOrName)) return idOrName;
7145
+ const needle = idOrName.startsWith("@") ? idOrName : "@" + idOrName;
7146
+ const slash = needle.indexOf("/");
7147
+ let ownerLogin = null;
7148
+ let slug;
7149
+ if (slash > 0) {
7150
+ ownerLogin = needle.slice(1, slash);
7151
+ slug = "@" + needle.slice(slash + 1).replace(/^@/, "");
7152
+ } else {
7153
+ slug = needle;
7154
+ }
7282
7155
  const data = await api.get("/api/v1/sessions");
7283
- const match = data.items.find((s) => s.routingName === idOrName);
7156
+ const match = data.items.find(
7157
+ (s) => s.routingName === slug && (ownerLogin === null || s.startedByLogin === ownerLogin)
7158
+ );
7284
7159
  if (!match) {
7285
- const err = new Error(`no session with routing name ${idOrName} (run \`claw session list\` to see what's available)`);
7160
+ const err = new Error(
7161
+ ownerLogin ? `no session @${ownerLogin}/${slug.slice(1)} (run \`claw session list\`)` : `no session with routing name ${slug} (run \`claw session list\`)`
7162
+ );
7286
7163
  err.code = "CLW_NO_ROUTING_MATCH";
7287
7164
  throw err;
7288
7165
  }
@@ -7301,18 +7178,20 @@ var sessionList = new Command("list").alias("ls").description("list sessions you
7301
7178
  }
7302
7179
  for (const s of data.items) {
7303
7180
  const dot = s.connected ? "\u25CF" : "\u25CB";
7304
- const route = s.routingName ?? "(no routing name)";
7181
+ const slug = s.routingName ?? "";
7182
+ const qualified = slug ? `@${s.startedByLogin}/${slug.replace(/^@/, "")}` : "(no routing name)";
7305
7183
  const where = s.cwd ? ` ${s.cwd}` : "";
7306
7184
  const role = s.role.padEnd(8);
7307
7185
  const seen = s.connected ? "online" : `offline \xB7 ${fmtAgo(s.lastSeenAt)}`;
7308
7186
  const arch = s.archivedAt ? " \xB7 ARCHIVED" : "";
7309
- console.log(`${dot} ${route.padEnd(20)} ${role} @${s.startedByLogin}${where} [${seen}]${arch}`);
7187
+ console.log(`${dot} ${qualified.padEnd(28)} ${role}${where} [${seen}]${arch}`);
7310
7188
  console.log(` id: ${s.id}`);
7311
7189
  }
7312
7190
  console.log("");
7313
- console.log(" use: claw session attach @<routing> OR claw session attach <id>");
7314
- console.log(" claw session events <ref> \u2014 recent hook/chat events");
7315
- console.log(" claw session messages <ref> \u2014 operator-to-operator chat");
7191
+ console.log(" attach to a session: claw session attach <ref>");
7192
+ console.log(" recent hook/chat: claw session events <ref>");
7193
+ console.log(" operator-to-op chat: claw session messages <ref>");
7194
+ console.log(" <ref> = UUID, @owner/slug, @slug, or bare slug");
7316
7195
  });
7317
7196
  var sessionInfo = new Command("info").description("show metadata for a single session").argument("<ref>", "session UUID or @routingName").action(async (ref) => {
7318
7197
  const id = await resolveSessionId(ref);
@@ -7389,11 +7268,11 @@ var sessionMessages = new Command("messages").alias("msgs").description("dump op
7389
7268
  console.log(`(more \u2014 older: --before ${data.firstId} \xB7 newer: --after ${data.lastId})`);
7390
7269
  }
7391
7270
  });
7392
- var sessionCmd = new Command("session").description("manage Claude Code sessions registered with this hub").addCommand(sessionList).addCommand(sessionInfo).addCommand(sessionAttach).addCommand(sessionInit).addCommand(sessionEvents).addCommand(sessionMessages);
7271
+ var sessionCmd = new Command("session").description("manage Claude Code sessions registered with this hub").addCommand(sessionList).addCommand(sessionInfo).addCommand(sessionAttach).addCommand(sessionEvents).addCommand(sessionMessages);
7393
7272
 
7394
7273
  // src/commands/token.ts
7395
- var import_node_fs3 = require("node:fs");
7396
- var import_node_path3 = require("node:path");
7274
+ var import_node_fs2 = require("node:fs");
7275
+ var import_node_path2 = require("node:path");
7397
7276
 
7398
7277
  // ../shared/dist/scopes.js
7399
7278
  var ALL_SCOPES = [
@@ -7450,8 +7329,8 @@ var tokenMint = new Command("mint").description("create a new token").requiredOp
7450
7329
  }
7451
7330
  }, null, 2) + "\n";
7452
7331
  if (opts.out) {
7453
- const target = (0, import_node_path3.resolve)(opts.out);
7454
- (0, import_node_fs3.writeFileSync)(target, json, "utf8");
7332
+ const target = (0, import_node_path2.resolve)(opts.out);
7333
+ (0, import_node_fs2.writeFileSync)(target, json, "utf8");
7455
7334
  prose("");
7456
7335
  prose(`\u2713 wrote ${target}`);
7457
7336
  } else {
@@ -7597,7 +7476,7 @@ var webhookCmd = new Command("webhook").description("manage webhook subscription
7597
7476
 
7598
7477
  // src/index.ts
7599
7478
  var program2 = new Command();
7600
- program2.name("claw").description("clawborrator CLI \u2014 control your Claude Code sessions from the terminal").version("0.0.8");
7479
+ program2.name("claw").description("clawborrator CLI \u2014 control your Claude Code sessions from the terminal").version("0.0.10");
7601
7480
  program2.addCommand(loginCmd);
7602
7481
  program2.addCommand(logoutCmd);
7603
7482
  program2.addCommand(whoamiCmd);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clawborrator-cli",
3
- "version": "0.0.8",
3
+ "version": "0.0.10",
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",