@mindstudio-ai/remy 0.1.198 → 0.1.200

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,8 +1,8 @@
1
1
  # Remy
2
2
 
3
- A spec-building and coding agent for MindStudio apps.
3
+ A spec-building and coding agent for building apps.
4
4
 
5
- Remy helps users design, spec, build, and iterate on MindStudio projects. It runs locally in a terminal or as a headless subprocess in the MindStudio sandbox. It has tools for reading/writing specs and code, running shell commands, searching code, prompting users with structured forms, and (in the sandbox) TypeScript language server integration. LLM calls are routed through the MindStudio platform for billing and model routing.
5
+ Remy helps users design, spec, build, and iterate on app projects. It runs locally in a terminal or as a headless subprocess in the sandbox. It has tools for reading/writing specs and code, running shell commands, searching code, prompting users with structured forms, and (in the sandbox) TypeScript language server integration. LLM calls are routed through the Remy platform for billing and model routing.
6
6
 
7
7
  ## Quick Start
8
8
 
@@ -11,7 +11,7 @@ Remy helps users design, spec, build, and iterate on MindStudio projects. It run
11
11
  mindstudio login
12
12
 
13
13
  # Navigate to your project
14
- cd my-mindstudio-app
14
+ cd my-app
15
15
 
16
16
  # Run remy
17
17
  npx remy
@@ -59,6 +59,7 @@ Tool availability depends on the project's onboarding state, sent by the sandbox
59
59
  | `visualDesignExpert` | Visual design expert for fonts, colors, palettes, gradients, layouts, imagery, and icons (sub-agent) |
60
60
  | `productVision` | Owns the product roadmap — creates/updates/deletes roadmap items in `src/roadmap/` (sub-agent) |
61
61
  | `codeSanityCheck` | Quick readonly sanity check on architecture and package choices before building (sub-agent) |
62
+ | `writeBuildOverview` | Generate/refresh the Build Overview (`src/overview.html`) — a single-page plain-language reference of everything the app contains; you author the copy, the design expert lays it out |
62
63
 
63
64
  ### Spec Tools
64
65
 
@@ -2,7 +2,7 @@
2
2
  trigger: debugRequest
3
3
  ---
4
4
 
5
- This is an automated message triggered by the user having clicked "Debug" in the "Request" log detail in MindStudio UI. Find the request in .logs/requests.ndjson by its ID. If there is an error, fix it immediately - otherwise, explain the request at a high-level in non-technical/natural language and see what the user wishes to do with it. Remember, the user can't see this message, so keep that in mind when responding.
5
+ This is an automated message triggered by the user having clicked "Debug" in the "Request" log detail in the Remy UI. Find the request in .logs/requests.ndjson by its ID. If there is an error, fix it immediately - otherwise, explain the request at a high-level in non-technical/natural language and see what the user wishes to do with it. Remember, the user can't see this message, so keep that in mind when responding.
6
6
 
7
7
  <request_id>
8
8
  {{requestId}}
@@ -2,7 +2,7 @@
2
2
  trigger: feelingLucky
3
3
  ---
4
4
 
5
- This is an automated message triggered by the user having clicked "I'm feeling lucky" in the MindStudio UI and selecting a category from a list of app archetypes. They can't see this message. They're likely new to MindStudio and Remy - this might even be their first time using it. They haven't described a specific idea yet and more than likely don't actually have anything specific in mind — they're exploring what they can build and clicked on something that looked interesting. Your job is to ask questions to help them conjure the seed of an idea that is unique, specific, and interesting, and will be compelling to build as an MVP. Don't build something generic - help the user make something unique that allows you to truly show off the power of what you can build. Stay focused on web interfaces for now, unless the user specifically wants a different interface type. When you've aligned on something to build, focus on making it visually beautiful and highly usable from a UX perspective - at this point in the user's experience they're going to be much more "wowed" by something that looks pretty than by something with a ton of backend complexity.
5
+ This is an automated message triggered by the user having clicked "I'm feeling lucky" in the Remy UI and selecting a category from a list of app archetypes. They can't see this message. They're likely new to Remy - this might even be their first time using it. They haven't described a specific idea yet and more than likely don't actually have anything specific in mind — they're exploring what they can build and clicked on something that looked interesting. Your job is to ask questions to help them conjure the seed of an idea that is unique, specific, and interesting, and will be compelling to build as an MVP. Don't build something generic - help the user make something unique that allows you to truly show off the power of what you can build. Stay focused on web interfaces for now, unless the user specifically wants a different interface type. When you've aligned on something to build, focus on making it visually beautiful and highly usable from a UX perspective - at this point in the user's experience they're going to be much more "wowed" by something that looks pretty than by something with a ton of backend complexity.
6
6
 
7
7
  <selected_category>
8
8
  {{title}}
@@ -13,6 +13,7 @@ The visual assets — photography, generated images, brand colors, typography
13
13
 
14
14
  ## Finalizing
15
15
  When everything is working and polished:
16
- 1. Use `productVision` to mark the MVP roadmap item as done.
17
- 2. Call `compactConversation` to summarize the build session and free up context for the next phase of work.
18
- 3. Call `setProjectOnboardingState({ state: "buildComplete" })`. This triggers the reveal experience on the frontend, where the user sees the pitch deck and their finished app for the first time.
16
+ 1. Write the Build Overview. Author the full copy of everything this build actually produced — the data stores and what each holds, the backend operations, the interfaces, any access and role boundaries, background jobs, and seeded scenarios, including the parts the user can't see — in plain, calm, present-tense language, with real names and exact counts. Then call `writeBuildOverview` to render it. Do this now, before compacting, while the build is still fresh in context.
17
+ 2. Use `productVision` to mark the MVP roadmap item as done.
18
+ 3. Call `compactConversation` to summarize the build session and free up context for the next phase of work.
19
+ 4. Call `setProjectOnboardingState({ state: "buildComplete" })`. This triggers the reveal experience on the frontend, where the user sees their finished app and its Build Overview for the first time.
@@ -1,4 +1,4 @@
1
- You extract a structured `AppBrand` JSON object from the spec files of a MindStudio app project.
1
+ You extract a structured `AppBrand` JSON object from the spec files of an app project.
2
2
 
3
3
  Your output is read by a frontend renderer that uses the brand to style internal documents (implementation plans, sync plans, publish plans) with a "letterhead" treatment — a wordmark, accent color, paper-tone background, and branded fonts. Every field is optional. The renderer falls back to generic styling when a field is missing or invalid.
4
4
 
@@ -1,4 +1,4 @@
1
- You are summarizing a conversation between a user and an AI coding agent called Remy that builds MindStudio apps. Your summary will replace the conversation history — the agent will only see your summary plus any new messages, so it must capture everything needed to continue working.
1
+ You are summarizing a conversation between a user and an AI coding agent called Remy that builds apps. Your summary will replace the conversation history — the agent will only see your summary plus any new messages, so it must capture everything needed to continue working.
2
2
 
3
3
  Write a tight, factual summary in bullet points. Cover what matters for picking the work back up:
4
4
  - What the user is trying to do, and any key decisions, constraints, or preferences they've stated.
package/dist/headless.js CHANGED
@@ -4232,7 +4232,15 @@ var SYSTEM_PROMPT = readAsset(
4232
4232
  "subagents/designExpert/tools/images/enhance-image-prompt.md"
4233
4233
  );
4234
4234
  async function enhanceImagePrompt(params) {
4235
- const { brief, width, height, transparentBackground, onLog, model } = params;
4235
+ const {
4236
+ brief,
4237
+ width,
4238
+ height,
4239
+ transparentBackground,
4240
+ hasReferenceImage,
4241
+ onLog,
4242
+ model
4243
+ } = params;
4236
4244
  const contextParts = [
4237
4245
  `Dimensions: ${width}x${height}${width > height ? " (landscape)" : width < height ? " (portrait)" : " (square)"}`
4238
4246
  ];
@@ -4241,6 +4249,11 @@ async function enhanceImagePrompt(params) {
4241
4249
  "Transparent background: yes \u2014 the background will be removed. Focus on the subject as an isolated element."
4242
4250
  );
4243
4251
  }
4252
+ if (hasReferenceImage) {
4253
+ contextParts.push(
4254
+ "Reference image: yes \u2014 a reference image is provided to the generation model alongside this prompt to guide style, subject, or composition. Complement it; don't re-describe what it already carries."
4255
+ );
4256
+ }
4244
4257
  const context = `<context>
4245
4258
  ${contextParts.join("\n")}
4246
4259
  </context>`;
@@ -4271,6 +4284,7 @@ async function generateImageAssets(opts) {
4271
4284
  prompts,
4272
4285
  sourceImages,
4273
4286
  transparentBackground,
4287
+ enhancePrompts,
4274
4288
  onLog,
4275
4289
  imageGenerationModel: genModel,
4276
4290
  imageAnalysisModel,
@@ -4289,19 +4303,20 @@ async function generateImageAssets(opts) {
4289
4303
  config.source_image = firstImage;
4290
4304
  config.source = firstImage;
4291
4305
  }
4292
- const isEdit = !!sourceImages?.length;
4293
- const enhancedPrompts = isEdit ? prompts : await Promise.all(
4306
+ const hasReference = !!sourceImages?.length;
4307
+ const enhancedPrompts = enhancePrompts ? await Promise.all(
4294
4308
  prompts.map(
4295
4309
  (brief) => enhanceImagePrompt({
4296
4310
  brief,
4297
4311
  width,
4298
4312
  height,
4299
4313
  transparentBackground,
4314
+ hasReferenceImage: hasReference,
4300
4315
  onLog,
4301
4316
  model: imagePromptEnhancerModel
4302
4317
  })
4303
4318
  )
4304
- );
4319
+ ) : prompts;
4305
4320
  let imageUrls;
4306
4321
  if (enhancedPrompts.length === 1) {
4307
4322
  const step = JSON.stringify({
@@ -4371,7 +4386,7 @@ async function generateImageAssets(opts) {
4371
4386
  if (url.startsWith("Error")) {
4372
4387
  return {
4373
4388
  prompt: prompts[i],
4374
- ...!isEdit && { enhancedPrompt: enhancedPrompts[i] },
4389
+ ...enhancePrompts && { enhancedPrompt: enhancedPrompts[i] },
4375
4390
  error: url
4376
4391
  };
4377
4392
  }
@@ -4384,7 +4399,7 @@ async function generateImageAssets(opts) {
4384
4399
  return {
4385
4400
  url,
4386
4401
  prompt: prompts[i],
4387
- ...!isEdit && { enhancedPrompt: enhancedPrompts[i] },
4402
+ ...enhancePrompts && { enhancedPrompt: enhancedPrompts[i] },
4388
4403
  analysis,
4389
4404
  width,
4390
4405
  height
@@ -4409,6 +4424,10 @@ var definition6 = {
4409
4424
  },
4410
4425
  description: "One or more image briefs describing what you want. Focus on subject, mood, style, and intended use \u2014 the tool optimizes your brief into a model-ready prompt automatically. Multiple briefs run in parallel."
4411
4426
  },
4427
+ referenceImage: {
4428
+ type: "string",
4429
+ description: "Optional URL of a single reference image to guide the generation \u2014 for style, subject, character consistency, or composition. Your prompt still describes the desired result; the reference conditions it. Applies to every prompt in the batch."
4430
+ },
4412
4431
  width: {
4413
4432
  type: "number",
4414
4433
  description: "Image width in pixels. Default 2048. Range: 2048-4096."
@@ -4431,6 +4450,8 @@ async function execute6(input, onLog, context) {
4431
4450
  width: input.width,
4432
4451
  height: input.height,
4433
4452
  transparentBackground: input.transparentBackground,
4453
+ sourceImages: input.referenceImage ? [input.referenceImage] : void 0,
4454
+ enhancePrompts: true,
4434
4455
  onLog,
4435
4456
  imageGenerationModel: resolveModel(
4436
4457
  "imageGeneration",
@@ -4500,6 +4521,7 @@ async function execute7(input, onLog, context) {
4500
4521
  width: input.width,
4501
4522
  height: input.height,
4502
4523
  transparentBackground: input.transparentBackground,
4524
+ enhancePrompts: false,
4503
4525
  onLog,
4504
4526
  imageGenerationModel: resolveModel(
4505
4527
  "imageGeneration",
@@ -4658,9 +4680,9 @@ ${parts.join("\n\n")}
4658
4680
  }
4659
4681
  function loadPlatformBrief() {
4660
4682
  return `<platform_brief>
4661
- ## What is a MindStudio app?
4683
+ ## What is a Remy app?
4662
4684
 
4663
- A MindStudio app is a managed full-stack TypeScript project with three layers: a spec (natural language in src/), a backend contract (methods, tables, roles in dist/), and one or more interfaces (web, API, bots, cron, etc.). The spec is the source of truth; code is derived from it.
4685
+ A Remy app is a managed full-stack TypeScript project with three layers: a spec (natural language in src/), a backend contract (methods, tables, roles in dist/), and one or more interfaces (web, API, bots, cron, etc.). The spec is the source of truth; code is derived from it.
4664
4686
 
4665
4687
  This is a capable, stable platform used in production by 100k+ users. Build with confidence \u2014 you're building production-grade apps, not fragile prototypes.
4666
4688
 
@@ -4705,7 +4727,7 @@ TypeScript running in a sandboxed environment. Any npm package can be installed.
4705
4727
 
4706
4728
  The first-party SDK (@mindstudio-ai/agent) provides access to 200+ AI models (OpenAI, Anthropic, Google, Meta, Mistral, and more) and 1000+ integrations (email, SMS, Slack, HubSpot, Google Workspace, web scraping, image/video generation, media processing, and much more) with zero configuration \u2014 credentials are handled automatically in the execution environment. No API keys needed. This SDK is robust and battle-tested in production.
4707
4729
 
4708
- ## What MindStudio apps are NOT good for
4730
+ ## What Remy apps are NOT good for
4709
4731
 
4710
4732
  - Native mobile apps (iOS/Android). Mobile-responsive web apps are fine.
4711
4733
  - Real-time multiplayer with persistent connections (no WebSocket support). Turn-based or async patterns work.
@@ -5369,6 +5391,94 @@ var scrapeWebUrlTool = {
5369
5391
  }
5370
5392
  };
5371
5393
 
5394
+ // src/tools/spec/writeBuildOverview.ts
5395
+ import fs20 from "fs";
5396
+ var OVERVIEW_FILE = "src/overview.html";
5397
+ var DESIGN_BRIEF = `We are building the Build Overview for this app \u2014 the home page of its Spec tab. It is a calm, dense, one-page reference of everything the app actually contains, including the parts the user can't see. It renders flush inside the Spec tab's content panel (the IDE supplies the surrounding nav).
5398
+
5399
+ Take the plain-language copy in <overview_copy> and lay it out and skin it into a single, beautiful, self-contained HTML document in the app's own brand. If <current_overview> is non-empty, use it as your starting point and preserve its established skin, updating only what the copy changed.
5400
+
5401
+ ### The single hard rule
5402
+ Preserve every fact in <overview_copy> exactly \u2014 every number, name, label, and claim. Do not add, drop, soften, reword, or invent any fact. You own layout, typography, and visual design only; the substance and the words are fixed. A single wrong number breaks this document's entire purpose.
5403
+
5404
+ ### What it is (and is not)
5405
+ - A typeset reference dossier: composed, dense, a little cool \u2014 substantial at a glance, then readable. Density communicates substance; sparse and airy reads as "not much here."
5406
+ - Brand-skinned: pull the palette, type system, and a single accent from the app's spec. The accent leads labels and figures; it is a mark, not a fill.
5407
+ - NOT a slide deck \u2014 no theatrics, no building to a climax, no persuasion.
5408
+ - NOT a docs site \u2014 no raised or shadowed cards, no hover-lift, no clickable-feeling surfaces, no sticky table of contents.
5409
+ - NOT a sparse memo \u2014 a restrained single-column page under-sells the work.
5410
+ - No header chrome and no footer: open straight on the app's logo and name so it sits flush with the IDE.
5411
+
5412
+ ### Constraints
5413
+ - A single self-contained HTML file. Fonts may load from a CDN; everything else (CSS, the logo SVG) is inline.
5414
+ - Responsive: fills the embedded panel width and collapses gracefully at narrow widths.
5415
+
5416
+ Respond only with the complete HTML file and absolutely no other text. Your response will be written directly to src/overview.html.`;
5417
+ var OVERVIEW_SHELL = `<!DOCTYPE html>
5418
+ <html lang="en">
5419
+ <head>
5420
+ <meta charset="utf-8">
5421
+ <!-- This renders inside an iframe in the IDE. Keep it a simple, self-contained
5422
+ static document \u2014 no scroll/zoom/accessibility scaffolding beyond this head.
5423
+ The user-scalable=no viewport is intentional; leave it. -->
5424
+ <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
5425
+ <title>Build Overview</title>
5426
+ <!-- SKIN: link the app's fonts here (CDN \u2014 e.g. Fontshare / Google Fonts). -->
5427
+ <style>
5428
+ *, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }
5429
+ </style>
5430
+ </head>
5431
+ <body>
5432
+ <!-- Compose the Build Overview here. Layout, sections, type, and styling are
5433
+ yours \u2014 keep everything inline and self-contained, brand-skinned from the
5434
+ app's spec. -->
5435
+ </body>
5436
+ </html>`;
5437
+ var buildOverviewTool = {
5438
+ clearable: false,
5439
+ definition: {
5440
+ name: "writeBuildOverview",
5441
+ description: "Generate or refresh the Build Overview \u2014 the project's home page in the Spec tab: a single-page, plain-language reference of everything the app actually contains, including the parts the user can't see (data stores, backend operations, access and roles, background jobs, seeded scenarios, the design system). You author the full copy: read the manifest and spec and state, plainly and exactly, what genuinely exists \u2014 real names and accurate counts \u2014 in calm, declarative, present-tense outcome language, with no persuasion or hype. Describe only what exists. Pass the complete copy as `content`; the design expert lays it out and skins it to the app's brand without altering any of your facts. Generate it at the end of a build and refresh it after meaningful work.",
5442
+ inputSchema: {
5443
+ type: "object",
5444
+ properties: {
5445
+ content: {
5446
+ type: "string",
5447
+ description: "The full Build Overview copy you authored: everything the app contains, in plain present-tense outcome language, with real names and exact counts. The design expert lays this out and skins it to the brand without changing any fact."
5448
+ }
5449
+ },
5450
+ required: ["content"]
5451
+ }
5452
+ },
5453
+ async execute(input, context) {
5454
+ if (!context) {
5455
+ return "Error: writeBuildOverview requires execution context for design expert delegation";
5456
+ }
5457
+ const content = (input.content ?? "").trim();
5458
+ if (!content) {
5459
+ return "Error: writeBuildOverview requires non-empty `content` (the overview copy).";
5460
+ }
5461
+ try {
5462
+ const existing = fs20.existsSync(OVERVIEW_FILE) ? fs20.readFileSync(OVERVIEW_FILE, "utf-8").trim() : "";
5463
+ const currentOverview = existing || OVERVIEW_SHELL;
5464
+ const task = `<overview_copy>${content}</overview_copy>
5465
+
5466
+ <current_overview>${currentOverview}</current_overview>
5467
+
5468
+ ${DESIGN_BRIEF}`;
5469
+ const result = await designExpertTool.execute({ task }, context);
5470
+ const htmlMatch = result.match(
5471
+ /```(?:html|wireframe)\n([\s\S]*?)```/
5472
+ );
5473
+ const html = htmlMatch ? htmlMatch[1].trim() : result;
5474
+ fs20.writeFileSync(OVERVIEW_FILE, html, "utf-8");
5475
+ return "Build overview written successfully to src/overview.html.";
5476
+ } catch (err) {
5477
+ return `Error generating build overview: ${err.message}`;
5478
+ }
5479
+ }
5480
+ };
5481
+
5372
5482
  // src/tools/index.ts
5373
5483
  function deriveContext(parent, toolCallId) {
5374
5484
  return { ...parent, toolCallId };
@@ -5385,6 +5495,7 @@ var ALL_TOOLS = [
5385
5495
  designExpertTool,
5386
5496
  productVisionTool,
5387
5497
  codeSanityCheckTool,
5498
+ buildOverviewTool,
5388
5499
  compactConversationTool,
5389
5500
  // Post-onboarding
5390
5501
  presentPublishPlanTool,
@@ -5767,7 +5878,7 @@ function triggerCompaction(state, apiConfig, opts = {}) {
5767
5878
  }
5768
5879
 
5769
5880
  // src/brandExtraction/index.ts
5770
- import fs20 from "fs";
5881
+ import fs21 from "fs";
5771
5882
  import path10 from "path";
5772
5883
  import { createHash } from "crypto";
5773
5884
  var log9 = createLogger("brandExtraction");
@@ -5816,7 +5927,7 @@ function sha256(input) {
5816
5927
  }
5817
5928
  function readSafe(filePath) {
5818
5929
  try {
5819
- return fs20.readFileSync(filePath, "utf-8");
5930
+ return fs21.readFileSync(filePath, "utf-8");
5820
5931
  } catch {
5821
5932
  return "";
5822
5933
  }
@@ -5824,7 +5935,7 @@ function readSafe(filePath) {
5824
5935
  function walkMdFiles3(dir) {
5825
5936
  const results = [];
5826
5937
  try {
5827
- const entries = fs20.readdirSync(dir, { withFileTypes: true });
5938
+ const entries = fs21.readdirSync(dir, { withFileTypes: true });
5828
5939
  for (const entry of entries) {
5829
5940
  const full = path10.join(dir, entry.name);
5830
5941
  if (entry.isDirectory()) {
@@ -5839,7 +5950,7 @@ function walkMdFiles3(dir) {
5839
5950
  }
5840
5951
  function parseFrontmatter3(filePath) {
5841
5952
  try {
5842
- const content = fs20.readFileSync(filePath, "utf-8");
5953
+ const content = fs21.readFileSync(filePath, "utf-8");
5843
5954
  const match = content.match(/^---\n([\s\S]*?)\n---/);
5844
5955
  if (!match) {
5845
5956
  return { type: "" };
@@ -6018,14 +6129,14 @@ function pickFont(raw) {
6018
6129
  }
6019
6130
  function persistBrand(brand, inputHash) {
6020
6131
  const tmp = `${BRAND_FILE}.tmp`;
6021
- fs20.writeFileSync(tmp, JSON.stringify(brand, null, 2), "utf-8");
6022
- fs20.renameSync(tmp, BRAND_FILE);
6132
+ fs21.writeFileSync(tmp, JSON.stringify(brand, null, 2), "utf-8");
6133
+ fs21.renameSync(tmp, BRAND_FILE);
6023
6134
  const cache = { inputHash, generatedAt: Date.now() };
6024
- fs20.writeFileSync(CACHE_FILE, JSON.stringify(cache, null, 2), "utf-8");
6135
+ fs21.writeFileSync(CACHE_FILE, JSON.stringify(cache, null, 2), "utf-8");
6025
6136
  }
6026
6137
  function readCache() {
6027
6138
  try {
6028
- const raw = fs20.readFileSync(CACHE_FILE, "utf-8");
6139
+ const raw = fs21.readFileSync(CACHE_FILE, "utf-8");
6029
6140
  const parsed = JSON.parse(raw);
6030
6141
  if (parsed && typeof parsed.inputHash === "string" && typeof parsed.generatedAt === "number") {
6031
6142
  return parsed;
@@ -6058,14 +6169,14 @@ function triggerBrandExtraction(apiConfig, model) {
6058
6169
  }
6059
6170
 
6060
6171
  // src/session.ts
6061
- import fs21 from "fs";
6172
+ import fs22 from "fs";
6062
6173
  import path11 from "path";
6063
6174
  var log11 = createLogger("session");
6064
6175
  var SESSION_FILE = ".remy-session.json";
6065
6176
  var ARCHIVE_DIR = ".logs/sessions";
6066
6177
  function loadSession(state) {
6067
6178
  try {
6068
- const raw = fs21.readFileSync(SESSION_FILE, "utf-8");
6179
+ const raw = fs22.readFileSync(SESSION_FILE, "utf-8");
6069
6180
  const data = JSON.parse(raw);
6070
6181
  if (data.models && typeof data.models === "object") {
6071
6182
  state.models = data.models;
@@ -6124,7 +6235,7 @@ function saveSession(state) {
6124
6235
  if (state.models && Object.keys(state.models).length > 0) {
6125
6236
  payload.models = state.models;
6126
6237
  }
6127
- fs21.writeFileSync(SESSION_FILE, JSON.stringify(payload, null, 2), "utf-8");
6238
+ fs22.writeFileSync(SESSION_FILE, JSON.stringify(payload, null, 2), "utf-8");
6128
6239
  log11.info("Session saved", { messageCount: state.messages.length });
6129
6240
  } catch (err) {
6130
6241
  log11.warn("Session save failed", { error: err.message });
@@ -6133,11 +6244,11 @@ function saveSession(state) {
6133
6244
  function clearSession(state) {
6134
6245
  state.messages = [];
6135
6246
  try {
6136
- if (fs21.existsSync(SESSION_FILE)) {
6137
- fs21.mkdirSync(ARCHIVE_DIR, { recursive: true });
6247
+ if (fs22.existsSync(SESSION_FILE)) {
6248
+ fs22.mkdirSync(ARCHIVE_DIR, { recursive: true });
6138
6249
  const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
6139
6250
  const dest = path11.join(ARCHIVE_DIR, `cleared-${ts}.json`);
6140
- fs21.renameSync(SESSION_FILE, dest);
6251
+ fs22.renameSync(SESSION_FILE, dest);
6141
6252
  log11.info("Session archived on clear", { dest });
6142
6253
  }
6143
6254
  } catch (err) {
@@ -6145,7 +6256,7 @@ function clearSession(state) {
6145
6256
  error: err.message
6146
6257
  });
6147
6258
  try {
6148
- fs21.unlinkSync(SESSION_FILE);
6259
+ fs22.unlinkSync(SESSION_FILE);
6149
6260
  } catch {
6150
6261
  }
6151
6262
  }
package/dist/index.js CHANGED
@@ -4957,7 +4957,15 @@ var init_screenshot3 = __esm({
4957
4957
 
4958
4958
  // src/subagents/designExpert/tools/images/enhancePrompt.ts
4959
4959
  async function enhanceImagePrompt(params) {
4960
- const { brief, width, height, transparentBackground, onLog, model } = params;
4960
+ const {
4961
+ brief,
4962
+ width,
4963
+ height,
4964
+ transparentBackground,
4965
+ hasReferenceImage,
4966
+ onLog,
4967
+ model
4968
+ } = params;
4961
4969
  const contextParts = [
4962
4970
  `Dimensions: ${width}x${height}${width > height ? " (landscape)" : width < height ? " (portrait)" : " (square)"}`
4963
4971
  ];
@@ -4966,6 +4974,11 @@ async function enhanceImagePrompt(params) {
4966
4974
  "Transparent background: yes \u2014 the background will be removed. Focus on the subject as an isolated element."
4967
4975
  );
4968
4976
  }
4977
+ if (hasReferenceImage) {
4978
+ contextParts.push(
4979
+ "Reference image: yes \u2014 a reference image is provided to the generation model alongside this prompt to guide style, subject, or composition. Complement it; don't re-describe what it already carries."
4980
+ );
4981
+ }
4969
4982
  const context = `<context>
4970
4983
  ${contextParts.join("\n")}
4971
4984
  </context>`;
@@ -5006,6 +5019,7 @@ async function generateImageAssets(opts) {
5006
5019
  prompts,
5007
5020
  sourceImages,
5008
5021
  transparentBackground,
5022
+ enhancePrompts,
5009
5023
  onLog,
5010
5024
  imageGenerationModel: genModel,
5011
5025
  imageAnalysisModel,
@@ -5024,19 +5038,20 @@ async function generateImageAssets(opts) {
5024
5038
  config.source_image = firstImage;
5025
5039
  config.source = firstImage;
5026
5040
  }
5027
- const isEdit = !!sourceImages?.length;
5028
- const enhancedPrompts = isEdit ? prompts : await Promise.all(
5041
+ const hasReference = !!sourceImages?.length;
5042
+ const enhancedPrompts = enhancePrompts ? await Promise.all(
5029
5043
  prompts.map(
5030
5044
  (brief) => enhanceImagePrompt({
5031
5045
  brief,
5032
5046
  width,
5033
5047
  height,
5034
5048
  transparentBackground,
5049
+ hasReferenceImage: hasReference,
5035
5050
  onLog,
5036
5051
  model: imagePromptEnhancerModel
5037
5052
  })
5038
5053
  )
5039
- );
5054
+ ) : prompts;
5040
5055
  let imageUrls;
5041
5056
  if (enhancedPrompts.length === 1) {
5042
5057
  const step = JSON.stringify({
@@ -5106,7 +5121,7 @@ async function generateImageAssets(opts) {
5106
5121
  if (url.startsWith("Error")) {
5107
5122
  return {
5108
5123
  prompt: prompts[i],
5109
- ...!isEdit && { enhancedPrompt: enhancedPrompts[i] },
5124
+ ...enhancePrompts && { enhancedPrompt: enhancedPrompts[i] },
5110
5125
  error: url
5111
5126
  };
5112
5127
  }
@@ -5119,7 +5134,7 @@ async function generateImageAssets(opts) {
5119
5134
  return {
5120
5135
  url,
5121
5136
  prompt: prompts[i],
5122
- ...!isEdit && { enhancedPrompt: enhancedPrompts[i] },
5137
+ ...enhancePrompts && { enhancedPrompt: enhancedPrompts[i] },
5123
5138
  analysis,
5124
5139
  width,
5125
5140
  height
@@ -5151,6 +5166,8 @@ async function execute6(input, onLog, context) {
5151
5166
  width: input.width,
5152
5167
  height: input.height,
5153
5168
  transparentBackground: input.transparentBackground,
5169
+ sourceImages: input.referenceImage ? [input.referenceImage] : void 0,
5170
+ enhancePrompts: true,
5154
5171
  onLog,
5155
5172
  imageGenerationModel: resolveModel(
5156
5173
  "imageGeneration",
@@ -5189,6 +5206,10 @@ var init_generateImages = __esm({
5189
5206
  },
5190
5207
  description: "One or more image briefs describing what you want. Focus on subject, mood, style, and intended use \u2014 the tool optimizes your brief into a model-ready prompt automatically. Multiple briefs run in parallel."
5191
5208
  },
5209
+ referenceImage: {
5210
+ type: "string",
5211
+ description: "Optional URL of a single reference image to guide the generation \u2014 for style, subject, character consistency, or composition. Your prompt still describes the desired result; the reference conditions it. Applies to every prompt in the batch."
5212
+ },
5192
5213
  width: {
5193
5214
  type: "number",
5194
5215
  description: "Image width in pixels. Default 2048. Range: 2048-4096."
@@ -5221,6 +5242,7 @@ async function execute7(input, onLog, context) {
5221
5242
  width: input.width,
5222
5243
  height: input.height,
5223
5244
  transparentBackground: input.transparentBackground,
5245
+ enhancePrompts: false,
5224
5246
  onLog,
5225
5247
  imageGenerationModel: resolveModel(
5226
5248
  "imageGeneration",
@@ -5439,9 +5461,9 @@ ${parts.join("\n\n")}
5439
5461
  }
5440
5462
  function loadPlatformBrief() {
5441
5463
  return `<platform_brief>
5442
- ## What is a MindStudio app?
5464
+ ## What is a Remy app?
5443
5465
 
5444
- A MindStudio app is a managed full-stack TypeScript project with three layers: a spec (natural language in src/), a backend contract (methods, tables, roles in dist/), and one or more interfaces (web, API, bots, cron, etc.). The spec is the source of truth; code is derived from it.
5466
+ A Remy app is a managed full-stack TypeScript project with three layers: a spec (natural language in src/), a backend contract (methods, tables, roles in dist/), and one or more interfaces (web, API, bots, cron, etc.). The spec is the source of truth; code is derived from it.
5445
5467
 
5446
5468
  This is a capable, stable platform used in production by 100k+ users. Build with confidence \u2014 you're building production-grade apps, not fragile prototypes.
5447
5469
 
@@ -5486,7 +5508,7 @@ TypeScript running in a sandboxed environment. Any npm package can be installed.
5486
5508
 
5487
5509
  The first-party SDK (@mindstudio-ai/agent) provides access to 200+ AI models (OpenAI, Anthropic, Google, Meta, Mistral, and more) and 1000+ integrations (email, SMS, Slack, HubSpot, Google Workspace, web scraping, image/video generation, media processing, and much more) with zero configuration \u2014 credentials are handled automatically in the execution environment. No API keys needed. This SDK is robust and battle-tested in production.
5488
5510
 
5489
- ## What MindStudio apps are NOT good for
5511
+ ## What Remy apps are NOT good for
5490
5512
 
5491
5513
  - Native mobile apps (iOS/Android). Mobile-responsive web apps are fine.
5492
5514
  - Real-time multiplayer with persistent connections (no WebSocket support). Turn-based or async patterns work.
@@ -6281,6 +6303,101 @@ var init_scrapeWebUrl2 = __esm({
6281
6303
  }
6282
6304
  });
6283
6305
 
6306
+ // src/tools/spec/writeBuildOverview.ts
6307
+ import fs19 from "fs";
6308
+ var OVERVIEW_FILE, DESIGN_BRIEF, OVERVIEW_SHELL, buildOverviewTool;
6309
+ var init_writeBuildOverview = __esm({
6310
+ "src/tools/spec/writeBuildOverview.ts"() {
6311
+ "use strict";
6312
+ init_designExpert();
6313
+ OVERVIEW_FILE = "src/overview.html";
6314
+ DESIGN_BRIEF = `We are building the Build Overview for this app \u2014 the home page of its Spec tab. It is a calm, dense, one-page reference of everything the app actually contains, including the parts the user can't see. It renders flush inside the Spec tab's content panel (the IDE supplies the surrounding nav).
6315
+
6316
+ Take the plain-language copy in <overview_copy> and lay it out and skin it into a single, beautiful, self-contained HTML document in the app's own brand. If <current_overview> is non-empty, use it as your starting point and preserve its established skin, updating only what the copy changed.
6317
+
6318
+ ### The single hard rule
6319
+ Preserve every fact in <overview_copy> exactly \u2014 every number, name, label, and claim. Do not add, drop, soften, reword, or invent any fact. You own layout, typography, and visual design only; the substance and the words are fixed. A single wrong number breaks this document's entire purpose.
6320
+
6321
+ ### What it is (and is not)
6322
+ - A typeset reference dossier: composed, dense, a little cool \u2014 substantial at a glance, then readable. Density communicates substance; sparse and airy reads as "not much here."
6323
+ - Brand-skinned: pull the palette, type system, and a single accent from the app's spec. The accent leads labels and figures; it is a mark, not a fill.
6324
+ - NOT a slide deck \u2014 no theatrics, no building to a climax, no persuasion.
6325
+ - NOT a docs site \u2014 no raised or shadowed cards, no hover-lift, no clickable-feeling surfaces, no sticky table of contents.
6326
+ - NOT a sparse memo \u2014 a restrained single-column page under-sells the work.
6327
+ - No header chrome and no footer: open straight on the app's logo and name so it sits flush with the IDE.
6328
+
6329
+ ### Constraints
6330
+ - A single self-contained HTML file. Fonts may load from a CDN; everything else (CSS, the logo SVG) is inline.
6331
+ - Responsive: fills the embedded panel width and collapses gracefully at narrow widths.
6332
+
6333
+ Respond only with the complete HTML file and absolutely no other text. Your response will be written directly to src/overview.html.`;
6334
+ OVERVIEW_SHELL = `<!DOCTYPE html>
6335
+ <html lang="en">
6336
+ <head>
6337
+ <meta charset="utf-8">
6338
+ <!-- This renders inside an iframe in the IDE. Keep it a simple, self-contained
6339
+ static document \u2014 no scroll/zoom/accessibility scaffolding beyond this head.
6340
+ The user-scalable=no viewport is intentional; leave it. -->
6341
+ <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
6342
+ <title>Build Overview</title>
6343
+ <!-- SKIN: link the app's fonts here (CDN \u2014 e.g. Fontshare / Google Fonts). -->
6344
+ <style>
6345
+ *, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }
6346
+ </style>
6347
+ </head>
6348
+ <body>
6349
+ <!-- Compose the Build Overview here. Layout, sections, type, and styling are
6350
+ yours \u2014 keep everything inline and self-contained, brand-skinned from the
6351
+ app's spec. -->
6352
+ </body>
6353
+ </html>`;
6354
+ buildOverviewTool = {
6355
+ clearable: false,
6356
+ definition: {
6357
+ name: "writeBuildOverview",
6358
+ description: "Generate or refresh the Build Overview \u2014 the project's home page in the Spec tab: a single-page, plain-language reference of everything the app actually contains, including the parts the user can't see (data stores, backend operations, access and roles, background jobs, seeded scenarios, the design system). You author the full copy: read the manifest and spec and state, plainly and exactly, what genuinely exists \u2014 real names and accurate counts \u2014 in calm, declarative, present-tense outcome language, with no persuasion or hype. Describe only what exists. Pass the complete copy as `content`; the design expert lays it out and skins it to the app's brand without altering any of your facts. Generate it at the end of a build and refresh it after meaningful work.",
6359
+ inputSchema: {
6360
+ type: "object",
6361
+ properties: {
6362
+ content: {
6363
+ type: "string",
6364
+ description: "The full Build Overview copy you authored: everything the app contains, in plain present-tense outcome language, with real names and exact counts. The design expert lays this out and skins it to the brand without changing any fact."
6365
+ }
6366
+ },
6367
+ required: ["content"]
6368
+ }
6369
+ },
6370
+ async execute(input, context) {
6371
+ if (!context) {
6372
+ return "Error: writeBuildOverview requires execution context for design expert delegation";
6373
+ }
6374
+ const content = (input.content ?? "").trim();
6375
+ if (!content) {
6376
+ return "Error: writeBuildOverview requires non-empty `content` (the overview copy).";
6377
+ }
6378
+ try {
6379
+ const existing = fs19.existsSync(OVERVIEW_FILE) ? fs19.readFileSync(OVERVIEW_FILE, "utf-8").trim() : "";
6380
+ const currentOverview = existing || OVERVIEW_SHELL;
6381
+ const task = `<overview_copy>${content}</overview_copy>
6382
+
6383
+ <current_overview>${currentOverview}</current_overview>
6384
+
6385
+ ${DESIGN_BRIEF}`;
6386
+ const result = await designExpertTool.execute({ task }, context);
6387
+ const htmlMatch = result.match(
6388
+ /```(?:html|wireframe)\n([\s\S]*?)```/
6389
+ );
6390
+ const html = htmlMatch ? htmlMatch[1].trim() : result;
6391
+ fs19.writeFileSync(OVERVIEW_FILE, html, "utf-8");
6392
+ return "Build overview written successfully to src/overview.html.";
6393
+ } catch (err) {
6394
+ return `Error generating build overview: ${err.message}`;
6395
+ }
6396
+ }
6397
+ };
6398
+ }
6399
+ });
6400
+
6284
6401
  // src/tools/index.ts
6285
6402
  function deriveContext(parent, toolCallId) {
6286
6403
  return { ...parent, toolCallId };
@@ -6335,6 +6452,7 @@ var init_tools6 = __esm({
6335
6452
  init_productVision();
6336
6453
  init_codeSanityCheck();
6337
6454
  init_scrapeWebUrl2();
6455
+ init_writeBuildOverview();
6338
6456
  ALL_TOOLS = [
6339
6457
  // Common
6340
6458
  setProjectOnboardingStateTool,
@@ -6347,6 +6465,7 @@ var init_tools6 = __esm({
6347
6465
  designExpertTool,
6348
6466
  productVisionTool,
6349
6467
  codeSanityCheckTool,
6468
+ buildOverviewTool,
6350
6469
  compactConversationTool,
6351
6470
  // Post-onboarding
6352
6471
  presentPublishPlanTool,
@@ -6389,11 +6508,11 @@ var init_tools6 = __esm({
6389
6508
  });
6390
6509
 
6391
6510
  // src/session.ts
6392
- import fs19 from "fs";
6511
+ import fs20 from "fs";
6393
6512
  import path9 from "path";
6394
6513
  function loadSession(state) {
6395
6514
  try {
6396
- const raw = fs19.readFileSync(SESSION_FILE, "utf-8");
6515
+ const raw = fs20.readFileSync(SESSION_FILE, "utf-8");
6397
6516
  const data = JSON.parse(raw);
6398
6517
  if (data.models && typeof data.models === "object") {
6399
6518
  state.models = data.models;
@@ -6452,7 +6571,7 @@ function saveSession(state) {
6452
6571
  if (state.models && Object.keys(state.models).length > 0) {
6453
6572
  payload.models = state.models;
6454
6573
  }
6455
- fs19.writeFileSync(SESSION_FILE, JSON.stringify(payload, null, 2), "utf-8");
6574
+ fs20.writeFileSync(SESSION_FILE, JSON.stringify(payload, null, 2), "utf-8");
6456
6575
  log8.info("Session saved", { messageCount: state.messages.length });
6457
6576
  } catch (err) {
6458
6577
  log8.warn("Session save failed", { error: err.message });
@@ -6461,11 +6580,11 @@ function saveSession(state) {
6461
6580
  function clearSession(state) {
6462
6581
  state.messages = [];
6463
6582
  try {
6464
- if (fs19.existsSync(SESSION_FILE)) {
6465
- fs19.mkdirSync(ARCHIVE_DIR, { recursive: true });
6583
+ if (fs20.existsSync(SESSION_FILE)) {
6584
+ fs20.mkdirSync(ARCHIVE_DIR, { recursive: true });
6466
6585
  const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
6467
6586
  const dest = path9.join(ARCHIVE_DIR, `cleared-${ts}.json`);
6468
- fs19.renameSync(SESSION_FILE, dest);
6587
+ fs20.renameSync(SESSION_FILE, dest);
6469
6588
  log8.info("Session archived on clear", { dest });
6470
6589
  }
6471
6590
  } catch (err) {
@@ -6473,7 +6592,7 @@ function clearSession(state) {
6473
6592
  error: err.message
6474
6593
  });
6475
6594
  try {
6476
- fs19.unlinkSync(SESSION_FILE);
6595
+ fs20.unlinkSync(SESSION_FILE);
6477
6596
  } catch {
6478
6597
  }
6479
6598
  }
@@ -6695,7 +6814,7 @@ var init_errors = __esm({
6695
6814
  });
6696
6815
 
6697
6816
  // src/brandExtraction/index.ts
6698
- import fs20 from "fs";
6817
+ import fs21 from "fs";
6699
6818
  import path10 from "path";
6700
6819
  import { createHash } from "crypto";
6701
6820
  async function runExtraction(apiConfig, model) {
@@ -6740,7 +6859,7 @@ function sha256(input) {
6740
6859
  }
6741
6860
  function readSafe(filePath) {
6742
6861
  try {
6743
- return fs20.readFileSync(filePath, "utf-8");
6862
+ return fs21.readFileSync(filePath, "utf-8");
6744
6863
  } catch {
6745
6864
  return "";
6746
6865
  }
@@ -6748,7 +6867,7 @@ function readSafe(filePath) {
6748
6867
  function walkMdFiles3(dir) {
6749
6868
  const results = [];
6750
6869
  try {
6751
- const entries = fs20.readdirSync(dir, { withFileTypes: true });
6870
+ const entries = fs21.readdirSync(dir, { withFileTypes: true });
6752
6871
  for (const entry of entries) {
6753
6872
  const full = path10.join(dir, entry.name);
6754
6873
  if (entry.isDirectory()) {
@@ -6763,7 +6882,7 @@ function walkMdFiles3(dir) {
6763
6882
  }
6764
6883
  function parseFrontmatter3(filePath) {
6765
6884
  try {
6766
- const content = fs20.readFileSync(filePath, "utf-8");
6885
+ const content = fs21.readFileSync(filePath, "utf-8");
6767
6886
  const match = content.match(/^---\n([\s\S]*?)\n---/);
6768
6887
  if (!match) {
6769
6888
  return { type: "" };
@@ -6942,14 +7061,14 @@ function pickFont(raw) {
6942
7061
  }
6943
7062
  function persistBrand(brand, inputHash) {
6944
7063
  const tmp = `${BRAND_FILE}.tmp`;
6945
- fs20.writeFileSync(tmp, JSON.stringify(brand, null, 2), "utf-8");
6946
- fs20.renameSync(tmp, BRAND_FILE);
7064
+ fs21.writeFileSync(tmp, JSON.stringify(brand, null, 2), "utf-8");
7065
+ fs21.renameSync(tmp, BRAND_FILE);
6947
7066
  const cache = { inputHash, generatedAt: Date.now() };
6948
- fs20.writeFileSync(CACHE_FILE, JSON.stringify(cache, null, 2), "utf-8");
7067
+ fs21.writeFileSync(CACHE_FILE, JSON.stringify(cache, null, 2), "utf-8");
6949
7068
  }
6950
7069
  function readCache() {
6951
7070
  try {
6952
- const raw = fs20.readFileSync(CACHE_FILE, "utf-8");
7071
+ const raw = fs21.readFileSync(CACHE_FILE, "utf-8");
6953
7072
  const parsed = JSON.parse(raw);
6954
7073
  if (parsed && typeof parsed.inputHash === "string" && typeof parsed.generatedAt === "number") {
6955
7074
  return parsed;
@@ -7616,12 +7735,12 @@ var init_agent = __esm({
7616
7735
  });
7617
7736
 
7618
7737
  // src/config.ts
7619
- import fs21 from "fs";
7738
+ import fs22 from "fs";
7620
7739
  import path11 from "path";
7621
7740
  import os from "os";
7622
7741
  function loadConfigFile() {
7623
7742
  try {
7624
- const raw = fs21.readFileSync(CONFIG_PATH, "utf-8");
7743
+ const raw = fs22.readFileSync(CONFIG_PATH, "utf-8");
7625
7744
  log12.debug("Loaded config file", { path: CONFIG_PATH });
7626
7745
  return JSON.parse(raw);
7627
7746
  } catch (err) {
@@ -8869,7 +8988,7 @@ var init_headless = __esm({
8869
8988
  // src/index.tsx
8870
8989
  import { render } from "ink";
8871
8990
  import os2 from "os";
8872
- import fs22 from "fs";
8991
+ import fs23 from "fs";
8873
8992
  import path12 from "path";
8874
8993
 
8875
8994
  // src/tui/App.tsx
@@ -9151,7 +9270,7 @@ Error: ${err.message}`,
9151
9270
  return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", gap: 1, children: [
9152
9271
  /* @__PURE__ */ jsxs4(Text5, { bold: true, color: "magenta", children: [
9153
9272
  "Remy ",
9154
- /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "v0.1.0 \u2014 MindStudio coding agent" })
9273
+ /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "v0.1.0 \u2014 AI coding agent" })
9155
9274
  ] }),
9156
9275
  sessionRestored && /* @__PURE__ */ jsxs4(Text5, { dimColor: true, children: [
9157
9276
  "Session restored (",
@@ -9188,7 +9307,7 @@ for (let i = 0; i < args.length; i++) {
9188
9307
  var startupLog = createLogger("startup");
9189
9308
  function printDebugInfo(config) {
9190
9309
  const pkg = JSON.parse(
9191
- fs22.readFileSync(
9310
+ fs23.readFileSync(
9192
9311
  path12.join(import.meta.dirname, "..", "package.json"),
9193
9312
  "utf-8"
9194
9313
  )
@@ -69,7 +69,7 @@ From research into v0, Lovable, Bolt, and Anthropic's `<frontend_aesthetics>` co
69
69
 
70
70
  ## SDK Usage
71
71
 
72
- The canonical import pattern for MindStudio app methods is `import { mindstudio } from '@mindstudio-ai/agent'` with `mindstudio.generateText(...)`, `mindstudio.runTask(...)`, etc. The `mindstudio` singleton handles auth automatically. `new MindStudioAgent({ apiKey })` is only for external usage outside MindStudio apps.
72
+ The canonical import pattern for app methods is `import { mindstudio } from '@mindstudio-ai/agent'` with `mindstudio.generateText(...)`, `mindstudio.runTask(...)`, etc. The `mindstudio` singleton handles auth automatically. `new MindStudioAgent({ apiKey })` is only for external usage outside an app.
73
73
 
74
74
  The SDK ships `llms.txt` at the package root with full signatures for all 170+ actions. The compiled fragment references this path (`dist/methods/node_modules/@mindstudio-ai/agent/llms.txt`) so the agent knows where to look up specific action details.
75
75
 
@@ -18,7 +18,7 @@ instructions:
18
18
  ---
19
19
 
20
20
  **You will compile source docs into prompt fragments for Remy, a coding agent
21
- that builds MindStudio apps. The compiled fragments go in `src/prompt/compiled/`
21
+ that builds apps. The compiled fragments go in `src/prompt/compiled/`
22
22
  and are loaded into the agent's system prompt at runtime.**
23
23
 
24
24
  **Work through this one source file at a time, sequentially.** For each one:
@@ -39,7 +39,7 @@ Source files are in `docs/developer-guide/` at the project root.
39
39
 
40
40
  **Your audience is an LLM acting as a coding agent.** It needs to produce
41
41
  correct code, not learn concepts. Everything you write should be optimized
42
- for an agent that is actively building a MindStudio app and needs to get
42
+ for an agent that is actively building an app and needs to get
43
43
  the details right.
44
44
 
45
45
  ### What to keep
@@ -1,6 +1,6 @@
1
1
  # Auth
2
2
 
3
- MindStudio apps can have and manage their own users. Auth is opt-in: configure it in the manifest, define a user table, and build your own login UI. The platform handles verification codes, cookies, and session management. Apps without auth config use anonymous guest sessions (current default behavior).
3
+ Remy apps can have and manage their own users. Auth is opt-in: configure it in the manifest, define a user table, and build your own login UI. The platform handles verification codes, cookies, and session management. Apps without auth config use anonymous guest sessions (current default behavior).
4
4
 
5
5
  **Auth is optional.** Many apps don't need it. Only add auth when the app needs to identify users or restrict access.
6
6
 
@@ -338,7 +338,7 @@ Roles are declared in the manifest, stored as an array column on the user table,
338
338
  - Declare roles in `mindstudio.json` with `id` and `name`
339
339
  - The mapped `roles` column holds a JSON array of role ID strings: `["vendor", "admin"]`
340
340
  - Writable from code: `Users.update(userId, { roles: ['admin'] })` — platform syncs automatically
341
- - Writable from dashboard: MindStudio dashboard shows app users and their roles
341
+ - Writable from dashboard: Remy dashboard shows app users and their roles
342
342
  - Backend enforcement: `auth.requireRole('admin')` works as before
343
343
 
344
344
  ## Apps Without Auth
@@ -1,12 +1,12 @@
1
1
  # Frontend Design Notes
2
2
 
3
- Design standards for web interfaces in MindStudio apps.
3
+ Design standards for web interfaces in Remy apps.
4
4
 
5
5
  ## Quality Bar
6
6
 
7
7
  Every interface must feel like a polished, shipping product — not a prototype, not a starter template, not a homework assignment. If it wouldn't look good on Dribbble, Behance, or Mobbin, it's not done.
8
8
 
9
- MindStudio apps are end-user products. The interface is the product. Users judge the entire app by how it looks and feels in the first 3 seconds.
9
+ Remy apps are end-user products. The interface is the product. Users judge the entire app by how it looks and feels in the first 3 seconds.
10
10
 
11
11
  For questions about design, layout, UI, interfaces, components, and anything else, ask the design expert! They have access to countless resources and references and can provide great inspiration as you plan and work - the response to a quick "I'm making XYZ - wdyt?" can be such a powerful input to your thinking!
12
12
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  Interfaces are projections of the backend contract into different modalities. The same methods power all of them. An interface can be as complex and polished as you want, but it's always safe — the backend contract is where anything real happens. The interface can't break business logic or corrupt data.
4
4
 
5
- All external service connections (Discord bot tokens, Telegram bot setup, webhook secrets, email addresses) are configured at the project level by the user through the MindStudio platform. The agent's job is to write the config files and the methods that handle the requests — not to manage API keys, OAuth flows, or service registration.
5
+ All external service connections (Discord bot tokens, Telegram bot setup, webhook secrets, email addresses) are configured at the project level by the user through the Remy platform. The agent's job is to write the config files and the methods that handle the requests — not to manage API keys, OAuth flows, or service registration.
6
6
 
7
7
  ## Web Interface
8
8
 
@@ -1,6 +1,6 @@
1
- # MindStudio Platform
1
+ # Remy Platform
2
2
 
3
- A MindStudio app has three layers: a **spec** (natural language in `src/`), a **backend contract** (methods, tables, roles in `dist/`), and **interfaces** (web, API, bots, cron, etc. — also in `dist/`). The spec is the source of truth; the code is a derivation.
3
+ A Remy app has three layers: a **spec** (natural language in `src/`), a **backend contract** (methods, tables, roles in `dist/`), and **interfaces** (web, API, bots, cron, etc. — also in `dist/`). The spec is the source of truth; the code is a derivation.
4
4
 
5
5
  `src/` is the authored source — natural language specs, brand guidelines, reference materials. No code. `dist/` is the compiled output — TypeScript methods, frontends, JSON configs. You can edit `dist/` directly, but `src/` is the reset point. Regenerate `dist/` from `src/` at any time.
6
6
 
@@ -6,7 +6,7 @@ There is a huge amount of capability here: hundreds of text generation models (O
6
6
 
7
7
  ## Usage in Methods
8
8
 
9
- Inside a MindStudio app method, use the `mindstudio` singleton — credentials come from the execution environment automatically:
9
+ Inside an app method, use the `mindstudio` singleton — credentials come from the execution environment automatically:
10
10
 
11
11
  ```typescript
12
12
  import { mindstudio } from '@mindstudio-ai/agent';
@@ -90,7 +90,7 @@ result.$billingCost; // cost in credits (if applicable)
90
90
 
91
91
  ### Third-Party Integrations (OAuth Connectors)
92
92
 
93
- 850+ additional actions from the MindStudio Connector Registry, covering services like HubSpot, Salesforce, Airtable, Google Workspace, Notion, Coda, and many more. These require OAuth connections set up by the user in MindStudio.
93
+ 850+ additional actions from the MindStudio Connector Registry, covering services like HubSpot, Salesforce, Airtable, Google Workspace, Notion, Coda, and many more. These require OAuth connections set up by the user in Remy.
94
94
 
95
95
  Built-in connector methods include: ActiveCampaign, Airtable, Apollo, Coda, Facebook, Gmail, Google Docs/Sheets/Calendar/Drive, HubSpot, Hunter.io, Instagram, LinkedIn, Notion, X (Twitter), YouTube.
96
96
 
@@ -76,7 +76,7 @@ Before installing a package you haven't used in this project, do a quick web sea
76
76
  You have access to the `mindstudio` CLI, which exposes every SDK action as a command-line tool. Use it via bash for one-off tasks: generating images, video, or audio, scraping URLs, sending emails, running AI completions, or anything else the SDK can do. Every JavaScript SDK method has a corresponding CLI command. Run `askMindStudioSdk` to discover commands for CLI usage.
77
77
 
78
78
  ### Production App Management
79
- 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.
79
+ You have access to `mindstudio-prod`, a CLI for managing the user's production 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.
80
80
 
81
81
  Available commands: `requests` (server-side request logs, error rates, latency), `crashes` (frontend browser errors — grouped issues + drill-down to individual events), `analytics` (traffic, top pages/referrers/geo, AI-referral attribution, live counters), `releases` (deploy status, history), `domains` (custom subdomains and fully custom domains), `users` (list, set roles), `db` (query production sql db), `data` (live db operations like lift-from-dev), `methods` (list, invoke), `secrets` (list, get, set, delete).
82
82
 
@@ -1 +1 @@
1
- You are Remy, a coding and spec-building agent for MindStudio apps. You were created by MindStudio.
1
+ You are Remy, a coding and spec-building agent that builds apps.
@@ -7,6 +7,7 @@
7
7
  ## Principles
8
8
  - The spec in `src/` is the source of truth. When in doubt, consult the spec before making code changes. When behavior changes, update the spec first.
9
9
  - Always keep the spec up to date after making changes to the code, especially when adding features or building things from the roadmap.
10
+ - Keep `src/overview.html` (the Build Overview — the project's home page) current the same way you keep the spec in sync: after meaningful work such as new features, interfaces, data stores, or background jobs, re-author its copy and call `writeBuildOverview` so it still reflects everything the app actually contains.
10
11
  - Change only what the task requires. Match existing styles. Keep solutions simple.
11
12
  - Read files before editing them. Understand the context before making changes.
12
13
  - When the user asks you to make a change, execute it fully — all steps, no pausing for confirmation. Use `confirmDestructiveAction` to gate before destructive or irreversible actions (e.g., deleting data, resetting the database). For large changes that touch many files or involve significant design decisions, use `writePlan` to write an implementation plan for user approval — but only when the scope genuinely warrants it or the user asks to see a plan. The plan is saved to `.remy-plan.md` and the user can review, discuss, and refine it before approving. Do not begin implementation until the plan is approved. Most work should be done autonomously without a plan.
@@ -6,7 +6,7 @@ The goal of the intake session is to truly and deeply align with the user on a s
6
6
 
7
7
  ### What You're Working With
8
8
 
9
- MindStudio apps are full-stack TypeScript projects. You have a lot to work with:
9
+ Remy apps are full-stack TypeScript projects. You have a lot to work with:
10
10
 
11
11
  - **Backend (Methods):** TypeScript in a sandboxed runtime. Any npm package. Managed SQLite database with typed schemas and automatic migrations. Built-in app-managed auth with email/SMS verification, cookie sessions, and role enforcement. None of these are required — use what the app needs.
12
12
  - **Frontend (Web Interface):** Starts as Vite + React, but any TypeScript project with a build command works. Any framework, any library, or no framework at all.
@@ -18,12 +18,12 @@ Most things are fine. These are fast-moving products built by non-technical user
18
18
 
19
19
  These are things we already know about and have decided to accept:
20
20
 
21
- - **`dist/` is where code lives.** MindStudio apps use `dist/` for all code (methods, interfaces, tables) and `src/` for natural language specs. This is NOT the conventional "dist is build output" pattern. Never flag code being in `dist/` as wrong.
21
+ - **`dist/` is where code lives.** Remy apps use `dist/` for all code (methods, interfaces, tables) and `src/` for natural language specs. This is NOT the conventional "dist is build output" pattern. Never flag code being in `dist/` as wrong.
22
22
  - The raw request body for webhook signature verification (Stripe, GitHub, etc.) is available natively — under `input._request.rawBody` on API interface methods, and at top-level `input.rawBody` on Webhook interface methods. Do NOT suggest external proxies or workarounds.
23
23
 
24
24
  - Ignore limited browser support for `oklch` gradients using `in <colorspace>` syntax — we accept the compatibility tradeoff for better color quality
25
25
  -Ignore limited browser support for CSS scroll-driven animations (`animation-timeline: scroll()` / `view()`) - we accept this tradeoff
26
- - Trust your knowledge about Platform SDKs (these are the core of every MindStudio app) - for our purposes, assume they're always current and stable:
26
+ - Trust your knowledge about Platform SDKs (these are the core of every app) - for our purposes, assume they're always current and stable:
27
27
  - `@mindstudio-ai/interface` — frontend SDK. `createClient<T>()` gives typed RPC to backend methods (no raw fetch). `auth` handles auth state (`auth.currentUser`, `auth.onAuthStateChanged(cb)`, verification flows, logout). `platform.uploadFile()` handles signed S3 uploads and returns permanent CDN URLs with query-string resizing for images and auto-thumbnails for videos.
28
28
  - `@mindstudio-ai/agent` — backend SDK. `db.defineTable<T>()` gives a typed ORM with Query (chainable reads) and direct writes. `auth` gives `auth.userId`, `auth.roles`, `auth.requireRole()`, `auth.hasRole()`. Also provides 200+ managed actions for AI models, email/SMS, third-party APIs, media processing.
29
29
  - We know these libriares are actively maintained, don't waste time checking:
@@ -1,12 +1,12 @@
1
1
  # Web App Interface Design Notes
2
2
 
3
- Design standards for web interfaces in MindStudio apps.
3
+ Design standards for web interfaces in Remy apps.
4
4
 
5
5
  ## Quality Bar
6
6
 
7
7
  Every interface must feel like a polished, shipping product — not a prototype, not a starter template, not a homework assignment. The standard is iOS and Apple's bundled iOS apps, Notion, Stripe. If it wouldn't look good on Dribbble, Behance, or Mobbin, it's not done.
8
8
 
9
- MindStudio apps are end-user products. The interface is the product. Users judge the entire app by how it looks and feels in the first 3 seconds.
9
+ Remy apps are end-user products. The interface is the product. Users judge the entire app by how it looks and feels in the first 3 seconds.
10
10
 
11
11
  ## Design System from the Spec
12
12
 
@@ -18,7 +18,7 @@ When specifying sheets, drawers, modals, or any surface that slides/fades into v
18
18
 
19
19
  Login and signup screens set the tone for the user's entire experience with the app and are important to get right - they should feel like exciting entry points into the next level of the user journy. A janky login form with misaligned inputs and no feedback dminishes excitement and undermines trust before the user even gets in.
20
20
 
21
- Authentication moments must feel natural and intuitive - they should not feel jarring or surprising. Take care to integrate them into the entire experience when building. MindStudio apps support SMS code verification, email verification, or both, depending on how the app is configured.
21
+ Authentication moments must feel natural and intuitive - they should not feel jarring or surprising. Take care to integrate them into the entire experience when building. Remy apps support SMS code verification, email verification, or both, depending on how the app is configured.
22
22
 
23
23
  **Verification code input:** The 6-digit code entry is the critical moment. Prefer to design it as individual digit boxes (not a single text input), with auto-advance between digits, auto-submit on paste, and clear visual feedback. The boxes should be large enough to tap easily on mobile. Show a subtle animation on successful verification. Error states should be inline and immediate, not a separate alert.
24
24
 
@@ -41,6 +41,7 @@ You'll receive context about the generation parameters. Use them:
41
41
 
42
42
  - **Dimensions**: If the image is wide (landscape), compose horizontally. If tall (portrait), compose vertically. If square, center the subject.
43
43
  - **Transparent background**: The background will be removed after generation and the image will be trimmed to the subject bounds (no extra padding). Don't describe elaborate backgrounds — focus on the subject. Describe it as an isolated element.
44
+ - **Reference image**: When a reference image is provided, the generation model receives it alongside your prompt to guide style, subject, or composition. Write the prompt to *complement* the reference, not duplicate it: describe the scene, action, and anything new or changed, and lean on the reference for what it already establishes (a specific face, product, logo, or art style). Don't exhaustively re-describe those — over-specifying competes with the reference image and can distort it.
44
45
 
45
46
  ## Photography prompts
46
47
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@mindstudio-ai/remy",
3
- "version": "0.1.198",
4
- "description": "MindStudio coding agent",
3
+ "version": "0.1.200",
4
+ "description": "Remy coding agent",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "https://github.com/mindstudio-ai/remy"