@phnx-labs/agents-cli 1.22.22 → 1.22.24

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 (138) hide show
  1. package/CHANGELOG.md +402 -0
  2. package/README.md +13 -6
  3. package/dist/bin/agents +0 -0
  4. package/dist/commands/attach.d.ts +2 -0
  5. package/dist/commands/attach.js +32 -7
  6. package/dist/commands/defaults.js +2 -0
  7. package/dist/commands/doctor.js +20 -7
  8. package/dist/commands/exec.js +100 -34
  9. package/dist/commands/feed.d.ts +18 -0
  10. package/dist/commands/feed.js +44 -1
  11. package/dist/commands/focus.d.ts +108 -5
  12. package/dist/commands/focus.js +455 -32
  13. package/dist/commands/fork.d.ts +20 -2
  14. package/dist/commands/fork.js +91 -64
  15. package/dist/commands/go.d.ts +39 -1
  16. package/dist/commands/go.js +112 -7
  17. package/dist/commands/harness-wizard.d.ts +206 -0
  18. package/dist/commands/harness-wizard.js +403 -0
  19. package/dist/commands/harness.d.ts +12 -0
  20. package/dist/commands/harness.js +97 -101
  21. package/dist/commands/insights.js +6 -2
  22. package/dist/commands/inspect.js +39 -5
  23. package/dist/commands/menubar.js +6 -1
  24. package/dist/commands/models.js +1 -0
  25. package/dist/commands/modes.d.ts +12 -0
  26. package/dist/commands/modes.js +147 -0
  27. package/dist/commands/resume.js +10 -3
  28. package/dist/commands/secrets-sync.js +11 -13
  29. package/dist/commands/secrets.d.ts +2 -0
  30. package/dist/commands/secrets.js +79 -47
  31. package/dist/commands/sessions-browser.d.ts +35 -0
  32. package/dist/commands/sessions-browser.js +140 -14
  33. package/dist/commands/sessions-resume.d.ts +23 -3
  34. package/dist/commands/sessions-resume.js +73 -19
  35. package/dist/commands/sessions.d.ts +91 -5
  36. package/dist/commands/sessions.js +359 -125
  37. package/dist/commands/setup-secrets.js +1 -1
  38. package/dist/commands/sync.js +246 -42
  39. package/dist/commands/view.js +2 -0
  40. package/dist/commands/watchdog.js +13 -2
  41. package/dist/index.js +2 -1
  42. package/dist/lib/agent-modes.d.ts +49 -0
  43. package/dist/lib/agent-modes.js +70 -0
  44. package/dist/lib/agents.d.ts +1 -1
  45. package/dist/lib/agents.js +132 -0
  46. package/dist/lib/codex-policy.d.ts +17 -0
  47. package/dist/lib/codex-policy.js +48 -0
  48. package/dist/lib/crabbox/lease.d.ts +25 -0
  49. package/dist/lib/crabbox/lease.js +62 -0
  50. package/dist/lib/daemon.js +70 -0
  51. package/dist/lib/doctor-diff.d.ts +3 -0
  52. package/dist/lib/doctor-diff.js +15 -13
  53. package/dist/lib/event-stream.d.ts +3 -1
  54. package/dist/lib/event-stream.js +14 -1
  55. package/dist/lib/exec.d.ts +16 -0
  56. package/dist/lib/exec.js +175 -62
  57. package/dist/lib/feed-broadcast.d.ts +1 -20
  58. package/dist/lib/feed-broadcast.js +31 -1
  59. package/dist/lib/hooks/cache.js +36 -3
  60. package/dist/lib/hooks.d.ts +19 -7
  61. package/dist/lib/hooks.js +100 -40
  62. package/dist/lib/hosts/session-index.d.ts +4 -0
  63. package/dist/lib/hosts/session-index.js +7 -0
  64. package/dist/lib/manifest.d.ts +12 -2
  65. package/dist/lib/manifest.js +60 -5
  66. package/dist/lib/mcp.js +44 -0
  67. package/dist/lib/menubar/MenubarHelper.app/Contents/CodeResources +0 -0
  68. package/dist/lib/menubar/MenubarHelper.app/Contents/MacOS/MenubarHelper +0 -0
  69. package/dist/lib/menubar/install-menubar.d.ts +52 -2
  70. package/dist/lib/menubar/install-menubar.js +128 -6
  71. package/dist/lib/models.d.ts +0 -5
  72. package/dist/lib/models.js +48 -0
  73. package/dist/lib/plugin-marketplace.js +9 -0
  74. package/dist/lib/pricing/prices.json +119 -92
  75. package/dist/lib/pricing/table.js +13 -0
  76. package/dist/lib/refresh.d.ts +5 -0
  77. package/dist/lib/refresh.js +37 -33
  78. package/dist/lib/remote-agents-json.d.ts +29 -1
  79. package/dist/lib/remote-agents-json.js +47 -10
  80. package/dist/lib/resource-inventory.d.ts +79 -0
  81. package/dist/lib/resource-inventory.js +122 -0
  82. package/dist/lib/resources/mcp.js +2 -0
  83. package/dist/lib/resources/permissions.js +3 -0
  84. package/dist/lib/resources/types.d.ts +2 -1
  85. package/dist/lib/resources.js +8 -5
  86. package/dist/lib/run-defaults.d.ts +2 -0
  87. package/dist/lib/run-defaults.js +23 -2
  88. package/dist/lib/runner.js +50 -36
  89. package/dist/lib/secrets/Agents CLI.app/Contents/CodeResources +0 -0
  90. package/dist/lib/secrets/Agents CLI.app/Contents/MacOS/Agents CLI +0 -0
  91. package/dist/lib/secrets/bundles.js +157 -65
  92. package/dist/lib/secrets/filestore.d.ts +5 -3
  93. package/dist/lib/secrets/filestore.js +12 -8
  94. package/dist/lib/secrets/index.d.ts +15 -1
  95. package/dist/lib/secrets/index.js +148 -53
  96. package/dist/lib/secrets/reaper.d.ts +97 -0
  97. package/dist/lib/secrets/reaper.js +219 -0
  98. package/dist/lib/secrets/remote.d.ts +29 -0
  99. package/dist/lib/secrets/remote.js +37 -1
  100. package/dist/lib/secrets/sync-passphrase.d.ts +27 -0
  101. package/dist/lib/secrets/sync-passphrase.js +78 -0
  102. package/dist/lib/session/active.d.ts +36 -1
  103. package/dist/lib/session/active.js +60 -19
  104. package/dist/lib/session/actor-sidecar.d.ts +14 -0
  105. package/dist/lib/session/actor-sidecar.js +67 -4
  106. package/dist/lib/session/db.d.ts +1 -1
  107. package/dist/lib/session/db.js +32 -1
  108. package/dist/lib/session/discover.js +168 -0
  109. package/dist/lib/session/parse.d.ts +10 -0
  110. package/dist/lib/session/parse.js +98 -0
  111. package/dist/lib/session/recovery.d.ts +37 -0
  112. package/dist/lib/session/recovery.js +95 -0
  113. package/dist/lib/session/remote-list.d.ts +10 -1
  114. package/dist/lib/session/remote-list.js +2 -8
  115. package/dist/lib/session/remote.d.ts +57 -3
  116. package/dist/lib/session/remote.js +90 -26
  117. package/dist/lib/session/resume-command.d.ts +6 -0
  118. package/dist/lib/session/resume-command.js +8 -0
  119. package/dist/lib/session/session-cache.d.ts +173 -0
  120. package/dist/lib/session/session-cache.js +399 -0
  121. package/dist/lib/session/types.d.ts +1 -1
  122. package/dist/lib/session/types.js +1 -1
  123. package/dist/lib/session/width.d.ts +1 -1
  124. package/dist/lib/session/width.js +12 -2
  125. package/dist/lib/shims.d.ts +2 -2
  126. package/dist/lib/shims.js +62 -8
  127. package/dist/lib/staleness/writers/hooks.js +1 -1
  128. package/dist/lib/startup/command-registry.d.ts +1 -0
  129. package/dist/lib/startup/command-registry.js +2 -0
  130. package/dist/lib/sync-umbrella.d.ts +5 -0
  131. package/dist/lib/sync-umbrella.js +5 -4
  132. package/dist/lib/tmux/session.d.ts +4 -2
  133. package/dist/lib/tmux/session.js +5 -5
  134. package/dist/lib/types.d.ts +3 -1
  135. package/dist/lib/usage.d.ts +13 -0
  136. package/dist/lib/usage.js +215 -0
  137. package/dist/lib/versions.js +13 -2
  138. package/package.json +1 -1
@@ -468,6 +468,115 @@ export function disableMenubarService() {
468
468
  }
469
469
  catch { /* best effort */ }
470
470
  }
471
+ /**
472
+ * Which install is allowed to (re)install the shared helper.
473
+ *
474
+ * The helper lives at ONE path in Application Support, but any number of
475
+ * agents-cli copies can be present on a box and every one of them runs the
476
+ * startup self-heal. The version stamp and the plist's baked `AGENTS_ENTRY` each
477
+ * record whichever copy acted last, so without an ownership rule every copy
478
+ * reads the others' marks as drift and recopies the bundle over them. Recopying
479
+ * replaces the executable under the live helper and kills it; launchd
480
+ * `KeepAlive` restarts it; the next copy repeats it. Measured on one box: a new
481
+ * pid every 5-15s, 578 launches in the helper's log, a status item that never
482
+ * stayed visible, and `agents menubar status` still reporting `running: yes`
483
+ * because a pid always existed (#2109).
484
+ *
485
+ * There is deliberately NO content comparison here. Comparing the shipped helper
486
+ * against the installed one cannot distinguish "real upgrade" from "another
487
+ * install's copy": the helper is rebuilt, re-signed and re-notarized on every
488
+ * release (`menubar/scripts/build.sh` via `release.sh`), so consecutive releases
489
+ * ship byte-different bundles from identical Swift source — 1.22.20/21/22 all
490
+ * have the same 2876288-byte executable and three different sha256s AND three
491
+ * different CDHashes. Any digest gate therefore reports "changed" for exactly
492
+ * the skew case it was meant to exempt.
493
+ *
494
+ * So ownership decides instead: the plist's `AGENTS_ENTRY` names the owner, and
495
+ * only the owner may reinstall. A non-owner takes over only once the recorded
496
+ * owner is gone from disk, which is what makes the rule converge — a dead
497
+ * install cannot hold the helper hostage, and a live one cannot be fought over.
498
+ * A same-install upgrade keeps its entry path, so `npm update` still installs
499
+ * the new helper normally. Pure so the truth table is unit-testable.
500
+ */
501
+ export function mayInstallMenubarHelper(opts) {
502
+ // Repairs are never gated: a missing binary or a broken signing identity leaves
503
+ // the menu bar dead or re-prompting for Accessibility, and no other install can
504
+ // be "fighting" for a bundle that isn't there. Blocking these behind ownership
505
+ // is what turned the first version of this gate into a silent stuck state.
506
+ if (opts.helperExecMissing || opts.needsDevIdHeal)
507
+ return true;
508
+ // Can't resolve which install we are (a dev/tsx run) — never churn the plist.
509
+ if (!opts.activeEntry)
510
+ return false;
511
+ // No owner recorded yet (fresh or pre-`AGENTS_ENTRY` plist) — adopt it.
512
+ if (!opts.plistEntry)
513
+ return true;
514
+ if (opts.plistEntry === opts.activeEntry)
515
+ return true; // we are the owner
516
+ if (!opts.ownerEntryExists)
517
+ return true; // the recorded owner is gone
518
+ // A foreign install while the owner still exists. Refusing outright bounds the
519
+ // loop but strands the user when the recorded owner is a stale copy that simply
520
+ // still sits on disk (an old nvm node dir) while their daily driver upgrades:
521
+ // that install would never heal again. So it may take over, but only once per
522
+ // cooldown — which turns an every-invocation storm into at most one restart per
523
+ // cooldown while keeping every install able to make progress.
524
+ //
525
+ // Except an ad-hoc/dev-signed copy, which never seizes a healthy helper on a
526
+ // timer. `scripts/install.sh` deliberately puts a dev build beside the npm
527
+ // global, and its bundle cannot be notarized; letting it win the timed takeover
528
+ // would recopy an ad-hoc bundle over a good Developer-ID one, and Gatekeeper
529
+ // then rejects the result as "damaged" and AppKit crashes at launch (RUSH-2134)
530
+ // — trading a cosmetic loop for a broken menu bar. It can still take over when
531
+ // the owner is genuinely gone (above), which is the case that must not deadlock.
532
+ if (!opts.sourceIsDeveloperId)
533
+ return false;
534
+ return opts.msSinceLastHeal === null || opts.msSinceLastHeal >= opts.cooldownMs;
535
+ }
536
+ /**
537
+ * How long a non-owner install waits before it may take the helper over. Long
538
+ * enough that a multi-install box restarts the helper at most once an hour
539
+ * instead of every few seconds; short enough that a user who switched installs
540
+ * gets their upgrade without hunting for `agents menubar setup`.
541
+ */
542
+ const MENUBAR_TAKEOVER_COOLDOWN_MS = 60 * 60 * 1000;
543
+ /** Timestamp of the last self-heal reinstall, next to the version stamp. */
544
+ function lastHealMarkerPath() {
545
+ return path.join(installDir(), '.menubar-last-heal');
546
+ }
547
+ function msSinceLastMenubarHeal() {
548
+ try {
549
+ const t = Number(fs.readFileSync(lastHealMarkerPath(), 'utf-8').trim());
550
+ if (!Number.isFinite(t))
551
+ return null;
552
+ return Math.max(0, Date.now() - t);
553
+ }
554
+ catch {
555
+ return null;
556
+ }
557
+ }
558
+ function stampMenubarHeal() {
559
+ try {
560
+ fs.mkdirSync(installDir(), { recursive: true });
561
+ fs.writeFileSync(lastHealMarkerPath(), String(Date.now()));
562
+ }
563
+ catch { /* best effort */ }
564
+ }
565
+ /** Whether this install may (re)install the helper (see `mayInstallMenubarHelper`). */
566
+ function mayHealMenubar(needsDevIdHeal) {
567
+ const plistEntry = readPlistEnvValue('AGENTS_ENTRY');
568
+ const src = sourceAppPath();
569
+ return mayInstallMenubarHelper({
570
+ plistEntry,
571
+ activeEntry: resolveCliEntry(),
572
+ ownerEntryExists: Boolean(plistEntry) && fs.existsSync(plistEntry),
573
+ helperExecMissing: !fs.existsSync(installedExecutablePath()),
574
+ needsDevIdHeal,
575
+ msSinceLastHeal: msSinceLastMenubarHeal(),
576
+ cooldownMs: MENUBAR_TAKEOVER_COOLDOWN_MS,
577
+ sourceIsDeveloperId: Boolean(src) && hasDeveloperIdSignature(src),
578
+ });
579
+ }
471
580
  /**
472
581
  * Startup self-heal, run on every darwin CLI invocation (see src/index.ts).
473
582
  * No-ops cheaply (a couple of existsSync + a tiny file read) unless work is
@@ -478,8 +587,10 @@ export function disableMenubarService() {
478
587
  *
479
588
  * Without the staleness re-enable, `npm update` refreshed the CLI but left the
480
589
  * menu bar running the previous release's helper binary on a possibly-stale
481
- * plist. No-ops if: not darwin, the user opted out, or no helper bundle ships.
482
- * Best-effort never throws into startup.
590
+ * plist. Everything past the ownership gate is unchanged; the gate is what stops
591
+ * coexisting installs reinstalling over each other forever (#2109). No-ops if:
592
+ * not darwin, the user opted out, or no helper bundle ships. Best-effort — never
593
+ * throws into startup.
483
594
  */
484
595
  export function installMenubarLaunchAgentOnUpgrade() {
485
596
  try {
@@ -495,12 +606,23 @@ export function installMenubarLaunchAgentOnUpgrade() {
495
606
  }
496
607
  // Re-enable (recopy helper + rewrite plist) when the version drifted OR the
497
608
  // plist's baked interpreter/entry no longer point at the install now running
498
- // `agents` — the dual-install skew a version bump alone can't catch — OR the
609
+ // `agents` — e.g. the owner moved between node interpreters — OR the
499
610
  // installed copy is still ad-hoc while the shipped source is Developer ID
500
611
  // (older heal path; Accessibility re-prompts until the identity is restored).
501
- if (menubarSetupStale() || menubarSetupNeedsRepoint() || installedNeedsDevIdHeal()) {
502
- enableMenubarService({ clearOptOut: false });
503
- }
612
+ const needsDevIdHeal = installedNeedsDevIdHeal();
613
+ if (!(menubarSetupStale() || menubarSetupNeedsRepoint() || needsDevIdHeal))
614
+ return;
615
+ // ...but a copy that does not own the helper only gets to act on that drift
616
+ // once per cooldown. Without the gate every coexisting install recopies the
617
+ // bundle on every invocation, killing the live helper on a loop (#2109).
618
+ if (!mayHealMenubar(needsDevIdHeal))
619
+ return;
620
+ // Stamp only a heal that actually happened. `enableMenubarService` returns
621
+ // false without installing when the bundle fails the Gatekeeper check, and
622
+ // stamping first would spend the shared cooldown on a no-op — locking every
623
+ // non-owner out for another hour while nothing had been fixed.
624
+ if (enableMenubarService({ clearOptOut: false }))
625
+ stampMenubarHeal();
504
626
  }
505
627
  catch {
506
628
  /* never block startup on the menu bar */
@@ -97,11 +97,6 @@ export declare function parseGrokModelsStdout(stdout: string): {
97
97
  models: ModelInfo[];
98
98
  aliases: Record<string, string>;
99
99
  };
100
- /**
101
- * Build (or load from cache) the model catalog for a specific (agent, version).
102
- * Cache is keyed on source-file mtime (binary or js module), so re-extracts
103
- * automatically when the user upgrades or reinstalls a version.
104
- */
105
100
  export declare function getModelCatalog(agent: AgentId, version: string): ModelCatalog | null;
106
101
  /** The result of resolving a user-supplied model string against the catalog. */
107
102
  export interface ResolvedModel {
@@ -246,6 +246,16 @@ export function locateModelSource(agent, version) {
246
246
  return { path: pathBin, kind: 'cli' };
247
247
  return null;
248
248
  }
249
+ if (agent === 'muse') {
250
+ // Muse Code is a self-updating native binary on PATH. It has no catalog
251
+ // CLI; the published model IDs are fixed by Meta Model API docs. Point at
252
+ // the binary so the cache key moves with upgrades, and extract a static
253
+ // catalog in getModelCatalog.
254
+ const pathBin = findOnPath('muse');
255
+ if (pathBin)
256
+ return { path: pathBin, kind: 'cli' };
257
+ return null;
258
+ }
249
259
  return null;
250
260
  }
251
261
  /** Real Grok binaries are ~100MB+; failed-download stubs are tens of bytes. */
@@ -973,6 +983,36 @@ function extractPiCatalog(binaryPath) {
973
983
  * Cache is keyed on source-file mtime (binary or js module), so re-extracts
974
984
  * automatically when the user upgrades or reinstalls a version.
975
985
  */
986
+ /**
987
+ * Static Muse Spark catalog. Meta Model API publishes these IDs; Muse Code
988
+ * has no `muse models` command. Default is muse-spark-1.2 (docs + first-run).
989
+ * Source: https://dev.meta.ai/docs/pricing-rate-limits and muse-code overview.
990
+ */
991
+ function extractMuseCatalog() {
992
+ const models = [
993
+ {
994
+ id: 'muse-spark-1.2',
995
+ displayName: 'Muse Spark 1.2',
996
+ isDefault: true,
997
+ },
998
+ {
999
+ id: 'muse-spark-1.1',
1000
+ displayName: 'Muse Spark 1.1',
1001
+ },
1002
+ {
1003
+ id: 'muse-spark-1.2-contributor',
1004
+ displayName: 'Muse Spark 1.2 Contributor',
1005
+ },
1006
+ ];
1007
+ const aliases = {
1008
+ spark: 'muse-spark-1.2',
1009
+ 'spark-1.2': 'muse-spark-1.2',
1010
+ 'spark-1.1': 'muse-spark-1.1',
1011
+ contributor: 'muse-spark-1.2-contributor',
1012
+ default: 'muse-spark-1.2',
1013
+ };
1014
+ return { models, aliases };
1015
+ }
976
1016
  export function getModelCatalog(agent, version) {
977
1017
  const src = locateModelSource(agent, version);
978
1018
  if (!src)
@@ -1027,6 +1067,8 @@ export function getModelCatalog(agent, version) {
1027
1067
  ({ models, aliases } = extractGrokCatalog(src.path));
1028
1068
  else if (agent === 'pi')
1029
1069
  ({ models, aliases } = extractPiCatalog(src.path));
1070
+ else if (agent === 'muse')
1071
+ ({ models, aliases } = extractMuseCatalog());
1030
1072
  }
1031
1073
  // Attach per-token pricing where the offline table knows the model, so the
1032
1074
  // catalog carries $/token for the tier display and budgeting. Subscription /
@@ -1237,5 +1279,11 @@ export function buildReasoningFlags(agent, level) {
1237
1279
  const grokLevel = (normalized === 'xhigh' || normalized === 'max') ? 'high' : normalized;
1238
1280
  return ['--reasoning-effort', grokLevel];
1239
1281
  }
1282
+ if (agent === 'muse') {
1283
+ // Muse Code: `--reasoning-effort none|minimal|low|medium|high|xhigh|ultra`.
1284
+ // Map our unified `max` to Muse's `ultra` (client-side multi-agent aggression).
1285
+ const museLevel = normalized === 'max' ? 'ultra' : normalized;
1286
+ return ['--reasoning-effort', museLevel];
1287
+ }
1240
1288
  return [];
1241
1289
  }
@@ -121,6 +121,11 @@ function dirExists(p) {
121
121
  }
122
122
  // ─── Per-version paths ────────────────────────────────────────────────────────
123
123
  function pluginsRootForVersion(agent, versionHome) {
124
+ // Muse Code keeps its plugin store under XDG data (`~/.local/share/muse/plugins`),
125
+ // not under the config dir. Under HOME isolation the version home is $HOME.
126
+ if (agent === 'muse') {
127
+ return path.join(versionHome, '.local', 'share', 'muse', 'plugins');
128
+ }
124
129
  return path.join(versionHome, agentConfigDirName(agent), 'plugins');
125
130
  }
126
131
  export function marketplaceRoot(specOrName, agent, versionHome) {
@@ -678,6 +683,10 @@ export function addPluginToSettings(pluginName, marketplaceName, agent, versionH
678
683
  settings = {};
679
684
  }
680
685
  }
686
+ // Muse refuses to start without schema_version: 1.
687
+ if (agent === 'muse' && settings.schema_version === undefined) {
688
+ settings.schema_version = 1;
689
+ }
681
690
  if (!settings.enabledPlugins || typeof settings.enabledPlugins !== 'object') {
682
691
  settings.enabledPlugins = {};
683
692
  }
@@ -1,153 +1,180 @@
1
1
  {
2
- "version": "2026-08-03",
2
+ "version": "2026-08-05",
3
3
  "models": {
4
4
  "claude-opus-4": {
5
+ "inputPerToken": 5e-06,
6
+ "outputPerToken": 2.5e-05,
7
+ "cacheReadPerToken": 5e-07,
8
+ "cacheWritePerToken": 6.25e-06
9
+ },
10
+ "claude-sonnet-4": {
11
+ "inputPerToken": 3e-06,
12
+ "outputPerToken": 1.5e-05,
13
+ "cacheReadPerToken": 3e-07,
14
+ "cacheWritePerToken": 3.75e-06
15
+ },
16
+ "claude-haiku-4": {
17
+ "inputPerToken": 1e-06,
18
+ "outputPerToken": 5e-06,
19
+ "cacheReadPerToken": 1e-07,
20
+ "cacheWritePerToken": 1.25e-06
21
+ },
22
+ "claude-opus-5": {
5
23
  "inputPerToken": 0.000005,
6
24
  "outputPerToken": 0.000025,
7
25
  "cacheReadPerToken": 0.0000005,
8
26
  "cacheWritePerToken": 0.00000625
9
27
  },
10
- "claude-sonnet-4": {
11
- "inputPerToken": 0.000003,
12
- "outputPerToken": 0.000015,
13
- "cacheReadPerToken": 0.0000003,
14
- "cacheWritePerToken": 0.00000375
15
- },
16
- "claude-haiku-4": {
17
- "inputPerToken": 0.000001,
18
- "outputPerToken": 0.000005,
19
- "cacheReadPerToken": 0.0000001,
20
- "cacheWritePerToken": 0.00000125
28
+ "claude-sonnet-5": {
29
+ "inputPerToken": 0.000002,
30
+ "outputPerToken": 0.00001,
31
+ "cacheReadPerToken": 0.0000002,
32
+ "cacheWritePerToken": 0.0000025
21
33
  },
22
34
  "claude-fable-5": {
23
- "inputPerToken": 0.00001,
24
- "outputPerToken": 0.00005,
25
- "cacheReadPerToken": 0.000001,
26
- "cacheWritePerToken": 0.0000125
35
+ "inputPerToken": 1e-05,
36
+ "outputPerToken": 5e-05,
37
+ "cacheReadPerToken": 1e-06,
38
+ "cacheWritePerToken": 1.25e-05
27
39
  },
28
40
  "claude-mythos-5": {
29
- "inputPerToken": 0.00001,
30
- "outputPerToken": 0.00005,
31
- "cacheReadPerToken": 0.000001,
32
- "cacheWritePerToken": 0.0000125
41
+ "inputPerToken": 1e-05,
42
+ "outputPerToken": 5e-05,
43
+ "cacheReadPerToken": 1e-06,
44
+ "cacheWritePerToken": 1.25e-05
33
45
  },
34
46
  "claude-3-5-sonnet": {
35
- "inputPerToken": 0.000003,
36
- "outputPerToken": 0.000015,
37
- "cacheReadPerToken": 0.0000003,
38
- "cacheWritePerToken": 0.00000375
47
+ "inputPerToken": 3e-06,
48
+ "outputPerToken": 1.5e-05,
49
+ "cacheReadPerToken": 3e-07,
50
+ "cacheWritePerToken": 3.75e-06
39
51
  },
40
52
  "claude-3-5-haiku": {
41
- "inputPerToken": 0.0000008,
42
- "outputPerToken": 0.000004,
43
- "cacheReadPerToken": 0.00000008,
44
- "cacheWritePerToken": 0.000001
53
+ "inputPerToken": 8e-07,
54
+ "outputPerToken": 4e-06,
55
+ "cacheReadPerToken": 8e-08,
56
+ "cacheWritePerToken": 1e-06
45
57
  },
46
58
  "claude-3-opus": {
47
- "inputPerToken": 0.000015,
48
- "outputPerToken": 0.000075,
49
- "cacheReadPerToken": 0.0000015,
50
- "cacheWritePerToken": 0.00001875
59
+ "inputPerToken": 1.5e-05,
60
+ "outputPerToken": 7.5e-05,
61
+ "cacheReadPerToken": 1.5e-06,
62
+ "cacheWritePerToken": 1.875e-05
51
63
  },
52
64
  "gpt-5.6-sol": {
53
- "inputPerToken": 0.000005,
54
- "outputPerToken": 0.00003,
55
- "cacheReadPerToken": 0.0000005
65
+ "inputPerToken": 5e-06,
66
+ "outputPerToken": 3e-05,
67
+ "cacheReadPerToken": 5e-07
56
68
  },
57
69
  "gpt-5.6-terra": {
58
- "inputPerToken": 0.0000025,
59
- "outputPerToken": 0.000015,
60
- "cacheReadPerToken": 0.00000025
70
+ "inputPerToken": 2.5e-06,
71
+ "outputPerToken": 1.5e-05,
72
+ "cacheReadPerToken": 2.5e-07
61
73
  },
62
74
  "gpt-5.6-luna": {
63
- "inputPerToken": 0.000001,
64
- "outputPerToken": 0.000006,
65
- "cacheReadPerToken": 0.0000001
75
+ "inputPerToken": 1e-06,
76
+ "outputPerToken": 6e-06,
77
+ "cacheReadPerToken": 1e-07
66
78
  },
67
79
  "gpt-5.5": {
68
- "inputPerToken": 0.000005,
69
- "outputPerToken": 0.00003,
70
- "cacheReadPerToken": 0.0000005
80
+ "inputPerToken": 5e-06,
81
+ "outputPerToken": 3e-05,
82
+ "cacheReadPerToken": 5e-07
71
83
  },
72
84
  "gpt-5.4": {
73
- "inputPerToken": 0.0000025,
74
- "outputPerToken": 0.000015,
75
- "cacheReadPerToken": 0.00000025
85
+ "inputPerToken": 2.5e-06,
86
+ "outputPerToken": 1.5e-05,
87
+ "cacheReadPerToken": 2.5e-07
76
88
  },
77
89
  "gpt-5.4-mini": {
78
- "inputPerToken": 0.00000075,
79
- "outputPerToken": 0.0000045,
80
- "cacheReadPerToken": 0.000000075
90
+ "inputPerToken": 7.5e-07,
91
+ "outputPerToken": 4.5e-06,
92
+ "cacheReadPerToken": 7.5e-08
81
93
  },
82
94
  "gpt-5.4-nano": {
83
- "inputPerToken": 0.0000002,
84
- "outputPerToken": 0.00000125,
85
- "cacheReadPerToken": 0.00000002
95
+ "inputPerToken": 2e-07,
96
+ "outputPerToken": 1.25e-06,
97
+ "cacheReadPerToken": 2e-08
86
98
  },
87
99
  "gpt-5": {
88
- "inputPerToken": 0.00000125,
89
- "outputPerToken": 0.00001,
90
- "cacheReadPerToken": 0.000000125
100
+ "inputPerToken": 1.25e-06,
101
+ "outputPerToken": 1e-05,
102
+ "cacheReadPerToken": 1.25e-07
91
103
  },
92
104
  "gpt-4.1": {
93
- "inputPerToken": 0.000002,
94
- "outputPerToken": 0.000008,
95
- "cacheReadPerToken": 0.0000005
105
+ "inputPerToken": 2e-06,
106
+ "outputPerToken": 8e-06,
107
+ "cacheReadPerToken": 5e-07
96
108
  },
97
109
  "gpt-4.1-mini": {
98
- "inputPerToken": 0.0000004,
99
- "outputPerToken": 0.0000016,
100
- "cacheReadPerToken": 0.0000001
110
+ "inputPerToken": 4e-07,
111
+ "outputPerToken": 1.6e-06,
112
+ "cacheReadPerToken": 1e-07
101
113
  },
102
114
  "gpt-4.1-nano": {
103
- "inputPerToken": 0.0000001,
104
- "outputPerToken": 0.0000004,
105
- "cacheReadPerToken": 0.000000025
115
+ "inputPerToken": 1e-07,
116
+ "outputPerToken": 4e-07,
117
+ "cacheReadPerToken": 2.5e-08
106
118
  },
107
119
  "gpt-4o": {
108
- "inputPerToken": 0.0000025,
109
- "outputPerToken": 0.00001,
110
- "cacheReadPerToken": 0.00000125
120
+ "inputPerToken": 2.5e-06,
121
+ "outputPerToken": 1e-05,
122
+ "cacheReadPerToken": 1.25e-06
111
123
  },
112
124
  "gpt-4o-mini": {
113
- "inputPerToken": 0.00000015,
114
- "outputPerToken": 0.0000006,
115
- "cacheReadPerToken": 0.000000075
125
+ "inputPerToken": 1.5e-07,
126
+ "outputPerToken": 6e-07,
127
+ "cacheReadPerToken": 7.5e-08
116
128
  },
117
129
  "o3": {
118
- "inputPerToken": 0.000002,
119
- "outputPerToken": 0.000008,
120
- "cacheReadPerToken": 0.0000005
130
+ "inputPerToken": 2e-06,
131
+ "outputPerToken": 8e-06,
132
+ "cacheReadPerToken": 5e-07
121
133
  },
122
134
  "o4-mini": {
123
- "inputPerToken": 0.0000011,
124
- "outputPerToken": 0.0000044,
125
- "cacheReadPerToken": 0.000000275
135
+ "inputPerToken": 1.1e-06,
136
+ "outputPerToken": 4.4e-06,
137
+ "cacheReadPerToken": 2.75e-07
126
138
  },
127
139
  "gemini-2.5-pro": {
128
- "inputPerToken": 0.00000125,
129
- "outputPerToken": 0.00001,
130
- "cacheReadPerToken": 0.0000003125
140
+ "inputPerToken": 1.25e-06,
141
+ "outputPerToken": 1e-05,
142
+ "cacheReadPerToken": 3.125e-07
131
143
  },
132
144
  "gemini-2.5-flash": {
133
- "inputPerToken": 0.0000003,
134
- "outputPerToken": 0.0000025,
135
- "cacheReadPerToken": 0.000000075
145
+ "inputPerToken": 3e-07,
146
+ "outputPerToken": 2.5e-06,
147
+ "cacheReadPerToken": 7.5e-08
136
148
  },
137
149
  "gemini-2.5-flash-lite": {
138
- "inputPerToken": 0.0000001,
139
- "outputPerToken": 0.0000004,
140
- "cacheReadPerToken": 0.000000025
150
+ "inputPerToken": 1e-07,
151
+ "outputPerToken": 4e-07,
152
+ "cacheReadPerToken": 2.5e-08
141
153
  },
142
154
  "gemini-1.5-pro": {
143
- "inputPerToken": 0.00000125,
144
- "outputPerToken": 0.000005,
145
- "cacheReadPerToken": 0.0000003125
155
+ "inputPerToken": 1.25e-06,
156
+ "outputPerToken": 5e-06,
157
+ "cacheReadPerToken": 3.125e-07
146
158
  },
147
159
  "gemini-1.5-flash": {
148
- "inputPerToken": 0.000000075,
149
- "outputPerToken": 0.0000003,
150
- "cacheReadPerToken": 0.00000001875
160
+ "inputPerToken": 7.5e-08,
161
+ "outputPerToken": 3e-07,
162
+ "cacheReadPerToken": 1.875e-08
163
+ },
164
+ "muse-spark-1.2": {
165
+ "inputPerToken": 1.25e-06,
166
+ "outputPerToken": 4.25e-06,
167
+ "cacheReadPerToken": 1.5e-07
168
+ },
169
+ "muse-spark-1.1": {
170
+ "inputPerToken": 1.25e-06,
171
+ "outputPerToken": 4.25e-06,
172
+ "cacheReadPerToken": 1.5e-07
173
+ },
174
+ "muse-spark-1.2-contributor": {
175
+ "inputPerToken": 1e-07,
176
+ "outputPerToken": 2e-07,
177
+ "cacheReadPerToken": 2e-09
151
178
  }
152
179
  }
153
180
  }
@@ -5,6 +5,19 @@
5
5
  * and is imported with a `type: json` attribute so it survives `tsc` emit AND
6
6
  * Node ESM's import-attribute requirement at runtime (the package is ESM).
7
7
  *
8
+ * ## Keeping it current
9
+ *
10
+ * A model missing from `prices.json` prices to NOTHING — `getModelPricing` returns
11
+ * null and the session contributes $0, silently. That is how 478 `claude-opus-5`
12
+ * sessions read as free: matching is dash-bounded, so `claude-opus-5` cannot fall back
13
+ * to the `claude-opus-4` entry. When a new model ships, add it here in the same change.
14
+ *
15
+ * **Dated rate: Claude Sonnet 5 is priced at its introductory $2/$10 per MTok, which
16
+ * ends 2026-08-31.** From 2026-09-01 the standard rate is $3/$15 (cache write $3.75,
17
+ * cache read $0.30). This table has no notion of an effective date — every row is a
18
+ * single current rate — so that entry MUST be updated then, or Sonnet 5 spend will
19
+ * read ~33% low. Source: https://platform.claude.com/docs/en/about-claude/pricing
20
+ *
8
21
  * `getModelPricing` is prefix/suffix-tolerant: real model identifiers carry
9
22
  * vendor prefixes (`us.anthropic.`), version dashes (`claude-opus-4-8`), and
10
23
  * date suffixes (`-20250514`), none of which appear in the canonical keys. We
@@ -17,6 +17,11 @@ export interface RefreshOptions {
17
17
  skipPrompts?: boolean;
18
18
  /** Skip CLI version install/upgrade from agents.yaml. */
19
19
  skipClis?: boolean;
20
+ /**
21
+ * Suppress human progress lines on stdout. Required for machine consumers
22
+ * (`agents sync --json` / fleet fan-out) so stdout stays a single JSON object.
23
+ */
24
+ quiet?: boolean;
20
25
  }
21
26
  /**
22
27
  * Re-materialize local state from declared configuration: install CLI versions,