codeam-cli 2.61.23 → 2.61.25

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/CHANGELOG.md CHANGED
@@ -4,6 +4,45 @@ 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.61.24] — 2026-07-22
8
+
9
+ ### Chore
10
+
11
+ - **cli:** Declare yaml as devDependency (skills materialize test)
12
+ - **deps:** Bump actions/setup-node from 4 to 7 (#452)
13
+ - **deps-dev:** Bump typescript from 6.0.3 to 7.0.2 in /apps/cli (#432)
14
+ - **deps-dev:** Bump typescript from 6.0.3 to 7.0.2 in /apps/vsc-plugin (#430)
15
+ - **deps:** Bump org.jetbrains.kotlin.jvm in /apps/jetbrains-plugin (#453)
16
+ - **deps:** Bump ignore from 5.3.2 to 7.0.6 in /apps/cli (#323)
17
+ - **deps:** Bump org.jetbrains.intellij.platform (#454)
18
+
19
+ ### Fixed
20
+
21
+ - **cli:** Break self-hosted enroll-token crash-loop on identity self-heal
22
+
23
+ ## [2.61.23] — 2026-07-20
24
+
25
+ ### Added
26
+
27
+ - **shared:** Add Agent Skills wire types (SkillDefinition, SkillsManifest)
28
+ - **shared:** Seed SKILL_REGISTRY with code-review + resolve-conflicts
29
+ - **cli:** Skills.json manifest read/persist/clear util
30
+ - **cli:** Materialize curated SKILL.md bundles under $HOME (namespaced)
31
+ - **cli:** ProvisionSkillsForStart materializes skills before agent spawn
32
+ - **cli:** Persist self-hosted deploy skills manifest to skills.json
33
+ - **cli:** Skills_configure relay command (add/remove/list) in both registries
34
+ - **shared:** Add skillIds to AgentReviewPlan wire type
35
+
36
+ ### Fixed
37
+
38
+ - **cli:** SKILL.md frontmatter name must match codeam-<id> skill dir
39
+ - **cli:** ConfigureSkill rejects unknown action instead of destructive remove fall-through
40
+ - **cli:** Quote SKILL.md description (valid YAML) + harden skills manifest read
41
+
42
+ ### Tests
43
+
44
+ - **cli:** Make skills path assertions separator-agnostic (Windows CI)
45
+
7
46
  ## [2.61.21] — 2026-07-18
8
47
 
9
48
  ### Added
package/dist/index.js CHANGED
@@ -6117,7 +6117,7 @@ function readAnonId() {
6117
6117
  }
6118
6118
  function superProperties() {
6119
6119
  return {
6120
- cliVersion: true ? "2.61.23" : "0.0.0-dev",
6120
+ cliVersion: true ? "2.61.25" : "0.0.0-dev",
6121
6121
  nodeVersion: process.version,
6122
6122
  platform: process.platform,
6123
6123
  arch: process.arch,
@@ -6298,7 +6298,7 @@ var os4 = __toESM(require("os"));
6298
6298
  // package.json
6299
6299
  var package_default = {
6300
6300
  name: "codeam-cli",
6301
- version: "2.61.23",
6301
+ version: "2.61.25",
6302
6302
  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.",
6303
6303
  type: "commonjs",
6304
6304
  main: "dist/index.js",
@@ -6375,7 +6375,7 @@ var package_default = {
6375
6375
  "@agentclientprotocol/sdk": "1.2.1",
6376
6376
  "@clack/prompts": "^1.2.0",
6377
6377
  chokidar: "^3.6.0",
6378
- ignore: "^5.3.2",
6378
+ ignore: "^7.0.6",
6379
6379
  picocolors: "^1.1.0",
6380
6380
  "qrcode-terminal": "^0.12.0",
6381
6381
  which: "^6.0.0",
@@ -6394,8 +6394,9 @@ var package_default = {
6394
6394
  "@vitest/coverage-v8": "^4.1.7",
6395
6395
  "node-pty": "^1.1.0",
6396
6396
  tsup: "^8.0.0",
6397
- typescript: "^6.0.3",
6398
- vitest: "^4.1.5"
6397
+ typescript: "^7.0.2",
6398
+ vitest: "^4.1.5",
6399
+ yaml: "^2.9.0"
6399
6400
  }
6400
6401
  };
6401
6402
 
@@ -7088,16 +7089,18 @@ var API_BASE2 = resolveApiBaseUrl();
7088
7089
  var SSE_LIVENESS_TIMEOUT_MS = 45e3;
7089
7090
  var SSE_WATCHDOG_INTERVAL_MS = 1e4;
7090
7091
  var CommandRelayService = class _CommandRelayService {
7091
- constructor(pluginId, onCommand, agentMeta, agentsOverride) {
7092
+ constructor(pluginId, onCommand, agentMeta, agentsOverride, explicitPollSecret) {
7092
7093
  this.pluginId = pluginId;
7093
7094
  this.onCommand = onCommand;
7094
7095
  this.agentMeta = agentMeta;
7095
7096
  this.agentsOverride = agentsOverride;
7097
+ this.explicitPollSecret = explicitPollSecret;
7096
7098
  }
7097
7099
  pluginId;
7098
7100
  onCommand;
7099
7101
  agentMeta;
7100
7102
  agentsOverride;
7103
+ explicitPollSecret;
7101
7104
  _running = false;
7102
7105
  pairingInvalid = false;
7103
7106
  heartbeatTimer = null;
@@ -7389,6 +7392,10 @@ var CommandRelayService = class _CommandRelayService {
7389
7392
  // backends (which ignore it).
7390
7393
  pollSecretHeader() {
7391
7394
  const headers = { "X-Codeam-Cmd-Ack": "1" };
7395
+ if (this.explicitPollSecret) {
7396
+ headers["X-Plugin-Poll-Secret"] = this.explicitPollSecret;
7397
+ return headers;
7398
+ }
7392
7399
  try {
7393
7400
  const secret = loadCliConfig().sessions.find(
7394
7401
  (s) => s.pluginId === this.pluginId
@@ -7462,7 +7469,7 @@ var CommandRelayService = class _CommandRelayService {
7462
7469
  // fresh + clear the "CLI update available" banner after a self-update
7463
7470
  // (a codespace that reinstalls @latest reconnects via heartbeat, not
7464
7471
  // pair/reconnect). Older backends ignore the extra field.
7465
- ..."2.61.23" ? { ideVersion: "2.61.23" } : {}
7472
+ ..."2.61.25" ? { ideVersion: "2.61.25" } : {}
7466
7473
  }).then(() => log.trace("relay", `heartbeat ok online=${online}`)).catch((err) => log.trace("relay", `heartbeat failed online=${online}`, err));
7467
7474
  }
7468
7475
  /**
@@ -16763,10 +16770,34 @@ function persistOrClearSkillsFromPayload(skills) {
16763
16770
  else clearSkillsManifest();
16764
16771
  }
16765
16772
 
16773
+ // src/lib/process-guards.ts
16774
+ var installed = false;
16775
+ function installRelayCrashGuards() {
16776
+ if (installed) return;
16777
+ installed = true;
16778
+ process.on("unhandledRejection", (reason) => {
16779
+ log.error("process", `unhandledRejection \u2014 relay kept alive \u2014 ${describeReason(reason)}`);
16780
+ });
16781
+ process.on("uncaughtException", (err) => {
16782
+ log.error("process", `uncaughtException \u2014 relay kept alive \u2014 ${describeReason(err)}`);
16783
+ });
16784
+ }
16785
+ function describeReason(reason) {
16786
+ if (reason instanceof Error) {
16787
+ return reason.stack ?? `${reason.name}: ${reason.message}`;
16788
+ }
16789
+ try {
16790
+ return typeof reason === "string" ? reason : JSON.stringify(reason);
16791
+ } catch {
16792
+ return String(reason);
16793
+ }
16794
+ }
16795
+
16766
16796
  // src/commands/host/host-client.ts
16767
16797
  var fs35 = __toESM(require("fs"));
16768
16798
  var os31 = __toESM(require("os"));
16769
16799
  var path39 = __toESM(require("path"));
16800
+ var import_node_crypto9 = require("crypto");
16770
16801
  function sampleCpuTimes() {
16771
16802
  let idle = 0;
16772
16803
  let total = 0;
@@ -16829,7 +16860,13 @@ function loadHostIdentity() {
16829
16860
  const parsed = JSON.parse(raw);
16830
16861
  if (typeof parsed === "object" && parsed !== null && typeof parsed.hostId === "string" && typeof parsed.hostToken === "string" && typeof parsed.controlPluginId === "string") {
16831
16862
  const p2 = parsed;
16832
- return { hostId: p2.hostId, hostToken: p2.hostToken, controlPluginId: p2.controlPluginId };
16863
+ return {
16864
+ hostId: p2.hostId,
16865
+ hostToken: p2.hostToken,
16866
+ controlPluginId: p2.controlPluginId,
16867
+ // Optional — absent on identities sealed by a pre-secret CLI.
16868
+ ...typeof p2.controlPollSecret === "string" ? { controlPollSecret: p2.controlPollSecret } : {}
16869
+ };
16833
16870
  }
16834
16871
  return null;
16835
16872
  } catch {
@@ -16912,15 +16949,21 @@ function resolveHostLabel(label) {
16912
16949
  return resolved.slice(0, 80);
16913
16950
  }
16914
16951
  async function redeemEnrollToken(token, label) {
16952
+ const controlPollSecret = (0, import_node_crypto9.randomBytes)(32).toString("base64url");
16953
+ const pluginSecretHash = (0, import_node_crypto9.createHash)("sha256").update(controlPollSecret).digest("hex");
16915
16954
  const data = await postJson("/api/self-hosted/redeem", {
16916
16955
  token,
16917
16956
  label: resolveHostLabel(label),
16918
- osInfo: collectOsInfo()
16957
+ osInfo: collectOsInfo(),
16958
+ // OPTIONAL + backward-compatible: older backends ignore the unknown field
16959
+ // and keep the pre-existing (no-secret) control-channel behavior.
16960
+ pluginSecretHash
16919
16961
  });
16920
16962
  return {
16921
16963
  hostId: data.hostId,
16922
16964
  hostToken: data.hostToken,
16923
- controlPluginId: data.controlPluginId
16965
+ controlPluginId: data.controlPluginId,
16966
+ controlPollSecret
16924
16967
  };
16925
16968
  }
16926
16969
  async function sendHostHeartbeat(identity, metrics) {
@@ -18288,7 +18331,7 @@ async function autoUpgradeBeforeCriticalCommand() {
18288
18331
  if (process.env.NODE_ENV === "test") return;
18289
18332
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
18290
18333
  if (process.env.CI) return;
18291
- const current = true ? "2.61.23" : null;
18334
+ const current = true ? "2.61.25" : null;
18292
18335
  if (!current) return;
18293
18336
  const cache = readCache();
18294
18337
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -18305,7 +18348,7 @@ function checkForUpdates() {
18305
18348
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
18306
18349
  if (process.env.CI) return;
18307
18350
  if (!process.stdout.isTTY) return;
18308
- const current = true ? "2.61.23" : null;
18351
+ const current = true ? "2.61.25" : null;
18309
18352
  if (!current) return;
18310
18353
  const cache = readCache();
18311
18354
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -18325,7 +18368,7 @@ var SELF_UPDATE_INTERVAL_MS = 60 * 60 * 1e3;
18325
18368
  var SELF_UPDATE_VIEW_TIMEOUT_MS = 3e4;
18326
18369
  var SELF_UPDATE_INSTALL_TIMEOUT_MS = 18e4;
18327
18370
  function currentCliVersion() {
18328
- return true ? "2.61.23" : null;
18371
+ return true ? "2.61.25" : null;
18329
18372
  }
18330
18373
  function runCmd(cmd, args2, timeoutMs) {
18331
18374
  return new Promise((resolve8) => {
@@ -18652,8 +18695,12 @@ var defaultResumeSpawner = (env, cwd) => (0, import_node_child_process24.spawn)(
18652
18695
  detached: false
18653
18696
  });
18654
18697
  var defaultOnIdentityRejected = () => {
18698
+ defaultDisableService();
18655
18699
  deleteHostIdentity();
18656
- log.warn("host-agent", "host identity rejected by backend \u2014 wiped sealed identity, exiting");
18700
+ log.warn(
18701
+ "host-agent",
18702
+ "host identity rejected by backend \u2014 disabled service + wiped sealed identity, exiting"
18703
+ );
18657
18704
  process.exit(1);
18658
18705
  };
18659
18706
  var defaultOnUpdated = (version3) => {
@@ -18733,11 +18780,12 @@ var HostAgentSupervisor = class {
18733
18780
  }
18734
18781
  /** Open the control channel (reusing the relay) + start heartbeats. */
18735
18782
  start() {
18736
- const make = this.deps.makeRelay ?? ((pluginId, onCommand, meta) => new CommandRelayService(pluginId, onCommand, meta));
18783
+ const make = this.deps.makeRelay ?? ((pluginId, onCommand, meta, pollSecret) => new CommandRelayService(pluginId, onCommand, meta, void 0, pollSecret));
18737
18784
  this.relay = make(
18738
18785
  this.identity.controlPluginId,
18739
18786
  (cmd) => this.handleCommand(cmd),
18740
- CONTROL_AGENT_META
18787
+ CONTROL_AGENT_META,
18788
+ this.identity.controlPollSecret
18741
18789
  );
18742
18790
  this.relay.start();
18743
18791
  void this.beat();
@@ -19072,10 +19120,13 @@ var HostAgentSupervisor = class {
19072
19120
  "CODEAM_HOST_LABEL=CodeAgent Box",
19073
19121
  // The enroll token above is a SINGLE-USE bootstrap, but it lives in the
19074
19122
  // container's fixed env — it can't be stripped after first boot like the
19075
- // self-hosted systemd unit does. This flag tells `resolveHostIdentity`
19076
- // that on a restart (docker restart / reboot / fleet_start_box wake) an
19077
- // expired-token redeem is EXPECTED: resume from the sealed identity
19078
- // instead of dying with "token expired". Not a secret → plain KEY=value.
19123
+ // self-hosted systemd unit does, so on every restart (docker restart /
19124
+ // reboot / fleet_start_box wake) the redeem terminally expires.
19125
+ // `resolveHostIdentity` now resumes from a sealed identity on ANY
19126
+ // terminal enroll-token rejection (not just ephemeral boxes see its
19127
+ // doc comment), so this flag is no longer load-bearing for that
19128
+ // decision; kept set for observability/back-compat with older CLI
19129
+ // builds that still gate on it. Not a secret → plain KEY=value.
19079
19130
  "-e",
19080
19131
  "CODEAM_ENROLL_EPHEMERAL=1",
19081
19132
  image
@@ -19522,10 +19573,10 @@ async function resolveHostIdentity(enrollToken) {
19522
19573
  return identity;
19523
19574
  } catch (err) {
19524
19575
  if (isTerminalEnrollError(err)) {
19525
- if (existing && process.env.CODEAM_ENROLL_EPHEMERAL === "1") {
19576
+ if (existing) {
19526
19577
  log.info(
19527
19578
  "host-agent",
19528
- "ephemeral enroll token expired on restart; resuming from sealed identity"
19579
+ "enroll token terminally rejected (expired/replayed) but a sealed identity is present; resuming from it \u2014 likely a restart, not a re-enroll"
19529
19580
  );
19530
19581
  return existing;
19531
19582
  }
@@ -19549,6 +19600,7 @@ async function resolveHostIdentity(enrollToken) {
19549
19600
  return null;
19550
19601
  }
19551
19602
  async function hostAgent(args2 = []) {
19603
+ installRelayCrashGuards();
19552
19604
  const tokenArg = args2.find((a) => a.startsWith("--token="));
19553
19605
  const enrollToken = (tokenArg ? tokenArg.slice("--token=".length).trim() : "") || process.env.CODEAM_ENROLL_TOKEN || void 0;
19554
19606
  const identity = await resolveHostIdentity(enrollToken);
@@ -23809,29 +23861,6 @@ function buildKeepAlive(ctx) {
23809
23861
  };
23810
23862
  }
23811
23863
 
23812
- // src/lib/process-guards.ts
23813
- var installed = false;
23814
- function installRelayCrashGuards() {
23815
- if (installed) return;
23816
- installed = true;
23817
- process.on("unhandledRejection", (reason) => {
23818
- log.error("process", `unhandledRejection \u2014 relay kept alive \u2014 ${describeReason(reason)}`);
23819
- });
23820
- process.on("uncaughtException", (err) => {
23821
- log.error("process", `uncaughtException \u2014 relay kept alive \u2014 ${describeReason(err)}`);
23822
- });
23823
- }
23824
- function describeReason(reason) {
23825
- if (reason instanceof Error) {
23826
- return reason.stack ?? `${reason.name}: ${reason.message}`;
23827
- }
23828
- try {
23829
- return typeof reason === "string" ? reason : JSON.stringify(reason);
23830
- } catch {
23831
- return String(reason);
23832
- }
23833
- }
23834
-
23835
23864
  // src/commands/start-infra-only.ts
23836
23865
  var INFRA_ONLY_COMMAND_TYPES = /* @__PURE__ */ new Set([
23837
23866
  // File ops (drive the dashboard's Files panel + open-file).
@@ -25020,7 +25049,7 @@ async function resolveAcpAdapterWithRetry(agent, opts = {}) {
25020
25049
  }
25021
25050
 
25022
25051
  // src/agents/acp/runner.ts
25023
- var import_node_crypto10 = require("crypto");
25052
+ var import_node_crypto11 = require("crypto");
25024
25053
 
25025
25054
  // src/services/history.service.ts
25026
25055
  var fs60 = __toESM(require("fs"));
@@ -31121,7 +31150,7 @@ async function runOnboardingTurn(opts) {
31121
31150
  }
31122
31151
 
31123
31152
  // src/agents/acp/mappers.ts
31124
- var import_node_crypto9 = require("crypto");
31153
+ var import_node_crypto10 = require("crypto");
31125
31154
  function mapSessionUpdate(notification) {
31126
31155
  const update = notification.update;
31127
31156
  switch (update.sessionUpdate) {
@@ -31184,7 +31213,7 @@ function mapPermissionRequest(request) {
31184
31213
  }
31185
31214
  return {
31186
31215
  event: {
31187
- questionId: (0, import_node_crypto9.randomUUID)(),
31216
+ questionId: (0, import_node_crypto10.randomUUID)(),
31188
31217
  prompt,
31189
31218
  options: labels.length > 0 ? labels : void 0
31190
31219
  },
@@ -31194,7 +31223,7 @@ function mapPermissionRequest(request) {
31194
31223
  }
31195
31224
  function messageChunkId(messageId) {
31196
31225
  if (typeof messageId === "string" && messageId.length > 0) return messageId;
31197
- return (0, import_node_crypto9.randomUUID)();
31226
+ return (0, import_node_crypto10.randomUUID)();
31198
31227
  }
31199
31228
  function extractText4(content) {
31200
31229
  if (!content || typeof content !== "object") return null;
@@ -33188,7 +33217,7 @@ var AcpHistory = class {
33188
33217
  this.summary = trimmed.length > 120 ? trimmed.slice(0, 117) + "\u2026" : trimmed;
33189
33218
  }
33190
33219
  this.messages.push({
33191
- id: (0, import_node_crypto10.randomUUID)(),
33220
+ id: (0, import_node_crypto11.randomUUID)(),
33192
33221
  role: "user",
33193
33222
  text,
33194
33223
  timestamp: Date.now()
@@ -33197,7 +33226,7 @@ var AcpHistory = class {
33197
33226
  appendAgentReply(text) {
33198
33227
  if (text.length === 0) return;
33199
33228
  this.messages.push({
33200
- id: (0, import_node_crypto10.randomUUID)(),
33229
+ id: (0, import_node_crypto11.randomUUID)(),
33201
33230
  role: "agent",
33202
33231
  text,
33203
33232
  timestamp: Date.now()
@@ -33415,7 +33444,7 @@ async function runAcpSession(opts) {
33415
33444
  currentIndex: 0,
33416
33445
  done: true
33417
33446
  }),
33418
- publishAwaitingAnswer: (prompt, options) => publisher.publishAwaitingAnswer({ questionId: (0, import_node_crypto10.randomUUID)(), prompt, options }),
33447
+ publishAwaitingAnswer: (prompt, options) => publisher.publishAwaitingAnswer({ questionId: (0, import_node_crypto11.randomUUID)(), prompt, options }),
33419
33448
  publishRawChunk: (chunk) => publisher.publishOutput(chunk),
33420
33449
  sendResult: (commandId, status2, result) => relay.sendResult(commandId, status2, result),
33421
33450
  appendAgentReply: (text) => history.appendAgentReply(text),
@@ -34902,7 +34931,7 @@ var NativeTuiDriver = class _NativeTuiDriver {
34902
34931
  };
34903
34932
 
34904
34933
  // src/baton/acp-driver.ts
34905
- var import_node_crypto11 = require("crypto");
34934
+ var import_node_crypto12 = require("crypto");
34906
34935
  var AcpDriver = class {
34907
34936
  constructor(deps) {
34908
34937
  this.deps = deps;
@@ -34995,7 +35024,7 @@ var AcpDriver = class {
34995
35024
  currentIndex: 0,
34996
35025
  done: true
34997
35026
  }),
34998
- publishAwaitingAnswer: (prompt, options) => publisher.publishAwaitingAnswer({ questionId: (0, import_node_crypto11.randomUUID)(), prompt, options }),
35027
+ publishAwaitingAnswer: (prompt, options) => publisher.publishAwaitingAnswer({ questionId: (0, import_node_crypto12.randomUUID)(), prompt, options }),
34999
35028
  publishRawChunk: (chunk) => publisher.publishOutput(chunk),
35000
35029
  sendResult: (commandId, status2, result) => relay.sendResult(commandId, status2, result),
35001
35030
  appendAgentReply: (text) => history.appendAgentReply(text),
@@ -38162,7 +38191,7 @@ async function invite() {
38162
38191
  // src/commands/doctor.ts
38163
38192
  var import_node_dns = require("dns");
38164
38193
  var import_node_util5 = require("util");
38165
- var import_node_crypto12 = require("crypto");
38194
+ var import_node_crypto13 = require("crypto");
38166
38195
  var fs68 = __toESM(require("fs"));
38167
38196
  var path76 = __toESM(require("path"));
38168
38197
  var import_picocolors14 = __toESM(require("picocolors"));
@@ -38332,9 +38361,9 @@ function checkChokidar() {
38332
38361
  }
38333
38362
  async function doctor(args2 = []) {
38334
38363
  const json = args2.includes("--json");
38335
- const cliVersion = true ? "2.61.23" : "0.0.0-dev";
38364
+ const cliVersion = true ? "2.61.25" : "0.0.0-dev";
38336
38365
  const apiBase2 = resolveApiBaseUrl();
38337
- const diagnosticId = (0, import_node_crypto12.randomUUID)();
38366
+ const diagnosticId = (0, import_node_crypto13.randomUUID)();
38338
38367
  log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
38339
38368
  const [dns, health] = await Promise.all([
38340
38369
  checkDns(apiBase2),
@@ -38843,7 +38872,7 @@ async function mcpRun(args2) {
38843
38872
  // src/commands/version.ts
38844
38873
  var import_picocolors15 = __toESM(require("picocolors"));
38845
38874
  function version2() {
38846
- const v = true ? "2.61.23" : "unknown";
38875
+ const v = true ? "2.61.25" : "unknown";
38847
38876
  console.log(`${import_picocolors15.default.bold("codeam-cli")} ${import_picocolors15.default.cyan(v)}`);
38848
38877
  }
38849
38878
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeam-cli",
3
- "version": "2.61.23",
3
+ "version": "2.61.25",
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",
@@ -77,7 +77,7 @@
77
77
  "@agentclientprotocol/sdk": "1.2.1",
78
78
  "@clack/prompts": "^1.2.0",
79
79
  "chokidar": "^3.6.0",
80
- "ignore": "^5.3.2",
80
+ "ignore": "^7.0.6",
81
81
  "picocolors": "^1.1.0",
82
82
  "qrcode-terminal": "^0.12.0",
83
83
  "which": "^6.0.0",
@@ -96,7 +96,8 @@
96
96
  "@vitest/coverage-v8": "^4.1.7",
97
97
  "node-pty": "^1.1.0",
98
98
  "tsup": "^8.0.0",
99
- "typescript": "^6.0.3",
100
- "vitest": "^4.1.5"
99
+ "typescript": "^7.0.2",
100
+ "vitest": "^4.1.5",
101
+ "yaml": "^2.9.0"
101
102
  }
102
103
  }