@mindstudio-ai/remy 0.1.110 → 0.1.112

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.
@@ -11,6 +11,7 @@ Review the current state of the working tree — what has changed since the last
11
11
  If approved:
12
12
  - Stage and commit any uncommitted changes with a clean, descriptive commit message
13
13
  - Push to main
14
- - Let the user know their app is deploying
14
+ - Use `mindstudio-prod releases status --wait` to poll the build until it completes. Let the user know it's deploying, then report back when it's live.
15
+ - Once deployed, offer to help with next steps: setting up a custom domain (`mindstudio-prod domains`), checking for errors (`mindstudio-prod requests stats`), seeding production data (`mindstudio-prod db`), or anything else they need for launch.
15
16
 
16
17
  If dismissed, acknowledge and do nothing.
package/dist/headless.js CHANGED
@@ -2235,11 +2235,62 @@ var globTool = {
2235
2235
 
2236
2236
  // src/tools/code/listDir.ts
2237
2237
  import fs12 from "fs/promises";
2238
+ import path7 from "path";
2239
+ var EXCLUDE = /* @__PURE__ */ new Set([".git", "node_modules"]);
2240
+ var MAX_CHILDREN = 15;
2241
+ async function readAndSort(dirPath) {
2242
+ const entries = await fs12.readdir(dirPath, { withFileTypes: true });
2243
+ return entries.filter((e) => !EXCLUDE.has(e.name)).sort((a, b) => {
2244
+ if (a.isDirectory() && !b.isDirectory()) {
2245
+ return -1;
2246
+ }
2247
+ if (!a.isDirectory() && b.isDirectory()) {
2248
+ return 1;
2249
+ }
2250
+ return a.name.localeCompare(b.name);
2251
+ });
2252
+ }
2253
+ async function collapsePath(basePath, name) {
2254
+ let display = name;
2255
+ let current = path7.join(basePath, name);
2256
+ for (; ; ) {
2257
+ let children;
2258
+ try {
2259
+ children = await readAndSort(current);
2260
+ } catch {
2261
+ break;
2262
+ }
2263
+ if (children.length === 1 && children[0].isDirectory()) {
2264
+ display += "/" + children[0].name;
2265
+ current = path7.join(current, children[0].name);
2266
+ } else {
2267
+ break;
2268
+ }
2269
+ }
2270
+ return [display, current];
2271
+ }
2272
+ function formatSize(bytes) {
2273
+ if (bytes < 1e3) {
2274
+ return `${bytes} B`;
2275
+ }
2276
+ if (bytes < 1e6) {
2277
+ return `${(bytes / 1e3).toFixed(1)} kB`;
2278
+ }
2279
+ return `${(bytes / 1e6).toFixed(1)} MB`;
2280
+ }
2281
+ async function formatFile(dirPath, name, indent) {
2282
+ try {
2283
+ const stat = await fs12.stat(path7.join(dirPath, name));
2284
+ return `${indent}${name}${" ".repeat(Math.max(1, 30 - indent.length - name.length))}${formatSize(stat.size)}`;
2285
+ } catch {
2286
+ return `${indent}${name}`;
2287
+ }
2288
+ }
2238
2289
  var listDirTool = {
2239
2290
  clearable: true,
2240
2291
  definition: {
2241
2292
  name: "listDir",
2242
- description: "List the contents of a directory. Shows entries with / suffix for directories, sorted directories-first then alphabetically. Use this for a quick overview of a directory's contents. For finding files across the whole project, use glob instead.",
2293
+ description: "List the contents of a directory with one level of subdirectory expansion. Shows file sizes and collapses single-child directory chains (a/b/c/ shown as one entry). Use this for a quick overview of a directory's structure. For finding files across the whole project, use glob instead.",
2243
2294
  inputSchema: {
2244
2295
  type: "object",
2245
2296
  properties: {
@@ -2253,16 +2304,34 @@ var listDirTool = {
2253
2304
  async execute(input) {
2254
2305
  const dirPath = input.path || ".";
2255
2306
  try {
2256
- const entries = await fs12.readdir(dirPath, { withFileTypes: true });
2257
- const lines = entries.filter((e) => e.name !== ".git" && e.name !== "node_modules").sort((a, b) => {
2258
- if (a.isDirectory() && !b.isDirectory()) {
2259
- return -1;
2260
- }
2261
- if (!a.isDirectory() && b.isDirectory()) {
2262
- return 1;
2307
+ const entries = await readAndSort(dirPath);
2308
+ const lines = [];
2309
+ for (const entry of entries) {
2310
+ if (entry.isDirectory()) {
2311
+ const [displayName, finalPath] = await collapsePath(
2312
+ dirPath,
2313
+ entry.name
2314
+ );
2315
+ lines.push(`${displayName}/`);
2316
+ try {
2317
+ const children = await readAndSort(finalPath);
2318
+ const capped = children.slice(0, MAX_CHILDREN);
2319
+ for (const child of capped) {
2320
+ if (child.isDirectory()) {
2321
+ lines.push(` ${child.name}/`);
2322
+ } else {
2323
+ lines.push(await formatFile(finalPath, child.name, " "));
2324
+ }
2325
+ }
2326
+ if (children.length > MAX_CHILDREN) {
2327
+ lines.push(` ... and ${children.length - MAX_CHILDREN} more`);
2328
+ }
2329
+ } catch {
2330
+ }
2331
+ } else {
2332
+ lines.push(await formatFile(dirPath, entry.name, ""));
2263
2333
  }
2264
- return a.name.localeCompare(b.name);
2265
- }).map((e) => e.isDirectory() ? `${e.name}/` : e.name);
2334
+ }
2266
2335
  return lines.join("\n") || "(empty directory)";
2267
2336
  } catch (err) {
2268
2337
  return `Error listing directory: ${err.message}`;
@@ -2476,11 +2545,11 @@ async function captureAndAnalyzeScreenshot(promptOrOptions) {
2476
2545
  let prompt;
2477
2546
  let existingUrl;
2478
2547
  let onLog;
2479
- let path9;
2548
+ let path10;
2480
2549
  if (typeof promptOrOptions === "object" && promptOrOptions !== null) {
2481
2550
  prompt = promptOrOptions.prompt;
2482
2551
  existingUrl = promptOrOptions.imageUrl;
2483
- path9 = promptOrOptions.path;
2552
+ path10 = promptOrOptions.path;
2484
2553
  onLog = promptOrOptions.onLog;
2485
2554
  } else {
2486
2555
  prompt = promptOrOptions;
@@ -2492,7 +2561,7 @@ async function captureAndAnalyzeScreenshot(promptOrOptions) {
2492
2561
  } else {
2493
2562
  const ssResult = await sidecarRequest(
2494
2563
  "/screenshot-full-page",
2495
- path9 ? { path: path9 } : void 0,
2564
+ path10 ? { path: path10 } : void 0,
2496
2565
  { timeout: 12e4 }
2497
2566
  );
2498
2567
  url = ssResult?.url || ssResult?.screenshotUrl;
@@ -3852,12 +3921,12 @@ async function executeDesignExpertTool(name, input, context, toolCallId, onLog)
3852
3921
 
3853
3922
  // src/subagents/common/context.ts
3854
3923
  import fs14 from "fs";
3855
- import path7 from "path";
3924
+ import path8 from "path";
3856
3925
  function walkMdFiles2(dir, skip) {
3857
3926
  const files = [];
3858
3927
  try {
3859
3928
  for (const entry of fs14.readdirSync(dir, { withFileTypes: true })) {
3860
- const full = path7.join(dir, entry.name);
3929
+ const full = path8.join(dir, entry.name);
3861
3930
  if (entry.isDirectory()) {
3862
3931
  if (!skip?.has(entry.name)) {
3863
3932
  files.push(...walkMdFiles2(full, skip));
@@ -4337,7 +4406,7 @@ var VISION_TOOLS = [
4337
4406
 
4338
4407
  // src/subagents/productVision/executor.ts
4339
4408
  import fs16 from "fs";
4340
- import path8 from "path";
4409
+ import path9 from "path";
4341
4410
  var ROADMAP_DIR = "src/roadmap";
4342
4411
  function formatRequires(requires) {
4343
4412
  return requires.length === 0 ? "[]" : `[${requires.map((r) => `"${r}"`).join(", ")}]`;
@@ -4353,7 +4422,7 @@ async function executeVisionTool(name, input) {
4353
4422
  requires,
4354
4423
  body
4355
4424
  } = input;
4356
- const filePath = path8.join(ROADMAP_DIR, `${slug}.md`);
4425
+ const filePath = path9.join(ROADMAP_DIR, `${slug}.md`);
4357
4426
  try {
4358
4427
  fs16.mkdirSync(ROADMAP_DIR, { recursive: true });
4359
4428
  const oldContent = fs16.existsSync(filePath) ? fs16.readFileSync(filePath, "utf-8") : "";
@@ -4379,7 +4448,7 @@ ${unifiedDiff(filePath, oldContent, content)}`;
4379
4448
  }
4380
4449
  case "updateRoadmapItem": {
4381
4450
  const { slug } = input;
4382
- const filePath = path8.join(ROADMAP_DIR, `${slug}.md`);
4451
+ const filePath = path9.join(ROADMAP_DIR, `${slug}.md`);
4383
4452
  try {
4384
4453
  if (!fs16.existsSync(filePath)) {
4385
4454
  return `Error: ${filePath} does not exist`;
@@ -4447,7 +4516,7 @@ ${unifiedDiff(filePath, oldContent, content)}`;
4447
4516
  }
4448
4517
  case "deleteRoadmapItem": {
4449
4518
  const { slug } = input;
4450
- const filePath = path8.join(ROADMAP_DIR, `${slug}.md`);
4519
+ const filePath = path9.join(ROADMAP_DIR, `${slug}.md`);
4451
4520
  try {
4452
4521
  if (!fs16.existsSync(filePath)) {
4453
4522
  return `Error: ${filePath} does not exist`;
package/dist/index.js CHANGED
@@ -1829,15 +1829,66 @@ var init_glob = __esm({
1829
1829
 
1830
1830
  // src/tools/code/listDir.ts
1831
1831
  import fs9 from "fs/promises";
1832
- var listDirTool;
1832
+ import path4 from "path";
1833
+ async function readAndSort(dirPath) {
1834
+ const entries = await fs9.readdir(dirPath, { withFileTypes: true });
1835
+ return entries.filter((e) => !EXCLUDE.has(e.name)).sort((a, b) => {
1836
+ if (a.isDirectory() && !b.isDirectory()) {
1837
+ return -1;
1838
+ }
1839
+ if (!a.isDirectory() && b.isDirectory()) {
1840
+ return 1;
1841
+ }
1842
+ return a.name.localeCompare(b.name);
1843
+ });
1844
+ }
1845
+ async function collapsePath(basePath, name) {
1846
+ let display = name;
1847
+ let current = path4.join(basePath, name);
1848
+ for (; ; ) {
1849
+ let children;
1850
+ try {
1851
+ children = await readAndSort(current);
1852
+ } catch {
1853
+ break;
1854
+ }
1855
+ if (children.length === 1 && children[0].isDirectory()) {
1856
+ display += "/" + children[0].name;
1857
+ current = path4.join(current, children[0].name);
1858
+ } else {
1859
+ break;
1860
+ }
1861
+ }
1862
+ return [display, current];
1863
+ }
1864
+ function formatSize(bytes) {
1865
+ if (bytes < 1e3) {
1866
+ return `${bytes} B`;
1867
+ }
1868
+ if (bytes < 1e6) {
1869
+ return `${(bytes / 1e3).toFixed(1)} kB`;
1870
+ }
1871
+ return `${(bytes / 1e6).toFixed(1)} MB`;
1872
+ }
1873
+ async function formatFile(dirPath, name, indent) {
1874
+ try {
1875
+ const stat = await fs9.stat(path4.join(dirPath, name));
1876
+ return `${indent}${name}${" ".repeat(Math.max(1, 30 - indent.length - name.length))}${formatSize(stat.size)}`;
1877
+ } catch {
1878
+ return `${indent}${name}`;
1879
+ }
1880
+ }
1881
+ var EXCLUDE, MAX_CHILDREN, listDirTool;
1833
1882
  var init_listDir = __esm({
1834
1883
  "src/tools/code/listDir.ts"() {
1835
1884
  "use strict";
1885
+ EXCLUDE = /* @__PURE__ */ new Set([".git", "node_modules"]);
1886
+ MAX_CHILDREN = 15;
1836
1887
  listDirTool = {
1837
1888
  clearable: true,
1838
1889
  definition: {
1839
1890
  name: "listDir",
1840
- description: "List the contents of a directory. Shows entries with / suffix for directories, sorted directories-first then alphabetically. Use this for a quick overview of a directory's contents. For finding files across the whole project, use glob instead.",
1891
+ description: "List the contents of a directory with one level of subdirectory expansion. Shows file sizes and collapses single-child directory chains (a/b/c/ shown as one entry). Use this for a quick overview of a directory's structure. For finding files across the whole project, use glob instead.",
1841
1892
  inputSchema: {
1842
1893
  type: "object",
1843
1894
  properties: {
@@ -1851,16 +1902,34 @@ var init_listDir = __esm({
1851
1902
  async execute(input) {
1852
1903
  const dirPath = input.path || ".";
1853
1904
  try {
1854
- const entries = await fs9.readdir(dirPath, { withFileTypes: true });
1855
- const lines = entries.filter((e) => e.name !== ".git" && e.name !== "node_modules").sort((a, b) => {
1856
- if (a.isDirectory() && !b.isDirectory()) {
1857
- return -1;
1858
- }
1859
- if (!a.isDirectory() && b.isDirectory()) {
1860
- return 1;
1905
+ const entries = await readAndSort(dirPath);
1906
+ const lines = [];
1907
+ for (const entry of entries) {
1908
+ if (entry.isDirectory()) {
1909
+ const [displayName, finalPath] = await collapsePath(
1910
+ dirPath,
1911
+ entry.name
1912
+ );
1913
+ lines.push(`${displayName}/`);
1914
+ try {
1915
+ const children = await readAndSort(finalPath);
1916
+ const capped = children.slice(0, MAX_CHILDREN);
1917
+ for (const child of capped) {
1918
+ if (child.isDirectory()) {
1919
+ lines.push(` ${child.name}/`);
1920
+ } else {
1921
+ lines.push(await formatFile(finalPath, child.name, " "));
1922
+ }
1923
+ }
1924
+ if (children.length > MAX_CHILDREN) {
1925
+ lines.push(` ... and ${children.length - MAX_CHILDREN} more`);
1926
+ }
1927
+ } catch {
1928
+ }
1929
+ } else {
1930
+ lines.push(await formatFile(dirPath, entry.name, ""));
1861
1931
  }
1862
- return a.name.localeCompare(b.name);
1863
- }).map((e) => e.isDirectory() ? `${e.name}/` : e.name);
1932
+ }
1864
1933
  return lines.join("\n") || "(empty directory)";
1865
1934
  } catch (err) {
1866
1935
  return `Error listing directory: ${err.message}`;
@@ -2174,11 +2243,11 @@ async function captureAndAnalyzeScreenshot(promptOrOptions) {
2174
2243
  let prompt;
2175
2244
  let existingUrl;
2176
2245
  let onLog;
2177
- let path10;
2246
+ let path11;
2178
2247
  if (typeof promptOrOptions === "object" && promptOrOptions !== null) {
2179
2248
  prompt = promptOrOptions.prompt;
2180
2249
  existingUrl = promptOrOptions.imageUrl;
2181
- path10 = promptOrOptions.path;
2250
+ path11 = promptOrOptions.path;
2182
2251
  onLog = promptOrOptions.onLog;
2183
2252
  } else {
2184
2253
  prompt = promptOrOptions;
@@ -2190,7 +2259,7 @@ async function captureAndAnalyzeScreenshot(promptOrOptions) {
2190
2259
  } else {
2191
2260
  const ssResult = await sidecarRequest(
2192
2261
  "/screenshot-full-page",
2193
- path10 ? { path: path10 } : void 0,
2262
+ path11 ? { path: path11 } : void 0,
2194
2263
  { timeout: 12e4 }
2195
2264
  );
2196
2265
  url = ssResult?.url || ssResult?.screenshotUrl;
@@ -2936,19 +3005,19 @@ var init_tools = __esm({
2936
3005
 
2937
3006
  // src/assets.ts
2938
3007
  import fs10 from "fs";
2939
- import path4 from "path";
3008
+ import path5 from "path";
2940
3009
  function findRoot(start) {
2941
3010
  let dir = start;
2942
- while (dir !== path4.dirname(dir)) {
2943
- if (fs10.existsSync(path4.join(dir, "package.json"))) {
3011
+ while (dir !== path5.dirname(dir)) {
3012
+ if (fs10.existsSync(path5.join(dir, "package.json"))) {
2944
3013
  return dir;
2945
3014
  }
2946
- dir = path4.dirname(dir);
3015
+ dir = path5.dirname(dir);
2947
3016
  }
2948
3017
  return start;
2949
3018
  }
2950
3019
  function assetPath(...segments) {
2951
- return path4.join(ASSETS_BASE, ...segments);
3020
+ return path5.join(ASSETS_BASE, ...segments);
2952
3021
  }
2953
3022
  function readAsset(...segments) {
2954
3023
  const full = assetPath(...segments);
@@ -2971,9 +3040,9 @@ var init_assets = __esm({
2971
3040
  "src/assets.ts"() {
2972
3041
  "use strict";
2973
3042
  ROOT = findRoot(
2974
- import.meta.dirname ?? path4.dirname(new URL(import.meta.url).pathname)
3043
+ import.meta.dirname ?? path5.dirname(new URL(import.meta.url).pathname)
2975
3044
  );
2976
- ASSETS_BASE = fs10.existsSync(path4.join(ROOT, "dist", "prompt")) ? path4.join(ROOT, "dist") : path4.join(ROOT, "src");
3045
+ ASSETS_BASE = fs10.existsSync(path5.join(ROOT, "dist", "prompt")) ? path5.join(ROOT, "dist") : path5.join(ROOT, "src");
2977
3046
  }
2978
3047
  });
2979
3048
 
@@ -3739,12 +3808,12 @@ var init_tools2 = __esm({
3739
3808
 
3740
3809
  // src/subagents/common/context.ts
3741
3810
  import fs12 from "fs";
3742
- import path5 from "path";
3811
+ import path6 from "path";
3743
3812
  function walkMdFiles(dir, skip) {
3744
3813
  const files = [];
3745
3814
  try {
3746
3815
  for (const entry of fs12.readdirSync(dir, { withFileTypes: true })) {
3747
- const full = path5.join(dir, entry.name);
3816
+ const full = path6.join(dir, entry.name);
3748
3817
  if (entry.isDirectory()) {
3749
3818
  if (!skip?.has(entry.name)) {
3750
3819
  files.push(...walkMdFiles(full, skip));
@@ -4292,7 +4361,7 @@ var init_tools3 = __esm({
4292
4361
 
4293
4362
  // src/subagents/productVision/executor.ts
4294
4363
  import fs14 from "fs";
4295
- import path6 from "path";
4364
+ import path7 from "path";
4296
4365
  function formatRequires(requires) {
4297
4366
  return requires.length === 0 ? "[]" : `[${requires.map((r) => `"${r}"`).join(", ")}]`;
4298
4367
  }
@@ -4307,7 +4376,7 @@ async function executeVisionTool(name, input) {
4307
4376
  requires,
4308
4377
  body
4309
4378
  } = input;
4310
- const filePath = path6.join(ROADMAP_DIR, `${slug}.md`);
4379
+ const filePath = path7.join(ROADMAP_DIR, `${slug}.md`);
4311
4380
  try {
4312
4381
  fs14.mkdirSync(ROADMAP_DIR, { recursive: true });
4313
4382
  const oldContent = fs14.existsSync(filePath) ? fs14.readFileSync(filePath, "utf-8") : "";
@@ -4333,7 +4402,7 @@ ${unifiedDiff(filePath, oldContent, content)}`;
4333
4402
  }
4334
4403
  case "updateRoadmapItem": {
4335
4404
  const { slug } = input;
4336
- const filePath = path6.join(ROADMAP_DIR, `${slug}.md`);
4405
+ const filePath = path7.join(ROADMAP_DIR, `${slug}.md`);
4337
4406
  try {
4338
4407
  if (!fs14.existsSync(filePath)) {
4339
4408
  return `Error: ${filePath} does not exist`;
@@ -4401,7 +4470,7 @@ ${unifiedDiff(filePath, oldContent, content)}`;
4401
4470
  }
4402
4471
  case "deleteRoadmapItem": {
4403
4472
  const { slug } = input;
4404
- const filePath = path6.join(ROADMAP_DIR, `${slug}.md`);
4473
+ const filePath = path7.join(ROADMAP_DIR, `${slug}.md`);
4405
4474
  try {
4406
4475
  if (!fs14.existsSync(filePath)) {
4407
4476
  return `Error: ${filePath} does not exist`;
@@ -5621,7 +5690,7 @@ var init_agent = __esm({
5621
5690
 
5622
5691
  // src/prompt/static/projectContext.ts
5623
5692
  import fs16 from "fs";
5624
- import path7 from "path";
5693
+ import path8 from "path";
5625
5694
  function loadProjectInstructions() {
5626
5695
  for (const file of AGENT_INSTRUCTION_FILES) {
5627
5696
  try {
@@ -5681,7 +5750,7 @@ function walkMdFiles2(dir) {
5681
5750
  try {
5682
5751
  const entries = fs16.readdirSync(dir, { withFileTypes: true });
5683
5752
  for (const entry of entries) {
5684
- const full = path7.join(dir, entry.name);
5753
+ const full = path8.join(dir, entry.name);
5685
5754
  if (entry.isDirectory()) {
5686
5755
  results.push(...walkMdFiles2(full));
5687
5756
  } else if (entry.name.endsWith(".md")) {
@@ -5893,7 +5962,7 @@ var init_prompt4 = __esm({
5893
5962
 
5894
5963
  // src/config.ts
5895
5964
  import fs17 from "fs";
5896
- import path8 from "path";
5965
+ import path9 from "path";
5897
5966
  import os from "os";
5898
5967
  function loadConfigFile() {
5899
5968
  try {
@@ -5934,7 +6003,7 @@ var init_config = __esm({
5934
6003
  "use strict";
5935
6004
  init_logger();
5936
6005
  log7 = createLogger("config");
5937
- CONFIG_PATH = path8.join(
6006
+ CONFIG_PATH = path9.join(
5938
6007
  os.homedir(),
5939
6008
  ".mindstudio-local-tunnel",
5940
6009
  "config.json"
@@ -6851,7 +6920,7 @@ var init_headless = __esm({
6851
6920
  import { render } from "ink";
6852
6921
  import os2 from "os";
6853
6922
  import fs18 from "fs";
6854
- import path9 from "path";
6923
+ import path10 from "path";
6855
6924
 
6856
6925
  // src/tui/App.tsx
6857
6926
  import { useState as useState2, useCallback, useRef } from "react";
@@ -7170,7 +7239,7 @@ var startupLog = createLogger("startup");
7170
7239
  function printDebugInfo(config) {
7171
7240
  const pkg = JSON.parse(
7172
7241
  fs18.readFileSync(
7173
- path9.join(import.meta.dirname, "..", "package.json"),
7242
+ path10.join(import.meta.dirname, "..", "package.json"),
7174
7243
  "utf-8"
7175
7244
  )
7176
7245
  );
@@ -25,6 +25,7 @@ Interfaces run fullscreen in the user's browser or a wrapped webview mobile app.
25
25
  - **No long scrolling pages.** Use structured layouts: cards, split panes, steppers, tabs, grouped sections that fit the viewport. The interface should feel like an award winning iOS or macOS app, not a document.
26
26
  - **On mobile**, scrolling may be necessary, but use sticky headers, fixed CTAs, and anchored navigation to keep key actions within reach. Always use "width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" to make sure apps feel like apps.
27
27
  - Think of every screen as something the user opens, uses, and closes — not something they read.
28
+ - Pay attention to details that will make things feel app-like - set user-select: none, use motion, use iOS/macOS design language and patterns.
28
29
 
29
30
  ## Layout Stability
30
31
 
@@ -47,3 +47,10 @@ For any work involving AI models, external actions (web scraping, email, SMS), o
47
47
 
48
48
  ### Dependencies
49
49
  Before installing a package you haven't used in this project, do a quick web search to confirm it's still the best option. The JavaScript ecosystem moves fast — the package you remember from training may have been superseded by something smaller, faster, or better maintained. A 10-second search beats debugging a deprecated library.
50
+
51
+ ### Production App Management
52
+ You have access to `mindstudio-prod`, a CLI for managing the user's production MindStudio app. Use it via your bash tool. All output is JSON. Run `mindstudio-prod --help` or `mindstudio-prod <command> --help` to discover usage and available options.
53
+
54
+ Available commands: `requests` (logs, error rates, latency), `releases` (deploy status, history), `domains` (custom subdomain management), `users` (list, set roles), `db` (query production sql db), `methods` (list, invoke).
55
+
56
+ Use when the user asks about production behavior (errors, logs, metrics), wants to manage their live app (domains, users, roles), needs to seed or query production data, or wants to check release status.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mindstudio-ai/remy",
3
- "version": "0.1.110",
3
+ "version": "0.1.112",
4
4
  "description": "MindStudio coding agent",
5
5
  "repository": {
6
6
  "type": "git",