@openape/apes 0.20.0 → 0.21.0

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/cli.js CHANGED
@@ -96,7 +96,7 @@ function rewriteApeShellArgs(argv, argv0) {
96
96
  import { defineCommand as defineCommand44, runMain } from "citty";
97
97
 
98
98
  // src/commands/auth/login.ts
99
- import { Buffer } from "buffer";
99
+ import { Buffer as Buffer2 } from "buffer";
100
100
  import { execFile } from "child_process";
101
101
  import { createServer } from "http";
102
102
  import { homedir as homedir2 } from "os";
@@ -394,7 +394,7 @@ async function loginWithKey(idp, keyPath, agentEmail) {
394
394
  const { challenge } = await challengeResp.json();
395
395
  const keyContent = readFileSync7(keyPath, "utf-8");
396
396
  const privateKey = loadEd25519PrivateKey2(keyContent);
397
- const signature = sign3(null, Buffer.from(challenge), privateKey).toString("base64");
397
+ const signature = sign3(null, Buffer2.from(challenge), privateKey).toString("base64");
398
398
  const authenticateUrl = await getAgentAuthenticateEndpoint(idp);
399
399
  const authResp = await fetch(authenticateUrl, {
400
400
  method: "POST",
@@ -1754,7 +1754,7 @@ import { defineCommand as defineCommand20 } from "citty";
1754
1754
  import consola18 from "consola";
1755
1755
 
1756
1756
  // src/lib/agent-bootstrap.ts
1757
- import { Buffer as Buffer2 } from "buffer";
1757
+ import { Buffer as Buffer3 } from "buffer";
1758
1758
  import { createPrivateKey, sign } from "crypto";
1759
1759
  var AGENT_NAME_REGEX = /^[a-z][a-z0-9-]{0,23}$/;
1760
1760
  var SSH_ED25519_PREFIX = "ssh-ed25519 ";
@@ -1779,7 +1779,7 @@ async function issueAgentToken(input) {
1779
1779
  throw new Error(`Challenge failed (${challengeResp.status}): ${text}`);
1780
1780
  }
1781
1781
  const { challenge } = await challengeResp.json();
1782
- const signature = sign(null, Buffer2.from(challenge), privateKey).toString("base64");
1782
+ const signature = sign(null, Buffer3.from(challenge), privateKey).toString("base64");
1783
1783
  const authenticateUrl = await getAgentAuthenticateEndpoint(input.idp);
1784
1784
  const authResp = await fetch(authenticateUrl, {
1785
1785
  method: "POST",
@@ -1811,6 +1811,25 @@ mkdir -p "$HOME_DIR/.claude/hooks"
1811
1811
  cat > "$HOME_DIR/.claude/settings.json" ${shHeredoc(input.claudeSettingsJson)}
1812
1812
  cat > "$HOME_DIR/.claude/hooks/bash-via-ape-shell.sh" ${shHeredoc(input.hookScriptSource)}
1813
1813
  chmod 755 "$HOME_DIR/.claude/hooks/bash-via-ape-shell.sh"
1814
+ ` : "";
1815
+ const claudeTokenBlock = input.claudeOauthToken ? `
1816
+ mkdir -p "$HOME_DIR/.config/openape"
1817
+ cat > "$HOME_DIR/.config/openape/claude-token.env" ${shHeredoc(`# Auto-generated by 'apes agents spawn'. chmod 600 \u2014 contains a long-lived
1818
+ # Claude Code OAuth token. Rotate by editing this file in place; the
1819
+ # .zshenv / .profile source-lines below will pick it up automatically.
1820
+ export CLAUDE_CODE_OAUTH_TOKEN=${shQuote(input.claudeOauthToken)}
1821
+ `)}
1822
+ SOURCE_LINE='[ -f "$HOME/.config/openape/claude-token.env" ] && . "$HOME/.config/openape/claude-token.env"'
1823
+ for f in "$HOME_DIR/.zshenv" "$HOME_DIR/.profile"; do
1824
+ touch "$f"
1825
+ if ! grep -qF 'config/openape/claude-token.env' "$f" 2>/dev/null; then
1826
+ {
1827
+ echo ''
1828
+ echo '# OpenApe: load Claude Code OAuth token (added by apes agents spawn)'
1829
+ echo "$SOURCE_LINE"
1830
+ } >> "$f"
1831
+ fi
1832
+ done
1814
1833
  ` : "";
1815
1834
  return `#!/bin/bash
1816
1835
  set -euo pipefail
@@ -1854,13 +1873,17 @@ mkdir -p "$HOME_DIR/.ssh" "$HOME_DIR/.config/apes"
1854
1873
  cat > "$HOME_DIR/.ssh/id_ed25519" ${shHeredoc(privatePemForHeredoc.trimEnd())}
1855
1874
  cat > "$HOME_DIR/.ssh/id_ed25519.pub" ${shHeredoc(`${input.publicKeySshLine}`)}
1856
1875
  cat > "$HOME_DIR/.config/apes/auth.json" ${shHeredoc(input.authJson)}
1857
- ${claudeBlock}
1876
+ ${claudeBlock}${claudeTokenBlock}
1858
1877
  chown -R "$NAME:staff" "$HOME_DIR"
1859
1878
  chmod 700 "$HOME_DIR/.ssh"
1860
1879
  chmod 700 "$HOME_DIR/.config"
1861
1880
  chmod 600 "$HOME_DIR/.ssh/id_ed25519"
1862
1881
  chmod 644 "$HOME_DIR/.ssh/id_ed25519.pub"
1863
1882
  chmod 600 "$HOME_DIR/.config/apes/auth.json"
1883
+ if [ -f "$HOME_DIR/.config/openape/claude-token.env" ]; then
1884
+ chmod 700 "$HOME_DIR/.config/openape"
1885
+ chmod 600 "$HOME_DIR/.config/openape/claude-token.env"
1886
+ fi
1864
1887
 
1865
1888
  echo "OK $NAME uid=$NEXT_UID home=$HOME_DIR"
1866
1889
  `;
@@ -2268,7 +2291,7 @@ import { defineCommand as defineCommand23 } from "citty";
2268
2291
  import consola21 from "consola";
2269
2292
 
2270
2293
  // src/lib/keygen.ts
2271
- import { Buffer as Buffer3 } from "buffer";
2294
+ import { Buffer as Buffer4 } from "buffer";
2272
2295
  import { existsSync as existsSync5, mkdirSync, readFileSync as readFileSync4, writeFileSync as writeFileSync2 } from "fs";
2273
2296
  import { generateKeyPairSync } from "crypto";
2274
2297
  import { homedir as homedir4 } from "os";
@@ -2278,11 +2301,11 @@ function resolveKeyPath(p) {
2278
2301
  }
2279
2302
  function buildSshEd25519Line(rawPub) {
2280
2303
  const keyTypeStr = "ssh-ed25519";
2281
- const keyTypeLen = Buffer3.alloc(4);
2304
+ const keyTypeLen = Buffer4.alloc(4);
2282
2305
  keyTypeLen.writeUInt32BE(keyTypeStr.length);
2283
- const pubKeyLen = Buffer3.alloc(4);
2306
+ const pubKeyLen = Buffer4.alloc(4);
2284
2307
  pubKeyLen.writeUInt32BE(rawPub.length);
2285
- const blob = Buffer3.concat([keyTypeLen, Buffer3.from(keyTypeStr), pubKeyLen, rawPub]);
2308
+ const blob = Buffer4.concat([keyTypeLen, Buffer4.from(keyTypeStr), pubKeyLen, rawPub]);
2286
2309
  return `ssh-ed25519 ${blob.toString("base64")}`;
2287
2310
  }
2288
2311
  function readPublicKey(keyPath) {
@@ -2293,7 +2316,7 @@ function readPublicKey(keyPath) {
2293
2316
  const keyContent = readFileSync4(keyPath, "utf-8");
2294
2317
  const privateKey = loadEd25519PrivateKey(keyContent);
2295
2318
  const jwk = privateKey.export({ format: "jwk" });
2296
- const pubBytes = Buffer3.from(jwk.x, "base64url");
2319
+ const pubBytes = Buffer4.from(jwk.x, "base64url");
2297
2320
  return buildSshEd25519Line(pubBytes);
2298
2321
  }
2299
2322
  function generateAndSaveKey(keyPath) {
@@ -2306,7 +2329,7 @@ function generateAndSaveKey(keyPath) {
2306
2329
  const privatePem = privateKey.export({ type: "pkcs8", format: "pem" });
2307
2330
  writeFileSync2(resolved, privatePem, { mode: 384 });
2308
2331
  const jwk = publicKey.export({ format: "jwk" });
2309
- const pubBytes = Buffer3.from(jwk.x, "base64url");
2332
+ const pubBytes = Buffer4.from(jwk.x, "base64url");
2310
2333
  const pubKeyStr = buildSshEd25519Line(pubBytes);
2311
2334
  writeFileSync2(`${resolved}.pub`, `${pubKeyStr}
2312
2335
  `, { mode: 420 });
@@ -2316,7 +2339,7 @@ function generateKeyPairInMemory() {
2316
2339
  const { publicKey, privateKey } = generateKeyPairSync("ed25519");
2317
2340
  const privatePem = privateKey.export({ type: "pkcs8", format: "pem" });
2318
2341
  const jwk = publicKey.export({ format: "jwk" });
2319
- const pubBytes = Buffer3.from(jwk.x, "base64url");
2342
+ const pubBytes = Buffer4.from(jwk.x, "base64url");
2320
2343
  return {
2321
2344
  privatePem,
2322
2345
  publicSshLine: buildSshEd25519Line(pubBytes)
@@ -2342,6 +2365,14 @@ var spawnAgentCommand = defineCommand23({
2342
2365
  "no-claude-hook": {
2343
2366
  type: "boolean",
2344
2367
  description: "Skip writing ~/.claude/settings.json + the Bash-rewrite hook"
2368
+ },
2369
+ "claude-token": {
2370
+ type: "string",
2371
+ description: "Claude Code OAuth token (sk-ant-oat01-\u2026) from `claude setup-token`. Visible to ps \u2014 prefer --claude-token-stdin in scripts."
2372
+ },
2373
+ "claude-token-stdin": {
2374
+ type: "boolean",
2375
+ description: "Read the Claude Code OAuth token from stdin (paranoid form of --claude-token)."
2345
2376
  }
2346
2377
  },
2347
2378
  async run({ args }) {
@@ -2408,6 +2439,10 @@ and try again.`
2408
2439
  expiresAt: Math.floor(Date.now() / 1e3) + expiresIn
2409
2440
  });
2410
2441
  const includeClaudeHook = !args["no-claude-hook"];
2442
+ const claudeOauthToken = await resolveClaudeToken({
2443
+ flag: typeof args["claude-token"] === "string" ? args["claude-token"] : void 0,
2444
+ fromStdin: !!args["claude-token-stdin"]
2445
+ });
2411
2446
  const script = buildSpawnSetupScript({
2412
2447
  name,
2413
2448
  homeDir,
@@ -2416,7 +2451,8 @@ and try again.`
2416
2451
  publicKeySshLine: publicSshLine,
2417
2452
  authJson,
2418
2453
  claudeSettingsJson: includeClaudeHook ? CLAUDE_SETTINGS_JSON : null,
2419
- hookScriptSource: includeClaudeHook ? BASH_VIA_APE_SHELL_HOOK_SOURCE : null
2454
+ hookScriptSource: includeClaudeHook ? BASH_VIA_APE_SHELL_HOOK_SOURCE : null,
2455
+ claudeOauthToken
2420
2456
  });
2421
2457
  writeFileSync3(scriptPath, script, { mode: 448 });
2422
2458
  consola21.start("Running privileged setup as root via `apes run --as root --wait`\u2026");
@@ -2431,6 +2467,28 @@ and try again.`
2431
2467
  }
2432
2468
  }
2433
2469
  });
2470
+ async function resolveClaudeToken(opts) {
2471
+ if (opts.flag && opts.fromStdin) {
2472
+ throw new CliError("Pass --claude-token OR --claude-token-stdin, not both.");
2473
+ }
2474
+ let raw = null;
2475
+ if (typeof opts.flag === "string") {
2476
+ raw = opts.flag.trim();
2477
+ } else if (opts.fromStdin) {
2478
+ const chunks = [];
2479
+ for await (const chunk of process.stdin) {
2480
+ chunks.push(typeof chunk === "string" ? Buffer.from(chunk) : chunk);
2481
+ }
2482
+ raw = Buffer.concat(chunks).toString("utf-8").trim();
2483
+ }
2484
+ if (!raw) return null;
2485
+ if (!raw.startsWith("sk-ant-oat01-")) {
2486
+ throw new CliError(
2487
+ `Claude token doesn't look right (expected sk-ant-oat01-\u2026). Run \`claude setup-token\` and paste the resulting token.`
2488
+ );
2489
+ }
2490
+ return raw;
2491
+ }
2434
2492
 
2435
2493
  // src/commands/agents/index.ts
2436
2494
  var agentsCommand = defineCommand24({
@@ -3698,7 +3756,7 @@ var mcpCommand = defineCommand32({
3698
3756
  if (transport !== "stdio" && transport !== "sse") {
3699
3757
  throw new Error('Transport must be "stdio" or "sse"');
3700
3758
  }
3701
- const { startMcpServer } = await import("./server-XZHBOWRD.js");
3759
+ const { startMcpServer } = await import("./server-UWKEQDNM.js");
3702
3760
  await startMcpServer(transport, port);
3703
3761
  }
3704
3762
  });
@@ -3858,7 +3916,7 @@ async function initIdP(targetDir) {
3858
3916
  }
3859
3917
 
3860
3918
  // src/commands/enroll.ts
3861
- import { Buffer as Buffer4 } from "buffer";
3919
+ import { Buffer as Buffer5 } from "buffer";
3862
3920
  import { existsSync as existsSync7, readFileSync as readFileSync5 } from "fs";
3863
3921
  import { execFile as execFile2 } from "child_process";
3864
3922
  import { sign as sign2 } from "crypto";
@@ -3889,7 +3947,7 @@ async function pollForEnrollment(idp, agentEmail, keyPath) {
3889
3947
  });
3890
3948
  if (challengeResp.ok) {
3891
3949
  const { challenge } = await challengeResp.json();
3892
- const signature = sign2(null, Buffer4.from(challenge), privateKey).toString("base64");
3950
+ const signature = sign2(null, Buffer5.from(challenge), privateKey).toString("base64");
3893
3951
  const authResp = await fetch(authenticateUrl, {
3894
3952
  method: "POST",
3895
3953
  headers: { "Content-Type": "application/json" },
@@ -4336,7 +4394,7 @@ async function bestEffortGrantCount(idp) {
4336
4394
  }
4337
4395
  }
4338
4396
  async function runHealth(args) {
4339
- const version = true ? "0.20.0" : "0.0.0";
4397
+ const version = true ? "0.21.0" : "0.0.0";
4340
4398
  const auth = loadAuth();
4341
4399
  if (!auth) {
4342
4400
  throw new CliError("Not logged in. Run `apes login` first.", 1);
@@ -4538,10 +4596,10 @@ if (shellRewrite) {
4538
4596
  if (shellRewrite.action === "rewrite") {
4539
4597
  process.argv = shellRewrite.argv;
4540
4598
  } else if (shellRewrite.action === "version") {
4541
- console.log(`ape-shell ${"0.20.0"} (OpenApe DDISA shell wrapper)`);
4599
+ console.log(`ape-shell ${"0.21.0"} (OpenApe DDISA shell wrapper)`);
4542
4600
  process.exit(0);
4543
4601
  } else if (shellRewrite.action === "help") {
4544
- console.log(`ape-shell ${"0.20.0"} \u2014 OpenApe DDISA shell wrapper`);
4602
+ console.log(`ape-shell ${"0.21.0"} \u2014 OpenApe DDISA shell wrapper`);
4545
4603
  console.log("");
4546
4604
  console.log("Usage:");
4547
4605
  console.log(" ape-shell Start interactive grant-mediated REPL");
@@ -4599,7 +4657,7 @@ var configCommand = defineCommand44({
4599
4657
  var main = defineCommand44({
4600
4658
  meta: {
4601
4659
  name: "apes",
4602
- version: "0.20.0",
4660
+ version: "0.21.0",
4603
4661
  description: "Unified CLI for OpenApe"
4604
4662
  },
4605
4663
  subCommands: {