codeam-cli 2.60.12 → 2.60.14

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.
Files changed (3) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/index.js +212 -54
  3. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -4,6 +4,18 @@ All notable changes to `codeam-cli` are documented here.
4
4
 
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [2.60.13] — 2026-07-08
8
+
9
+ ### Fixed
10
+
11
+ - **cli:** Pair-auto must never be a local/baton session (agent_banner regression)
12
+
13
+ ## [2.60.12] — 2026-07-08
14
+
15
+ ### Fixed
16
+
17
+ - **cli:** Local self-update relaunch orphaned the interactive session
18
+
7
19
  ## [2.60.11] — 2026-07-08
8
20
 
9
21
  ### Fixed
package/dist/index.js CHANGED
@@ -389,6 +389,23 @@ var AGENT_REGISTRY = {
389
389
  headroomWrappable: false,
390
390
  // Native ACP server: `gemini --skip-trust --acp`.
391
391
  acp: true
392
+ },
393
+ kimi: {
394
+ id: "kimi",
395
+ displayName: "Kimi Code",
396
+ binaryName: "kimi",
397
+ enabled: true,
398
+ // API key (KIMI_API_KEY, + optional KIMI_BASE_URL) is the shipping auth —
399
+ // fully documented, no reverse-engineering. OAuth `/login` (login-state at
400
+ // ~/.kimi-code/credentials/<name>.json, base https://api.kimi.com/coding/)
401
+ // is declared so it can land later without a wire change, but capturing
402
+ // that blob server-side is a separate reverse-engineering spike (phase 2).
403
+ supportedAuthKinds: ["api_key", "oauth_token"],
404
+ preferredAuthKind: "api_key",
405
+ // Moonshot's `kimi` is not listed by `headroom wrap --help` — runs native.
406
+ headroomWrappable: false,
407
+ // Native ACP server: `kimi acp` (stdio JSON-RPC, answers `initialize`).
408
+ acp: true
392
409
  }
393
410
  };
394
411
  function getEnabledAgents() {
@@ -417,6 +434,7 @@ var PUBLIC_TO_INTERNAL = {
417
434
  aider: "aider",
418
435
  coderabbit: "coderabbit",
419
436
  gemini: "gemini",
437
+ kimi: "kimi",
420
438
  // The house agent runs Claude Code under the hood (pointed at the
421
439
  // MiniMax proxy). Its internal runtime is therefore `claude`.
422
440
  [HOUSE_AGENT_ID]: "claude"
@@ -5662,7 +5680,7 @@ function readAnonId() {
5662
5680
  }
5663
5681
  function superProperties() {
5664
5682
  return {
5665
- cliVersion: true ? "2.60.12" : "0.0.0-dev",
5683
+ cliVersion: true ? "2.60.14" : "0.0.0-dev",
5666
5684
  nodeVersion: process.version,
5667
5685
  platform: process.platform,
5668
5686
  arch: process.arch,
@@ -5843,7 +5861,7 @@ var os4 = __toESM(require("os"));
5843
5861
  // package.json
5844
5862
  var package_default = {
5845
5863
  name: "codeam-cli",
5846
- version: "2.60.12",
5864
+ version: "2.60.14",
5847
5865
  description: "Workflow-continuity bridge for AI coding agents. Wrap Claude Code or Codex in a PTY and supervise, approve, and redirect the session from any device \u2014 async. The terminal companion for CodeAgent Mobile.",
5848
5866
  type: "commonjs",
5849
5867
  main: "dist/index.js",
@@ -6914,7 +6932,7 @@ var CommandRelayService = class {
6914
6932
  // fresh + clear the "CLI update available" banner after a self-update
6915
6933
  // (a codespace that reinstalls @latest reconnects via heartbeat, not
6916
6934
  // pair/reconnect). Older backends ignore the extra field.
6917
- ..."2.60.12" ? { ideVersion: "2.60.12" } : {}
6935
+ ..."2.60.14" ? { ideVersion: "2.60.14" } : {}
6918
6936
  }).then(() => log.trace("relay", `heartbeat ok online=${online}`)).catch((err) => log.trace("relay", `heartbeat failed online=${online}`, err));
6919
6937
  }
6920
6938
  /**
@@ -7141,10 +7159,10 @@ var WINDOWS_LEGACY_JUNCTIONS = [
7141
7159
  /[\\/]Start Menu([\\/]|$)/i,
7142
7160
  /[\\/]Templates([\\/]|$)/i
7143
7161
  ];
7144
- function isUnsafeWindowsWatchRoot(dir, homedir38) {
7162
+ function isUnsafeWindowsWatchRoot(dir, homedir39) {
7145
7163
  const norm = (p2) => p2.replace(/\//g, "\\").replace(/\\+$/, "").toLowerCase();
7146
7164
  const cwd = norm(dir);
7147
- const home = norm(homedir38);
7165
+ const home = norm(homedir39);
7148
7166
  if (cwd === home) return true;
7149
7167
  if (/^[a-z]:$/.test(cwd)) return true;
7150
7168
  const sysRoots = [
@@ -14258,6 +14276,111 @@ var GeminiRuntimeStrategy = class {
14258
14276
  }
14259
14277
  };
14260
14278
 
14279
+ // src/agents/kimi/runtime.ts
14280
+ var import_node_child_process12 = require("child_process");
14281
+ var import_node_os3 = require("os");
14282
+ var import_node_path4 = require("path");
14283
+ var KIMI_CONTEXT_WINDOW = 262144;
14284
+ var KIMI_MODELS = [
14285
+ { id: "kimi-for-coding", label: "Kimi for Coding", contextWindow: KIMI_CONTEXT_WINDOW }
14286
+ ];
14287
+ function kimiCredentialsDir() {
14288
+ const root = process.env.KIMI_CODE_HOME || (0, import_node_path4.join)((0, import_node_os3.homedir)(), ".kimi-code");
14289
+ return (0, import_node_path4.join)(root, "credentials");
14290
+ }
14291
+ var KimiRuntimeStrategy = class {
14292
+ id = "kimi";
14293
+ meta = getAgent("kimi");
14294
+ mode = "interactive";
14295
+ os;
14296
+ constructor(os48) {
14297
+ this.os = os48;
14298
+ }
14299
+ async prepareLaunch() {
14300
+ const binary = this.os.findInPath("kimi");
14301
+ if (!binary) {
14302
+ throw new Error(
14303
+ "Kimi Code CLI is not on PATH. Install it with:\n curl -fsSL https://code.kimi.com/kimi-code/install.sh | bash\n Then run `codeam pair` again."
14304
+ );
14305
+ }
14306
+ const launch = this.os.buildLaunch(binary, []);
14307
+ return { cmd: launch.cmd, args: launch.args };
14308
+ }
14309
+ resumeLaunchArgs(_sessionId, _opts) {
14310
+ return [];
14311
+ }
14312
+ resolveHistoryDir(_cwd) {
14313
+ return null;
14314
+ }
14315
+ parseHistoryFile(_filePath) {
14316
+ return [];
14317
+ }
14318
+ getCurrentUsage(_historyDir) {
14319
+ return null;
14320
+ }
14321
+ async fetchWeeklyUsage() {
14322
+ return null;
14323
+ }
14324
+ async listModels() {
14325
+ return KIMI_MODELS;
14326
+ }
14327
+ changeModelInstruction(modelId) {
14328
+ return { type: "pty", ptyInput: `/model ${modelId}\r` };
14329
+ }
14330
+ summarizeInstruction(_mode) {
14331
+ return { ptyInput: "/compact\r" };
14332
+ }
14333
+ filterTuiOutput(lines) {
14334
+ return lines;
14335
+ }
14336
+ detectInteractivePrompt(_lines) {
14337
+ return null;
14338
+ }
14339
+ /**
14340
+ * Headless single-prompt invocation — powers `request_ai_summary` /
14341
+ * `request_ai_insight` (Files review) AND Preview detection, same as
14342
+ * claude/codex/gemini. Kimi's non-interactive print mode is
14343
+ * `kimi -p "<prompt>" --output-format text`: it streams the assistant reply
14344
+ * to stdout under the `auto` permission policy (no approval prompt) and exits.
14345
+ * Returns `null` on spawn failure / timeout / empty output so callers skip
14346
+ * silently instead of bubbling a partial reply.
14347
+ */
14348
+ async generateOneShot(prompt, opts) {
14349
+ const binary = this.os.findInPath("kimi");
14350
+ if (!binary) return null;
14351
+ const launch = this.os.buildLaunch(binary, ["-p", prompt, "--output-format", "text"]);
14352
+ return spawnAndCapture(launch.cmd, launch.args, {
14353
+ cwd: opts?.cwd,
14354
+ timeoutMs: opts?.timeoutMs
14355
+ });
14356
+ }
14357
+ credentialLocator() {
14358
+ return {
14359
+ publicId: "kimi",
14360
+ vendor: "Moonshot",
14361
+ hint: "~/.kimi-code/credentials/",
14362
+ watchPaths: () => [kimiCredentialsDir()],
14363
+ // Phase-2 OAuth capture: the `kimi` toolchain writes per-provider OAuth
14364
+ // JSON under this dir after `/login`. Until that flow is reverse-engineered
14365
+ // (blob format + refresh), file capture is a no-op — the shipping auth is
14366
+ // the API key (KIMI_API_KEY), delivered by the provisioner, not this
14367
+ // watcher. Returning null means "nothing captured here yet".
14368
+ extract: async () => null,
14369
+ validate: validateNonEmptyCredential
14370
+ };
14371
+ }
14372
+ loginLauncher() {
14373
+ return {
14374
+ async ensureInstalled() {
14375
+ return createOsStrategy().findInPath("kimi") !== null;
14376
+ },
14377
+ launch() {
14378
+ return (0, import_node_child_process12.spawn)("kimi", [], { stdio: "inherit" });
14379
+ }
14380
+ };
14381
+ }
14382
+ };
14383
+
14261
14384
  // src/agents/registry.ts
14262
14385
  var runtimeBuilders = {
14263
14386
  claude: (os48) => new ClaudeRuntimeStrategy(os48),
@@ -14265,7 +14388,8 @@ var runtimeBuilders = {
14265
14388
  coderabbit: (os48) => new CoderabbitRuntimeStrategy(os48),
14266
14389
  cursor: (os48) => new CursorRuntimeStrategy(os48),
14267
14390
  aider: (os48) => new AiderRuntimeStrategy(os48),
14268
- gemini: (os48) => new GeminiRuntimeStrategy(os48)
14391
+ gemini: (os48) => new GeminiRuntimeStrategy(os48),
14392
+ kimi: (os48) => new KimiRuntimeStrategy(os48)
14269
14393
  };
14270
14394
  var deployBuilders = {
14271
14395
  claude: () => new ClaudeDeployStrategy(),
@@ -14684,7 +14808,7 @@ async function linkDryRunPreflight(ctx) {
14684
14808
  }
14685
14809
 
14686
14810
  // src/commands/host-agent.ts
14687
- var import_node_child_process19 = require("child_process");
14811
+ var import_node_child_process20 = require("child_process");
14688
14812
  var os33 = __toESM(require("os"));
14689
14813
  var fs39 = __toESM(require("fs"));
14690
14814
  var path41 = __toESM(require("path"));
@@ -14696,8 +14820,8 @@ var path34 = __toESM(require("path"));
14696
14820
 
14697
14821
  // src/lib/restrict-to-owner.ts
14698
14822
  var import_node_fs5 = __toESM(require("fs"));
14699
- var import_node_os3 = __toESM(require("os"));
14700
- var import_node_child_process12 = require("child_process");
14823
+ var import_node_os4 = __toESM(require("os"));
14824
+ var import_node_child_process13 = require("child_process");
14701
14825
  var BROAD_WINDOWS_SIDS = [
14702
14826
  "*S-1-1-0",
14703
14827
  "*S-1-5-11",
@@ -14708,8 +14832,8 @@ var BROAD_WINDOWS_SIDS = [
14708
14832
  function restrictToOwner(filePath) {
14709
14833
  try {
14710
14834
  if (process.platform === "win32") {
14711
- const username = import_node_os3.default.userInfo().username;
14712
- (0, import_node_child_process12.execFileSync)(
14835
+ const username = import_node_os4.default.userInfo().username;
14836
+ (0, import_node_child_process13.execFileSync)(
14713
14837
  "icacls",
14714
14838
  [
14715
14839
  filePath,
@@ -14971,9 +15095,9 @@ async function reportDeployProgress(auth, deployId, step, message, sessionId) {
14971
15095
  var fs32 = __toESM(require("fs"));
14972
15096
  var os28 = __toESM(require("os"));
14973
15097
  var path35 = __toESM(require("path"));
14974
- var import_node_child_process13 = require("child_process");
15098
+ var import_node_child_process14 = require("child_process");
14975
15099
  var import_node_util4 = require("util");
14976
- var execFileP4 = (0, import_node_util4.promisify)(import_node_child_process13.execFile);
15100
+ var execFileP4 = (0, import_node_util4.promisify)(import_node_child_process14.execFile);
14977
15101
  function isAbsolutePathTarget(target) {
14978
15102
  return path35.isAbsolute(target);
14979
15103
  }
@@ -15111,7 +15235,8 @@ var PUBLIC_TO_INTERNAL_AGENT = {
15111
15235
  cursor: "cursor",
15112
15236
  aider: "aider",
15113
15237
  coderabbit: "coderabbit",
15114
- gemini: "gemini"
15238
+ gemini: "gemini",
15239
+ kimi: "kimi"
15115
15240
  };
15116
15241
  function toInternalAgentId(publicAgentId) {
15117
15242
  return PUBLIC_TO_INTERNAL_AGENT[publicAgentId] ?? null;
@@ -15204,8 +15329,20 @@ var cursorProvisioner = {
15204
15329
  return {};
15205
15330
  }
15206
15331
  };
15332
+ var kimiProvisioner = {
15333
+ write(auth, home) {
15334
+ const credentialsFile = path36.join(home, ".kimi-code", "credentials", "kimi.json");
15335
+ if (auth.kind === "api_key") {
15336
+ rmIfExists(credentialsFile);
15337
+ return { KIMI_API_KEY: auth.value };
15338
+ }
15339
+ writeFile0600(credentialsFile, auth.value);
15340
+ return {};
15341
+ }
15342
+ };
15207
15343
  var PROVISIONERS = {
15208
15344
  claude: claudeProvisioner,
15345
+ kimi: kimiProvisioner,
15209
15346
  codex: codexProvisioner,
15210
15347
  gemini: geminiProvisioner,
15211
15348
  cursor: cursorProvisioner
@@ -15227,7 +15364,7 @@ function provisionAgentCredentials(publicAgentId, auth, homeDir2 = os29.homedir(
15227
15364
  }
15228
15365
 
15229
15366
  // src/commands/host/git-tooling.ts
15230
- var import_node_child_process14 = require("child_process");
15367
+ var import_node_child_process15 = require("child_process");
15231
15368
  var fs34 = __toESM(require("fs"));
15232
15369
  var os30 = __toESM(require("os"));
15233
15370
  var path37 = __toESM(require("path"));
@@ -15341,7 +15478,7 @@ var defaultGitToolingRunner = {
15341
15478
  which(cmd) {
15342
15479
  try {
15343
15480
  const probe = process.platform === "win32" ? "where" : "which";
15344
- (0, import_node_child_process14.execFileSync)(probe, [cmd], { stdio: "ignore" });
15481
+ (0, import_node_child_process15.execFileSync)(probe, [cmd], { stdio: "ignore" });
15345
15482
  return true;
15346
15483
  } catch {
15347
15484
  return false;
@@ -15349,7 +15486,7 @@ var defaultGitToolingRunner = {
15349
15486
  },
15350
15487
  run(cmd, args2, opts = {}) {
15351
15488
  return new Promise((resolve7) => {
15352
- const child = (0, import_node_child_process14.spawn)(cmd, args2, {
15489
+ const child = (0, import_node_child_process15.spawn)(cmd, args2, {
15353
15490
  stdio: [opts.input !== void 0 ? "pipe" : "ignore", "ignore", "pipe"]
15354
15491
  });
15355
15492
  let stderr = "";
@@ -15503,12 +15640,12 @@ var HeadroomStatsReporter = class {
15503
15640
  };
15504
15641
 
15505
15642
  // src/commands/host/os-packages.ts
15506
- var import_node_child_process15 = require("child_process");
15643
+ var import_node_child_process16 = require("child_process");
15507
15644
  var PM_INSTALL_TIMEOUT_MS = 18e4;
15508
15645
  var defaultHeadroomRunner = {
15509
15646
  which(cmd) {
15510
15647
  try {
15511
- (0, import_node_child_process15.execFileSync)("which", [cmd], { stdio: "ignore" });
15648
+ (0, import_node_child_process16.execFileSync)("which", [cmd], { stdio: "ignore" });
15512
15649
  return true;
15513
15650
  } catch {
15514
15651
  return false;
@@ -15517,7 +15654,7 @@ var defaultHeadroomRunner = {
15517
15654
  run(cmd, args2, opts = {}) {
15518
15655
  return new Promise((resolve7) => {
15519
15656
  const spawnEnv = opts.env ?? process.env;
15520
- const child = (0, import_node_child_process15.spawn)(cmd, args2, { stdio: ["ignore", "pipe", "pipe"], env: spawnEnv });
15657
+ const child = (0, import_node_child_process16.spawn)(cmd, args2, { stdio: ["ignore", "pipe", "pipe"], env: spawnEnv });
15521
15658
  let stderrBuf = "";
15522
15659
  let stdoutBuf = "";
15523
15660
  let settled = false;
@@ -16024,14 +16161,14 @@ async function setupHeadroomForSelfHosted(agent, runner = defaultHeadroomRunner,
16024
16161
  }
16025
16162
 
16026
16163
  // src/commands/host/self-update.ts
16027
- var import_node_child_process17 = require("child_process");
16164
+ var import_node_child_process18 = require("child_process");
16028
16165
 
16029
16166
  // src/lib/updateNotifier.ts
16030
16167
  var fs37 = __toESM(require("fs"));
16031
16168
  var os32 = __toESM(require("os"));
16032
16169
  var path40 = __toESM(require("path"));
16033
16170
  var https6 = __toESM(require("https"));
16034
- var import_node_child_process16 = require("child_process");
16171
+ var import_node_child_process17 = require("child_process");
16035
16172
  var import_picocolors3 = __toESM(require("picocolors"));
16036
16173
  var PKG_NAME = "codeam-cli";
16037
16174
  var REGISTRY_URL = `https://registry.npmjs.org/${PKG_NAME}/latest`;
@@ -16125,7 +16262,7 @@ function notifyIfStale(currentVersion, latest) {
16125
16262
  }
16126
16263
  function isLinkedInstall() {
16127
16264
  try {
16128
- const root = (0, import_node_child_process16.execSync)("npm root -g", {
16265
+ const root = (0, import_node_child_process17.execSync)("npm root -g", {
16129
16266
  encoding: "utf8",
16130
16267
  stdio: ["ignore", "pipe", "ignore"],
16131
16268
  timeout: 2e3
@@ -16153,7 +16290,7 @@ function maybeAutoUpdate(currentVersion, latest) {
16153
16290
 
16154
16291
  `
16155
16292
  );
16156
- const install = (0, import_node_child_process16.spawnSync)("npm", ["install", "-g", `${PKG_NAME}@latest`], {
16293
+ const install = (0, import_node_child_process17.spawnSync)("npm", ["install", "-g", `${PKG_NAME}@latest`], {
16157
16294
  stdio: "inherit",
16158
16295
  env: process.env
16159
16296
  });
@@ -16174,7 +16311,7 @@ function maybeAutoUpdate(currentVersion, latest) {
16174
16311
  process.stderr.write(` ${import_picocolors3.default.green("\u2713")} Updated. Resuming session...
16175
16312
 
16176
16313
  `);
16177
- const child = (0, import_node_child_process16.spawnSync)("codeam", process.argv.slice(2), {
16314
+ const child = (0, import_node_child_process17.spawnSync)("codeam", process.argv.slice(2), {
16178
16315
  stdio: "inherit",
16179
16316
  env: process.env
16180
16317
  });
@@ -16184,7 +16321,7 @@ async function autoUpgradeBeforeCriticalCommand() {
16184
16321
  if (process.env.NODE_ENV === "test") return;
16185
16322
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
16186
16323
  if (process.env.CI) return;
16187
- const current = true ? "2.60.12" : null;
16324
+ const current = true ? "2.60.14" : null;
16188
16325
  if (!current) return;
16189
16326
  const cache = readCache();
16190
16327
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -16201,7 +16338,7 @@ function checkForUpdates() {
16201
16338
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
16202
16339
  if (process.env.CI) return;
16203
16340
  if (!process.stdout.isTTY) return;
16204
- const current = true ? "2.60.12" : null;
16341
+ const current = true ? "2.60.14" : null;
16205
16342
  if (!current) return;
16206
16343
  const cache = readCache();
16207
16344
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -16221,11 +16358,11 @@ var SELF_UPDATE_INTERVAL_MS = 60 * 60 * 1e3;
16221
16358
  var SELF_UPDATE_VIEW_TIMEOUT_MS = 3e4;
16222
16359
  var SELF_UPDATE_INSTALL_TIMEOUT_MS = 18e4;
16223
16360
  function currentCliVersion() {
16224
- return true ? "2.60.12" : null;
16361
+ return true ? "2.60.14" : null;
16225
16362
  }
16226
16363
  function runCmd(cmd, args2, timeoutMs) {
16227
16364
  return new Promise((resolve7) => {
16228
- (0, import_node_child_process17.execFile)(cmd, args2, { timeout: timeoutMs }, (err, stdout, stderr) => {
16365
+ (0, import_node_child_process18.execFile)(cmd, args2, { timeout: timeoutMs }, (err, stdout, stderr) => {
16229
16366
  const code = err && typeof err.code === "number" ? err.code : err ? null : 0;
16230
16367
  resolve7({ code, stdout: stdout ?? "", stderr: stderr ?? "" });
16231
16368
  });
@@ -16287,11 +16424,11 @@ async function runSelfUpdate() {
16287
16424
  }
16288
16425
 
16289
16426
  // src/commands/host/teardown.ts
16290
- var import_node_child_process18 = require("child_process");
16427
+ var import_node_child_process19 = require("child_process");
16291
16428
  var fs38 = __toESM(require("fs"));
16292
16429
  var defaultDisableService = () => {
16293
16430
  try {
16294
- (0, import_node_child_process18.execFileSync)("systemctl", ["disable", "--now", "codeam-host-agent"], { stdio: "ignore" });
16431
+ (0, import_node_child_process19.execFileSync)("systemctl", ["disable", "--now", "codeam-host-agent"], { stdio: "ignore" });
16295
16432
  } catch {
16296
16433
  }
16297
16434
  };
@@ -16299,7 +16436,7 @@ var defaultTeardownHeadroom = () => {
16299
16436
  try {
16300
16437
  const kind = JSON.parse(fs38.readFileSync(headroomConfigPath(), "utf8")).agent;
16301
16438
  if (kind) {
16302
- (0, import_node_child_process18.execFileSync)("headroom", ["unwrap", kind], { stdio: "ignore", timeout: 15e3 });
16439
+ (0, import_node_child_process19.execFileSync)("headroom", ["unwrap", kind], { stdio: "ignore", timeout: 15e3 });
16303
16440
  }
16304
16441
  } catch {
16305
16442
  }
@@ -16457,7 +16594,7 @@ var CONTROL_AGENT_META = {
16457
16594
  headroomWrappable: false,
16458
16595
  acp: false
16459
16596
  };
16460
- var defaultSpawner = (env, cwd, args2 = []) => (0, import_node_child_process19.spawn)(process.execPath, [process.argv[1], "pair-auto", ...args2], {
16597
+ var defaultSpawner = (env, cwd, args2 = []) => (0, import_node_child_process20.spawn)(process.execPath, [process.argv[1], "pair-auto", ...args2], {
16461
16598
  cwd,
16462
16599
  env: { ...process.env, ...env },
16463
16600
  stdio: ["ignore", "pipe", "pipe"],
@@ -16937,7 +17074,7 @@ var HostAgentSupervisor = class {
16937
17074
  runAgentInstall(script) {
16938
17075
  return new Promise((resolve7) => {
16939
17076
  const home = process.env.HOME || os33.homedir();
16940
- const child = (0, import_node_child_process19.spawn)("sh", ["-c", script], {
17077
+ const child = (0, import_node_child_process20.spawn)("sh", ["-c", script], {
16941
17078
  env: { ...process.env, HOME: home },
16942
17079
  stdio: ["ignore", "pipe", "pipe"]
16943
17080
  });
@@ -17245,11 +17382,11 @@ function makeRealApplyBudgetDeps() {
17245
17382
  var import_child_process14 = require("child_process");
17246
17383
  var import_fs = require("fs");
17247
17384
  var import_promises = __toESM(require("fs/promises"));
17248
- var import_os6 = __toESM(require("os"));
17385
+ var import_os7 = __toESM(require("os"));
17249
17386
  var import_path4 = __toESM(require("path"));
17250
17387
  var import_promises2 = require("stream/promises");
17251
17388
  var import_which = __toESM(require("which"));
17252
- var CACHED_BINARY = import_path4.default.join(import_os6.default.homedir(), ".codeam", "bin", "cloudflared");
17389
+ var CACHED_BINARY = import_path4.default.join(import_os7.default.homedir(), ".codeam", "bin", "cloudflared");
17253
17390
  async function resolveCloudflared(opts = {}) {
17254
17391
  try {
17255
17392
  return await (0, import_which.default)("cloudflared");
@@ -17349,7 +17486,7 @@ function decodeTunnelToken(token) {
17349
17486
  }
17350
17487
  async function spawnNamedTunnel(bin, token, port) {
17351
17488
  const creds = decodeTunnelToken(token);
17352
- const credDir = import_path4.default.join(import_os6.default.homedir(), ".codeam");
17489
+ const credDir = import_path4.default.join(import_os7.default.homedir(), ".codeam");
17353
17490
  await import_promises.default.mkdir(credDir, { recursive: true });
17354
17491
  const credFile = import_path4.default.join(credDir, `tunnel-${creds.TunnelID}.json`);
17355
17492
  await import_promises.default.writeFile(credFile, JSON.stringify(creds), { mode: 384 });
@@ -18969,6 +19106,9 @@ var AGENT_SETUP_RECIPE = {
18969
19106
  cursor: "cursor",
18970
19107
  aider: "aider",
18971
19108
  gemini: "gemini",
19109
+ // bd 1.0.5 has no Kimi recipe → skip (like coderabbit); beads still works,
19110
+ // the agent just isn't wired natively via `bd setup`.
19111
+ kimi: null,
18972
19112
  coderabbit: null
18973
19113
  };
18974
19114
  var _provisionSeam = {
@@ -19537,10 +19677,10 @@ async function handleBeadsActionCommand(action, started) {
19537
19677
 
19538
19678
  // src/beads/config-store.ts
19539
19679
  var import_node_fs6 = __toESM(require("fs"));
19540
- var import_node_os4 = __toESM(require("os"));
19541
- var import_node_path4 = __toESM(require("path"));
19680
+ var import_node_os5 = __toESM(require("os"));
19681
+ var import_node_path5 = __toESM(require("path"));
19542
19682
  function beadsConfigPath() {
19543
- return import_node_path4.default.join(import_node_os4.default.homedir(), ".codeam", "beads-config.json");
19683
+ return import_node_path5.default.join(import_node_os5.default.homedir(), ".codeam", "beads-config.json");
19544
19684
  }
19545
19685
  function readBeadsEnabled() {
19546
19686
  try {
@@ -19553,7 +19693,7 @@ function readBeadsEnabled() {
19553
19693
  }
19554
19694
  function persistBeadsConfig(cfg) {
19555
19695
  const file = beadsConfigPath();
19556
- import_node_fs6.default.mkdirSync(import_node_path4.default.dirname(file), { recursive: true });
19696
+ import_node_fs6.default.mkdirSync(import_node_path5.default.dirname(file), { recursive: true });
19557
19697
  const tmp = `${file}.tmp`;
19558
19698
  import_node_fs6.default.writeFileSync(tmp, JSON.stringify(cfg), { mode: 384 });
19559
19699
  import_node_fs6.default.renameSync(tmp, file);
@@ -21085,7 +21225,7 @@ function fail(msg) {
21085
21225
  `);
21086
21226
  process.exit(1);
21087
21227
  }
21088
- function readTokenFromArgs(args2) {
21228
+ function resolveTokenValue(args2) {
21089
21229
  const inline = args2.find((a) => a.startsWith("--token="));
21090
21230
  if (inline) {
21091
21231
  const value = inline.slice("--token=".length).trim();
@@ -21106,6 +21246,11 @@ function readTokenFromArgs(args2) {
21106
21246
  if (process.env.CODEAM_AUTO_TOKEN) return process.env.CODEAM_AUTO_TOKEN;
21107
21247
  fail("codeam pair-auto requires --token-file=<path>, --token=<value>, or CODEAM_AUTO_TOKEN env");
21108
21248
  }
21249
+ function readTokenFromArgs(args2) {
21250
+ const token = resolveTokenValue(args2);
21251
+ process.env.CODEAM_AUTO_TOKEN = token;
21252
+ return token;
21253
+ }
21109
21254
  var CLAIM_TIMEOUT_MS = 15e3;
21110
21255
  var RETRY_BACKOFF_MS2 = 2e3;
21111
21256
  function networkError(msg, cause) {
@@ -21335,7 +21480,7 @@ async function pairAuto(args2) {
21335
21480
  }
21336
21481
 
21337
21482
  // src/services/headroom/wrap-launch.ts
21338
- var import_node_child_process20 = require("child_process");
21483
+ var import_node_child_process21 = require("child_process");
21339
21484
  function wrapWithHeadroom(launch, opts) {
21340
21485
  if (!opts.enabled || !opts.headroomPresent) return launch;
21341
21486
  return {
@@ -21348,7 +21493,7 @@ var _present;
21348
21493
  function headroomPresent() {
21349
21494
  if (_present !== void 0) return Promise.resolve(_present);
21350
21495
  return new Promise((resolve7) => {
21351
- (0, import_node_child_process20.execFile)("headroom", ["--version"], (err) => {
21496
+ (0, import_node_child_process21.execFile)("headroom", ["--version"], (err) => {
21352
21497
  _present = !err;
21353
21498
  resolve7(_present);
21354
21499
  });
@@ -21702,7 +21847,7 @@ var path57 = __toESM(require("path"));
21702
21847
 
21703
21848
  // src/agents/acp/agent-binary.ts
21704
21849
  var import_fs4 = __toESM(require("fs"));
21705
- var import_os7 = __toESM(require("os"));
21850
+ var import_os8 = __toESM(require("os"));
21706
21851
  var import_path8 = __toESM(require("path"));
21707
21852
  var import_child_process25 = require("child_process");
21708
21853
  function currentPlatformKey() {
@@ -21798,7 +21943,7 @@ function resolveCursorAgentBinary(deps = {}) {
21798
21943
  const exe = import_path8.default.win32.join(localAppData, "cursor-agent", "cursor-agent.exe");
21799
21944
  return existsSync25(exe) ? exe : null;
21800
21945
  }
21801
- const home = deps.homedir ?? import_os7.default.homedir();
21946
+ const home = deps.homedir ?? import_os8.default.homedir();
21802
21947
  const unix = import_path8.default.posix.join(home, ".local", "bin", "cursor-agent");
21803
21948
  return existsSync25(unix) ? unix : null;
21804
21949
  }
@@ -21955,6 +22100,19 @@ var REGISTRY = {
21955
22100
  args: ["--skip-trust", "--acp"],
21956
22101
  requiresAgentBinary: "gemini",
21957
22102
  waitForBinary: (o) => waitForCommandOnPath("gemini", o)
22103
+ }),
22104
+ // Kimi Code (Moonshot) speaks ACP natively via `kimi acp` — a stdio
22105
+ // JSON-RPC server that answers `initialize` (agentInfo `Kimi Code CLI`,
22106
+ // capabilities, authMethods) and prints no TUI banner. No npm adapter, just
22107
+ // the user-installed `kimi` binary on PATH. Same {@link AdapterSpec} shape as
22108
+ // gemini/cursor. Auth (KIMI_API_KEY env, or the ~/.kimi-code/credentials
22109
+ // login-state file) reaches kimi because the ACP client spawns the adapter
22110
+ // with `env: { ...process.env, ...extraEnv }`.
22111
+ kimi: () => ({
22112
+ command: "kimi",
22113
+ args: ["acp"],
22114
+ requiresAgentBinary: "kimi",
22115
+ waitForBinary: (o) => waitForCommandOnPath("kimi", o)
21958
22116
  })
21959
22117
  };
21960
22118
  function getAcpAdapter(agent) {
@@ -22546,7 +22704,7 @@ var HistoryService = class _HistoryService {
22546
22704
  };
22547
22705
 
22548
22706
  // src/agents/acp/client.ts
22549
- var import_node_child_process21 = require("child_process");
22707
+ var import_node_child_process22 = require("child_process");
22550
22708
  var fs55 = __toESM(require("fs/promises"));
22551
22709
  var fsSync = __toESM(require("fs"));
22552
22710
  var os44 = __toESM(require("os"));
@@ -25150,7 +25308,7 @@ var AcpClient = class {
25150
25308
  "acpClient",
25151
25309
  `spawn cmd=${adapter.command} args=[${adapter.args.join(",")}] cwd=${cwd}`
25152
25310
  );
25153
- const child = (0, import_node_child_process21.spawn)(adapter.command, adapter.args, {
25311
+ const child = (0, import_node_child_process22.spawn)(adapter.command, adapter.args, {
25154
25312
  cwd,
25155
25313
  // extraEnv (e.g. CLAUDE_CODE_DISABLE_1M_CONTEXT=1 on an on-demand
25156
25314
  // re-spawn) layers over process.env; PATH stays last so the augmented
@@ -25588,12 +25746,12 @@ function buildRelaunchProxyEnv(baseEnv) {
25588
25746
  return env;
25589
25747
  }
25590
25748
  var relaunchProxyWithoutBudget = async () => {
25591
- const { spawn: spawn38 } = await import("child_process");
25749
+ const { spawn: spawn39 } = await import("child_process");
25592
25750
  killHeadroomProxy();
25593
25751
  await new Promise((r) => setTimeout(r, 500));
25594
25752
  const proxyEnv = buildRelaunchProxyEnv(process.env);
25595
25753
  try {
25596
- const proxy = spawn38(
25754
+ const proxy = spawn39(
25597
25755
  "headroom",
25598
25756
  ["proxy", "--port", "8787"],
25599
25757
  { stdio: "ignore", detached: true, env: proxyEnv }
@@ -26534,7 +26692,7 @@ async function discoverRepos(workingDir, maxDepth = 4) {
26534
26692
  // src/services/turn-files/files-outbox.ts
26535
26693
  var fs58 = __toESM(require("fs/promises"));
26536
26694
  var path62 = __toESM(require("path"));
26537
- var import_os8 = require("os");
26695
+ var import_os9 = require("os");
26538
26696
  var HOME_OUTBOX_DIR = ".codeam/outbox";
26539
26697
  var MAX_AGE_MS = 24 * 60 * 60 * 1e3;
26540
26698
  var BACKOFF_STEPS_MS = [
@@ -26701,7 +26859,7 @@ function applyJitter(ms) {
26701
26859
  return Math.round(ms * factor);
26702
26860
  }
26703
26861
  function homeDir() {
26704
- return process.env.HOME ?? process.env.USERPROFILE ?? (0, import_os8.tmpdir)();
26862
+ return process.env.HOME ?? process.env.USERPROFILE ?? (0, import_os9.tmpdir)();
26705
26863
  }
26706
26864
 
26707
26865
  // src/services/turn-files/turn-file-aggregator.ts
@@ -32995,7 +33153,7 @@ function checkChokidar() {
32995
33153
  }
32996
33154
  async function doctor(args2 = []) {
32997
33155
  const json = args2.includes("--json");
32998
- const cliVersion = true ? "2.60.12" : "0.0.0-dev";
33156
+ const cliVersion = true ? "2.60.14" : "0.0.0-dev";
32999
33157
  const apiBase2 = resolveApiBaseUrl();
33000
33158
  const diagnosticId = (0, import_node_crypto10.randomUUID)();
33001
33159
  log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
@@ -33194,7 +33352,7 @@ async function completion(args2) {
33194
33352
  // src/commands/version.ts
33195
33353
  var import_picocolors15 = __toESM(require("picocolors"));
33196
33354
  function version2() {
33197
- const v = true ? "2.60.12" : "unknown";
33355
+ const v = true ? "2.60.14" : "unknown";
33198
33356
  console.log(`${import_picocolors15.default.bold("codeam-cli")} ${import_picocolors15.default.cyan(v)}`);
33199
33357
  }
33200
33358
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeam-cli",
3
- "version": "2.60.12",
3
+ "version": "2.60.14",
4
4
  "description": "Workflow-continuity bridge for AI coding agents. Wrap Claude Code or Codex in a PTY and supervise, approve, and redirect the session from any device — async. The terminal companion for CodeAgent Mobile.",
5
5
  "type": "commonjs",
6
6
  "main": "dist/index.js",