codeam-cli 2.76.37 → 2.76.39

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,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.76.38] — 2026-10-29
8
+
9
+ ### Performance
10
+
11
+ - **cli:** Coalesce streaming-chunk posts per chunkId (latest wins, one in flight)
12
+
13
+ ## [2.76.37] — 2026-10-26
14
+
15
+ ### Fixed
16
+
17
+ - **cli:** Require cloudflared >= 2026.10.2 for previews (#994)
18
+
7
19
  ## [2.76.36] — 2026-10-25
8
20
 
9
21
  ### Added
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/codeam-cli.svg?color=34d399&style=flat-square)](https://www.npmjs.com/package/codeam-cli)
4
4
  [![npm downloads](https://img.shields.io/npm/dm/codeam-cli.svg?color=34d399&style=flat-square)](https://www.npmjs.com/package/codeam-cli)
5
- [![license](https://img.shields.io/npm/l/codeam-cli.svg?color=34d399&style=flat-square)](https://github.com/edgar-durand/codeagent-mobile-clients/blob/main/LICENSE)
5
+ [![license](https://img.shields.io/npm/l/codeam-cli.svg?color=34d399&style=flat-square)](https://github.com/CodeAgentMobile/codeagent-mobile-clients/blob/main/LICENSE)
6
6
  [![node](https://img.shields.io/node/v/codeam-cli.svg?color=34d399&style=flat-square)](https://nodejs.org/)
7
7
 
8
8
  > **The workflow-continuity bridge for AI coding agents.**
@@ -198,4 +198,4 @@ This is the same path `codeam deploy` uses inside a freshly-provisioned Codespac
198
198
 
199
199
  MIT © [Edgar Durand](https://github.com/edgar-durand)
200
200
 
201
- Source: [github.com/edgar-durand/codeagent-mobile-clients](https://github.com/edgar-durand/codeagent-mobile-clients)
201
+ Source: [github.com/CodeAgentMobile/codeagent-mobile-clients](https://github.com/CodeAgentMobile/codeagent-mobile-clients)
package/dist/index.js CHANGED
@@ -11354,7 +11354,7 @@ function readAnonId() {
11354
11354
  }
11355
11355
  function superProperties() {
11356
11356
  return {
11357
- cliVersion: true ? "2.76.37" : "0.0.0-dev",
11357
+ cliVersion: true ? "2.76.39" : "0.0.0-dev",
11358
11358
  nodeVersion: process.version,
11359
11359
  platform: process.platform,
11360
11360
  arch: process.arch,
@@ -11463,7 +11463,7 @@ function maybePrintFirstRunBanner() {
11463
11463
  } catch {
11464
11464
  }
11465
11465
  process.stderr.write(
11466
- "\n codeam-cli sends anonymous + identified usage events to PostHog\n (same project as the mobile + web apps). Opt out at any time:\n export CODEAM_TELEMETRY=0\n See https://github.com/edgar-durand/codeagent-mobile-clients#telemetry\n\n"
11466
+ "\n codeam-cli sends anonymous + identified usage events to PostHog\n (same project as the mobile + web apps). Opt out at any time:\n export CODEAM_TELEMETRY=0\n See https://github.com/CodeAgentMobile/codeagent-mobile-clients#telemetry\n\n"
11467
11467
  );
11468
11468
  }
11469
11469
 
@@ -11603,7 +11603,7 @@ var http = __toESM(require("http"));
11603
11603
  // package.json
11604
11604
  var package_default = {
11605
11605
  name: "codeam-cli",
11606
- version: "2.76.37",
11606
+ version: "2.76.39",
11607
11607
  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.",
11608
11608
  type: "commonjs",
11609
11609
  main: "dist/index.js",
@@ -11657,12 +11657,12 @@ var package_default = {
11657
11657
  ],
11658
11658
  homepage: "https://codeagent-mobile.com",
11659
11659
  bugs: {
11660
- url: "https://github.com/edgar-durand/codeagent-mobile-clients/issues"
11660
+ url: "https://github.com/CodeAgentMobile/codeagent-mobile-clients/issues"
11661
11661
  },
11662
11662
  author: "Edgar Durand",
11663
11663
  repository: {
11664
11664
  type: "git",
11665
- url: "git+https://github.com/edgar-durand/codeagent-mobile-clients.git"
11665
+ url: "git+https://github.com/CodeAgentMobile/codeagent-mobile-clients.git"
11666
11666
  },
11667
11667
  license: "MIT",
11668
11668
  publishConfig: {
@@ -12979,7 +12979,7 @@ var CommandRelayService = class _CommandRelayService {
12979
12979
  // fresh + clear the "CLI update available" banner after a self-update
12980
12980
  // (a codespace that reinstalls @latest reconnects via heartbeat, not
12981
12981
  // pair/reconnect). Older backends ignore the extra field.
12982
- ..."2.76.37" ? { ideVersion: "2.76.37" } : {}
12982
+ ..."2.76.39" ? { ideVersion: "2.76.39" } : {}
12983
12983
  };
12984
12984
  try {
12985
12985
  const res = await _postJson(`${API_BASE2}/api/plugin/heartbeat`, body, this.pollSecretHeader());
@@ -39471,6 +39471,95 @@ function _get(url2, headers) {
39471
39471
  });
39472
39472
  }
39473
39473
 
39474
+ // src/services/streaming/chunk-coalescer.ts
39475
+ var STREAMING_CHUNK_MIN_INTERVAL_MS = 100;
39476
+ var FINALIZED_MEMORY = 512;
39477
+ var StreamingChunkCoalescer = class {
39478
+ constructor(opts) {
39479
+ this.opts = opts;
39480
+ }
39481
+ opts;
39482
+ chunks = /* @__PURE__ */ new Map();
39483
+ finalized = /* @__PURE__ */ new Set();
39484
+ submit(event) {
39485
+ const { chunkId } = event;
39486
+ if (this.finalized.has(chunkId)) return Promise.resolve();
39487
+ const state = this.chunks.get(chunkId) ?? this.open(chunkId);
39488
+ const settled = new Promise((resolve13) => {
39489
+ const waiters = state.pending ? state.pending.waiters : [];
39490
+ waiters.push(resolve13);
39491
+ state.pending = { event, waiters };
39492
+ });
39493
+ if (event.isFinal) {
39494
+ this.markFinalized(chunkId);
39495
+ this.drain(chunkId, state);
39496
+ } else {
39497
+ this.schedule(chunkId, state);
39498
+ }
39499
+ return settled;
39500
+ }
39501
+ /** Send every pending snapshot now (ignoring the spacing) and wait for all
39502
+ * requests to settle. Used on shutdown so the latest content is not lost. */
39503
+ async flush() {
39504
+ const work = Array.from(this.chunks.entries()).map(async ([chunkId, state]) => {
39505
+ while (state.inFlight || state.pending) {
39506
+ if (!state.inFlight) this.drain(chunkId, state);
39507
+ await state.inFlight;
39508
+ }
39509
+ });
39510
+ await Promise.all(work);
39511
+ }
39512
+ open(chunkId) {
39513
+ const state = { pending: null, inFlight: null, timer: null, lastSentAt: 0 };
39514
+ this.chunks.set(chunkId, state);
39515
+ return state;
39516
+ }
39517
+ schedule(chunkId, state) {
39518
+ if (state.inFlight || state.timer || !state.pending) return;
39519
+ const wait = this.intervalFor(state.pending.event) - (Date.now() - state.lastSentAt);
39520
+ if (wait <= 0) {
39521
+ this.drain(chunkId, state);
39522
+ return;
39523
+ }
39524
+ state.timer = setTimeout(() => {
39525
+ state.timer = null;
39526
+ this.drain(chunkId, state);
39527
+ }, wait);
39528
+ }
39529
+ /** Send the pending snapshot now, unless a request is still in flight
39530
+ * (its completion re-enters here or {@link schedule}). */
39531
+ drain(chunkId, state) {
39532
+ if (state.inFlight || !state.pending) return;
39533
+ if (state.timer) {
39534
+ clearTimeout(state.timer);
39535
+ state.timer = null;
39536
+ }
39537
+ const { event, waiters } = state.pending;
39538
+ state.pending = null;
39539
+ state.lastSentAt = Date.now();
39540
+ state.inFlight = this.opts.send(event).catch(() => void 0).then(() => {
39541
+ state.inFlight = null;
39542
+ for (const resolve13 of waiters) resolve13();
39543
+ if (!state.pending) {
39544
+ if (event.isFinal) this.chunks.delete(chunkId);
39545
+ return;
39546
+ }
39547
+ if (state.pending.event.isFinal) this.drain(chunkId, state);
39548
+ else this.schedule(chunkId, state);
39549
+ });
39550
+ }
39551
+ intervalFor(event) {
39552
+ return this.opts.intervalFor?.(event) ?? STREAMING_CHUNK_MIN_INTERVAL_MS;
39553
+ }
39554
+ markFinalized(chunkId) {
39555
+ this.finalized.add(chunkId);
39556
+ if (this.finalized.size > FINALIZED_MEMORY) {
39557
+ const oldest = this.finalized.values().next().value;
39558
+ if (oldest !== void 0) this.finalized.delete(oldest);
39559
+ }
39560
+ }
39561
+ };
39562
+
39474
39563
  // src/agents/acp/publisher.ts
39475
39564
  var STREAMING_CHUNK_SNAPSHOT_MAX_CHARS = 56 * 1024;
39476
39565
  var STREAMING_CHUNK_COALESCE_MIN_CHARS = 8 * 1024;
@@ -39516,8 +39605,12 @@ var AcpPublisher = class {
39516
39605
  /** chunkIds whose truncated snapshot already went out — nothing new to show
39517
39606
  * until the terminal frame. */
39518
39607
  truncatedChunks = /* @__PURE__ */ new Set();
39519
- lastChunkPostAt = /* @__PURE__ */ new Map();
39520
- pendingChunkPosts = /* @__PURE__ */ new Map();
39608
+ /** Latest-wins, one-in-flight-per-chunkId pacing of the streaming-chunk
39609
+ * feed (2026-10-29: one CLI posted 10–30 cumulative snapshots/s). */
39610
+ chunkCoalescer = new StreamingChunkCoalescer({
39611
+ send: (event) => this.postStreamingChunk(event),
39612
+ intervalFor: (event) => event.content.length >= STREAMING_CHUNK_COALESCE_MIN_CHARS ? STREAMING_CHUNK_COALESCE_WINDOW_MS : STREAMING_CHUNK_MIN_INTERVAL_MS
39613
+ });
39521
39614
  /** Latched on an unrecoverable 401/403 — every surface stops posting
39522
39615
  * (2026-06-28 incident: a dead-token publisher spammed 401 ×34 while
39523
39616
  * the agent's replies silently never reached the phone). */
@@ -39681,14 +39774,13 @@ var AcpPublisher = class {
39681
39774
  * ({@link publishOutput}) is independent and carries `type:'text'`
39682
39775
  * for the main chat bubble; this feed is purely additive for the
39683
39776
  * richer SessionDetail surface.
39777
+ *
39778
+ * POSTs are paced per chunkId by {@link StreamingChunkCoalescer}: latest
39779
+ * snapshot wins, one request in flight, and the `isFinal` frame always goes
39780
+ * last. The promise settles once this content (or a newer one) is sent.
39684
39781
  */
39685
39782
  async publishStreamingChunk(event) {
39686
39783
  const { chunkId, isFinal } = event;
39687
- const pending2 = this.pendingChunkPosts.get(chunkId);
39688
- if (pending2) {
39689
- clearTimeout(pending2.timer);
39690
- this.pendingChunkPosts.delete(chunkId);
39691
- }
39692
39784
  const bounded = boundStreamingChunkContent(event.content);
39693
39785
  if (bounded.truncated) {
39694
39786
  if (!isFinal && this.truncatedChunks.has(chunkId)) return;
@@ -39700,27 +39792,16 @@ var AcpPublisher = class {
39700
39792
  }
39701
39793
  this.truncatedChunks.add(chunkId);
39702
39794
  }
39703
- if (isFinal) {
39704
- this.truncatedChunks.delete(chunkId);
39705
- this.lastChunkPostAt.delete(chunkId);
39706
- } else if (!bounded.truncated && bounded.content.length >= STREAMING_CHUNK_COALESCE_MIN_CHARS) {
39707
- const last = this.lastChunkPostAt.get(chunkId) ?? 0;
39708
- const wait = STREAMING_CHUNK_COALESCE_WINDOW_MS - (Date.now() - last);
39709
- if (wait > 0) {
39710
- const timer = setTimeout(() => {
39711
- const latest = this.pendingChunkPosts.get(chunkId);
39712
- this.pendingChunkPosts.delete(chunkId);
39713
- if (latest) void this.postStreamingChunk(latest.event);
39714
- }, wait);
39715
- this.pendingChunkPosts.set(chunkId, { timer, event });
39716
- return;
39717
- }
39718
- }
39719
- await this.postStreamingChunk({ ...event, content: bounded.content });
39795
+ if (isFinal) this.truncatedChunks.delete(chunkId);
39796
+ await this.chunkCoalescer.submit({ ...event, content: bounded.content });
39797
+ }
39798
+ /** Send any coalesced streaming-chunk snapshot still waiting, and wait for
39799
+ * the in-flight ones — so shutdown never loses the latest content. */
39800
+ flushStreamingChunks() {
39801
+ return this.chunkCoalescer.flush();
39720
39802
  }
39721
39803
  async postStreamingChunk(event) {
39722
39804
  const url2 = `${this.apiBase}/api/sessions/${encodeURIComponent(this.opts.sessionId)}/streaming-chunk`;
39723
- if (!event.isFinal) this.lastChunkPostAt.set(event.chunkId, Date.now());
39724
39805
  try {
39725
39806
  const { statusCode, body } = await this.postWithReauth(
39726
39807
  url2,
@@ -45987,6 +46068,10 @@ async function runAcpSession(opts) {
45987
46068
  const shutdown = async (signal) => {
45988
46069
  showInfo(`Shutting down ACP session (${signal})\u2026`);
45989
46070
  clearTimeout(prewarmTimer);
46071
+ await Promise.race([
46072
+ publisher.flushStreamingChunks(),
46073
+ new Promise((resolve13) => setTimeout(resolve13, 2e3).unref())
46074
+ ]);
45990
46075
  await stopRelayWithGoodbye(relay);
45991
46076
  void fileWatcher.stop();
45992
46077
  turnFiles.stop();
@@ -46736,6 +46821,10 @@ var StreamingEmitterService = class {
46736
46821
  */
46737
46822
  lastSelectorSignature = null;
46738
46823
  selectorFirstSeenAt = 0;
46824
+ /** Latest-wins, one-in-flight-per-chunkId pacing of the chunk POSTs. */
46825
+ chunkCoalescer = new StreamingChunkCoalescer({
46826
+ send: (event) => this.postChunk(event)
46827
+ });
46739
46828
  // ─── Lifecycle ─────────────────────────────────────────────────────
46740
46829
  start() {
46741
46830
  if (this.active) return;
@@ -46766,13 +46855,14 @@ var StreamingEmitterService = class {
46766
46855
  const finalContent = this.activeChunk.currentContent;
46767
46856
  const chunk = this.activeChunk;
46768
46857
  this.activeChunk = null;
46769
- await this.postChunk({
46858
+ await this.chunkCoalescer.submit({
46770
46859
  chunkId: chunk.chunkId,
46771
46860
  kind: chunk.kind,
46772
46861
  content: finalContent,
46773
46862
  isFinal: true
46774
46863
  });
46775
46864
  }
46865
+ await this.chunkCoalescer.flush();
46776
46866
  log.trace("streamingEmitter", `stopped session=${this.opts.sessionId.slice(0, 8)}`);
46777
46867
  }
46778
46868
  // ─── Input pump ────────────────────────────────────────────────────
@@ -46823,7 +46913,7 @@ var StreamingEmitterService = class {
46823
46913
  if (this.activeChunk) {
46824
46914
  const closing = this.activeChunk;
46825
46915
  this.activeChunk = null;
46826
- void this.postChunk({
46916
+ void this.chunkCoalescer.submit({
46827
46917
  chunkId: closing.chunkId,
46828
46918
  kind: closing.kind,
46829
46919
  content: closing.currentContent,
@@ -46847,7 +46937,7 @@ var StreamingEmitterService = class {
46847
46937
  if (chunk.currentContent === chunk.emittedContent) return;
46848
46938
  chunk.emittedContent = chunk.currentContent;
46849
46939
  chunk.lastEmitAt = now;
46850
- void this.postChunk({
46940
+ void this.chunkCoalescer.submit({
46851
46941
  chunkId: chunk.chunkId,
46852
46942
  kind: chunk.kind,
46853
46943
  content: chunk.currentContent,
@@ -52063,7 +52153,7 @@ async function autoUpgradeBeforeCriticalCommand() {
52063
52153
  if (process.env.NODE_ENV === "test") return;
52064
52154
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
52065
52155
  if (process.env.CI) return;
52066
- const current2 = true ? "2.76.37" : null;
52156
+ const current2 = true ? "2.76.39" : null;
52067
52157
  if (!current2) return;
52068
52158
  const cache = readCache();
52069
52159
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -52080,7 +52170,7 @@ function checkForUpdates() {
52080
52170
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
52081
52171
  if (process.env.CI) return;
52082
52172
  if (!process.stdout.isTTY) return;
52083
- const current2 = true ? "2.76.37" : null;
52173
+ const current2 = true ? "2.76.39" : null;
52084
52174
  if (!current2) return;
52085
52175
  const cache = readCache();
52086
52176
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -52386,7 +52476,7 @@ var SELF_UPDATE_VIEW_TIMEOUT_MS = 3e4;
52386
52476
  var SELF_UPDATE_INSTALL_TIMEOUT_MS = 18e4;
52387
52477
  var SELF_UPDATE_LS_TIMEOUT_MS = 15e3;
52388
52478
  function currentCliVersion() {
52389
- return true ? "2.76.37" : null;
52479
+ return true ? "2.76.39" : null;
52390
52480
  }
52391
52481
  async function installedVersion(deps) {
52392
52482
  const ls = await deps.run(
@@ -52609,7 +52699,7 @@ function signalHostReady(send = process.send?.bind(process)) {
52609
52699
  }
52610
52700
  function defaultDeps() {
52611
52701
  return {
52612
- ownVersion: true ? "2.76.37" : null,
52702
+ ownVersion: true ? "2.76.39" : null,
52613
52703
  root: cliVersionsRoot(),
52614
52704
  args: process.argv.slice(3),
52615
52705
  execPath: process.execPath,
@@ -52903,7 +52993,7 @@ function isFleetPruneHostPayload(v) {
52903
52993
  function isMissingVolumeError(stderr) {
52904
52994
  return /no such volume/i.test(stderr);
52905
52995
  }
52906
- var FLEET_BOX_REPO = "ghcr.io/edgar-durand/codeam-box";
52996
+ var FLEET_BOX_REPO = "ghcr.io/codeagentmobile/codeam-box";
52907
52997
  var DOCKER_TAG_RE = /^[A-Za-z0-9_][A-Za-z0-9_.-]{0,127}$/;
52908
52998
  function resolveFleetBoxImage() {
52909
52999
  if (process.env.CODEAM_FLEET_BOX_IMAGE) return process.env.CODEAM_FLEET_BOX_IMAGE;
@@ -55147,7 +55237,7 @@ function checkChokidar() {
55147
55237
  }
55148
55238
  async function doctor(args2 = []) {
55149
55239
  const json = args2.includes("--json");
55150
- const cliVersion = true ? "2.76.37" : "0.0.0-dev";
55240
+ const cliVersion = true ? "2.76.39" : "0.0.0-dev";
55151
55241
  const apiBase2 = resolveApiBaseUrl();
55152
55242
  const diagnosticId = (0, import_node_crypto17.randomUUID)();
55153
55243
  log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
@@ -55683,7 +55773,7 @@ async function mcpWarm(argv = [], opts = {}) {
55683
55773
  // src/commands/version.ts
55684
55774
  var import_picocolors15 = __toESM(require("picocolors"));
55685
55775
  function version2() {
55686
- const v = true ? "2.76.37" : "unknown";
55776
+ const v = true ? "2.76.39" : "unknown";
55687
55777
  console.log(`${import_picocolors15.default.bold("codeam-cli")} ${import_picocolors15.default.cyan(v)}`);
55688
55778
  }
55689
55779
 
@@ -55720,7 +55810,7 @@ function help() {
55720
55810
  "",
55721
55811
  ` ${import_picocolors16.default.bold("Links")}`,
55722
55812
  ` ${import_picocolors16.default.dim("Docs:")} ${import_picocolors16.default.green("https://www.codeagent-mobile.com")}`,
55723
- ` ${import_picocolors16.default.dim("Issues:")} ${import_picocolors16.default.green("https://github.com/edgar-durand/codeagent-mobile-clients/issues")}`,
55813
+ ` ${import_picocolors16.default.dim("Issues:")} ${import_picocolors16.default.green("https://github.com/CodeAgentMobile/codeagent-mobile-clients/issues")}`,
55724
55814
  ""
55725
55815
  ];
55726
55816
  process.stdout.write(lines.join("\n") + "\n");
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+
4
+ // src/postinstall.ts
5
+ var c = {
6
+ reset: "\x1B[0m",
7
+ bold: "\x1B[1m",
8
+ dim: "\x1B[2m",
9
+ green: "\x1B[32m",
10
+ cyan: "\x1B[36m",
11
+ violet: "\x1B[35m",
12
+ white: "\x1B[97m"
13
+ };
14
+ var lines = [
15
+ "",
16
+ ` ${c.violet}${c.bold}codeam-cli${c.reset} ${c.dim}\u2014 Claude Code remote control${c.reset}`,
17
+ "",
18
+ ` ${c.dim}1.${c.reset} Pair your phone:`,
19
+ ` ${c.cyan}codeam pair${c.reset}`,
20
+ "",
21
+ ` ${c.dim}2.${c.reset} Launch Claude Code with mobile control:`,
22
+ ` ${c.cyan}codeam${c.reset}`,
23
+ "",
24
+ ` ${c.dim}Other commands:${c.reset}`,
25
+ ` ${c.white}codeam sessions${c.reset} ${c.dim}list paired devices${c.reset}`,
26
+ ` ${c.white}codeam status${c.reset} ${c.dim}show connection info${c.reset}`,
27
+ ` ${c.white}codeam logout${c.reset} ${c.dim}remove all sessions${c.reset}`,
28
+ "",
29
+ ` ${c.dim}Requires Claude Code:${c.reset} ${c.green}npm install -g @anthropic-ai/claude-code${c.reset}`,
30
+ ` ${c.dim}Mobile app:${c.reset} ${c.green}https://www.codeagent-mobile.com${c.reset}`,
31
+ ""
32
+ ];
33
+ process.stdout.write(lines.join("\n") + "\n");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeam-cli",
3
- "version": "2.76.37",
3
+ "version": "2.76.39",
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",
@@ -54,12 +54,12 @@
54
54
  ],
55
55
  "homepage": "https://codeagent-mobile.com",
56
56
  "bugs": {
57
- "url": "https://github.com/edgar-durand/codeagent-mobile-clients/issues"
57
+ "url": "https://github.com/CodeAgentMobile/codeagent-mobile-clients/issues"
58
58
  },
59
59
  "author": "Edgar Durand",
60
60
  "repository": {
61
61
  "type": "git",
62
- "url": "git+https://github.com/edgar-durand/codeagent-mobile-clients.git"
62
+ "url": "git+https://github.com/CodeAgentMobile/codeagent-mobile-clients.git"
63
63
  },
64
64
  "license": "MIT",
65
65
  "publishConfig": {