@mushi-mushi/cli 0.34.0 → 0.34.1

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
@@ -4,6 +4,8 @@
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
 
7
+ Docs: [CLI reference](https://kensaur.us/mushi-mushi/docs/sdks/cli)
8
+
7
9
  ```mermaid
8
10
  flowchart LR
9
11
  A["mushi init<br/>SDK in your app"] --> B["mushi setup<br/>editor reads diagnoses"] --> C["mushi reports<br/>see what broke"] --> D["mushi fix<br/>agent opens a draft PR"] --> E["mushi fixes merge"]
@@ -70,7 +72,7 @@ Other `init` flags: `--framework next`, `--cwd apps/web` (monorepos), `--endpoin
70
72
  | `MUSHI_NO_UPDATE_CHECK=1` | Skip the "newer version" hint |
71
73
  | `MUSHI_DEBUG=1` | Full stack traces on error |
72
74
 
73
- Config lives in `~/.config/mushi/config.json`, written with mode `0o600` (a legacy `~/.mushirc` is auto-migrated). `--endpoint` must be `https://` except on localhost.
75
+ Config lives in `~/.config/mushi/config.json` (`%APPDATA%\mushi\config.json` on Windows, `$XDG_CONFIG_HOME/mushi/config.json` when that is set), written with mode `0o600` on macOS and Linux and an account-only ACL on Windows (a legacy `~/.mushirc` is auto-migrated). `--endpoint` must be `https://` except on localhost.
74
76
 
75
77
  ## Programmatic use
76
78
 
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  MUSHI_CLI_VERSION
3
- } from "./chunk-CY2BHCA5.js";
3
+ } from "./chunk-QI7DE6J3.js";
4
4
  import {
5
5
  assertEndpoint,
6
6
  normalizeEndpoint
@@ -0,0 +1,8 @@
1
+ // src/version.ts
2
+ var MUSHI_CLI_VERSION = true ? "0.34.1" : "0.0.0-dev";
3
+ var MUSHI_MCP_PIN_SPEC = "@mushi-mushi/mcp@0.29.2";
4
+
5
+ export {
6
+ MUSHI_CLI_VERSION,
7
+ MUSHI_MCP_PIN_SPEC
8
+ };
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  MUSHI_CLI_VERSION,
4
4
  MUSHI_MCP_PIN_SPEC
5
- } from "./chunk-FPVAQNHT.js";
5
+ } from "./chunk-XXBGTUGX.js";
6
6
  import {
7
7
  CLOUD_API_ENDPOINT,
8
8
  assertEndpoint,
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/version.ts
4
+ var MUSHI_CLI_VERSION = true ? "0.34.1" : "0.0.0-dev";
5
+ var MUSHI_MCP_PIN_SPEC = "@mushi-mushi/mcp@0.29.2";
6
+
7
+ export {
8
+ MUSHI_CLI_VERSION,
9
+ MUSHI_MCP_PIN_SPEC
10
+ };
@@ -6,10 +6,10 @@ import {
6
6
  saveConfig,
7
7
  savedSdkKeyFor,
8
8
  waitForIngestReady
9
- } from "./chunk-OS2ZLURO.js";
9
+ } from "./chunk-67WU4UYB.js";
10
10
  import {
11
11
  MUSHI_MCP_PIN_SPEC
12
- } from "./chunk-CY2BHCA5.js";
12
+ } from "./chunk-QI7DE6J3.js";
13
13
  import {
14
14
  detectFramework,
15
15
  envVarsToWrite,
@@ -2,8 +2,8 @@
2
2
  import {
3
3
  resolveSdkEnvKey,
4
4
  runConnect
5
- } from "./chunk-VECP4KOK.js";
6
- import "./chunk-FPVAQNHT.js";
5
+ } from "./chunk-VBEYT4RS.js";
6
+ import "./chunk-XXBGTUGX.js";
7
7
  import "./chunk-LGGE3LH7.js";
8
8
  import "./chunk-KOBEOGNF.js";
9
9
  export {
package/dist/index.js CHANGED
@@ -57,11 +57,11 @@ import {
57
57
  syncKeychainAfterKeyChange,
58
58
  trySaveKeyToKeychain,
59
59
  writeMcpServerEntry
60
- } from "./chunk-VECP4KOK.js";
60
+ } from "./chunk-VBEYT4RS.js";
61
61
  import {
62
62
  MUSHI_CLI_VERSION,
63
63
  MUSHI_MCP_PIN_SPEC
64
- } from "./chunk-FPVAQNHT.js";
64
+ } from "./chunk-XXBGTUGX.js";
65
65
  import {
66
66
  CLOUD_API_ENDPOINT,
67
67
  CLOUD_MCP_OAUTH_URL,
@@ -1552,7 +1552,7 @@ async function checkOnboardingStatus(config, _consoleBase, cwd, doFetch = global
1552
1552
  }
1553
1553
  async function checkVersionDrift(cwd, doFetch) {
1554
1554
  const checks = [];
1555
- const { MUSHI_CLI_VERSION: MUSHI_CLI_VERSION2 } = await import("./version-UVLMVFNO.js");
1555
+ const { MUSHI_CLI_VERSION: MUSHI_CLI_VERSION2 } = await import("./version-MD563FA6.js");
1556
1556
  if (MUSHI_CLI_VERSION2 === "0.0.0-dev") return checks;
1557
1557
  const parse2 = (v) => {
1558
1558
  const m = v.replace(/^[~^]/, "").match(/^(\d+)\.(\d+)\.(\d+)/);
@@ -2476,7 +2476,7 @@ async function maybeOfferConnect(credentials, options, _consoleBase) {
2476
2476
  if (p.isCancel(answer) || !answer) return;
2477
2477
  const endpoint = resolveCloudEndpoint(options.endpoint);
2478
2478
  try {
2479
- const { runConnect: runConnect2 } = await import("./connect-T5BBOIWS.js");
2479
+ const { runConnect: runConnect2 } = await import("./connect-HZAHHWBI.js");
2480
2480
  const saved = loadConfig();
2481
2481
  const result = await runConnect2(
2482
2482
  {
@@ -13055,6 +13055,7 @@ import { createHash as createHash3 } from "crypto";
13055
13055
  import { existsSync as existsSync7, mkdirSync as mkdirSync4, rmSync } from "fs";
13056
13056
  import { homedir, tmpdir } from "os";
13057
13057
  import { basename as basename3, join as join13 } from "path";
13058
+ import { stripVTControlCharacters } from "util";
13058
13059
  var WORK_AGENT_KIND = "mcp";
13059
13060
  var WORK_AGENT_TIMEOUT_MS = 30 * 6e4;
13060
13061
  var PROMPT_MAX_CHARS = 4e4;
@@ -13212,6 +13213,32 @@ function prTitle(summary, reportId) {
13212
13213
  return `fix: ${s.charAt(0).toLowerCase()}${s.slice(1)}${suffix}`;
13213
13214
  }
13214
13215
  var SUBJECT_MAX = 72;
13216
+ var BODY_LINE_MAX = 100;
13217
+ var FOOTER_LIKE = /^(?:[\w-]+(?:\([^)]*\))?!?:|BREAKING[ -]CHANGE\b)/i;
13218
+ function commitBody(...paragraphs) {
13219
+ const width = BODY_LINE_MAX - 2;
13220
+ return paragraphs.map((p4) => p4.replace(/\s+/g, " ").trim()).filter(Boolean).map((p4) => {
13221
+ const lines = [];
13222
+ let line = "";
13223
+ for (let word of p4.split(" ")) {
13224
+ while (word.length > width) {
13225
+ if (line) lines.push(line);
13226
+ line = "";
13227
+ lines.push(word.slice(0, width));
13228
+ word = word.slice(width);
13229
+ }
13230
+ if (!word) continue;
13231
+ if (!line) line = word;
13232
+ else if (line.length + 1 + word.length <= width) line += ` ${word}`;
13233
+ else {
13234
+ lines.push(line);
13235
+ line = word;
13236
+ }
13237
+ }
13238
+ if (line) lines.push(line);
13239
+ return lines.map((l) => FOOTER_LIKE.test(l) ? ` ${l}` : l).join("\n");
13240
+ }).join("\n\n");
13241
+ }
13215
13242
  function agentEnv(base, emptyDir) {
13216
13243
  const keep = ["PATH", "HOME", "USER", "LOGNAME", "LANG", "LC_ALL", "TERM", "SHELL", "TMPDIR", "TZ", "XDG_CONFIG_HOME", "XDG_DATA_HOME", "XDG_CACHE_HOME", "NODE_OPTIONS"];
13217
13244
  const env = {};
@@ -13405,9 +13432,7 @@ async function workOne(api, detail, o) {
13405
13432
  }
13406
13433
  await git(wt, ["add", "-A"]);
13407
13434
  const last = run.stdout.trim().split("\n").filter((l) => l.trim()).slice(-6).join(" ");
13408
- await commitWithHooks(wt, ["--quiet", "-m", prTitle(detail.summary, detail.id), "-m", `Mushi report: ${detail.id}
13409
-
13410
- Made by a local Cursor agent through \`mushi work\`.`], o.log);
13435
+ await commitWithHooks(wt, ["--quiet", "-m", prTitle(detail.summary, detail.id), "-m", commitBody(`Mushi report: ${detail.id}`, "Made by a local Cursor agent through `mushi work`.")], o.log);
13411
13436
  const sha = await git(wt, ["rev-parse", "HEAD"]);
13412
13437
  const numstat = await git(wt, ["diff", "--numstat", `origin/${base}`, "HEAD"]);
13413
13438
  const files = [];
@@ -13492,9 +13517,7 @@ async function followUpOne(api, f, o) {
13492
13517
  return { fixId: f.fixId, outcome: `no change: ${why || `cursor-agent exited ${run.code}`}` };
13493
13518
  }
13494
13519
  await git(wt, ["add", "-A"]);
13495
- await commitWithHooks(wt, ["--quiet", "-m", `fix: address the Opus review (round ${claim.round})`, "-m", `${cap(last, 1500) || "See the diff."}
13496
-
13497
- Made by a local Cursor agent through \`mushi work --followups\`.`], o.log);
13520
+ await commitWithHooks(wt, ["--quiet", "-m", `fix: address the Opus review (round ${claim.round})`, "-m", commitBody(cap(last, 1500) || "See the diff.", "Made by a local Cursor agent through `mushi work --followups`.")], o.log);
13498
13521
  const sha = await git(wt, ["rev-parse", "HEAD"]);
13499
13522
  await git(wt, ["push", "--quiet", "origin", `HEAD:refs/heads/${claim.branch}`]);
13500
13523
  await done(sha, cap(last, 300));
@@ -13536,11 +13559,41 @@ async function commitWithHooks(wt, args, log3) {
13536
13559
  await git(wt, ["commit", ...args]);
13537
13560
  }
13538
13561
  }
13539
- async function preflight(repoDir) {
13540
- const status = await runProc("cursor-agent", ["status"], { timeoutMs: 6e4 });
13541
- if (status.code !== 0 || !/logged in/i.test(status.stdout + status.stderr)) {
13562
+ function cursorSignInState(p4) {
13563
+ if (p4.code === null && /\bENOENT\b/.test(p4.stderr)) return "missing";
13564
+ if (p4.timedOut || p4.code === null) return "unknown";
13565
+ const out = stripVTControlCharacters(`${p4.stdout}
13566
+ ${p4.stderr}`);
13567
+ if (/\bnot\s+(?:logged|signed)\s+in\b|\blogged\s+out\b/i.test(out)) return "signed_out";
13568
+ if (p4.code === 0 && /\b(?:logged|signed)\s+in\b/i.test(out)) return "signed_in";
13569
+ return "unknown";
13570
+ }
13571
+ var CURSOR_STATUS_TIMEOUT_MS = 9e4;
13572
+ var CURSOR_STATUS_RETRY_DELAY_MS = 5e3;
13573
+ async function checkCursorSignIn(run = runProc, wait = (ms) => new Promise((r) => setTimeout(r, ms))) {
13574
+ let last = { state: "unknown", detail: "not checked" };
13575
+ for (let attempt = 0; attempt < 2; attempt++) {
13576
+ if (attempt > 0) await wait(CURSOR_STATUS_RETRY_DELAY_MS);
13577
+ const p4 = await run("cursor-agent", ["status"], { timeoutMs: CURSOR_STATUS_TIMEOUT_MS });
13578
+ const state = cursorSignInState(p4);
13579
+ const detail = p4.timedOut ? `timed out after ${CURSOR_STATUS_TIMEOUT_MS / 1e3} s` : stripVTControlCharacters(`${p4.stdout}
13580
+ ${p4.stderr}`).trim().split("\n")[0]?.slice(0, 200) || `exit ${p4.code}`;
13581
+ last = { state, detail };
13582
+ if (state === "signed_in" || state === "missing") break;
13583
+ }
13584
+ return last;
13585
+ }
13586
+ async function preflight(repoDir, warn) {
13587
+ const signIn = await checkCursorSignIn();
13588
+ if (signIn.state === "missing") {
13589
+ throw new MushiCliError("E_FILE_NOT_FOUND", "The Cursor CLI (cursor-agent) is not installed or not on PATH.", "Install it: https://cursor.com/cli");
13590
+ }
13591
+ if (signIn.state === "signed_out") {
13542
13592
  throw new MushiCliError("E_AUTH_MISSING", "The Cursor CLI is not signed in.", "Run: cursor-agent login");
13543
13593
  }
13594
+ if (signIn.state === "unknown") {
13595
+ warn(`Could not confirm the Cursor CLI sign-in (${signIn.detail}); continuing. If it is signed out, the agent stops at once: run cursor-agent login.`);
13596
+ }
13544
13597
  const gh = await runProc("gh", ["auth", "status"], { timeoutMs: 3e4 });
13545
13598
  if (gh.code !== 0) throw new MushiCliError("E_AUTH_MISSING", "gh is not signed in.", "Run: gh auth login");
13546
13599
  await git(repoDir, ["rev-parse", "--git-dir"]);
@@ -13568,6 +13621,8 @@ function registerWorkCommands(program2) {
13568
13621
  if (!opts.json) process.stdout.write(`${l}
13569
13622
  `);
13570
13623
  };
13624
+ const warn = (l) => process.stderr.write(`${l}
13625
+ `);
13571
13626
  if (opts.followups) {
13572
13627
  const listed = await api(`/v1/admin/projects/${cfg.projectId}/local-followups`);
13573
13628
  const due = listed.fixes.slice(0, max);
@@ -13578,7 +13633,7 @@ function registerWorkCommands(program2) {
13578
13633
  if (!due.length) log3("No pull request is waiting for a follow-up.");
13579
13634
  return;
13580
13635
  }
13581
- await preflight(opts.repoDir);
13636
+ await preflight(opts.repoDir, warn);
13582
13637
  await requireWriteScope(cfg);
13583
13638
  const results2 = [];
13584
13639
  for (const f of due) {
@@ -13605,7 +13660,7 @@ function registerWorkCommands(program2) {
13605
13660
  if (!plan.length) log3("Nothing to work on.");
13606
13661
  return;
13607
13662
  }
13608
- await preflight(opts.repoDir);
13663
+ await preflight(opts.repoDir, warn);
13609
13664
  await requireWriteScope(cfg);
13610
13665
  const results = [];
13611
13666
  for (const d of picked) {
package/dist/init.js CHANGED
@@ -25,10 +25,10 @@ import {
25
25
  saveConfig,
26
26
  savedSdkKeyFor,
27
27
  trySaveKeyToKeychain
28
- } from "./chunk-OS2ZLURO.js";
28
+ } from "./chunk-67WU4UYB.js";
29
29
  import {
30
30
  MUSHI_CLI_VERSION
31
- } from "./chunk-CY2BHCA5.js";
31
+ } from "./chunk-QI7DE6J3.js";
32
32
  import {
33
33
  FRAMEWORKS,
34
34
  detectFramework,
@@ -2058,7 +2058,7 @@ async function maybeOfferConnect(credentials, options, _consoleBase) {
2058
2058
  if (p.isCancel(answer) || !answer) return;
2059
2059
  const endpoint = resolveCloudEndpoint(options.endpoint);
2060
2060
  try {
2061
- const { runConnect } = await import("./connect-3UDYCZKF.js");
2061
+ const { runConnect } = await import("./connect-354QHAUQ.js");
2062
2062
  const saved = loadConfig();
2063
2063
  const result = await runConnect(
2064
2064
  {
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  MUSHI_CLI_VERSION,
4
4
  MUSHI_MCP_PIN_SPEC
5
- } from "./chunk-FPVAQNHT.js";
5
+ } from "./chunk-XXBGTUGX.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.29.1";
17
+ declare const MUSHI_MCP_PIN_SPEC = "@mushi-mushi/mcp@0.29.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-CY2BHCA5.js";
4
+ } from "./chunk-QI7DE6J3.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.34.0",
3
+ "version": "0.34.1",
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,8 +0,0 @@
1
- // src/version.ts
2
- var MUSHI_CLI_VERSION = true ? "0.34.0" : "0.0.0-dev";
3
- var MUSHI_MCP_PIN_SPEC = "@mushi-mushi/mcp@0.29.1";
4
-
5
- export {
6
- MUSHI_CLI_VERSION,
7
- MUSHI_MCP_PIN_SPEC
8
- };
@@ -1,10 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- // src/version.ts
4
- var MUSHI_CLI_VERSION = true ? "0.34.0" : "0.0.0-dev";
5
- var MUSHI_MCP_PIN_SPEC = "@mushi-mushi/mcp@0.29.1";
6
-
7
- export {
8
- MUSHI_CLI_VERSION,
9
- MUSHI_MCP_PIN_SPEC
10
- };