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.
- package/dist-bundled/claw.cjs +50 -32
- package/package.json +1 -1
package/dist-bundled/claw.cjs
CHANGED
|
@@ -63999,13 +63999,14 @@ var {
|
|
|
63999
63999
|
|
|
64000
64000
|
// src/commands/login.ts
|
|
64001
64001
|
var import_node_http = require("node:http");
|
|
64002
|
-
var
|
|
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
|
-
|
|
64020
|
-
|
|
64021
|
-
|
|
64022
|
-
|
|
64023
|
-
|
|
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
|
-
|
|
64026
|
-
|
|
64027
|
-
|
|
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,
|
|
64154
|
-
const challenge = base64url((0,
|
|
64155
|
-
const state = base64url((0,
|
|
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
|
|
68869
|
-
const
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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,
|
|
69253
|
-
const challenge = base64url2((0,
|
|
69254
|
-
const stateNonce = base64url2((0,
|
|
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.
|
|
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.
|
|
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",
|