stashes 0.1.55 → 0.1.57

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/dist/cli.js CHANGED
@@ -20,7 +20,7 @@ var __require = import.meta.require;
20
20
 
21
21
  // src/index.ts
22
22
  import { readFileSync as readFileSync10 } from "fs";
23
- import { join as join15, dirname as dirname6 } from "path";
23
+ import { join as join14, dirname as dirname6 } from "path";
24
24
  import { fileURLToPath as fileURLToPath3 } from "url";
25
25
  import { Command } from "commander";
26
26
 
@@ -31,9 +31,9 @@ import open from "open";
31
31
  // ../server/dist/index.js
32
32
  import { Hono as Hono2 } from "hono";
33
33
  import { cors } from "hono/cors";
34
- import { join as join11, dirname as dirname3 } from "path";
34
+ import { join as join10, dirname as dirname3 } from "path";
35
35
  import { fileURLToPath } from "url";
36
- import { existsSync as existsSync11, readFileSync as readFileSync6 } from "fs";
36
+ import { existsSync as existsSync10, readFileSync as readFileSync6 } from "fs";
37
37
  // ../shared/dist/constants/index.js
38
38
  var STASHES_PORT = 4000;
39
39
  var DEFAULT_STASH_COUNT = 3;
@@ -56,12 +56,12 @@ var DEFAULT_DIRECTIVES = [
56
56
  ];
57
57
  // ../server/dist/routes/api.js
58
58
  import { Hono } from "hono";
59
- import { join as join10, basename } from "path";
60
- import { existsSync as existsSync10, readFileSync as readFileSync5 } from "fs";
59
+ import { join as join9, basename } from "path";
60
+ import { existsSync as existsSync9, readFileSync as readFileSync5 } from "fs";
61
61
 
62
62
  // ../core/dist/generation.js
63
- import { readFileSync as readFileSync2, existsSync as existsSync7 } from "fs";
64
- import { join as join7 } from "path";
63
+ import { readFileSync as readFileSync2, existsSync as existsSync6 } from "fs";
64
+ import { join as join6 } from "path";
65
65
  var {spawn: spawn3 } = globalThis.Bun;
66
66
  import simpleGit3 from "simple-git";
67
67
 
@@ -544,65 +544,19 @@ class PersistenceService {
544
544
 
545
545
  // ../core/dist/ai-process.js
546
546
  var {spawn } = globalThis.Bun;
547
- import { writeFileSync as writeFileSync2, existsSync as existsSync4, mkdirSync as mkdirSync3 } from "fs";
548
- import { join as join4 } from "path";
549
- import { tmpdir } from "os";
550
547
  var CLAUDE_BIN = "/opt/homebrew/bin/claude";
551
- function getPlaywrightMcpConfigPath() {
552
- const configDir = join4(tmpdir(), "stashes-mcp");
553
- const configPath = join4(configDir, "playwright.json");
554
- if (!existsSync4(configPath)) {
555
- mkdirSync3(configDir, { recursive: true });
556
- writeFileSync2(configPath, JSON.stringify({
557
- mcpServers: {
558
- playwright: { command: "npx", args: ["@playwright/mcp@latest"] }
559
- }
560
- }), "utf-8");
561
- }
562
- return configPath;
563
- }
564
- var OVERHEAD_TOOLS = [
565
- "Agent",
566
- "TodoWrite",
567
- "TaskCreate",
568
- "TaskUpdate",
569
- "TaskList",
570
- "TaskGet",
571
- "Skill",
572
- "ToolSearch",
573
- "EnterPlanMode",
574
- "ExitPlanMode",
575
- "WebSearch",
576
- "WebFetch",
577
- "NotebookEdit",
578
- "mcp__UseAI__*",
579
- "mcp__stashes__*",
580
- "mcp__plugin_drills*",
581
- "mcp__plugin_coverit*"
582
- ];
583
548
  var processes = new Map;
584
549
  function startAiProcess(idOrOpts, prompt, cwd, resumeSessionId, model) {
585
550
  const opts = typeof idOrOpts === "string" ? { id: idOrOpts, prompt, cwd, resumeSessionId, model } : idOrOpts;
586
- const restricted = opts.tools !== undefined;
587
551
  killAiProcess(opts.id);
588
552
  logger.info("claude", `spawning process: ${opts.id}`, {
589
553
  cwd: opts.cwd,
590
554
  promptLength: opts.prompt.length,
591
555
  promptPreview: opts.prompt.substring(0, 100),
592
556
  resumeSessionId: opts.resumeSessionId,
593
- model: opts.model,
594
- restricted,
595
- tools: restricted ? opts.tools.join(",") || "none" : "all"
557
+ model: opts.model
596
558
  });
597
559
  const cmd = [CLAUDE_BIN, "-p", opts.prompt, "--output-format=stream-json", "--verbose", "--dangerously-skip-permissions"];
598
- if (restricted) {
599
- cmd.push("--tools", opts.tools.length > 0 ? opts.tools.join(",") : '""');
600
- cmd.push("--disallowedTools", OVERHEAD_TOOLS.join(","));
601
- cmd.push("--strict-mcp-config");
602
- if (opts.mcpConfigPath) {
603
- cmd.push("--mcp-config", opts.mcpConfigPath);
604
- }
605
- }
606
560
  if (opts.resumeSessionId) {
607
561
  cmd.push("--resume", opts.resumeSessionId);
608
562
  }
@@ -733,35 +687,47 @@ async function* parseClaudeStream(proc) {
733
687
  }
734
688
 
735
689
  // ../core/dist/smart-screenshot.js
736
- import { join as join6 } from "path";
737
- import { mkdirSync as mkdirSync5, existsSync as existsSync6 } from "fs";
690
+ import { join as join5 } from "path";
691
+ import { mkdirSync as mkdirSync4, existsSync as existsSync5 } from "fs";
738
692
  import simpleGit2 from "simple-git";
739
693
 
740
694
  // ../core/dist/screenshot.js
741
695
  var {spawn: spawn2 } = globalThis.Bun;
742
- import { join as join5 } from "path";
743
- import { mkdirSync as mkdirSync4, existsSync as existsSync5 } from "fs";
696
+ import { join as join4 } from "path";
697
+ import { mkdirSync as mkdirSync3, existsSync as existsSync4 } from "fs";
744
698
  var SCREENSHOTS_DIR = ".stashes/screenshots";
745
- async function captureScreenshot(port, projectPath, stashId) {
746
- const screenshotsDir = join5(projectPath, SCREENSHOTS_DIR);
747
- if (!existsSync5(screenshotsDir)) {
748
- mkdirSync4(screenshotsDir, { recursive: true });
749
- }
750
- const filename = `${stashId}.png`;
751
- const outputPath = join5(screenshotsDir, filename);
699
+ async function captureScreenshot(portOrOpts, projectPath, stashId) {
700
+ const opts = typeof portOrOpts === "number" ? { port: portOrOpts, projectPath, stashId } : portOrOpts;
701
+ const screenshotsDir = join4(opts.projectPath, SCREENSHOTS_DIR);
702
+ if (!existsSync4(screenshotsDir)) {
703
+ mkdirSync3(screenshotsDir, { recursive: true });
704
+ }
705
+ const filename = `${opts.stashId}.png`;
706
+ const outputPath = join4(screenshotsDir, filename);
707
+ const url = `http://localhost:${opts.port}${opts.route || "/"}`;
708
+ const scrollCode = opts.scrollToSelector ? `
709
+ try {
710
+ const el = await page.waitForSelector('${opts.scrollToSelector.replace(/'/g, "\\'")}', { timeout: 5000 });
711
+ if (el) {
712
+ await el.scrollIntoViewIfNeeded();
713
+ await page.waitForTimeout(500);
714
+ }
715
+ } catch(e) { /* selector not found, capture viewport */ }
716
+ ` : "";
752
717
  const playwrightScript = `
753
718
  const { chromium } = require('playwright');
754
719
  (async () => {
755
720
  const browser = await chromium.launch({ headless: true });
756
721
  const page = await browser.newPage({ viewport: { width: 1280, height: 720 } });
757
722
  try {
758
- await page.goto('http://localhost:${port}', { waitUntil: 'networkidle', timeout: 20000 });
723
+ await page.goto('${url}', { waitUntil: 'networkidle', timeout: 20000 });
759
724
  await page.waitForTimeout(2000);
760
725
  } catch(e) {
761
- await page.goto('http://localhost:${port}', { waitUntil: 'domcontentloaded', timeout: 10000 });
726
+ await page.goto('${url}', { waitUntil: 'domcontentloaded', timeout: 10000 });
762
727
  await page.waitForTimeout(3000);
763
728
  }
764
- await page.screenshot({ path: '${outputPath.replace(/'/g, "\\'")}', type: 'png' });
729
+ ${scrollCode}
730
+ await page.screenshot({ path: '${outputPath.replace(/'/g, "\\'")}', type: 'png'${opts.fullPage ? ", fullPage: true" : ""} });
765
731
  await browser.close();
766
732
  })();
767
733
  `;
@@ -797,62 +763,56 @@ ${diffStat}
797
763
  ## Partial diff (truncated):
798
764
  ${truncatedDiff}`;
799
765
  } catch (err) {
800
- logger.warn("smart-screenshot", `git diff failed, falling back`, {
766
+ logger.warn("smart-screenshot", `git diff failed`, {
801
767
  error: err instanceof Error ? err.message : String(err)
802
768
  });
803
769
  return "";
804
770
  }
805
771
  }
806
772
  function buildScreenshotPrompt(port, diff, screenshotDir, stashId) {
807
- const outputPath = join6(screenshotDir, `${stashId}.png`);
773
+ const outputPath = join5(screenshotDir, `${stashId}.png`);
808
774
  return [
809
- "You are a screenshot assistant. Take a screenshot of a running web app.",
810
- "Be fast \u2014 you have a strict time limit.",
775
+ "## CRITICAL: You are an automated screenshot subprocess. Follow these rules exactly.",
811
776
  "",
812
- `The app is running at: http://localhost:${port}`,
777
+ "FORBIDDEN \u2014 do NOT call any of these tools:",
778
+ "- ToolSearch, Skill, Agent, TodoWrite, TaskCreate, TaskUpdate, TaskList",
779
+ "- mcp__UseAI__useai_start, mcp__UseAI__useai_end, mcp__UseAI__useai_heartbeat",
780
+ "- mcp__stashes__*, mcp__plugin_drills__*, mcp__plugin_coverit__*",
781
+ "- EnterPlanMode, ExitPlanMode, WebSearch, WebFetch, LSP",
782
+ "- Read, Write, Edit, Glob, Grep (you do NOT need to read code)",
813
783
  "",
814
- "## Git diff of changes (tells you what was modified):",
815
- "```",
816
- diff,
817
- "```",
784
+ "YOUR ONLY JOB: navigate to the app and take a screenshot using Playwright.",
818
785
  "",
819
- "## Instructions",
820
- "Use mcp__playwright__browser_run_code to navigate AND screenshot in a single call.",
821
- "From the diff, determine the route/section that shows the changes.",
786
+ `## App URL: http://localhost:${port}`,
822
787
  "",
823
- "**Call this tool:**",
824
- "```",
825
- "mcp__playwright__browser_run_code",
788
+ "## Git diff (shows what changed \u2014 use this to decide where to navigate):",
826
789
  "```",
827
- "",
828
- "**With this code parameter** (adjust the URL path and scroll if needed):",
829
- "```javascript",
830
- `async (page) => {`,
831
- ` await page.setViewportSize({ width: 1280, height: 720 });`,
832
- ` await page.goto('http://localhost:${port}', { waitUntil: 'networkidle', timeout: 15000 });`,
833
- ` // If the changed component is further down, scroll to it:`,
834
- ` // await page.evaluate(() => window.scrollTo(0, 500));`,
835
- ` // await page.waitForTimeout(500);`,
836
- ` await page.waitForTimeout(2000);`,
837
- ` await page.screenshot({ path: '${outputPath.replace(/'/g, "\\'")}', type: 'png' });`,
838
- ` return 'saved';`,
839
- `}`,
790
+ diff,
840
791
  "```",
841
792
  "",
842
- "If the diff shows changes to a component that requires scrolling or navigation,",
843
- "adjust the code: change the URL path, add scrollTo, or click a tab first.",
793
+ "## Steps (do these in order, nothing else):",
794
+ `1. Navigate: call mcp__plugin_playwright_playwright__browser_navigate with url "http://localhost:${port}"`,
795
+ "2. Wait 3 seconds for the page to render",
796
+ "3. If the diff shows changes below the fold, scroll down using mcp__plugin_playwright_playwright__browser_evaluate",
797
+ `4. Take screenshot: call mcp__plugin_playwright_playwright__browser_take_screenshot with type "png"`,
798
+ ` The screenshot will be saved automatically.`,
799
+ "5. Output ONLY this JSON (replace the screenshot path with the actual path returned):",
844
800
  "",
845
- `After the tool call succeeds, respond with ONLY this JSON:`,
801
+ "```json",
846
802
  "{",
847
803
  ' "screenshots": [',
848
804
  " {",
849
805
  ` "path": "${outputPath}",`,
850
- ' "label": "Short description of what is shown",',
851
- ' "route": "/the-url-path",',
806
+ ' "label": "Description of what is shown",',
807
+ ' "route": "/",',
852
808
  ' "isPrimary": true',
853
809
  " }",
854
810
  " ]",
855
- "}"
811
+ "}",
812
+ "```",
813
+ "",
814
+ "REMEMBER: Do NOT call ToolSearch, Skill, UseAI, Read, or any tool not listed above.",
815
+ "You have a strict time limit. Just navigate, screenshot, output JSON, done."
856
816
  ].join(`
857
817
  `);
858
818
  }
@@ -887,9 +847,9 @@ async function fallbackScreenshot(port, projectPath, stashId) {
887
847
  }
888
848
  async function captureSmartScreenshots(opts) {
889
849
  const { projectPath, stashId, stashBranch, parentBranch, worktreePath, port, model = "sonnet", timeout = DEFAULT_TIMEOUT } = opts;
890
- const screenshotDir = join6(projectPath, SCREENSHOTS_DIR2);
891
- if (!existsSync6(screenshotDir)) {
892
- mkdirSync5(screenshotDir, { recursive: true });
850
+ const screenshotDir = join5(projectPath, SCREENSHOTS_DIR2);
851
+ if (!existsSync5(screenshotDir)) {
852
+ mkdirSync4(screenshotDir, { recursive: true });
893
853
  }
894
854
  const diff = await getStashDiff(worktreePath, parentBranch);
895
855
  if (!diff) {
@@ -903,9 +863,7 @@ async function captureSmartScreenshots(opts) {
903
863
  id: processId,
904
864
  prompt,
905
865
  cwd: worktreePath,
906
- model: modelFlag,
907
- tools: [],
908
- mcpConfigPath: getPlaywrightMcpConfigPath()
866
+ model: modelFlag
909
867
  });
910
868
  let textOutput = "";
911
869
  let timedOut = false;
@@ -931,6 +889,15 @@ async function captureSmartScreenshots(opts) {
931
889
  }
932
890
  const result = parseAiResult(textOutput);
933
891
  if (!result || !result.screenshots || result.screenshots.length === 0) {
892
+ const expectedPath = join5(screenshotDir, `${stashId}.png`);
893
+ if (existsSync5(expectedPath)) {
894
+ logger.info("smart-screenshot", `AI saved screenshot for ${stashId} (no JSON response, but file exists)`);
895
+ const url = `/api/screenshots/${stashId}.png`;
896
+ return {
897
+ primary: url,
898
+ screenshots: [{ url, label: "AI screenshot", route: "/", isPrimary: true }]
899
+ };
900
+ }
934
901
  logger.info("smart-screenshot", `AI returned no screenshots for ${stashId} (timedOut=${timedOut}), falling back`);
935
902
  return fallbackScreenshot(port, projectPath, stashId);
936
903
  }
@@ -938,18 +905,12 @@ async function captureSmartScreenshots(opts) {
938
905
  let primaryUrl = "";
939
906
  for (const shot of result.screenshots) {
940
907
  const filename = shot.path.split("/").pop() || "";
941
- if (!existsSync6(shot.path)) {
908
+ if (!existsSync5(shot.path)) {
942
909
  logger.warn("smart-screenshot", `Screenshot file not found: ${shot.path}`);
943
910
  continue;
944
911
  }
945
912
  const url = `/api/screenshots/${filename}`;
946
- const screenshot = {
947
- url,
948
- label: shot.label,
949
- route: shot.route,
950
- isPrimary: shot.isPrimary
951
- };
952
- screenshots.push(screenshot);
913
+ screenshots.push({ url, label: shot.label, route: shot.route, isPrimary: shot.isPrimary });
953
914
  if (shot.isPrimary)
954
915
  primaryUrl = url;
955
916
  }
@@ -1032,8 +993,8 @@ async function generate(opts) {
1032
993
  const selectedDirectives = directives.slice(0, count);
1033
994
  let sourceCode = "";
1034
995
  if (component?.filePath) {
1035
- const sourceFile = join7(projectPath, component.filePath);
1036
- if (existsSync7(sourceFile)) {
996
+ const sourceFile = join6(projectPath, component.filePath);
997
+ if (existsSync6(sourceFile)) {
1037
998
  sourceCode = readFileSync2(sourceFile, "utf-8");
1038
999
  }
1039
1000
  }
@@ -1403,8 +1364,8 @@ async function cleanup(projectPath) {
1403
1364
  logger.info("manage", "cleanup complete");
1404
1365
  }
1405
1366
  // ../server/dist/services/stash-service.js
1406
- import { readFileSync as readFileSync3, existsSync as existsSync8 } from "fs";
1407
- import { join as join8 } from "path";
1367
+ import { readFileSync as readFileSync3, existsSync as existsSync7 } from "fs";
1368
+ import { join as join7 } from "path";
1408
1369
 
1409
1370
  // ../server/dist/services/app-proxy.js
1410
1371
  import { spawn as spawn5 } from "child_process";
@@ -1940,8 +1901,7 @@ class StashService {
1940
1901
  id: "resolve-component",
1941
1902
  prompt,
1942
1903
  cwd: this.projectPath,
1943
- model: "claude-haiku-4-5-20251001",
1944
- tools: ["Read", "Grep", "Glob", "Bash"]
1904
+ model: "claude-haiku-4-5-20251001"
1945
1905
  });
1946
1906
  let resolvedPath = "";
1947
1907
  try {
@@ -2003,8 +1963,8 @@ class StashService {
2003
1963
  let sourceCode = "";
2004
1964
  const filePath = component?.filePath || "";
2005
1965
  if (filePath && filePath !== "auto-detect") {
2006
- const sourceFile = join8(this.projectPath, filePath);
2007
- if (existsSync8(sourceFile)) {
1966
+ const sourceFile = join7(this.projectPath, filePath);
1967
+ if (existsSync7(sourceFile)) {
2008
1968
  sourceCode = readFileSync3(sourceFile, "utf-8");
2009
1969
  }
2010
1970
  }
@@ -2356,8 +2316,8 @@ ${refDescriptions.join(`
2356
2316
  }
2357
2317
 
2358
2318
  // ../server/dist/services/activity-store.js
2359
- import { appendFileSync as appendFileSync2, readFileSync as readFileSync4, existsSync as existsSync9, mkdirSync as mkdirSync6, rmSync as rmSync3 } from "fs";
2360
- import { join as join9, dirname as dirname2 } from "path";
2319
+ import { appendFileSync as appendFileSync2, readFileSync as readFileSync4, existsSync as existsSync8, mkdirSync as mkdirSync5, rmSync as rmSync3 } from "fs";
2320
+ import { join as join8, dirname as dirname2 } from "path";
2361
2321
 
2362
2322
  class ActivityStore {
2363
2323
  cache = new Map;
@@ -2366,7 +2326,7 @@ class ActivityStore {
2366
2326
  this.projectPath = projectPath;
2367
2327
  }
2368
2328
  jsonlPath(stashId) {
2369
- return join9(this.projectPath, ".stashes", "activity", `${stashId}.jsonl`);
2329
+ return join8(this.projectPath, ".stashes", "activity", `${stashId}.jsonl`);
2370
2330
  }
2371
2331
  append(event) {
2372
2332
  const existing = this.cache.get(event.stashId) ?? [];
@@ -2374,8 +2334,8 @@ class ActivityStore {
2374
2334
  this.cache.set(event.stashId, existing);
2375
2335
  const filePath = this.jsonlPath(event.stashId);
2376
2336
  const dir = dirname2(filePath);
2377
- if (!existsSync9(dir))
2378
- mkdirSync6(dir, { recursive: true });
2337
+ if (!existsSync8(dir))
2338
+ mkdirSync5(dir, { recursive: true });
2379
2339
  appendFileSync2(filePath, JSON.stringify(event) + `
2380
2340
  `, "utf-8");
2381
2341
  }
@@ -2384,7 +2344,7 @@ class ActivityStore {
2384
2344
  if (cached && cached.length > 0)
2385
2345
  return cached;
2386
2346
  const filePath = this.jsonlPath(stashId);
2387
- if (!existsSync9(filePath))
2347
+ if (!existsSync8(filePath))
2388
2348
  return [];
2389
2349
  const lines = readFileSync4(filePath, "utf-8").trim().split(`
2390
2350
  `).filter(Boolean);
@@ -2410,14 +2370,14 @@ class ActivityStore {
2410
2370
  clear(stashId) {
2411
2371
  this.cache.delete(stashId);
2412
2372
  const filePath = this.jsonlPath(stashId);
2413
- if (existsSync9(filePath)) {
2373
+ if (existsSync8(filePath)) {
2414
2374
  rmSync3(filePath);
2415
2375
  }
2416
2376
  }
2417
2377
  has(stashId) {
2418
2378
  if (this.cache.has(stashId) && (this.cache.get(stashId)?.length ?? 0) > 0)
2419
2379
  return true;
2420
- return existsSync9(this.jsonlPath(stashId));
2380
+ return existsSync8(this.jsonlPath(stashId));
2421
2381
  }
2422
2382
  }
2423
2383
 
@@ -2659,8 +2619,8 @@ app.get("/dev-server-status", async (c) => {
2659
2619
  });
2660
2620
  app.get("/screenshots/:filename", (c) => {
2661
2621
  const filename = c.req.param("filename");
2662
- const filePath = join10(serverState.projectPath, ".stashes", "screenshots", filename);
2663
- if (!existsSync10(filePath))
2622
+ const filePath = join9(serverState.projectPath, ".stashes", "screenshots", filename);
2623
+ if (!existsSync9(filePath))
2664
2624
  return c.json({ error: "Not found" }, 404);
2665
2625
  const content = readFileSync5(filePath);
2666
2626
  return new Response(content, {
@@ -2712,12 +2672,12 @@ app2.route("/api", apiRoutes);
2712
2672
  app2.get("/*", async (c) => {
2713
2673
  const path = c.req.path;
2714
2674
  const selfDir = dirname3(fileURLToPath(import.meta.url));
2715
- const bundledWebDir = join11(selfDir, "web");
2716
- const monorepoWebDir = join11(selfDir, "../../web/dist");
2717
- const webDistDir = existsSync11(join11(bundledWebDir, "index.html")) ? bundledWebDir : monorepoWebDir;
2675
+ const bundledWebDir = join10(selfDir, "web");
2676
+ const monorepoWebDir = join10(selfDir, "../../web/dist");
2677
+ const webDistDir = existsSync10(join10(bundledWebDir, "index.html")) ? bundledWebDir : monorepoWebDir;
2718
2678
  const requestPath = path === "/" ? "/index.html" : path;
2719
- const filePath = join11(webDistDir, requestPath);
2720
- if (existsSync11(filePath) && !filePath.includes("..")) {
2679
+ const filePath = join10(webDistDir, requestPath);
2680
+ if (existsSync10(filePath) && !filePath.includes("..")) {
2721
2681
  const content = readFileSync6(filePath);
2722
2682
  const ext = filePath.split(".").pop() || "";
2723
2683
  const contentTypes = {
@@ -2736,8 +2696,8 @@ app2.get("/*", async (c) => {
2736
2696
  headers: { "content-type": contentTypes[ext] || "application/octet-stream" }
2737
2697
  });
2738
2698
  }
2739
- const indexPath = join11(webDistDir, "index.html");
2740
- if (existsSync11(indexPath)) {
2699
+ const indexPath = join10(webDistDir, "index.html");
2700
+ if (existsSync10(indexPath)) {
2741
2701
  const html = readFileSync6(indexPath, "utf-8");
2742
2702
  return new Response(html, {
2743
2703
  headers: { "content-type": "text/html; charset=utf-8" }
@@ -2798,11 +2758,11 @@ async function startServer(projectPath, userDevPort, requestedPort = STASHES_POR
2798
2758
  }
2799
2759
 
2800
2760
  // ../server/dist/services/detector.js
2801
- import { existsSync as existsSync12, readFileSync as readFileSync7 } from "fs";
2802
- import { join as join12 } from "path";
2761
+ import { existsSync as existsSync11, readFileSync as readFileSync7 } from "fs";
2762
+ import { join as join11 } from "path";
2803
2763
  function detectFramework(projectPath) {
2804
- const packageJsonPath = join12(projectPath, "package.json");
2805
- if (!existsSync12(packageJsonPath)) {
2764
+ const packageJsonPath = join11(projectPath, "package.json");
2765
+ if (!existsSync11(packageJsonPath)) {
2806
2766
  return {
2807
2767
  framework: "unknown",
2808
2768
  devCommand: "npm run dev",
@@ -2864,7 +2824,7 @@ function getDevCommand(packageJson, fallback) {
2864
2824
  }
2865
2825
  function findConfig(projectPath, candidates) {
2866
2826
  for (const candidate of candidates) {
2867
- if (existsSync12(join12(projectPath, candidate))) {
2827
+ if (existsSync11(join11(projectPath, candidate))) {
2868
2828
  return candidate;
2869
2829
  }
2870
2830
  }
@@ -3056,8 +3016,8 @@ Cleaning up all stashes and worktrees...`);
3056
3016
  }
3057
3017
 
3058
3018
  // src/commands/setup.ts
3059
- import { existsSync as existsSync13, readFileSync as readFileSync8, writeFileSync as writeFileSync3, mkdirSync as mkdirSync7 } from "fs";
3060
- import { dirname as dirname4, join as join13 } from "path";
3019
+ import { existsSync as existsSync12, readFileSync as readFileSync8, writeFileSync as writeFileSync2, mkdirSync as mkdirSync6 } from "fs";
3020
+ import { dirname as dirname4, join as join12 } from "path";
3061
3021
  import { homedir } from "os";
3062
3022
  import * as p from "@clack/prompts";
3063
3023
  import pc from "picocolors";
@@ -3076,60 +3036,60 @@ var MCP_ENTRY_ZED = {
3076
3036
  };
3077
3037
  function buildToolDefinitions() {
3078
3038
  const home = homedir();
3079
- const appSupport = join13(home, "Library", "Application Support");
3039
+ const appSupport = join12(home, "Library", "Application Support");
3080
3040
  return [
3081
3041
  {
3082
3042
  id: "claude-code",
3083
3043
  name: "Claude Code",
3084
- configPath: join13(home, ".claude.json"),
3044
+ configPath: join12(home, ".claude.json"),
3085
3045
  serversKey: "mcpServers",
3086
3046
  format: "standard",
3087
- detect: () => existsSync13(join13(home, ".claude.json")) || existsSync13(join13(home, ".claude"))
3047
+ detect: () => existsSync12(join12(home, ".claude.json")) || existsSync12(join12(home, ".claude"))
3088
3048
  },
3089
3049
  {
3090
3050
  id: "claude-desktop",
3091
3051
  name: "Claude Desktop",
3092
- configPath: join13(appSupport, "Claude", "claude_desktop_config.json"),
3052
+ configPath: join12(appSupport, "Claude", "claude_desktop_config.json"),
3093
3053
  serversKey: "mcpServers",
3094
3054
  format: "standard",
3095
- detect: () => existsSync13(join13(appSupport, "Claude")) || existsSync13("/Applications/Claude.app")
3055
+ detect: () => existsSync12(join12(appSupport, "Claude")) || existsSync12("/Applications/Claude.app")
3096
3056
  },
3097
3057
  {
3098
3058
  id: "vscode",
3099
3059
  name: "VS Code",
3100
- configPath: join13(appSupport, "Code", "User", "mcp.json"),
3060
+ configPath: join12(appSupport, "Code", "User", "mcp.json"),
3101
3061
  serversKey: "servers",
3102
3062
  format: "standard",
3103
- detect: () => existsSync13(join13(appSupport, "Code", "User"))
3063
+ detect: () => existsSync12(join12(appSupport, "Code", "User"))
3104
3064
  },
3105
3065
  {
3106
3066
  id: "cursor",
3107
3067
  name: "Cursor",
3108
- configPath: join13(home, ".cursor", "mcp.json"),
3068
+ configPath: join12(home, ".cursor", "mcp.json"),
3109
3069
  serversKey: "mcpServers",
3110
3070
  format: "standard",
3111
- detect: () => existsSync13(join13(home, ".cursor"))
3071
+ detect: () => existsSync12(join12(home, ".cursor"))
3112
3072
  },
3113
3073
  {
3114
3074
  id: "windsurf",
3115
3075
  name: "Windsurf",
3116
- configPath: join13(home, ".codeium", "windsurf", "mcp_config.json"),
3076
+ configPath: join12(home, ".codeium", "windsurf", "mcp_config.json"),
3117
3077
  serversKey: "mcpServers",
3118
3078
  format: "standard",
3119
- detect: () => existsSync13(join13(home, ".codeium", "windsurf"))
3079
+ detect: () => existsSync12(join12(home, ".codeium", "windsurf"))
3120
3080
  },
3121
3081
  {
3122
3082
  id: "zed",
3123
3083
  name: "Zed",
3124
- configPath: join13(appSupport, "Zed", "settings.json"),
3084
+ configPath: join12(appSupport, "Zed", "settings.json"),
3125
3085
  serversKey: "context_servers",
3126
3086
  format: "zed",
3127
- detect: () => existsSync13(join13(appSupport, "Zed"))
3087
+ detect: () => existsSync12(join12(appSupport, "Zed"))
3128
3088
  }
3129
3089
  ];
3130
3090
  }
3131
3091
  function readJsonFile(path) {
3132
- if (!existsSync13(path))
3092
+ if (!existsSync12(path))
3133
3093
  return {};
3134
3094
  try {
3135
3095
  const raw = readFileSync8(path, "utf-8").trim();
@@ -3141,8 +3101,8 @@ function readJsonFile(path) {
3141
3101
  }
3142
3102
  }
3143
3103
  function writeJsonFile(path, data) {
3144
- mkdirSync7(dirname4(path), { recursive: true });
3145
- writeFileSync3(path, JSON.stringify(data, null, 2) + `
3104
+ mkdirSync6(dirname4(path), { recursive: true });
3105
+ writeFileSync2(path, JSON.stringify(data, null, 2) + `
3146
3106
  `);
3147
3107
  }
3148
3108
  function isConfigured(tool) {
@@ -3280,15 +3240,15 @@ async function setupCommand(options) {
3280
3240
 
3281
3241
  // src/commands/update.ts
3282
3242
  import { execFileSync, execSync } from "child_process";
3283
- import { writeFileSync as writeFileSync4, unlinkSync, chmodSync, readFileSync as readFileSync9 } from "fs";
3284
- import { tmpdir as tmpdir2 } from "os";
3285
- import { join as join14, dirname as dirname5 } from "path";
3243
+ import { writeFileSync as writeFileSync3, unlinkSync, chmodSync, readFileSync as readFileSync9 } from "fs";
3244
+ import { tmpdir } from "os";
3245
+ import { join as join13, dirname as dirname5 } from "path";
3286
3246
  import { fileURLToPath as fileURLToPath2 } from "url";
3287
3247
  import * as p2 from "@clack/prompts";
3288
3248
  import pc2 from "picocolors";
3289
3249
  function getCurrentVersion() {
3290
3250
  const selfDir = dirname5(fileURLToPath2(import.meta.url));
3291
- const pkgPath = join14(selfDir, "..", "package.json");
3251
+ const pkgPath = join13(selfDir, "..", "package.json");
3292
3252
  return JSON.parse(readFileSync9(pkgPath, "utf-8")).version;
3293
3253
  }
3294
3254
  function fetchLatestVersion() {
@@ -3365,8 +3325,8 @@ async function updateCommand() {
3365
3325
  }
3366
3326
  s.stop(`Removed from ${configuredTools.length} tool${configuredTools.length === 1 ? "" : "s"}`);
3367
3327
  }
3368
- const scriptPath = join14(tmpdir2(), `stashes-update-${Date.now()}.sh`);
3369
- writeFileSync4(scriptPath, buildUpdateScript(), "utf-8");
3328
+ const scriptPath = join13(tmpdir(), `stashes-update-${Date.now()}.sh`);
3329
+ writeFileSync3(scriptPath, buildUpdateScript(), "utf-8");
3370
3330
  chmodSync(scriptPath, 493);
3371
3331
  try {
3372
3332
  execFileSync("bash", [scriptPath], { stdio: "inherit" });
@@ -3384,7 +3344,7 @@ Update failed. Try manually:`);
3384
3344
 
3385
3345
  // src/index.ts
3386
3346
  var selfDir = dirname6(fileURLToPath3(import.meta.url));
3387
- var pkgPath = join15(selfDir, "..", "package.json");
3347
+ var pkgPath = join14(selfDir, "..", "package.json");
3388
3348
  var version = JSON.parse(readFileSync10(pkgPath, "utf-8")).version;
3389
3349
  var program = new Command;
3390
3350
  program.name("stashes").description("Generate AI-powered UI design explorations in your project").version(version, "-v, --version");