clawborrator-cli 0.2.6 → 0.2.8

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.
@@ -63999,13 +63999,14 @@ var {
63999
63999
 
64000
64000
  // src/commands/login.ts
64001
64001
  var import_node_http = require("node:http");
64002
- var import_node_crypto = require("node:crypto");
64002
+ var import_node_crypto2 = require("node:crypto");
64003
64003
  var import_node_child_process = require("node:child_process");
64004
64004
 
64005
64005
  // src/config.ts
64006
64006
  var import_node_os = require("node:os");
64007
64007
  var import_node_path = require("node:path");
64008
64008
  var import_node_fs = require("node:fs");
64009
+ var import_node_crypto = require("node:crypto");
64009
64010
  var CONFIG_DIR = (0, import_node_path.resolve)((0, import_node_os.homedir)(), ".clawborrator");
64010
64011
  var CONFIG_PATH = (0, import_node_path.resolve)(CONFIG_DIR, "cli_v1.json");
64011
64012
  var DEFAULTS = {
@@ -64013,24 +64014,37 @@ var DEFAULTS = {
64013
64014
  // CLAWBORRATOR_HUB=http://localhost:8787 or `claw login --hub <url>`,
64014
64015
  // which persists into ~/.clawborrator/cli_v1.json.
64015
64016
  hubUrl: process.env.CLAWBORRATOR_HUB ?? "https://next.clawborrator.com",
64016
- sessionToken: null
64017
+ sessionToken: null,
64018
+ machineId: ""
64019
+ // populated on first loadConfig()
64017
64020
  };
64018
64021
  function loadConfig() {
64019
- if (!(0, import_node_fs.existsSync)(CONFIG_PATH)) return { ...DEFAULTS };
64020
- try {
64021
- const raw = (0, import_node_fs.readFileSync)(CONFIG_PATH, "utf8");
64022
- const parsed = JSON.parse(raw);
64023
- return {
64022
+ let parsed = {};
64023
+ if ((0, import_node_fs.existsSync)(CONFIG_PATH)) {
64024
+ try {
64025
+ const raw = (0, import_node_fs.readFileSync)(CONFIG_PATH, "utf8");
64026
+ parsed = JSON.parse(raw);
64027
+ } catch {
64028
+ }
64029
+ }
64030
+ let machineId = parsed.machineId?.trim() || "";
64031
+ if (!machineId) {
64032
+ machineId = (0, import_node_crypto.randomUUID)();
64033
+ saveConfig({
64024
64034
  hubUrl: parsed.hubUrl?.trim() || DEFAULTS.hubUrl,
64025
- // Forward-migrate a legacy `pat` field. The token itself is now
64026
- // dead on the server side, but carrying it forward avoids loud
64027
- // "config corrupt" errors — the next API call will 401 cleanly
64028
- // and prompt re-login.
64029
- sessionToken: parsed.sessionToken ?? parsed.pat ?? null
64030
- };
64031
- } catch {
64032
- return { ...DEFAULTS };
64035
+ sessionToken: parsed.sessionToken ?? parsed.pat ?? null,
64036
+ machineId
64037
+ });
64033
64038
  }
64039
+ return {
64040
+ hubUrl: parsed.hubUrl?.trim() || DEFAULTS.hubUrl,
64041
+ // Forward-migrate a legacy `pat` field. The token itself is now
64042
+ // dead on the server side, but carrying it forward avoids loud
64043
+ // "config corrupt" errors — the next API call will 401 cleanly
64044
+ // and prompt re-login.
64045
+ sessionToken: parsed.sessionToken ?? parsed.pat ?? null,
64046
+ machineId
64047
+ };
64034
64048
  }
64035
64049
  function saveConfig(cfg) {
64036
64050
  if (!(0, import_node_fs.existsSync)(CONFIG_DIR)) {
@@ -64149,10 +64163,10 @@ function awaitCallback(server) {
64149
64163
  server.on("error", reject);
64150
64164
  });
64151
64165
  }
64152
- async function browserOAuthFlow(hubUrl) {
64153
- const verifier = base64url((0, import_node_crypto.randomBytes)(32));
64154
- const challenge = base64url((0, import_node_crypto.createHash)("sha256").update(verifier).digest());
64155
- const state = base64url((0, import_node_crypto.randomBytes)(16));
64166
+ async function browserOAuthFlow(hubUrl, machineId) {
64167
+ const verifier = base64url((0, import_node_crypto2.randomBytes)(32));
64168
+ const challenge = base64url((0, import_node_crypto2.createHash)("sha256").update(verifier).digest());
64169
+ const state = base64url((0, import_node_crypto2.randomBytes)(16));
64156
64170
  const server = (0, import_node_http.createServer)();
64157
64171
  await new Promise((resolve3, reject) => {
64158
64172
  server.once("error", reject);
@@ -64165,6 +64179,7 @@ async function browserOAuthFlow(hubUrl) {
64165
64179
  startUrl.searchParams.set("state", state);
64166
64180
  startUrl.searchParams.set("code_challenge", challenge);
64167
64181
  startUrl.searchParams.set("code_challenge_method", "S256");
64182
+ startUrl.searchParams.set("machine_id", machineId);
64168
64183
  console.log("opening browser to authenticate with GitHub\u2026");
64169
64184
  console.log(` if it doesn't open automatically, paste this URL into a browser:`);
64170
64185
  console.log(` ${startUrl}`);
@@ -64209,8 +64224,8 @@ var loginCmd = new Command("login").description("authenticate against a hub_v1 i
64209
64224
  const hubUrl = (opts.hub ?? cfg.hubUrl).replace(/\/+$/, "");
64210
64225
  console.log(`hub: ${hubUrl}`);
64211
64226
  try {
64212
- const { user, session } = await browserOAuthFlow(hubUrl);
64213
- saveConfig({ hubUrl, sessionToken: session.token });
64227
+ const { user, session } = await browserOAuthFlow(hubUrl, cfg.machineId);
64228
+ saveConfig({ hubUrl, sessionToken: session.token, machineId: cfg.machineId });
64214
64229
  console.log(`logged in as @${user.githubLogin}`);
64215
64230
  console.log(`hub: ${hubUrl}`);
64216
64231
  console.log(`session: ${session.token.slice(0, 16)}\u2026 (stored in ~/.clawborrator/cli_v1.json)`);
@@ -68865,22 +68880,25 @@ var tokenMint = new Command("mint").description("create a new channel token").re
68865
68880
  prose(" claude --dangerously-load-development-channels server:clawborrator");
68866
68881
  }
68867
68882
  });
68868
- var tokenList = new Command("list").alias("ls").description("list channel tokens for the current user").action(async () => {
68869
- const data = await api.get("/api/v1/tokens");
68883
+ var tokenList = new Command("list").alias("ls").description("list this user's active tokens \u2014 both channel (ck_live_\u2026) and app (cw_app_\u2026). Pass --all to include revoked rows.").option("--all", "include revoked tokens").action(async (opts) => {
68884
+ const qs = opts.all ? "?includeRevoked=true" : "";
68885
+ const data = await api.get("/api/v1/tokens" + qs);
68870
68886
  if (data.items.length === 0) {
68871
- console.log("no active channel tokens");
68887
+ console.log("no active tokens");
68872
68888
  return;
68873
68889
  }
68874
68890
  for (const t of data.items) {
68875
68891
  const used = t.lastUsedAt ? `last used ${fmtAgo2(t.lastUsedAt)}` : "never used";
68876
- console.log(`${t.id.toString().padStart(3)} ${t.prefix}\u2026 ${t.name.padEnd(28)} ${used}`);
68892
+ const status = t.revokedAt ? " REVOKED" : "";
68893
+ const mach = t.machineId ? ` mach=${t.machineId.slice(0, 12)}\u2026` : "";
68894
+ console.log(`${t.id.toString().padStart(3)} ${t.kind.padEnd(7)} ${t.prefix}\u2026 ${t.name.padEnd(28)} ${used}${mach}${status}`);
68877
68895
  }
68878
68896
  });
68879
- var tokenRevoke = new Command("revoke").description("revoke a channel token by id").argument("<id>", "token id (from `claw token list`)").action(async (id) => {
68897
+ var tokenRevoke = new Command("revoke").description("revoke a token by id (channel or app)").argument("<id>", "token id (from `claw token list`)").action(async (id) => {
68880
68898
  await api.delete(`/api/v1/tokens/${encodeURIComponent(id)}`);
68881
68899
  console.log(`\u2713 token ${id} revoked`);
68882
68900
  });
68883
- var tokenCmd = new Command("token").description("mint, list, and revoke channel tokens").addCommand(tokenMint).addCommand(tokenList).addCommand(tokenRevoke);
68901
+ var tokenCmd = new Command("token").description("mint channel tokens; list/revoke channel + app tokens").addCommand(tokenMint).addCommand(tokenList).addCommand(tokenRevoke);
68884
68902
  function fmtAgo2(iso) {
68885
68903
  const ms = Date.now() - new Date(iso).getTime();
68886
68904
  if (ms < 6e4) return Math.max(1, Math.floor(ms / 1e3)) + "s ago";
@@ -69122,7 +69140,7 @@ var agentsCmd = new Command("agents").description("public expert agents \u2014 l
69122
69140
  // src/commands/apps.ts
69123
69141
  var import_promises = require("node:readline/promises");
69124
69142
  var import_node_http2 = require("node:http");
69125
- var import_node_crypto2 = require("node:crypto");
69143
+ var import_node_crypto3 = require("node:crypto");
69126
69144
  var import_node_child_process2 = require("node:child_process");
69127
69145
  function fmtAgo3(iso) {
69128
69146
  if (!iso) return "never";
@@ -69249,9 +69267,9 @@ function awaitSpaCallback(server) {
69249
69267
  });
69250
69268
  }
69251
69269
  async function spaTestOauthFlow(args) {
69252
- const verifier = base64url2((0, import_node_crypto2.randomBytes)(32));
69253
- const challenge = base64url2((0, import_node_crypto2.createHash)("sha256").update(verifier).digest());
69254
- const stateNonce = base64url2((0, import_node_crypto2.randomBytes)(16));
69270
+ const verifier = base64url2((0, import_node_crypto3.randomBytes)(32));
69271
+ const challenge = base64url2((0, import_node_crypto3.createHash)("sha256").update(verifier).digest());
69272
+ const stateNonce = base64url2((0, import_node_crypto3.randomBytes)(16));
69255
69273
  const appName = "claw-cli-test-oauth";
69256
69274
  const server = (0, import_node_http2.createServer)();
69257
69275
  await new Promise((resolve3, reject) => {
@@ -69386,7 +69404,7 @@ function fmtAgo4(iso) {
69386
69404
 
69387
69405
  // src/index.ts
69388
69406
  var program2 = new Command();
69389
- program2.name("claw").description("clawborrator CLI \u2014 control your Claude Code sessions from the terminal").version("0.2.6");
69407
+ program2.name("claw").description("clawborrator CLI \u2014 control your Claude Code sessions from the terminal").version("0.2.8");
69390
69408
  program2.addCommand(loginCmd);
69391
69409
  program2.addCommand(logoutCmd);
69392
69410
  program2.addCommand(whoamiCmd);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clawborrator-cli",
3
- "version": "0.2.6",
3
+ "version": "0.2.8",
4
4
  "type": "module",
5
5
  "description": "claw — command-line client for clawborrator. Attach to remote Claude Code sessions, send prompts, resolve permission gates, route across sessions, manage public agents and webhooks. Auth via GitHub OAuth + PKCE.",
6
6
  "license": "MIT",