@openape/apes 0.19.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)
@@ -2327,7 +2350,7 @@ function generateKeyPairInMemory() {
2327
2350
  var spawnAgentCommand = defineCommand23({
2328
2351
  meta: {
2329
2352
  name: "spawn",
2330
- description: "Provision a local macOS agent end-to-end (OS user, keypair, IdP agent, ape-shell, Claude hook)"
2353
+ description: "Provision a local macOS agent end-to-end (OS user, keypair, IdP agent, Claude hook)"
2331
2354
  },
2332
2355
  args: {
2333
2356
  name: {
@@ -2337,11 +2360,19 @@ var spawnAgentCommand = defineCommand23({
2337
2360
  },
2338
2361
  shell: {
2339
2362
  type: "string",
2340
- description: "Override login shell. Default: $(which ape-shell)"
2363
+ description: "Login shell for the macOS user. Default: /bin/zsh. Pass $(which ape-shell) to opt into the grant-mediated REPL as login shell."
2341
2364
  },
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 }) {
@@ -2364,10 +2395,7 @@ var spawnAgentCommand = defineCommand23({
2364
2395
  if (!idp) {
2365
2396
  throw new CliError("No IdP URL configured. Run `apes login` first.");
2366
2397
  }
2367
- const apeShell = args.shell ?? whichBinary("ape-shell");
2368
- if (!apeShell) {
2369
- throw new CliError("`ape-shell` not found on PATH. Install @openape/apes globally first.");
2370
- }
2398
+ const loginShell = (args.shell ?? "/bin/zsh").toString();
2371
2399
  const apes = whichBinary("apes");
2372
2400
  if (!apes) {
2373
2401
  throw new CliError("`apes` not found on PATH. Install @openape/apes globally first.");
@@ -2378,10 +2406,10 @@ var spawnAgentCommand = defineCommand23({
2378
2406
  "`escapes` not found on PATH. spawn delegates the privileged setup phase to escapes; install it before running spawn."
2379
2407
  );
2380
2408
  }
2381
- if (!isShellRegistered(apeShell)) {
2409
+ if (!isShellRegistered(loginShell)) {
2382
2410
  throw new CliError(
2383
- `${apeShell} is not registered in /etc/shells. macOS refuses to set it as a login shell. Run:
2384
- echo ${apeShell} | sudo tee -a /etc/shells
2411
+ `${loginShell} is not registered in /etc/shells. macOS refuses to set it as a login shell. Run:
2412
+ echo ${loginShell} | sudo tee -a /etc/shells
2385
2413
  and try again.`
2386
2414
  );
2387
2415
  }
@@ -2411,15 +2439,20 @@ and try again.`
2411
2439
  expiresAt: Math.floor(Date.now() / 1e3) + expiresIn
2412
2440
  });
2413
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
+ });
2414
2446
  const script = buildSpawnSetupScript({
2415
2447
  name,
2416
2448
  homeDir,
2417
- shellPath: apeShell,
2449
+ shellPath: loginShell,
2418
2450
  privateKeyPem: privatePem,
2419
2451
  publicKeySshLine: publicSshLine,
2420
2452
  authJson,
2421
2453
  claudeSettingsJson: includeClaudeHook ? CLAUDE_SETTINGS_JSON : null,
2422
- hookScriptSource: includeClaudeHook ? BASH_VIA_APE_SHELL_HOOK_SOURCE : null
2454
+ hookScriptSource: includeClaudeHook ? BASH_VIA_APE_SHELL_HOOK_SOURCE : null,
2455
+ claudeOauthToken
2423
2456
  });
2424
2457
  writeFileSync3(scriptPath, script, { mode: 448 });
2425
2458
  consola21.start("Running privileged setup as root via `apes run --as root --wait`\u2026");
@@ -2434,6 +2467,28 @@ and try again.`
2434
2467
  }
2435
2468
  }
2436
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
+ }
2437
2492
 
2438
2493
  // src/commands/agents/index.ts
2439
2494
  var agentsCommand = defineCommand24({
@@ -3701,7 +3756,7 @@ var mcpCommand = defineCommand32({
3701
3756
  if (transport !== "stdio" && transport !== "sse") {
3702
3757
  throw new Error('Transport must be "stdio" or "sse"');
3703
3758
  }
3704
- const { startMcpServer } = await import("./server-GYHLAJXV.js");
3759
+ const { startMcpServer } = await import("./server-UWKEQDNM.js");
3705
3760
  await startMcpServer(transport, port);
3706
3761
  }
3707
3762
  });
@@ -3861,7 +3916,7 @@ async function initIdP(targetDir) {
3861
3916
  }
3862
3917
 
3863
3918
  // src/commands/enroll.ts
3864
- import { Buffer as Buffer4 } from "buffer";
3919
+ import { Buffer as Buffer5 } from "buffer";
3865
3920
  import { existsSync as existsSync7, readFileSync as readFileSync5 } from "fs";
3866
3921
  import { execFile as execFile2 } from "child_process";
3867
3922
  import { sign as sign2 } from "crypto";
@@ -3892,7 +3947,7 @@ async function pollForEnrollment(idp, agentEmail, keyPath) {
3892
3947
  });
3893
3948
  if (challengeResp.ok) {
3894
3949
  const { challenge } = await challengeResp.json();
3895
- const signature = sign2(null, Buffer4.from(challenge), privateKey).toString("base64");
3950
+ const signature = sign2(null, Buffer5.from(challenge), privateKey).toString("base64");
3896
3951
  const authResp = await fetch(authenticateUrl, {
3897
3952
  method: "POST",
3898
3953
  headers: { "Content-Type": "application/json" },
@@ -4339,7 +4394,7 @@ async function bestEffortGrantCount(idp) {
4339
4394
  }
4340
4395
  }
4341
4396
  async function runHealth(args) {
4342
- const version = true ? "0.19.0" : "0.0.0";
4397
+ const version = true ? "0.21.0" : "0.0.0";
4343
4398
  const auth = loadAuth();
4344
4399
  if (!auth) {
4345
4400
  throw new CliError("Not logged in. Run `apes login` first.", 1);
@@ -4541,10 +4596,10 @@ if (shellRewrite) {
4541
4596
  if (shellRewrite.action === "rewrite") {
4542
4597
  process.argv = shellRewrite.argv;
4543
4598
  } else if (shellRewrite.action === "version") {
4544
- console.log(`ape-shell ${"0.19.0"} (OpenApe DDISA shell wrapper)`);
4599
+ console.log(`ape-shell ${"0.21.0"} (OpenApe DDISA shell wrapper)`);
4545
4600
  process.exit(0);
4546
4601
  } else if (shellRewrite.action === "help") {
4547
- console.log(`ape-shell ${"0.19.0"} \u2014 OpenApe DDISA shell wrapper`);
4602
+ console.log(`ape-shell ${"0.21.0"} \u2014 OpenApe DDISA shell wrapper`);
4548
4603
  console.log("");
4549
4604
  console.log("Usage:");
4550
4605
  console.log(" ape-shell Start interactive grant-mediated REPL");
@@ -4559,7 +4614,7 @@ if (shellRewrite) {
4559
4614
  console.log(" --help, -h Show this help message");
4560
4615
  process.exit(0);
4561
4616
  } else if (shellRewrite.action === "interactive") {
4562
- const { runInteractiveShell } = await import("./orchestrator-FJVDWH45.js");
4617
+ const { runInteractiveShell } = await import("./orchestrator-RWTALOSA.js");
4563
4618
  await runInteractiveShell();
4564
4619
  process.exit(0);
4565
4620
  } else {
@@ -4602,7 +4657,7 @@ var configCommand = defineCommand44({
4602
4657
  var main = defineCommand44({
4603
4658
  meta: {
4604
4659
  name: "apes",
4605
- version: "0.19.0",
4660
+ version: "0.21.0",
4606
4661
  description: "Unified CLI for OpenApe"
4607
4662
  },
4608
4663
  subCommands: {