@mushi-mushi/cli 0.35.0 → 0.35.2

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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @mushi-mushi/cli
2
2
 
3
- > **Your AI wrote it. Mushi tells you why it broke.**
3
+ > **Your AI wrote it. Mushi Mushi tells you why it broke.**
4
4
 
5
5
  The `mushi` command for [Mushi Mushi](https://github.com/kensaurus/mushi-mushi). Install the SDK in your app, connect your editor, then read bugs, dispatch fixes and merge them without leaving the terminal.
6
6
 
@@ -29,11 +29,13 @@ For your editor, `mushi setup` writes the hosted MCP entry by default: the edito
29
29
 
30
30
  | Group | Commands |
31
31
  | --- | --- |
32
- | Set up | `init`, `login`, `setup`, `connect`, `doctor`, `upgrade`, `nudge`, `completion` |
33
- | Bugs | `reports list/show/search/triage`, `lessons list/show` |
32
+ | Set up | `init`, `login`, `setup`, `connect`, `doctor`, `test` (send a test report), `upgrade`, `nudge`, `completion`, `profile` |
33
+ | Bugs | `reports list/show/search/triage`, `lessons list/show`, `sentry import` |
34
34
  | Fixes | `fix <reportId>`, `fixes tail/merge/refresh-ci/review/verify`, `verify workflow` |
35
- | Ship | `sourcemaps upload`, `deploy check`, `migrate`, `audit` |
36
- | Test and UX | `qa stories/runs/run`, `tdd gen/pending/approve/improve`, `stories map`, `ux` |
35
+ | Local agent | `work` (a Cursor agent on your own computer fixes a report; you push), `worker install/status/revoke` (keeps it running, steered from the console) |
36
+ | Ship | `sourcemaps upload`, `deploy check`, `migrate`, `audit`, `releases` |
37
+ | Test and UX | `qa stories/runs/run`, `tdd gen/pending/approve/improve`, `stories map`, `ux` (including `ux fresh-eyes`, the first-time user test) |
38
+ | CI | `runner status/compare/bill`: where your tests run, what they cost, and whether a red check was your code or the machine |
37
39
  | Account | `whoami`, `status`, `usage`, `billing`, `keys`, `integrations`, `slack` |
38
40
 
39
41
  `mushi --help` and `mushi <command> --help` list every command and flag.
@@ -43,7 +45,7 @@ For your editor, `mushi setup` writes the hosted MCP entry by default: the edito
43
45
  ```bash
44
46
  mushi doctor --fix # check SDK, ingest and dispatch; fix what's safe locally
45
47
  mushi reports list --status new --severity critical # what broke
46
- mushi fix <reportId> --wait # an agent opens a draft PR for it
48
+ mushi fix <reportId> --wait # an agent opens a draft PR for it (your own AI key)
47
49
  mushi fixes merge <fixId> # merge it and mark the report Fixed
48
50
  mushi upgrade # bump @mushi-mushi/* to the latest stable
49
51
  mushi upgrade --check # CI: exit 0 current, 1 outdated, 2 registry down
@@ -58,7 +60,9 @@ mushi init --yes --project-id <uuid> --api-key mushi_xxx --skip-test-report
58
60
  MUSHI_API_KEY=mushi_xxx mushi connect --project-id <uuid> --endpoint <url> --wait # wire a repo, wait for the first SDK heartbeat
59
61
  ```
60
62
 
61
- Other `init` flags: `--framework next`, `--cwd apps/web` (monorepos), `--endpoint <url>` (self-hosted), `--skip-install`.
63
+ Other `init` flags: `--framework next`, `--cwd apps/web` (monorepos), `--endpoint <url>` (self-hosted), `--skip-install`, `--audit` (check an existing install instead).
64
+
65
+ **What needs your own key.** Reading reports, diagnoses and fix prompts does not. `mushi fix` hands the report to an agent that runs on your own key: Anthropic for the built-in fixer (the default), or Cursor with `--agent cursor_cloud`. `mushi work` runs a Cursor agent on your own computer instead.
62
66
 
63
67
  ## Environment variables
64
68
 
@@ -68,6 +72,7 @@ Other `init` flags: `--framework next`, `--cwd apps/web` (monorepos), `--endpoin
68
72
  | `MUSHI_PROJECT_ID` | Project UUID |
69
73
  | `MUSHI_API_ENDPOINT` | API base URL (defaults to Mushi Cloud) |
70
74
  | `MUSHI_CONSOLE_URL` | Console base for links and browser opens |
75
+ | `MUSHI_PROFILE` | Named credential profile to use (same as `--profile`) |
71
76
  | `MUSHI_BYOK_KEY` | Key for `mushi keys add`, kept out of shell history |
72
77
  | `MUSHI_NO_UPDATE_CHECK=1` | Skip the "newer version" hint |
73
78
  | `MUSHI_DEBUG=1` | Full stack traces on error |
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  MUSHI_CLI_VERSION
4
- } from "./chunk-GNTEONTU.js";
4
+ } from "./chunk-OWUJYMV6.js";
5
5
  import {
6
6
  CLOUD_API_ENDPOINT,
7
7
  normalizeEndpoint
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/version.ts
4
+ var MUSHI_CLI_VERSION = true ? "0.35.2" : "0.0.0-dev";
5
+ var MUSHI_MCP_PIN_SPEC = "@mushi-mushi/mcp@0.30.2";
6
+
7
+ export {
8
+ MUSHI_CLI_VERSION,
9
+ MUSHI_MCP_PIN_SPEC
10
+ };
@@ -8,10 +8,10 @@ import {
8
8
  requireConfig,
9
9
  requireUuid,
10
10
  tryLoadWorkerKey
11
- } from "./chunk-T36WTCFM.js";
11
+ } from "./chunk-DBXL4RLE.js";
12
12
  import {
13
13
  MUSHI_CLI_VERSION
14
- } from "./chunk-GNTEONTU.js";
14
+ } from "./chunk-OWUJYMV6.js";
15
15
 
16
16
  // src/worker/daemon.ts
17
17
  import { existsSync as existsSync6, readFileSync as readFileSync5 } from "fs";
@@ -983,7 +983,7 @@ function registerWorkCommands(program) {
983
983
  if (opts.repoDir || opts.report || opts.followups) {
984
984
  throw new MushiCliError("E_INVALID_INPUT", "--daemon takes its lanes and clones from the worker config, not from --repo-dir, --report or --followups.", "mushi worker install");
985
985
  }
986
- const { runDaemon: runDaemon2 } = await import("./daemon-LG3VI5EK.js");
986
+ const { runDaemon: runDaemon2 } = await import("./daemon-STJJNPRM.js");
987
987
  await runDaemon2({ configPath: opts.workerConfig });
988
988
  return;
989
989
  }
@@ -0,0 +1,8 @@
1
+ // src/version.ts
2
+ var MUSHI_CLI_VERSION = true ? "0.35.2" : "0.0.0-dev";
3
+ var MUSHI_MCP_PIN_SPEC = "@mushi-mushi/mcp@0.30.2";
4
+
5
+ export {
6
+ MUSHI_CLI_VERSION,
7
+ MUSHI_MCP_PIN_SPEC
8
+ };
@@ -9,10 +9,10 @@ import {
9
9
  requireUuid,
10
10
  saveConfig,
11
11
  savedSdkKeyFor
12
- } from "./chunk-T36WTCFM.js";
12
+ } from "./chunk-DBXL4RLE.js";
13
13
  import {
14
14
  MUSHI_MCP_PIN_SPEC
15
- } from "./chunk-GNTEONTU.js";
15
+ } from "./chunk-OWUJYMV6.js";
16
16
  import {
17
17
  assertEndpoint,
18
18
  normalizeEndpoint
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  MUSHI_CLI_VERSION
3
- } from "./chunk-HXLBH5GE.js";
3
+ } from "./chunk-VNGG2M3O.js";
4
4
  import {
5
5
  assertEndpoint,
6
6
  normalizeEndpoint
@@ -2,10 +2,10 @@
2
2
  import {
3
3
  resolveSdkEnvKey,
4
4
  runConnect
5
- } from "./chunk-DSYPYBJT.js";
5
+ } from "./chunk-XUPFPVB2.js";
6
6
  import "./chunk-KOBEOGNF.js";
7
- import "./chunk-T36WTCFM.js";
8
- import "./chunk-GNTEONTU.js";
7
+ import "./chunk-DBXL4RLE.js";
8
+ import "./chunk-OWUJYMV6.js";
9
9
  import "./chunk-LGGE3LH7.js";
10
10
  export {
11
11
  resolveSdkEnvKey,
@@ -6,10 +6,10 @@ import {
6
6
  saveConfig,
7
7
  savedSdkKeyFor,
8
8
  waitForIngestReady
9
- } from "./chunk-BC3Y5C3L.js";
9
+ } from "./chunk-ZA2HNXTH.js";
10
10
  import {
11
11
  MUSHI_MCP_PIN_SPEC
12
- } from "./chunk-HXLBH5GE.js";
12
+ } from "./chunk-VNGG2M3O.js";
13
13
  import {
14
14
  detectFramework,
15
15
  envVarsToWrite,
@@ -7,9 +7,9 @@ import {
7
7
  readWorkerKey,
8
8
  runDaemon,
9
9
  workerHostId
10
- } from "./chunk-RQEWLXGY.js";
11
- import "./chunk-T36WTCFM.js";
12
- import "./chunk-GNTEONTU.js";
10
+ } from "./chunk-VAQTC77F.js";
11
+ import "./chunk-DBXL4RLE.js";
12
+ import "./chunk-OWUJYMV6.js";
13
13
  import "./chunk-LGGE3LH7.js";
14
14
  export {
15
15
  assertWorkerKey,
package/dist/index.js CHANGED
@@ -22,7 +22,7 @@ import {
22
22
  sanitizeEndpoint,
23
23
  sanitizeProjectId,
24
24
  writeMcpServerEntry
25
- } from "./chunk-DSYPYBJT.js";
25
+ } from "./chunk-XUPFPVB2.js";
26
26
  import {
27
27
  FRAMEWORKS,
28
28
  detectFramework,
@@ -49,7 +49,7 @@ import {
49
49
  registerUxCommands,
50
50
  registerWorkCommands,
51
51
  validateWorkerConfig
52
- } from "./chunk-RQEWLXGY.js";
52
+ } from "./chunk-VAQTC77F.js";
53
53
  import {
54
54
  CONFIG_PATH,
55
55
  MushiCliError,
@@ -87,11 +87,11 @@ import {
87
87
  tryDeleteWorkerKey,
88
88
  trySaveKeyToKeychain,
89
89
  trySaveWorkerKey
90
- } from "./chunk-T36WTCFM.js";
90
+ } from "./chunk-DBXL4RLE.js";
91
91
  import {
92
92
  MUSHI_CLI_VERSION,
93
93
  MUSHI_MCP_PIN_SPEC
94
- } from "./chunk-GNTEONTU.js";
94
+ } from "./chunk-OWUJYMV6.js";
95
95
  import {
96
96
  CLOUD_API_ENDPOINT,
97
97
  CLOUD_MCP_OAUTH_URL,
@@ -1594,7 +1594,7 @@ async function checkOnboardingStatus(config, _consoleBase, cwd, doFetch = global
1594
1594
  }
1595
1595
  async function checkVersionDrift(cwd, doFetch) {
1596
1596
  const checks = [];
1597
- const { MUSHI_CLI_VERSION: MUSHI_CLI_VERSION2 } = await import("./version-XGDCADFX.js");
1597
+ const { MUSHI_CLI_VERSION: MUSHI_CLI_VERSION2 } = await import("./version-6ZDAJV77.js");
1598
1598
  if (MUSHI_CLI_VERSION2 === "0.0.0-dev") return checks;
1599
1599
  const parse2 = (v) => {
1600
1600
  const m = v.replace(/^[~^]/, "").match(/^(\d+)\.(\d+)\.(\d+)/);
@@ -1686,6 +1686,46 @@ async function checkPipelineDoctor(config, doFetch) {
1686
1686
  }];
1687
1687
  }
1688
1688
  }
1689
+ var HEARTBEAT_ROWS = /* @__PURE__ */ new Set(["never_seen", "sdk_stale"]);
1690
+ async function checkHealthRegistry(config, doFetch) {
1691
+ if (!config.endpoint || !config.apiKey || !config.projectId) return [];
1692
+ let creds;
1693
+ try {
1694
+ creds = sanitizeCliCredentials(config);
1695
+ } catch {
1696
+ return [];
1697
+ }
1698
+ try {
1699
+ const { endpoint, apiKey, projectId: projectId2 } = creds;
1700
+ const res = await doFetch(`${endpoint}/v1/admin/health-checks?projectId=${encodeURIComponent(projectId2)}`, {
1701
+ headers: apiKeyHeaders(apiKey, projectId2),
1702
+ signal: AbortSignal.timeout(3e4)
1703
+ });
1704
+ if (res.status === 401 || res.status === 403 || res.status === 404) return [];
1705
+ if (!res.ok) {
1706
+ return [{ name: "[health] Health check", ok: true, warn: true, detail: `GET /v1/admin/health-checks returned HTTP ${res.status}; health unknown.` }];
1707
+ }
1708
+ const body = await res.json();
1709
+ const rows = (body.data?.projects?.[0]?.checks ?? []).filter((r) => r.source !== "doctor" && !HEARTBEAT_ROWS.has(r.id));
1710
+ const out = [];
1711
+ for (const r of rows) {
1712
+ if (r.status === "ok") continue;
1713
+ const waiting = r.affects && r.affects > 0 ? ` ${r.affects} waiting on this.` : "";
1714
+ const fix = r.fix ? ` \u2192 Fix: ${r.fix.label}${r.fix.to ? ` (console ${r.fix.to})` : ""}${r.fix.steps?.length ? `: ${r.fix.steps.join(" ")}` : ""}` : "";
1715
+ out.push({
1716
+ name: `[health] ${r.title}`,
1717
+ ok: true,
1718
+ warn: true,
1719
+ detail: r.status === "unknown" ? `Not checked: ${r.detail}` : `${r.detail}${waiting}${fix}`
1720
+ });
1721
+ }
1722
+ const passing = rows.filter((r) => r.status === "ok").length;
1723
+ if (passing > 0) out.push({ name: "[health] Other checks", ok: true, detail: `${passing} passed.` });
1724
+ return out;
1725
+ } catch {
1726
+ return [{ name: "[health] Health check", ok: true, warn: true, detail: "Could not reach /v1/admin/health-checks (timeout); health unknown." }];
1727
+ }
1728
+ }
1689
1729
  async function runDoctor(config, options = {}) {
1690
1730
  const doFetch = options.fetch ?? globalThis.fetch;
1691
1731
  const checks = [];
@@ -1726,6 +1766,7 @@ async function runDoctor(config, options = {}) {
1726
1766
  const serverChecks = await checkServerPreflight(config, doFetch);
1727
1767
  checks.push(...serverChecks);
1728
1768
  checks.push(...await checkPipelineDoctor(config, doFetch));
1769
+ checks.push(...await checkHealthRegistry(config, doFetch));
1729
1770
  }
1730
1771
  checks.push(...await checkVersionDrift(options.cwd ?? process.cwd(), doFetch));
1731
1772
  if (runIngest) {
@@ -2512,7 +2553,7 @@ import { MushiRewardsBadge } from '@mushi-mushi/react';
2512
2553
  " [ ] 1. Paste the init snippet above into your app entry file",
2513
2554
  " [ ] 2. Start your dev server",
2514
2555
  " [ ] 3. Wire your editor: npx mushi-mushi setup --ide cursor (or --ide claude)",
2515
- ` [ ] 4. Open the Verify tab to send a test report: ${consoleUrl(consoleBase, "/onboarding?tab=verify")}`
2556
+ ` [ ] 4. Open the Test it tab to send a test report: ${consoleUrl(consoleBase, "/onboarding?tab=verify")}`
2516
2557
  ].join("\n"),
2517
2558
  "Next steps:"
2518
2559
  );
@@ -2526,7 +2567,7 @@ async function maybeOfferConnect(credentials, options, _consoleBase) {
2526
2567
  if (p.isCancel(answer) || !answer) return;
2527
2568
  const endpoint = resolveCloudEndpoint(options.endpoint);
2528
2569
  try {
2529
- const { runConnect: runConnect2 } = await import("./connect-DCXEXEIG.js");
2570
+ const { runConnect: runConnect2 } = await import("./connect-SH7D5RJP.js");
2530
2571
  const saved = loadConfig();
2531
2572
  const result = await runConnect2(
2532
2573
  {
@@ -2544,7 +2585,9 @@ async function maybeOfferConnect(credentials, options, _consoleBase) {
2544
2585
  for (const line of result.messages) p.log.message(line);
2545
2586
  } catch (err) {
2546
2587
  p.log.warn(err instanceof Error ? err.message : String(err));
2547
- p.log.info("You can run manually: mushi connect --write-env --wire-ide --wait");
2588
+ p.log.info(
2589
+ `You can run it yourself: npx mushi-mushi connect --project-id ${credentials.projectId} --endpoint ${endpoint} --write-env --wire-ide --wait`
2590
+ );
2548
2591
  }
2549
2592
  }
2550
2593
  async function maybeEnableRewards(options) {
@@ -5318,7 +5361,7 @@ Examples:
5318
5361
 
5319
5362
  // src/commands/connect-cli.ts
5320
5363
  function registerConnectCommand(program2) {
5321
- program2.command("connect").description("Save credentials, merge env vars, wire Cursor MCP, optionally wait for SDK heartbeat").option("--api-key <key>", "Mushi API key (mushi_\u2026) saved to the CLI config \u2014 or set MUSHI_API_KEY to keep it out of shell history").option(
5364
+ program2.command("connect").description("Save credentials, merge env vars, wire Cursor MCP, optionally wait for SDK heartbeat").option("--api-key <key>", "Mushi API key (mushi_\u2026) saved to the CLI config \u2014 or set MUSHI_API_KEY to keep it out of shell history. Default: the key `npx mushi-mushi` or `mushi login` saved").option(
5322
5365
  "--sdk-key <key>",
5323
5366
  "Ingest-only (report:write) key for the SDK env vars \u2014 or set MUSHI_SDK_KEY. Default: the key saved for this project, else --api-key if it is ingest-only"
5324
5367
  ).requiredOption("--project-id <id>", "Project UUID").requiredOption("--endpoint <url>", "Supabase edge function URL").option("--cwd <path>", "Target repo").option("--write-env", "Force-write SDK env vars to .env.local (default; overrides --no-env)").option("--wire-ide", "Force-wire Cursor MCP into .cursor/mcp.json (default; overrides --no-ide)").option("--no-env", "Skip writing .env.local").option("--no-ide", "Skip writing .cursor/mcp.json").option("--wait", "Poll ingest-setup until SDK heartbeat lands").option("--wait-timeout <sec>", "Max seconds for --wait", "120").option("--json", "Machine-readable output").addHelpText("after", `
@@ -5330,9 +5373,10 @@ Examples:
5330
5373
  SDK env vars (VITE_ / NEXT_PUBLIC_ / EXPO_PUBLIC_ \u2026) ship inside your app bundle,
5331
5374
  so connect only writes a key the backend confirms is ingest-only (report:write).
5332
5375
  A key that can read reports is refused for .env.local; it still works for the CLI and MCP.`).action(async (opts) => {
5333
- const apiKey = process.env.MUSHI_API_KEY ?? opts.apiKey;
5376
+ const saved = loadConfig();
5377
+ const apiKey = process.env.MUSHI_API_KEY ?? opts.apiKey ?? saved.apiKey;
5334
5378
  if (!apiKey) {
5335
- console.error("Provide the API key via the MUSHI_API_KEY env var (recommended) or --api-key <key>.");
5379
+ console.error("No API key found. Run `npx mushi-mushi` or `mushi login` first, or set MUSHI_API_KEY (recommended) or pass --api-key <key>.");
5336
5380
  process.exit(1);
5337
5381
  }
5338
5382
  const result = await runConnect({
@@ -5346,7 +5390,7 @@ A key that can read reports is refused for .env.local; it still works for the CL
5346
5390
  wait: opts.wait,
5347
5391
  waitTimeoutSec: parseInt(opts.waitTimeout, 10) || 120,
5348
5392
  json: opts.json
5349
- }, loadConfig());
5393
+ }, saved);
5350
5394
  if (opts.json) {
5351
5395
  console.log(JSON.stringify(result, null, 2));
5352
5396
  } else {
@@ -12772,12 +12816,23 @@ Uploaded ${p5.rows} day \xD7 repo \xD7 SKU rows for ${p5.month}. The console's C
12772
12816
  });
12773
12817
  const placement = runner.command("placement").description("Where each repo's CI runs, and changing it through one runner variable with approval (ADR 0037)");
12774
12818
  const placementBody = (opts, config) => {
12775
- if (!opts.remove && !opts.value) throw new MushiCliError("E_INVALID_INPUT", "Pass --value <runner label>, or --remove to delete the variable.");
12819
+ if (!opts.remove && !opts.value) throw new MushiCliError("E_INVALID_INPUT", "Pass --value <runner label | economy | thorough>, or --remove to delete the variable.");
12776
12820
  if (opts.remove && opts.value) throw new MushiCliError("E_INVALID_INPUT", "Pass either --value or --remove, not both.");
12777
12821
  if (!/^[A-Za-z0-9._-]+\/[A-Za-z0-9._-]+$/.test(opts.repo)) throw new MushiCliError("E_INVALID_INPUT", "--repo must be owner/repo.");
12778
12822
  const raw = opts.projectId ?? opts.project ?? config.projectId;
12779
12823
  if (!raw) throw new MushiCliError("E_INVALID_INPUT", "Pass --project-id (or configure a project).");
12780
- return { projectId: requireUuid(raw, "project id"), repo: opts.repo, variable: opts.variable, value: opts.remove ? null : opts.value };
12824
+ let revertAfterHours;
12825
+ if (opts.revertAfter !== void 0) {
12826
+ revertAfterHours = Number(opts.revertAfter);
12827
+ if (!Number.isInteger(revertAfterHours) || revertAfterHours < 1 || revertAfterHours > 168) throw new MushiCliError("E_INVALID_INPUT", "--revert-after is a whole number of hours from 1 to 168.");
12828
+ }
12829
+ return {
12830
+ projectId: requireUuid(raw, "project id"),
12831
+ repo: opts.repo,
12832
+ variable: opts.variable,
12833
+ value: opts.remove ? null : opts.value,
12834
+ ...revertAfterHours !== void 0 ? { revertAfterHours } : {}
12835
+ };
12781
12836
  };
12782
12837
  placement.command("show").description("Each repo: the runner variables its workflows read and their values, the CI agreement, runner labels, pending requests").option("--project-id <id>", "Project ID (defaults to the configured project)").option("--project <id>", "Same as --project-id").option("--json", "Machine-readable JSON output").action(async (opts) => {
12783
12838
  const config = requireConfig();
@@ -12810,7 +12865,7 @@ Uploaded ${p5.rows} day \xD7 repo \xD7 SKU rows for ${p5.month}. The console's C
12810
12865
  console.log(`
12811
12866
  Requested ${r.id} (${r.status}). ${r.next ?? "An owner or admin approves and runs it in the console."}`);
12812
12867
  };
12813
- const changeOptions = (cmd) => cmd.requiredOption("--repo <owner/repo>", "Repository connected to the project").option("--variable <name>", "LINUX_RUNNER or RUNNER_<WORKFLOW>", "LINUX_RUNNER").option("--value <label>", "The runner label jobs should ask for").option("--remove", "Remove the variable (jobs use the workflow's fallback, usually GitHub-hosted)").option("--project-id <id>", "Project ID (defaults to the configured project)").option("--project <id>", "Same as --project-id").option("--json", "Machine-readable JSON output");
12868
+ const changeOptions = (cmd) => cmd.requiredOption("--repo <owner/repo>", "Repository connected to the project").option("--variable <name>", "LINUX_RUNNER, RUNNER_<WORKFLOW>, or CI_PROFILE (where a workflow reads it)", "LINUX_RUNNER").option("--value <label>", "The runner label jobs should ask for (CI_PROFILE: economy or thorough)").option("--revert-after <hours>", "A move to GitHub-hosted runners switches back after this many hours (1-168)").option("--remove", "Remove the variable (jobs use the workflow's fallback, usually GitHub-hosted)").option("--project-id <id>", "Project ID (defaults to the configured project)").option("--project <id>", "Same as --project-id").option("--json", "Machine-readable JSON output");
12814
12869
  changeOptions(
12815
12870
  placement.command("preview").description("Dry run: what would move, what stays and why, the target runners, cost, the CI agreement's verdict. Changes nothing")
12816
12871
  ).action(placementAction("preview"));
package/dist/init.js CHANGED
@@ -25,10 +25,10 @@ import {
25
25
  saveConfig,
26
26
  savedSdkKeyFor,
27
27
  trySaveKeyToKeychain
28
- } from "./chunk-BC3Y5C3L.js";
28
+ } from "./chunk-ZA2HNXTH.js";
29
29
  import {
30
30
  MUSHI_CLI_VERSION
31
- } from "./chunk-HXLBH5GE.js";
31
+ } from "./chunk-VNGG2M3O.js";
32
32
  import {
33
33
  FRAMEWORKS,
34
34
  detectFramework,
@@ -1246,6 +1246,46 @@ async function checkPipelineDoctor(config, doFetch) {
1246
1246
  }];
1247
1247
  }
1248
1248
  }
1249
+ var HEARTBEAT_ROWS = /* @__PURE__ */ new Set(["never_seen", "sdk_stale"]);
1250
+ async function checkHealthRegistry(config, doFetch) {
1251
+ if (!config.endpoint || !config.apiKey || !config.projectId) return [];
1252
+ let creds;
1253
+ try {
1254
+ creds = sanitizeCliCredentials(config);
1255
+ } catch {
1256
+ return [];
1257
+ }
1258
+ try {
1259
+ const { endpoint, apiKey, projectId } = creds;
1260
+ const res = await doFetch(`${endpoint}/v1/admin/health-checks?projectId=${encodeURIComponent(projectId)}`, {
1261
+ headers: apiKeyHeaders(apiKey, projectId),
1262
+ signal: AbortSignal.timeout(3e4)
1263
+ });
1264
+ if (res.status === 401 || res.status === 403 || res.status === 404) return [];
1265
+ if (!res.ok) {
1266
+ return [{ name: "[health] Health check", ok: true, warn: true, detail: `GET /v1/admin/health-checks returned HTTP ${res.status}; health unknown.` }];
1267
+ }
1268
+ const body = await res.json();
1269
+ const rows = (body.data?.projects?.[0]?.checks ?? []).filter((r) => r.source !== "doctor" && !HEARTBEAT_ROWS.has(r.id));
1270
+ const out = [];
1271
+ for (const r of rows) {
1272
+ if (r.status === "ok") continue;
1273
+ const waiting = r.affects && r.affects > 0 ? ` ${r.affects} waiting on this.` : "";
1274
+ const fix = r.fix ? ` \u2192 Fix: ${r.fix.label}${r.fix.to ? ` (console ${r.fix.to})` : ""}${r.fix.steps?.length ? `: ${r.fix.steps.join(" ")}` : ""}` : "";
1275
+ out.push({
1276
+ name: `[health] ${r.title}`,
1277
+ ok: true,
1278
+ warn: true,
1279
+ detail: r.status === "unknown" ? `Not checked: ${r.detail}` : `${r.detail}${waiting}${fix}`
1280
+ });
1281
+ }
1282
+ const passing = rows.filter((r) => r.status === "ok").length;
1283
+ if (passing > 0) out.push({ name: "[health] Other checks", ok: true, detail: `${passing} passed.` });
1284
+ return out;
1285
+ } catch {
1286
+ return [{ name: "[health] Health check", ok: true, warn: true, detail: "Could not reach /v1/admin/health-checks (timeout); health unknown." }];
1287
+ }
1288
+ }
1249
1289
  async function runDoctor(config, options = {}) {
1250
1290
  const doFetch = options.fetch ?? globalThis.fetch;
1251
1291
  const checks = [];
@@ -1286,6 +1326,7 @@ async function runDoctor(config, options = {}) {
1286
1326
  const serverChecks = await checkServerPreflight(config, doFetch);
1287
1327
  checks.push(...serverChecks);
1288
1328
  checks.push(...await checkPipelineDoctor(config, doFetch));
1329
+ checks.push(...await checkHealthRegistry(config, doFetch));
1289
1330
  }
1290
1331
  checks.push(...await checkVersionDrift(options.cwd ?? process.cwd(), doFetch));
1291
1332
  if (runIngest) {
@@ -2072,7 +2113,7 @@ import { MushiRewardsBadge } from '@mushi-mushi/react';
2072
2113
  " [ ] 1. Paste the init snippet above into your app entry file",
2073
2114
  " [ ] 2. Start your dev server",
2074
2115
  " [ ] 3. Wire your editor: npx mushi-mushi setup --ide cursor (or --ide claude)",
2075
- ` [ ] 4. Open the Verify tab to send a test report: ${consoleUrl(consoleBase, "/onboarding?tab=verify")}`
2116
+ ` [ ] 4. Open the Test it tab to send a test report: ${consoleUrl(consoleBase, "/onboarding?tab=verify")}`
2076
2117
  ].join("\n"),
2077
2118
  "Next steps:"
2078
2119
  );
@@ -2086,7 +2127,7 @@ async function maybeOfferConnect(credentials, options, _consoleBase) {
2086
2127
  if (p.isCancel(answer) || !answer) return;
2087
2128
  const endpoint = resolveCloudEndpoint(options.endpoint);
2088
2129
  try {
2089
- const { runConnect } = await import("./connect-TBE7M2G5.js");
2130
+ const { runConnect } = await import("./connect-YC6MRVZN.js");
2090
2131
  const saved = loadConfig();
2091
2132
  const result = await runConnect(
2092
2133
  {
@@ -2104,7 +2145,9 @@ async function maybeOfferConnect(credentials, options, _consoleBase) {
2104
2145
  for (const line of result.messages) p.log.message(line);
2105
2146
  } catch (err) {
2106
2147
  p.log.warn(err instanceof Error ? err.message : String(err));
2107
- p.log.info("You can run manually: mushi connect --write-env --wire-ide --wait");
2148
+ p.log.info(
2149
+ `You can run it yourself: npx mushi-mushi connect --project-id ${credentials.projectId} --endpoint ${endpoint} --write-env --wire-ide --wait`
2150
+ );
2108
2151
  }
2109
2152
  }
2110
2153
  async function maybeEnableRewards(options) {
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  MUSHI_CLI_VERSION,
4
4
  MUSHI_MCP_PIN_SPEC
5
- } from "./chunk-GNTEONTU.js";
5
+ } from "./chunk-OWUJYMV6.js";
6
6
  export {
7
7
  MUSHI_CLI_VERSION,
8
8
  MUSHI_MCP_PIN_SPEC
package/dist/version.d.ts CHANGED
@@ -14,6 +14,6 @@ declare const MUSHI_CLI_VERSION: string;
14
14
  * setup refreshes the pin. Synced to packages/mcp/package.json by
15
15
  * `scripts/sync-mcp-pin.mjs` — never hand-edit the version.
16
16
  */
17
- declare const MUSHI_MCP_PIN_SPEC = "@mushi-mushi/mcp@0.30.0";
17
+ declare const MUSHI_MCP_PIN_SPEC = "@mushi-mushi/mcp@0.30.2";
18
18
 
19
19
  export { MUSHI_CLI_VERSION, MUSHI_MCP_PIN_SPEC };
package/dist/version.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  MUSHI_CLI_VERSION,
3
3
  MUSHI_MCP_PIN_SPEC
4
- } from "./chunk-HXLBH5GE.js";
4
+ } from "./chunk-VNGG2M3O.js";
5
5
  export {
6
6
  MUSHI_CLI_VERSION,
7
7
  MUSHI_MCP_PIN_SPEC
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mushi-mushi/cli",
3
- "version": "0.35.0",
3
+ "version": "0.35.2",
4
4
  "license": "MIT",
5
5
  "description": "Mushi CLI: SDK setup, MCP wiring, bug triage. The bug mediator for AI-built apps: plain-English diagnosis + a ready fix, in your editor.",
6
6
  "bin": {
@@ -1,10 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- // src/version.ts
4
- var MUSHI_CLI_VERSION = true ? "0.35.0" : "0.0.0-dev";
5
- var MUSHI_MCP_PIN_SPEC = "@mushi-mushi/mcp@0.30.0";
6
-
7
- export {
8
- MUSHI_CLI_VERSION,
9
- MUSHI_MCP_PIN_SPEC
10
- };
@@ -1,8 +0,0 @@
1
- // src/version.ts
2
- var MUSHI_CLI_VERSION = true ? "0.35.0" : "0.0.0-dev";
3
- var MUSHI_MCP_PIN_SPEC = "@mushi-mushi/mcp@0.30.0";
4
-
5
- export {
6
- MUSHI_CLI_VERSION,
7
- MUSHI_MCP_PIN_SPEC
8
- };