claw-design 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +72 -0
  3. package/dist/cli/commands/start.d.ts +7 -0
  4. package/dist/cli/commands/start.d.ts.map +1 -0
  5. package/dist/cli/commands/start.js +176 -0
  6. package/dist/cli/commands/start.js.map +1 -0
  7. package/dist/cli/index.d.ts +3 -0
  8. package/dist/cli/index.d.ts.map +1 -0
  9. package/dist/cli/index.js +20 -0
  10. package/dist/cli/index.js.map +1 -0
  11. package/dist/cli/utils/claude.d.ts +21 -0
  12. package/dist/cli/utils/claude.d.ts.map +1 -0
  13. package/dist/cli/utils/claude.js +42 -0
  14. package/dist/cli/utils/claude.js.map +1 -0
  15. package/dist/cli/utils/dev-server.d.ts +14 -0
  16. package/dist/cli/utils/dev-server.d.ts.map +1 -0
  17. package/dist/cli/utils/dev-server.js +57 -0
  18. package/dist/cli/utils/dev-server.js.map +1 -0
  19. package/dist/cli/utils/electron.d.ts +7 -0
  20. package/dist/cli/utils/electron.d.ts.map +1 -0
  21. package/dist/cli/utils/electron.js +36 -0
  22. package/dist/cli/utils/electron.js.map +1 -0
  23. package/dist/cli/utils/output.d.ts +6 -0
  24. package/dist/cli/utils/output.d.ts.map +1 -0
  25. package/dist/cli/utils/output.js +21 -0
  26. package/dist/cli/utils/output.js.map +1 -0
  27. package/dist/cli/utils/port-detect.d.ts +30 -0
  28. package/dist/cli/utils/port-detect.d.ts.map +1 -0
  29. package/dist/cli/utils/port-detect.js +95 -0
  30. package/dist/cli/utils/port-detect.js.map +1 -0
  31. package/dist/cli/utils/preflight.d.ts +20 -0
  32. package/dist/cli/utils/preflight.d.ts.map +1 -0
  33. package/dist/cli/utils/preflight.js +33 -0
  34. package/dist/cli/utils/preflight.js.map +1 -0
  35. package/dist/cli/utils/process.d.ts +23 -0
  36. package/dist/cli/utils/process.d.ts.map +1 -0
  37. package/dist/cli/utils/process.js +57 -0
  38. package/dist/cli/utils/process.js.map +1 -0
  39. package/out/main/index.js +1123 -0
  40. package/out/preload/overlay.cjs +56 -0
  41. package/out/preload/sidebar.cjs +29 -0
  42. package/out/renderer/assets/overlay-Bsx1u_qg.css +449 -0
  43. package/out/renderer/assets/overlay-DZl3I3jq.js +689 -0
  44. package/out/renderer/assets/sidebar-Bt34gvPU.js +563 -0
  45. package/out/renderer/assets/sidebar-BxEPS84k.css +515 -0
  46. package/out/renderer/assets/toast-CLlgwMU_.js +110 -0
  47. package/out/renderer/overlay.html +131 -0
  48. package/out/renderer/sidebar.html +64 -0
  49. package/package.json +67 -0
  50. package/resources/icon.icns +0 -0
  51. package/resources/icon.png +0 -0
  52. package/scripts/postinstall.cjs +56 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 prodoxx
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,72 @@
1
+ # Claw Design
2
+
3
+ Point at your running website. Describe what to change. Watch Claude edit the code live.
4
+
5
+ [![npm version](https://img.shields.io/npm/v/claw-design)](https://www.npmjs.com/package/claw-design)
6
+ [![license](https://img.shields.io/npm/l/claw-design)](./LICENSE)
7
+ [![node](https://img.shields.io/node/v/claw-design)](https://nodejs.org)
8
+
9
+ ![Claw Design demo](./docs/demo.gif)
10
+
11
+ ## Why Claw Design?
12
+
13
+ Web developers constantly context-switch between browser and editor. Claw Design eliminates this -- select any part of your running site, describe the change in plain English, and Claude Code edits the source files directly. Changes appear instantly via hot module reload.
14
+
15
+ ## Quick Start
16
+
17
+ ```bash
18
+ npm install -g claw-design
19
+ cd your-project
20
+ clawdesign start
21
+ ```
22
+
23
+ ## Requirements
24
+
25
+ - **Node.js >= 20** (LTS recommended)
26
+ - **[Claude Code CLI](https://claude.ai/download)** installed and authenticated
27
+ - A web project with a dev server
28
+
29
+ ## How It Works
30
+
31
+ 1. **Detects your dev server** from `package.json` scripts and starts it automatically
32
+ 2. **Opens a browser window** showing your running site with a selection overlay
33
+ 3. **You draw a selection** over any area and describe what you want to change
34
+ 4. **Claude Code edits your source files** based on the visual context and instruction -- HMR shows the result instantly
35
+
36
+ ## CLI Options
37
+
38
+ | Flag | Description |
39
+ |------|-------------|
40
+ | `--cmd <command>` | Override dev server command (e.g. `--cmd "python -m http.server 8000"`) |
41
+ | `--port <number>` | Specify dev server port instead of auto-detecting |
42
+ | `--verbose` | Show dev server output in the terminal |
43
+ | `--version` | Show version number |
44
+
45
+ ## Viewport Switching
46
+
47
+ Switch between viewport presets using the toolbar buttons:
48
+
49
+ - **Desktop** (1280x800)
50
+ - **Tablet** (768x1024)
51
+ - **Mobile** (375x812)
52
+
53
+ ## Framework Support
54
+
55
+ Works with anything that serves on localhost:
56
+
57
+ - React
58
+ - Vue
59
+ - Svelte
60
+ - Next.js
61
+ - Nuxt
62
+ - Angular
63
+ - Astro
64
+ - Plain HTML
65
+
66
+ ## Contributing
67
+
68
+ See [CONTRIBUTING.md](./CONTRIBUTING.md) for development setup and guidelines.
69
+
70
+ ## License
71
+
72
+ MIT -- see [LICENSE](./LICENSE) for details.
@@ -0,0 +1,7 @@
1
+ export interface StartOptions {
2
+ cmd?: string;
3
+ port?: string;
4
+ verbose?: boolean;
5
+ }
6
+ export declare function startCommand(options: StartOptions): Promise<void>;
7
+ //# sourceMappingURL=start.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"start.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/start.ts"],"names":[],"mappings":"AAaA,MAAM,WAAW,YAAY;IAC3B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,wBAAsB,YAAY,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAkNvE"}
@@ -0,0 +1,176 @@
1
+ import { detectDevServerScript, detectPackageManager, spawnDevServer, DetectionError } from '../utils/dev-server.js';
2
+ import { extractPortFromOutput, waitForPort, getProcessOnPort } from '../utils/port-detect.js';
3
+ import { isClaudeInstalled, getClaudeAuthStatus } from '../utils/claude.js';
4
+ import { checkNodeVersion, checkElectronBinary } from '../utils/preflight.js';
5
+ import { spawnElectron } from '../utils/electron.js';
6
+ import { registerShutdownHandlers } from '../utils/process.js';
7
+ import { createSpinner, printReady, printError } from '../utils/output.js';
8
+ import pc from 'picocolors';
9
+ import path from 'node:path';
10
+ import { readFileSync } from 'node:fs';
11
+ import { createInterface } from 'node:readline';
12
+ export async function startCommand(options) {
13
+ const verbose = options.verbose ?? false;
14
+ // Pre-flight checks (D-14): fast checks before any async work
15
+ const nodeCheck = checkNodeVersion();
16
+ if (!nodeCheck.ok) {
17
+ printError('Node.js 20+ required', `Found Node ${nodeCheck.version}.`, 'Update Node.js: https://nodejs.org');
18
+ process.exit(1);
19
+ }
20
+ if (!checkElectronBinary()) {
21
+ printError('Browser component not found', 'A required browser component is missing from the installation.', 'Reinstall: npm install -g claw-design');
22
+ process.exit(1);
23
+ }
24
+ // Step 1: Check Claude Code installed (per D-12)
25
+ if (!isClaudeInstalled()) {
26
+ printError('Claude Code not found', 'Claude Code CLI is not installed or not in PATH.', 'Install: https://claude.ai/download');
27
+ process.exit(1);
28
+ }
29
+ // Step 1b: Check Claude Code authentication
30
+ const authStatus = getClaudeAuthStatus();
31
+ if (!authStatus.loggedIn) {
32
+ printError('Claude Code not authenticated', 'You need to sign in before using clawdesign.', 'Run: claude login');
33
+ process.exit(1);
34
+ }
35
+ // Step 2: Detect dev server (per D-05, D-06)
36
+ let command;
37
+ const detectSpinner = createSpinner('Detecting dev server...');
38
+ if (options.cmd) {
39
+ command = options.cmd;
40
+ detectSpinner.succeed(`Using custom command: ${pc.cyan(command)}`);
41
+ }
42
+ else {
43
+ try {
44
+ const detected = await detectDevServerScript(process.cwd());
45
+ const pm = await detectPackageManager(process.cwd());
46
+ const runCmd = pm === 'npm' ? `npm run ${detected.name}` : `${pm} run ${detected.name}`;
47
+ command = runCmd;
48
+ detectSpinner.succeed(`Detected: ${pc.cyan(runCmd)} (from package.json)`);
49
+ }
50
+ catch (err) {
51
+ if (err instanceof DetectionError) {
52
+ detectSpinner.fail('No dev server detected');
53
+ printError('No dev server detected', err.message);
54
+ }
55
+ else {
56
+ detectSpinner.fail('Dev server detection failed');
57
+ printError('Dev server detection failed', err instanceof Error ? err.message : String(err));
58
+ }
59
+ process.exit(1);
60
+ }
61
+ }
62
+ // Read project name from package.json for Claw Design window title (D-03)
63
+ let projectName = 'unknown';
64
+ try {
65
+ const pkg = JSON.parse(readFileSync(path.join(process.cwd(), 'package.json'), 'utf-8'));
66
+ projectName = pkg.name || 'unknown';
67
+ }
68
+ catch {
69
+ // Not critical -- window title will show 'unknown'
70
+ }
71
+ // Step 3: Spawn dev server (per CLI-04)
72
+ const serverSpinner = createSpinner('Starting dev server...');
73
+ const devServer = spawnDevServer(command, verbose);
74
+ serverSpinner.succeed(`Dev server started ${pc.dim(command)}`);
75
+ // Step 4: Detect port (per D-07, D-08)
76
+ let port;
77
+ if (options.port) {
78
+ port = parseInt(options.port, 10);
79
+ }
80
+ else {
81
+ // Listen to stdout/stderr for port detection
82
+ const portSpinner = createSpinner('Detecting port from dev server output...');
83
+ let accumulatedOutput = '';
84
+ port = await new Promise((resolve, reject) => {
85
+ const timeout = setTimeout(() => {
86
+ cleanup();
87
+ reject(new Error('port-detect-timeout'));
88
+ }, 10_000);
89
+ function onData(chunk) {
90
+ accumulatedOutput += chunk.toString();
91
+ const detected = extractPortFromOutput(accumulatedOutput);
92
+ if (detected !== null) {
93
+ cleanup();
94
+ resolve(detected);
95
+ }
96
+ }
97
+ function cleanup() {
98
+ clearTimeout(timeout);
99
+ devServer.stdout?.removeListener('data', onData);
100
+ devServer.stderr?.removeListener('data', onData);
101
+ }
102
+ devServer.stdout?.on('data', onData);
103
+ devServer.stderr?.on('data', onData);
104
+ }).catch(async () => {
105
+ // Port not detected from stdout -- prompt user interactively (per D-07)
106
+ portSpinner.stop();
107
+ const rl = createInterface({
108
+ input: process.stdin,
109
+ output: process.stdout,
110
+ });
111
+ return new Promise((resolve, reject) => {
112
+ rl.question(`${pc.yellow(' Could not detect port from dev server output.')}\n Enter port number: `, (answer) => {
113
+ rl.close();
114
+ const parsed = parseInt(answer.trim(), 10);
115
+ if (Number.isNaN(parsed) || parsed <= 0 || parsed > 65535) {
116
+ reject(new Error('Invalid port number'));
117
+ }
118
+ else {
119
+ resolve(parsed);
120
+ }
121
+ });
122
+ });
123
+ });
124
+ portSpinner.succeed(`Port detected: ${pc.cyan(String(port))}`);
125
+ }
126
+ // Step 5: Wait for port readiness (per D-09, D-14, D-15)
127
+ const readySpinner = createSpinner(`Waiting for localhost:${port}...`);
128
+ const readyStart = Date.now();
129
+ const elapsedTimer = setInterval(() => {
130
+ const elapsed = Math.round((Date.now() - readyStart) / 1000);
131
+ readySpinner.text = `Waiting for localhost:${port}... ${pc.dim(`${elapsed}s`)}`;
132
+ }, 1000);
133
+ try {
134
+ await waitForPort(port, { timeout: 30_000 });
135
+ clearInterval(elapsedTimer);
136
+ readySpinner.succeed(`Dev server ready on ${pc.cyan(`http://localhost:${port}`)}`);
137
+ }
138
+ catch {
139
+ clearInterval(elapsedTimer);
140
+ readySpinner.fail(`Port ${port} not ready`);
141
+ // Check if port is in use by another process (per D-14)
142
+ const occupant = getProcessOnPort(port);
143
+ if (occupant) {
144
+ printError('Port already in use', `Port ${port} is occupied by ${occupant.name} (PID ${occupant.pid})`, `Try: kill ${occupant.pid} or clawdesign start --port <other>`);
145
+ }
146
+ else {
147
+ printError('Startup timeout', `Port ${port} not ready after 30s`, 'Try: clawdesign start --verbose\n Or: clawdesign start --port <port>');
148
+ }
149
+ process.exit(1);
150
+ }
151
+ // Step 6: Launch Electron window (per CLI-06)
152
+ // Pre-built by `npm run build` / prepublishOnly hook (D-18).
153
+ // No runtime build needed -- out/ is included in the npm package.
154
+ // Claude Code session is managed by AgentManager inside the Electron main process.
155
+ const electronSpinner = createSpinner('Starting Claw Design...');
156
+ const electronProcess = spawnElectron(`http://localhost:${port}`, projectName);
157
+ electronSpinner.succeed(`Claw Design ready ${pc.dim(`localhost:${port}`)}`);
158
+ // Step 7: Register shutdown and print ready (per D-01 final step)
159
+ // AgentManager handles its own cleanup from within Electron main process.
160
+ registerShutdownHandlers({
161
+ devServer: { pid: devServer.pid },
162
+ electronProcess: { pid: electronProcess.pid },
163
+ });
164
+ // Dev server crash handling (per D-13): notify but do NOT exit
165
+ devServer.on('exit', (code, signal) => {
166
+ console.log(pc.yellow('\n Dev server exited.'));
167
+ console.log(pc.dim(' Press Ctrl+C to stop, then re-run clawdesign start'));
168
+ });
169
+ // Electron window closed -- trigger shutdown to kill dev server + Claude
170
+ electronProcess.on('exit', () => {
171
+ console.log(pc.dim('\n Claw Design window closed.'));
172
+ process.emit('SIGINT');
173
+ });
174
+ printReady(port);
175
+ }
176
+ //# sourceMappingURL=start.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"start.js","sourceRoot":"","sources":["../../../src/cli/commands/start.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":""}
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from 'commander';
3
+ import { createRequire } from 'node:module';
4
+ import { startCommand } from './commands/start.js';
5
+ const require = createRequire(import.meta.url);
6
+ const { version } = require('../../package.json');
7
+ const program = new Command();
8
+ program
9
+ .name('clawdesign')
10
+ .description('Visual web development tool powered by Claude Code')
11
+ .version(version);
12
+ program
13
+ .command('start')
14
+ .description('Launch dev server and open visual editor')
15
+ .option('--cmd <command>', 'Override dev server command')
16
+ .option('--port <number>', 'Specify dev server port (skip auto-detection)')
17
+ .option('--verbose', 'Show dev server output')
18
+ .action(startCommand);
19
+ program.parse();
20
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/C,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC;AAElD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,YAAY,CAAC;KAClB,WAAW,CAAC,oDAAoD,CAAC;KACjE,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO;KACJ,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CAAC,0CAA0C,CAAC;KACvD,MAAM,CAAC,iBAAiB,EAAE,6BAA6B,CAAC;KACxD,MAAM,CAAC,iBAAiB,EAAE,+CAA+C,CAAC;KAC1E,MAAM,CAAC,WAAW,EAAE,wBAAwB,CAAC;KAC7C,MAAM,CAAC,YAAY,CAAC,CAAC;AAExB,OAAO,CAAC,KAAK,EAAE,CAAC"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Check if Claude Code CLI is installed and available in PATH.
3
+ * Synchronous check -- runs once at startup (per D-12).
4
+ */
5
+ export declare function isClaudeInstalled(): boolean;
6
+ export interface ClaudeAuthStatus {
7
+ loggedIn: boolean;
8
+ authMethod?: string;
9
+ apiProvider?: string;
10
+ apiKeySource?: string;
11
+ email?: string | null;
12
+ }
13
+ /**
14
+ * Check if the user is authenticated with Claude Code.
15
+ *
16
+ * Runs `claude auth status --json` and parses the result.
17
+ * Returns the parsed status, or `{ loggedIn: false }` if the command
18
+ * fails or produces unparseable output.
19
+ */
20
+ export declare function getClaudeAuthStatus(): ClaudeAuthStatus;
21
+ //# sourceMappingURL=claude.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/claude.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,wBAAgB,iBAAiB,IAAI,OAAO,CAO3C;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,IAAI,gBAAgB,CAkBtD"}
@@ -0,0 +1,42 @@
1
+ import { execFileSync } from 'node:child_process';
2
+ /**
3
+ * Check if Claude Code CLI is installed and available in PATH.
4
+ * Synchronous check -- runs once at startup (per D-12).
5
+ */
6
+ export function isClaudeInstalled() {
7
+ try {
8
+ execFileSync('which', ['claude'], { stdio: 'ignore' });
9
+ return true;
10
+ }
11
+ catch {
12
+ return false;
13
+ }
14
+ }
15
+ /**
16
+ * Check if the user is authenticated with Claude Code.
17
+ *
18
+ * Runs `claude auth status --json` and parses the result.
19
+ * Returns the parsed status, or `{ loggedIn: false }` if the command
20
+ * fails or produces unparseable output.
21
+ */
22
+ export function getClaudeAuthStatus() {
23
+ try {
24
+ const raw = execFileSync('claude', ['auth', 'status', '--json'], {
25
+ encoding: 'utf-8',
26
+ timeout: 10_000,
27
+ stdio: ['ignore', 'pipe', 'ignore'],
28
+ });
29
+ const parsed = JSON.parse(raw.trim());
30
+ return {
31
+ loggedIn: Boolean(parsed.loggedIn),
32
+ authMethod: parsed.authMethod,
33
+ apiProvider: parsed.apiProvider,
34
+ apiKeySource: parsed.apiKeySource,
35
+ email: parsed.email,
36
+ };
37
+ }
38
+ catch {
39
+ return { loggedIn: false };
40
+ }
41
+ }
42
+ //# sourceMappingURL=claude.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude.js","sourceRoot":"","sources":["../../../src/cli/utils/claude.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD;;;GAGG;AACH,MAAM,UAAU,iBAAiB;IAC/B,IAAI,CAAC;QACH,YAAY,CAAC,OAAO,EAAE,CAAC,QAAQ,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;QACvD,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAUD;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB;IACjC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,YAAY,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,CAAC,EAAE;YAC/D,QAAQ,EAAE,OAAO;YACjB,OAAO,EAAE,MAAM;YACf,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC;SACpC,CAAC,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;QACtC,OAAO;YACL,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC;YAClC,UAAU,EAAE,MAAM,CAAC,UAAU;YAC7B,WAAW,EAAE,MAAM,CAAC,WAAW;YAC/B,YAAY,EAAE,MAAM,CAAC,YAAY;YACjC,KAAK,EAAE,MAAM,CAAC,KAAK;SACpB,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;IAC7B,CAAC;AACH,CAAC"}
@@ -0,0 +1,14 @@
1
+ import { type ChildProcess } from 'node:child_process';
2
+ export declare const SCRIPT_PRIORITY: readonly ["dev", "start", "serve"];
3
+ export declare class DetectionError extends Error {
4
+ constructor(message: string);
5
+ }
6
+ export interface DetectedScript {
7
+ name: string;
8
+ command: string;
9
+ }
10
+ export declare function detectDevServerScript(projectDir: string): Promise<DetectedScript>;
11
+ export type PackageManager = 'npm' | 'pnpm' | 'bun';
12
+ export declare function detectPackageManager(projectDir: string): Promise<PackageManager>;
13
+ export declare function spawnDevServer(command: string, verbose: boolean): ChildProcess;
14
+ //# sourceMappingURL=dev-server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dev-server.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/dev-server.ts"],"names":[],"mappings":"AAEA,OAAO,EAAS,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAE9D,eAAO,MAAM,eAAe,oCAAqC,CAAC;AAElE,qBAAa,cAAe,SAAQ,KAAK;gBAC3B,OAAO,EAAE,MAAM;CAI5B;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAsB,qBAAqB,CACzC,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,cAAc,CAAC,CAoBzB;AAED,MAAM,MAAM,cAAc,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,CAAC;AASpD,wBAAsB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAUtF;AAED,wBAAgB,cAAc,CAC5B,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,OAAO,GACf,YAAY,CAad"}
@@ -0,0 +1,57 @@
1
+ import { readFile, access } from 'node:fs/promises';
2
+ import { join } from 'node:path';
3
+ import { spawn } from 'node:child_process';
4
+ export const SCRIPT_PRIORITY = ['dev', 'start', 'serve'];
5
+ export class DetectionError extends Error {
6
+ constructor(message) {
7
+ super(message);
8
+ this.name = 'DetectionError';
9
+ }
10
+ }
11
+ export async function detectDevServerScript(projectDir) {
12
+ const pkgPath = join(projectDir, 'package.json');
13
+ const raw = await readFile(pkgPath, 'utf-8');
14
+ const pkg = JSON.parse(raw);
15
+ if (!pkg.scripts) {
16
+ throw new DetectionError('No "scripts" field found in package.json');
17
+ }
18
+ for (const name of SCRIPT_PRIORITY) {
19
+ if (pkg.scripts[name]) {
20
+ return { name, command: pkg.scripts[name] };
21
+ }
22
+ }
23
+ throw new DetectionError(`No dev server script found in package.json.\n` +
24
+ ` Looked for: ${SCRIPT_PRIORITY.join(', ')}\n` +
25
+ ` Tip: use --cmd "your-dev-command" to specify manually`);
26
+ }
27
+ const LOCKFILE_MAP = [
28
+ ['bun.lock', 'bun'],
29
+ ['bun.lockb', 'bun'],
30
+ ['pnpm-lock.yaml', 'pnpm'],
31
+ ['package-lock.json', 'npm'],
32
+ ];
33
+ export async function detectPackageManager(projectDir) {
34
+ for (const [lockfile, pm] of LOCKFILE_MAP) {
35
+ try {
36
+ await access(join(projectDir, lockfile));
37
+ return pm;
38
+ }
39
+ catch {
40
+ // lockfile not found, try next
41
+ }
42
+ }
43
+ return 'npm';
44
+ }
45
+ export function spawnDevServer(command, verbose) {
46
+ const child = spawn(command, {
47
+ shell: true,
48
+ stdio: ['ignore', 'pipe', 'pipe'],
49
+ cwd: process.cwd(),
50
+ });
51
+ if (verbose) {
52
+ child.stdout?.pipe(process.stdout);
53
+ child.stderr?.pipe(process.stderr);
54
+ }
55
+ return child;
56
+ }
57
+ //# sourceMappingURL=dev-server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dev-server.js","sourceRoot":"","sources":["../../../src/cli/utils/dev-server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,KAAK,EAAqB,MAAM,oBAAoB,CAAC;AAE9D,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAU,CAAC;AAElE,MAAM,OAAO,cAAe,SAAQ,KAAK;IACvC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;IAC/B,CAAC;CACF;AAOD,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,UAAkB;IAElB,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,EAAE,cAAc,CAAC,CAAC;IACjD,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC7C,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAE5B,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;QACjB,MAAM,IAAI,cAAc,CAAC,0CAA0C,CAAC,CAAC;IACvE,CAAC;IAED,KAAK,MAAM,IAAI,IAAI,eAAe,EAAE,CAAC;QACnC,IAAI,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YACtB,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QAC9C,CAAC;IACH,CAAC;IAED,MAAM,IAAI,cAAc,CACtB,+CAA+C;QAC7C,iBAAiB,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI;QAC/C,yDAAyD,CAC5D,CAAC;AACJ,CAAC;AAID,MAAM,YAAY,GAAoC;IACpD,CAAC,UAAU,EAAE,KAAK,CAAC;IACnB,CAAC,WAAW,EAAE,KAAK,CAAC;IACpB,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAC1B,CAAC,mBAAmB,EAAE,KAAK,CAAC;CAC7B,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,UAAkB;IAC3D,KAAK,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC,IAAI,YAAY,EAAE,CAAC;QAC1C,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC,CAAC;YACzC,OAAO,EAAE,CAAC;QACZ,CAAC;QAAC,MAAM,CAAC;YACP,+BAA+B;QACjC,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,cAAc,CAC5B,OAAe,EACf,OAAgB;IAEhB,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,EAAE;QAC3B,KAAK,EAAE,IAAI;QACX,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC;QACjC,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE;KACnB,CAAC,CAAC;IAEH,IAAI,OAAO,EAAE,CAAC;QACZ,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACnC,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACrC,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { type ChildProcess } from 'node:child_process';
2
+ /**
3
+ * Spawn the Electron binary with the built main process script.
4
+ * Passes URL and project metadata via environment variables.
5
+ */
6
+ export declare function spawnElectron(url: string, projectName: string): ChildProcess;
7
+ //# sourceMappingURL=electron.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"electron.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/electron.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAQ9D;;;GAGG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,YAAY,CA4B5E"}
@@ -0,0 +1,36 @@
1
+ import { spawn } from 'node:child_process';
2
+ import { createRequire } from 'node:module';
3
+ import path from 'node:path';
4
+ import { fileURLToPath } from 'node:url';
5
+ const __filename = fileURLToPath(import.meta.url);
6
+ const __dirname = path.dirname(__filename);
7
+ /**
8
+ * Spawn the Electron binary with the built main process script.
9
+ * Passes URL and project metadata via environment variables.
10
+ */
11
+ export function spawnElectron(url, projectName) {
12
+ // Resolve electron binary path from the electron npm package
13
+ const require = createRequire(import.meta.url);
14
+ const electronPath = require('electron');
15
+ // Path to built main process (from electron-vite build output)
16
+ const projectRoot = path.resolve(__dirname, '..', '..', '..');
17
+ const mainScript = path.join(projectRoot, 'out', 'main', 'index.js');
18
+ const child = spawn(electronPath, [mainScript], {
19
+ stdio: ['pipe', 'pipe', 'pipe'],
20
+ env: {
21
+ ...process.env,
22
+ CLAW_URL: url,
23
+ CLAW_PROJECT_NAME: projectName,
24
+ CLAW_PROJECT_DIR: process.cwd(),
25
+ },
26
+ });
27
+ // Forward Electron main process logs to CLI terminal
28
+ child.stdout?.on('data', (chunk) => {
29
+ process.stdout.write(chunk);
30
+ });
31
+ child.stderr?.on('data', (chunk) => {
32
+ process.stderr.write(chunk);
33
+ });
34
+ return child;
35
+ }
36
+ //# sourceMappingURL=electron.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"electron.js","sourceRoot":"","sources":["../../../src/cli/utils/electron.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAqB,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;AAE3C;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,GAAW,EAAE,WAAmB;IAC5D,6DAA6D;IAC7D,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/C,MAAM,YAAY,GAAG,OAAO,CAAC,UAAU,CAAsB,CAAC;IAE9D,+DAA+D;IAC/D,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;IAC9D,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC;IAErE,MAAM,KAAK,GAAG,KAAK,CAAC,YAAY,EAAE,CAAC,UAAU,CAAC,EAAE;QAC9C,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;QAC/B,GAAG,EAAE;YACH,GAAG,OAAO,CAAC,GAAG;YACd,QAAQ,EAAE,GAAG;YACb,iBAAiB,EAAE,WAAW;YAC9B,gBAAgB,EAAE,OAAO,CAAC,GAAG,EAAE;SAChC;KACF,CAAC,CAAC;IAEH,qDAAqD;IACrD,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;QACzC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC9B,CAAC,CAAC,CAAC;IACH,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;QACzC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC9B,CAAC,CAAC,CAAC;IAEH,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { type Ora } from 'ora';
2
+ export declare function createSpinner(text: string): Ora;
3
+ export declare function printHeader(version: string): void;
4
+ export declare function printReady(port: number): void;
5
+ export declare function printError(title: string, message: string, suggestion?: string): void;
6
+ //# sourceMappingURL=output.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/output.ts"],"names":[],"mappings":"AAAA,OAAY,EAAE,KAAK,GAAG,EAAE,MAAM,KAAK,CAAC;AAGpC,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,GAAG,CAE/C;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAEjD;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAI7C;AAED,wBAAgB,UAAU,CACxB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,UAAU,CAAC,EAAE,MAAM,GAClB,IAAI,CAMN"}
@@ -0,0 +1,21 @@
1
+ import ora from 'ora';
2
+ import pc from 'picocolors';
3
+ export function createSpinner(text) {
4
+ return ora(text).start();
5
+ }
6
+ export function printHeader(version) {
7
+ console.log(pc.bold(`clawdesign v${version}`));
8
+ }
9
+ export function printReady(port) {
10
+ console.log(`\n ${pc.green('Ready!')}`);
11
+ console.log(pc.dim(` Dev server: http://localhost:${port}`));
12
+ console.log(pc.dim(' Press Ctrl+C to stop'));
13
+ }
14
+ export function printError(title, message, suggestion) {
15
+ console.error(`\n ${pc.red('\u2718')} ${pc.bold(title)}`);
16
+ console.error(` ${message}`);
17
+ if (suggestion) {
18
+ console.error(pc.dim(` ${suggestion}`));
19
+ }
20
+ }
21
+ //# sourceMappingURL=output.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output.js","sourceRoot":"","sources":["../../../src/cli/utils/output.ts"],"names":[],"mappings":"AAAA,OAAO,GAAiB,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,MAAM,YAAY,CAAC;AAE5B,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,OAAO,GAAG,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC;AAC3B,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,OAAe;IACzC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,eAAe,OAAO,EAAE,CAAC,CAAC,CAAC;AACjD,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IACzC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,kCAAkC,IAAI,EAAE,CAAC,CAAC,CAAC;IAC9D,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,UAAU,CACxB,KAAa,EACb,OAAe,EACf,UAAmB;IAEnB,OAAO,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC3D,OAAO,CAAC,KAAK,CAAC,KAAK,OAAO,EAAE,CAAC,CAAC;IAC9B,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,UAAU,EAAE,CAAC,CAAC,CAAC;IAC3C,CAAC;AACH,CAAC"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Ordered patterns for extracting port numbers from dev server stdout.
3
+ * Most specific first to avoid false positives (Pitfall 4 from research).
4
+ */
5
+ export declare const PORT_PATTERNS: readonly RegExp[];
6
+ /**
7
+ * Extract a port number from dev server output text.
8
+ * Tests patterns from most specific (URL) to least specific (colon:digits).
9
+ * Filters out error lines to avoid false positives from port-in-use messages.
10
+ * Returns null if no valid port found.
11
+ */
12
+ export declare function extractPortFromOutput(output: string): number | null;
13
+ /**
14
+ * Poll a TCP port until it accepts connections or timeout expires.
15
+ * Default timeout: 30s (per D-09). Default poll interval: 250ms.
16
+ */
17
+ export declare function waitForPort(port: number, opts?: {
18
+ timeout?: number;
19
+ interval?: number;
20
+ }): Promise<void>;
21
+ /**
22
+ * Attempt to identify which process is listening on a given port.
23
+ * Best-effort -- returns null if lsof/ps unavailable or port is free.
24
+ * Used for D-14: port-in-use diagnostics.
25
+ */
26
+ export declare function getProcessOnPort(port: number): {
27
+ pid: number;
28
+ name: string;
29
+ } | null;
30
+ //# sourceMappingURL=port-detect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"port-detect.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/port-detect.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,eAAO,MAAM,aAAa,EAAE,SAAS,MAAM,EASjC,CAAC;AASX;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAenE;AAED;;;GAGG;AACH,wBAAgB,WAAW,CACzB,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAC7C,OAAO,CAAC,IAAI,CAAC,CA8Bf;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,GACX;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAkBtC"}