clawborrator-cli 0.0.11 → 0.0.13

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.
@@ -6948,7 +6948,7 @@ var sessionAttach = new Command("attach").description("open a TUI on a session \
6948
6948
  printInbound(msg);
6949
6949
  if (msg.type === "subscribed") {
6950
6950
  mySubscription = true;
6951
- console.log(`${DIM}attached as ${BOLD}${msg.role}${RESET}${DIM}. type for op-message; /y or /n on permissions; /q to quit.${RESET}`);
6951
+ 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}`);
6952
6952
  }
6953
6953
  });
6954
6954
  ws.on("close", (code, reason) => {
@@ -6986,10 +6986,20 @@ var sessionAttach = new Command("attach").description("open a TUI on a session \
6986
6986
  ws.send(JSON.stringify(approval));
6987
6987
  return;
6988
6988
  }
6989
+ if (text === "/m" || text.startsWith("/m ")) {
6990
+ const opText = text.slice(2).trim();
6991
+ if (!opText) {
6992
+ console.log(`${DIM}usage: /m <text> (sends as op-message; bare text is a prompt)${RESET}`);
6993
+ return;
6994
+ }
6995
+ const out2 = { type: "op_message", sessionId, text: opText };
6996
+ ws.send(JSON.stringify(out2));
6997
+ return;
6998
+ }
6989
6999
  if (text === "/p" || text.startsWith("/p ")) {
6990
7000
  const promptText = text.slice(2).trim();
6991
7001
  if (!promptText) {
6992
- console.log(`${DIM}usage: /p <text>${RESET}`);
7002
+ console.log(`${DIM}usage: /p <text> (or just type \u2014 bare text is a prompt now)${RESET}`);
6993
7003
  return;
6994
7004
  }
6995
7005
  const out2 = { type: "prompt", sessionId, text: promptText };
@@ -6998,11 +7008,49 @@ var sessionAttach = new Command("attach").description("open a TUI on a session \
6998
7008
  return;
6999
7009
  }
7000
7010
  if (text.startsWith("/")) {
7001
- console.log(`${DIM}unknown slash-command: ${text} (try /p /y /n /q)${RESET}`);
7011
+ console.log(`${DIM}unknown slash-command: ${text} (try /m /y /n /q)${RESET}`);
7012
+ return;
7013
+ }
7014
+ const xMatch = /^(@[A-Za-z0-9._\-/]+)\s+([\s\S]+)$/.exec(text);
7015
+ if (xMatch) {
7016
+ const targetRef = xMatch[1];
7017
+ const promptText = xMatch[2].trim();
7018
+ if (!promptText) {
7019
+ console.log(`${DIM}usage: ${targetRef} <prompt>${RESET}`);
7020
+ return;
7021
+ }
7022
+ (async () => {
7023
+ const needle = targetRef.startsWith("@") ? targetRef : "@" + targetRef;
7024
+ const slash = needle.indexOf("/");
7025
+ let ownerLogin = null;
7026
+ let slug;
7027
+ if (slash > 0) {
7028
+ ownerLogin = needle.slice(1, slash);
7029
+ slug = "@" + needle.slice(slash + 1).replace(/^@/, "");
7030
+ } else {
7031
+ slug = needle;
7032
+ }
7033
+ try {
7034
+ const data = await api.get("/api/v1/sessions");
7035
+ const match = data.items.find(
7036
+ (s) => s.routingName === slug && (ownerLogin === null || s.startedByLogin === ownerLogin)
7037
+ );
7038
+ if (!match) {
7039
+ console.error(`${RED}error: no session ${targetRef} (try \`claw session list\` in another terminal)${RESET}`);
7040
+ return;
7041
+ }
7042
+ const out2 = { type: "prompt", sessionId: match.id, text: promptText };
7043
+ ws.send(JSON.stringify(out2));
7044
+ console.log(`${DIM}[${ts()}]${RESET} ${AMBER}\u2192 prompt \u2192 ${targetRef}${RESET} ${promptText}`);
7045
+ } catch (e) {
7046
+ console.error(`${RED}error: ${e?.message ?? String(e)}${RESET}`);
7047
+ }
7048
+ })();
7002
7049
  return;
7003
7050
  }
7004
- const out = { type: "op_message", sessionId, text };
7051
+ const out = { type: "prompt", sessionId, text };
7005
7052
  ws.send(JSON.stringify(out));
7053
+ console.log(`${DIM}[${ts()}]${RESET} ${AMBER}\u2192 prompt${RESET} ${text}`);
7006
7054
  });
7007
7055
  process.on("SIGINT", () => {
7008
7056
  ws.close(1e3, "sigint");
@@ -7314,18 +7362,19 @@ var sessionArchive = new Command("archive").description("soft-delete a session (
7314
7362
  console.log(`\u2713 archived ${r.sessionId} at ${r.archivedAt}`);
7315
7363
  }
7316
7364
  });
7317
- var sessionPrune = new Command("prune").description("archive duplicate session rows that share a routing name. The live (or most-recently-seen) row is kept; the rest are archived. Stale dups never reconnect, so they're effectively gone after this.").option("--dry-run", "show what would be pruned without writing").option("--routing <name>", "narrow to a single routing name (e.g. @driver)").action(async (opts) => {
7365
+ var sessionPrune = new Command("prune").description("hard-delete duplicate session rows that share a routing name. The live (or most-recently-seen) row is kept; the rest are removed along with their events / op-messages / shares (FK cascade). Use --dry-run first if unsure.").option("--dry-run", "show what would be deleted without writing").option("--routing <name>", "narrow to a single routing name (e.g. @driver)").action(async (opts) => {
7318
7366
  const body = { dryRun: !!opts.dryRun };
7319
7367
  if (opts.routing) body.routingName = opts.routing.startsWith("@") ? opts.routing : "@" + opts.routing;
7320
7368
  const r = await api.post(`/api/v1/sessions/prune`, body);
7321
- if (r.pruned.length === 0) {
7369
+ if (r.deleted.length === 0) {
7322
7370
  console.log("nothing to prune (no routing-name duplicates).");
7323
7371
  return;
7324
7372
  }
7325
- const verb = r.dryRun ? "would archive" : "archived";
7326
- console.log(`${verb} ${r.pruned.length} duplicate${r.pruned.length === 1 ? "" : "s"}:`);
7327
- for (const p of r.pruned) {
7328
- console.log(` \u2022 ${p.routingName.padEnd(20)} ${p.sessionId} (last seen ${p.lastSeenAt})`);
7373
+ const verb = r.dryRun ? "would delete" : "deleted";
7374
+ console.log(`${verb} ${r.deleted.length} duplicate${r.deleted.length === 1 ? "" : "s"}:`);
7375
+ for (const d of r.deleted) {
7376
+ const tag = d.wasArchived ? " [was archived]" : "";
7377
+ console.log(` \u2717 ${d.routingName.padEnd(20)} ${d.sessionId} (last seen ${d.lastSeenAt})${tag}`);
7329
7378
  }
7330
7379
  console.log(`keeping:`);
7331
7380
  for (const k of r.kept) {
@@ -7333,6 +7382,17 @@ var sessionPrune = new Command("prune").description("archive duplicate session r
7333
7382
  }
7334
7383
  if (r.dryRun) console.log("\n(--dry-run \u2014 re-run without it to apply)");
7335
7384
  });
7385
+ var sessionDelete = new Command("delete").description("hard-delete a single session \u2014 cascades events / op-messages / shares. Irreversible. Use `archive` for the soft form (auto-resurrects on reconnect).").argument("<ref>", "session UUID or @routingName").option("--hard", "required: confirm you want a permanent delete (no soft form is offered without this flag)").action(async (ref, opts) => {
7386
+ if (!opts.hard) {
7387
+ console.error("error: hard delete requires --hard. Did you mean `claw session archive <ref>`?");
7388
+ process.exit(2);
7389
+ }
7390
+ const id = await resolveSessionId(ref);
7391
+ const r = await api.delete(
7392
+ `/api/v1/sessions/${encodeURIComponent(id)}?hard=true`
7393
+ );
7394
+ console.log(`\u2717 deleted ${r.sessionId} (events / op-messages / shares cascaded).`);
7395
+ });
7336
7396
  var sessionPrompt = new Command("prompt").description("send a one-shot prompt to a session's live Claude (lands in the same inbox as cross-session route prompts; receiving Claude must be polling `await_routed_prompt`)").argument("<ref>", "session UUID or @routingName").argument("<text>", "prompt text \u2014 quote multi-word").action(async (ref, text) => {
7337
7397
  const id = await resolveSessionId(ref);
7338
7398
  const cfg = loadConfig();
@@ -7374,7 +7434,7 @@ var sessionPrompt = new Command("prompt").description("send a one-shot prompt to
7374
7434
  });
7375
7435
  });
7376
7436
  });
7377
- var sessionCmd = new Command("session").description("manage Claude Code sessions registered with this hub").addCommand(sessionList).addCommand(sessionInfo).addCommand(sessionAttach).addCommand(sessionEvents).addCommand(sessionMessages).addCommand(sessionArchive).addCommand(sessionPrune).addCommand(sessionPrompt);
7437
+ var sessionCmd = new Command("session").description("manage Claude Code sessions registered with this hub").addCommand(sessionList).addCommand(sessionInfo).addCommand(sessionAttach).addCommand(sessionEvents).addCommand(sessionMessages).addCommand(sessionArchive).addCommand(sessionPrune).addCommand(sessionPrompt).addCommand(sessionDelete);
7378
7438
 
7379
7439
  // src/commands/token.ts
7380
7440
  var import_node_fs2 = require("node:fs");
@@ -7582,7 +7642,7 @@ var webhookCmd = new Command("webhook").description("manage webhook subscription
7582
7642
 
7583
7643
  // src/index.ts
7584
7644
  var program2 = new Command();
7585
- program2.name("claw").description("clawborrator CLI \u2014 control your Claude Code sessions from the terminal").version("0.0.11");
7645
+ program2.name("claw").description("clawborrator CLI \u2014 control your Claude Code sessions from the terminal").version("0.0.13");
7586
7646
  program2.addCommand(loginCmd);
7587
7647
  program2.addCommand(logoutCmd);
7588
7648
  program2.addCommand(whoamiCmd);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clawborrator-cli",
3
- "version": "0.0.11",
3
+ "version": "0.0.13",
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",