@mushi-mushi/cli 0.22.1 → 0.23.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
@@ -2,7 +2,7 @@
2
2
 
3
3
  > **Your AI wrote it. Mushi tells you why it broke.**
4
4
 
5
- Set up the Mushi SDK, wire Cursor MCP, and triage reports from your terminal.
5
+ Set up the Mushi SDK, wire Cursor MCP, and review bugs from your terminal.
6
6
 
7
7
  Positioning and product overview: [docs site](https://github.com/kensaurus/mushi-mushi/blob/master/apps/docs/content/quickstart/index.mdx) · [VISION.md](https://github.com/kensaurus/mushi-mushi/blob/master/VISION.md)
8
8
 
@@ -51,7 +51,7 @@ npx mushi-mushi
51
51
  The wizard:
52
52
 
53
53
  1. **Prerequisite step** (unless flags/config already present): open console to create a project, paste existing credentials, or exit to run `mushi login` first.
54
- 2. Detects your framework (Next.js, Nuxt, SvelteKit, Angular, Expo, Capacitor, plain React/Vue/Svelte, or vanilla JS) from `package.json` and config files.
54
+ 2. Detects your framework (Next.js, Remix, Astro, Nuxt, SvelteKit, Angular, Expo, Capacitor, Create React App, Solid/SolidStart, plain React/Vue/Svelte, Express/Fastify/Hono, or vanilla JS) from `package.json` and config files — and writes the correct client env-var prefix for each (`NEXT_PUBLIC_`, `VITE_`, `PUBLIC_`, `REACT_APP_`, `EXPO_PUBLIC_`, or bare `MUSHI_*`).
55
55
  3. Calls **`GET /v1/sync/whoami`** to verify Project ID + API key before installing anything.
56
56
  4. Picks the right SDK package (`@mushi-mushi/react`, `@mushi-mushi/vue`, etc.) plus `@mushi-mushi/web` when the framework SDK is API-only.
57
57
  5. Detects your package manager (npm / pnpm / yarn / bun) from your lockfile and installs with that — `shell: false`, with Windows `.cmd` shim resolution.
@@ -86,6 +86,20 @@ Monorepo awareness: if you run the wizard at a workspace root with no framework
86
86
 
87
87
  Console URL resolution: `MUSHI_CONSOLE_URL` → saved `consoleUrl` in config → localhost `:6464` probe → mushi-mushi monorepo heuristic → hosted default. Saved on successful `mushi login`.
88
88
 
89
+ ### Browser sign-in reliability
90
+
91
+ Device auth (RFC 8628) uses a stable per-machine `client_id` stored in
92
+ `~/.config/mushi/config.json`. Starting a new login on the same machine supersedes
93
+ any older pending approval for that id.
94
+
95
+ During token polling the CLI retries **429** and **408** responses automatically.
96
+ If saved credentials exist, re-running the wizard validates them with
97
+ `GET /v1/sync/whoami` before reinstalling.
98
+
99
+ The browser approval page waits until the CLI actually claims the token (not
100
+ just when you click Approve). Full flow + troubleshooting:
101
+ [CLI ↔ console loop](https://kensaur.us/mushi-mushi/docs/quickstart/cli-console-loop).
102
+
89
103
  ## Install globally
90
104
 
91
105
  ```bash
@@ -212,6 +226,18 @@ the CLI never points users at a 404. This safety property is unit-pinned in
212
226
  `packages/cli/src/migrate.test.ts` (positive control + negative control +
213
227
  real-catalog regression guard).
214
228
 
229
+ ### `mushi completion`
230
+
231
+ Prints a tab-completion script for bash, zsh, or fish, generated from the
232
+ CLI's live command tree — so it never drifts as commands are added.
233
+
234
+ ```bash
235
+ eval "$(mushi completion bash)" # try it for the current session
236
+ mushi completion bash >> ~/.bashrc # bash: persist across sessions
237
+ mushi completion zsh > "${fpath[1]}/_mushi" # zsh: needs a dir already on $fpath
238
+ mushi completion fish > ~/.config/fish/completions/mushi.fish
239
+ ```
240
+
215
241
  ### `mushi doctor`
216
242
 
217
243
  Checks CLI and SDK health. **Ingest and dispatch (server) checks run by
@@ -4,6 +4,10 @@ import { join } from "path";
4
4
  var FRAMEWORK_IDS = [
5
5
  "next",
6
6
  "react",
7
+ "cra",
8
+ "remix",
9
+ "astro",
10
+ "solid",
7
11
  "vue",
8
12
  "nuxt",
9
13
  "svelte",
@@ -57,6 +61,90 @@ createRoot(document.getElementById('root')!).render(
57
61
  <App />
58
62
  </MushiProvider>
59
63
  )`
64
+ },
65
+ cra: {
66
+ id: "cra",
67
+ label: "Create React App",
68
+ packageName: "@mushi-mushi/react",
69
+ needsWebPackage: false,
70
+ // CRA inlines only REACT_APP_*-prefixed vars into process.env at build time.
71
+ snippet: () => `// src/index.tsx
72
+ import { MushiProvider } from '@mushi-mushi/react'
73
+
74
+ root.render(
75
+ <MushiProvider config={{
76
+ projectId: process.env.REACT_APP_MUSHI_PROJECT_ID,
77
+ apiKey: process.env.REACT_APP_MUSHI_API_KEY,
78
+ }}>
79
+ <App />
80
+ </MushiProvider>
81
+ )`
82
+ },
83
+ remix: {
84
+ id: "remix",
85
+ label: "Remix",
86
+ packageName: "@mushi-mushi/react",
87
+ needsWebPackage: false,
88
+ // Remix doesn't inline client env. Expose public values at runtime via the
89
+ // root loader + window.ENV (works on both the classic compiler and Vite).
90
+ snippet: () => `// app/root.tsx
91
+ import { MushiProvider } from '@mushi-mushi/react'
92
+ import { useLoaderData } from '@remix-run/react'
93
+
94
+ export async function loader() {
95
+ return { ENV: {
96
+ MUSHI_PROJECT_ID: process.env.MUSHI_PROJECT_ID,
97
+ MUSHI_API_KEY: process.env.MUSHI_API_KEY,
98
+ } }
99
+ }
100
+
101
+ export default function App() {
102
+ const { ENV } = useLoaderData<typeof loader>()
103
+ return (
104
+ <html>
105
+ <body>
106
+ <MushiProvider config={{ projectId: ENV.MUSHI_PROJECT_ID, apiKey: ENV.MUSHI_API_KEY }}>
107
+ <Outlet />
108
+ </MushiProvider>
109
+ <Scripts />
110
+ </body>
111
+ </html>
112
+ )
113
+ }`
114
+ },
115
+ astro: {
116
+ id: "astro",
117
+ label: "Astro",
118
+ packageName: "@mushi-mushi/web",
119
+ needsWebPackage: false,
120
+ // Astro exposes only PUBLIC_*-prefixed vars to client code (Vite-based).
121
+ snippet: () => `---
122
+ // src/layouts/Layout.astro (add this <script> once, e.g. in your base layout)
123
+ ---
124
+ <script>
125
+ import { Mushi } from '@mushi-mushi/web'
126
+ Mushi.init({
127
+ projectId: import.meta.env.PUBLIC_MUSHI_PROJECT_ID,
128
+ apiKey: import.meta.env.PUBLIC_MUSHI_API_KEY,
129
+ })
130
+ </script>`
131
+ },
132
+ solid: {
133
+ id: "solid",
134
+ label: "Solid",
135
+ packageName: "@mushi-mushi/web",
136
+ needsWebPackage: false,
137
+ // Solid / SolidStart are Vite-based → VITE_*-prefixed client env.
138
+ snippet: () => `// src/index.tsx (or src/app.tsx for SolidStart)
139
+ import { onMount } from 'solid-js'
140
+ import { Mushi } from '@mushi-mushi/web'
141
+
142
+ onMount(() => {
143
+ Mushi.init({
144
+ projectId: import.meta.env.VITE_MUSHI_PROJECT_ID,
145
+ apiKey: import.meta.env.VITE_MUSHI_API_KEY,
146
+ })
147
+ })`
60
148
  },
61
149
  vue: {
62
150
  id: "vue",
@@ -287,10 +375,16 @@ function detectFramework(cwd, pkg) {
287
375
  if (deps.has("@angular/core")) return FRAMEWORKS.angular;
288
376
  if (deps.has("expo")) return FRAMEWORKS.expo;
289
377
  if (deps.has("react-native")) return FRAMEWORKS["react-native"];
378
+ if (deps.has("@remix-run/react") || deps.has("@remix-run/node") || deps.has("@remix-run/serve")) {
379
+ return FRAMEWORKS.remix;
380
+ }
381
+ if (deps.has("astro")) return FRAMEWORKS.astro;
382
+ if (deps.has("@solidjs/start") || deps.has("solid-js")) return FRAMEWORKS.solid;
290
383
  if (deps.has("@capacitor/core") && deps.has("react")) return FRAMEWORKS.react;
291
384
  if (deps.has("@capacitor/core")) return FRAMEWORKS.capacitor;
292
385
  if (deps.has("svelte")) return FRAMEWORKS.svelte;
293
386
  if (deps.has("vue")) return FRAMEWORKS.vue;
387
+ if (deps.has("react-scripts")) return FRAMEWORKS.cra;
294
388
  if (deps.has("react")) return FRAMEWORKS.react;
295
389
  if (deps.has("express")) return FRAMEWORKS.express;
296
390
  if (deps.has("fastify")) return FRAMEWORKS.fastify;
@@ -303,6 +397,12 @@ function detectFramework(cwd, pkg) {
303
397
  }
304
398
  if (existsSync(join(cwd, "svelte.config.js"))) return FRAMEWORKS.svelte;
305
399
  if (existsSync(join(cwd, "angular.json"))) return FRAMEWORKS.angular;
400
+ if (existsSync(join(cwd, "remix.config.js")) || existsSync(join(cwd, "remix.config.ts"))) {
401
+ return FRAMEWORKS.remix;
402
+ }
403
+ if (existsSync(join(cwd, "astro.config.mjs")) || existsSync(join(cwd, "astro.config.ts")) || existsSync(join(cwd, "astro.config.js"))) {
404
+ return FRAMEWORKS.astro;
405
+ }
306
406
  return FRAMEWORKS.vanilla;
307
407
  }
308
408
  function detectPackageManager(cwd) {
@@ -331,7 +431,7 @@ function envVarsToWrite(apiKey, projectId, framework, endpoint) {
331
431
  endpointLine
332
432
  ].filter(Boolean).join("\n");
333
433
  }
334
- if (framework.id === "react-native") {
434
+ if (framework.id === "react-native" || framework.id === "remix") {
335
435
  return [
336
436
  `MUSHI_PROJECT_ID=${projectId}`,
337
437
  `MUSHI_API_KEY=${apiKey}`,
@@ -345,7 +445,7 @@ function envVarsToWrite(apiKey, projectId, framework, endpoint) {
345
445
  endpointLine ? `EXPO_PUBLIC_${endpointLine}` : null
346
446
  ].filter(Boolean).join("\n");
347
447
  }
348
- const prefix = framework.id === "next" ? "NEXT_PUBLIC_" : framework.id === "nuxt" ? "NUXT_PUBLIC_" : "VITE_";
448
+ const prefix = framework.id === "next" ? "NEXT_PUBLIC_" : framework.id === "nuxt" ? "NUXT_PUBLIC_" : framework.id === "cra" ? "REACT_APP_" : framework.id === "astro" ? "PUBLIC_" : "VITE_";
349
449
  return [
350
450
  `${prefix}MUSHI_PROJECT_ID=${projectId}`,
351
451
  `${prefix}MUSHI_API_KEY=${apiKey}`,
@@ -0,0 +1,6 @@
1
+ // src/version.ts
2
+ var MUSHI_CLI_VERSION = true ? "0.23.1" : "0.0.0-dev";
3
+
4
+ export {
5
+ MUSHI_CLI_VERSION
6
+ };