@buda-ai/connector 0.1.1 → 0.1.2

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 (46) hide show
  1. package/README.md +22 -1
  2. package/agent-templates/scripts/skill-scanner.sh +125 -0
  3. package/agent-templates/shared/AGENTS.md +220 -0
  4. package/agent-templates/shared/BOOTSTRAP.md +15 -0
  5. package/agent-templates/shared/HEARTBEAT.md +5 -0
  6. package/agent-templates/shared/IDENTITY.md +29 -0
  7. package/agent-templates/shared/MEMORY.md +19 -0
  8. package/agent-templates/shared/SOUL.md +43 -0
  9. package/agent-templates/shared/TOOLS.md +85 -0
  10. package/agent-templates/shared/USER.md +23 -0
  11. package/agent-templates/system-skills/app-builder/README.md +8 -0
  12. package/agent-templates/system-skills/app-builder/SKILL.md +678 -0
  13. package/agent-templates/system-skills/app-builder/buda.app.schema.json +165 -0
  14. package/agent-templates/system-skills/app-builder/evals/evals.json +23 -0
  15. package/agent-templates/system-skills/app-builder/scripts/check-preview-url.mjs +184 -0
  16. package/agent-templates/system-skills/buda-automations/SKILL.md +175 -0
  17. package/agent-templates/system-skills/buda-automations/scripts/create-automation.sh +226 -0
  18. package/agent-templates/system-skills/buda-automations/scripts/delete-automation.sh +73 -0
  19. package/agent-templates/system-skills/buda-automations/scripts/list-automations.sh +77 -0
  20. package/agent-templates/system-skills/buda-far/SKILL.md +221 -0
  21. package/agent-templates/system-skills/buda-far/far_gen.py +1499 -0
  22. package/agent-templates/system-skills/buda-machine-info/SKILL.md +67 -0
  23. package/agent-templates/system-skills/buda-machine-info/scripts/get-info.sh +25 -0
  24. package/agent-templates/system-skills/buda-machine-info/scripts/send-file.mjs +62 -0
  25. package/agent-templates/system-skills/buda-web-preview/SKILL.md +462 -0
  26. package/agent-templates/system-skills/find-skills/SKILL.md +142 -0
  27. package/agent-templates/system-skills/skill-creator/LICENSE.txt +202 -0
  28. package/agent-templates/system-skills/skill-creator/SKILL.md +479 -0
  29. package/agent-templates/system-skills/skill-creator/agents/analyzer.md +274 -0
  30. package/agent-templates/system-skills/skill-creator/agents/comparator.md +202 -0
  31. package/agent-templates/system-skills/skill-creator/agents/grader.md +223 -0
  32. package/agent-templates/system-skills/skill-creator/assets/eval_review.html +146 -0
  33. package/agent-templates/system-skills/skill-creator/eval-viewer/generate_review.py +471 -0
  34. package/agent-templates/system-skills/skill-creator/eval-viewer/viewer.html +1325 -0
  35. package/agent-templates/system-skills/skill-creator/references/schemas.md +430 -0
  36. package/agent-templates/system-skills/skill-creator/scripts/__init__.py +0 -0
  37. package/agent-templates/system-skills/skill-creator/scripts/aggregate_benchmark.py +401 -0
  38. package/agent-templates/system-skills/skill-creator/scripts/generate_report.py +326 -0
  39. package/agent-templates/system-skills/skill-creator/scripts/improve_description.py +248 -0
  40. package/agent-templates/system-skills/skill-creator/scripts/package_skill.py +136 -0
  41. package/agent-templates/system-skills/skill-creator/scripts/quick_validate.py +103 -0
  42. package/agent-templates/system-skills/skill-creator/scripts/run_eval.py +310 -0
  43. package/agent-templates/system-skills/skill-creator/scripts/run_loop.py +332 -0
  44. package/agent-templates/system-skills/skill-creator/scripts/utils.py +47 -0
  45. package/dist/cli.js +2747 -180
  46. package/package.json +10 -6
@@ -0,0 +1,67 @@
1
+ ---
2
+ name: buda-machine-info
3
+ description: "Use this skill when the user asks about their Buda sandbox environment: CPU, memory, disk, OS, kernel, or installed software versions. Trigger on direct questions (\"how much RAM?\", \"what OS?\", \"check disk space\") and indirect ones (\"can this run Docker?\", \"am I out of memory?\", \"what tools are available?\"). Also use when troubleshooting resource constraints or deciding whether the sandbox can handle a workload, even without keywords like \"system info\" or \"specs\"."
4
+ compatibility: Requires /proc/meminfo, /etc/os-release, lscpu, df, and common CLI tools (node, git, python3). Auto-available in Buda sandboxes.
5
+ metadata:
6
+ author: buda
7
+ version: "1.0"
8
+ ---
9
+
10
+ # System & Machine Information
11
+
12
+ Retrieve hardware specs, resource usage, and installed tool versions for the
13
+ current Buda sandbox environment.
14
+
15
+ ## When to use this skill
16
+
17
+ - User asks about CPU, memory, disk, OS, or kernel details
18
+ - User wants to know available disk space or memory
19
+ - User asks what software versions are installed (Node, Python, Git, etc.)
20
+ - User says "system info", "my specs", "what machine is this", "show environment"
21
+ - User needs to troubleshoot resource constraints (out of memory, disk full)
22
+ - User is deciding whether the sandbox can handle a workload
23
+
24
+ ## Step-by-step instructions
25
+
26
+ 1. Run the info script:
27
+
28
+ ```bash
29
+ bash scripts/get-info.sh
30
+ ```
31
+
32
+ 2. Parse the output and present it to the user in a clear, readable format.
33
+ 3. If the user asked about a specific resource (e.g., "how much disk space"),
34
+ highlight the relevant section rather than dumping everything.
35
+
36
+ ## Output sections
37
+
38
+ The script reports the following:
39
+
40
+ | Section | What it shows |
41
+ |------------------|----------------------------------------------------|
42
+ | Operating System | Distro name and version (from `/etc/os-release`) |
43
+ | Kernel | Linux kernel version (`uname -r`) |
44
+ | CPU | Model name and vCPU count |
45
+ | Memory | Total and available RAM in GB |
46
+ | Disk Usage | Mount point, total size, free space, usage percent |
47
+ | Versions | Node.js, Git, and Python versions |
48
+
49
+ ## Baseline specs (Buda sandbox defaults)
50
+
51
+ For quick reference when the user asks without needing a live check:
52
+
53
+ - **OS:** Debian 12 (bookworm)
54
+ - **CPU:** Intel Xeon Platinum 8488C (8 vCPUs)
55
+ - **Memory:** 32 GB total
56
+ - **Disk:** /agent (200 GB)
57
+
58
+ Always prefer running the script for live data — these are just defaults that
59
+ may vary by sandbox tier.
60
+
61
+ ## Tips
62
+
63
+ - If the user asks "can I run X here?", run the script first, then assess
64
+ whether the available resources are sufficient.
65
+ - When memory or disk is low, proactively suggest cleanup actions.
66
+ - For version checks, if a specific tool is missing from the output, note that
67
+ it may not be installed and suggest how to install it.
@@ -0,0 +1,25 @@
1
+ #!/bin/bash
2
+ # system-info script
3
+ echo "=== System Report $(date) ==="
4
+
5
+ echo -e "\n[Operating System]"
6
+ cat /etc/os-release | grep PRETTY_NAME | cut -d= -f2 | tr -d '"'
7
+
8
+ echo -e "\n[Kernel]"
9
+ uname -r
10
+
11
+ echo -e "\n[CPU]"
12
+ lscpu | grep "Model name" | sed 's/Model name: *//'
13
+ echo "CPU(s): $(lscpu | grep '^CPU(s):' | awk '{print $2}')"
14
+
15
+ echo -e "\n[Memory]"
16
+ echo "Total: $(grep MemTotal /proc/meminfo | awk '{print $2/1024/1024 " GB"}')"
17
+ echo "Available: $(grep MemAvailable /proc/meminfo | awk '{print $2/1024/1024 " GB"}')"
18
+
19
+ echo -e "\n[Disk Usage]"
20
+ df -h | grep -E '/$|/agent' | awk '{print $1, $6, $2, $4, $5, "used"}'
21
+
22
+ echo -e "\n[Versions]"
23
+ echo "Node: $(node -v)"
24
+ echo "Git: $(git --version)"
25
+ echo "Python: $(python3 --version)"
@@ -0,0 +1,62 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * send-file.mjs
4
+ *
5
+ * Resolves a file path relative to /agent and returns a [send:] marker
6
+ * if the file exists, or an empty string if it does not.
7
+ *
8
+ * Usage:
9
+ * node scripts/send-file.mjs <path>
10
+ *
11
+ * Path rules (mirrors the system prompt convention):
12
+ * - Relative path (no leading slash): resolved against /agent
13
+ * e.g. "uploads/photo.jpg" → /agent/uploads/photo.jpg
14
+ * - Absolute path starting with /agent: used as-is
15
+ * e.g. "/agent/chart.png" → /agent/chart.png
16
+ * - Any other absolute path: used as-is (escape hatch)
17
+ *
18
+ * Output:
19
+ * [send:uploads/photo.jpg] — file exists (path is relative to /agent)
20
+ * (empty string) — file does not exist
21
+ */
22
+
23
+ import { existsSync } from "node:fs";
24
+ import { isAbsolute, resolve } from "node:path";
25
+
26
+ const AGENT_ROOT = "/agent";
27
+
28
+ function resolveAgentPath(input) {
29
+ if (!input) return null;
30
+
31
+ // Strip a leading /agent prefix so the returned marker stays relative
32
+ if (input.startsWith("/agent/")) {
33
+ return { abs: input, rel: input.slice("/agent/".length) };
34
+ }
35
+
36
+ // Other absolute paths — use as-is, keep the full path in the marker
37
+ if (isAbsolute(input)) {
38
+ return { abs: input, rel: input };
39
+ }
40
+
41
+ // Relative path — resolve against /agent
42
+ const abs = resolve(AGENT_ROOT, input);
43
+ return { abs, rel: input };
44
+ }
45
+
46
+ const input = process.argv[2];
47
+
48
+ if (!input) {
49
+ // No argument — print nothing (empty result)
50
+ process.exit(0);
51
+ }
52
+
53
+ const resolved = resolveAgentPath(input);
54
+
55
+ if (!resolved || !existsSync(resolved.abs)) {
56
+ // File does not exist — return empty string
57
+ process.stdout.write("");
58
+ process.exit(0);
59
+ }
60
+
61
+ // File exists — emit the [send:] marker
62
+ process.stdout.write(`[send:${resolved.rel}]`);
@@ -0,0 +1,462 @@
1
+ ---
2
+ name: buda-web-preview
3
+ description: "Use this skill when the user wants to create, view, run, or preview any web page, HTML file, game, landing page, demo, prototype, or frontend project."
4
+ triggers:
5
+ - "make a cat game"
6
+ - "create a landing page"
7
+ - "build a todo app"
8
+ - "Check HTML"
9
+ - "See HTML"
10
+ - "Preview HTML file"
11
+ - "show me a preview"
12
+ - "start a dev server"
13
+ - "run it in the background"
14
+ - "give me the link"
15
+ - "start a web server"
16
+ - "start http server"
17
+ - "serve the files"
18
+ - "run bun dev"
19
+ - "use browser"
20
+ - "use local browser"
21
+ - "open page"
22
+ - "做个小游戏"
23
+ - "做个网页"
24
+ - "帮我写个HTML"
25
+ - "打开HTML"
26
+ - "查看HTML"
27
+ - "搭个演示页面"
28
+ - "搭个网页应用"
29
+ - "使用浏览器"
30
+ - "本地浏览器"
31
+ - "打开浏览器"
32
+ - "启用Web服务"
33
+ metadata:
34
+ author: buda
35
+ version: "1.3"
36
+ ---
37
+
38
+ # Web Preview Skill
39
+
40
+ Launch a live browser preview for any web page, game, or frontend project you create.
41
+
42
+ Launch a live browser preview for any web page, HTML, when user want to use browser to check something.
43
+
44
+
45
+ ## When to use this skill
46
+
47
+ Activate whenever the user wants to **see** something in a browser, not just read code:
48
+
49
+ - "Make me a cat game" / "做个小猫游戏"
50
+ - "Create a landing page" / "做个首页"
51
+ - "Build a todo app" / "做个待办事项"
52
+ - "Build a todo app" / "做个网页"
53
+ - "Write me an HTML page" / "帮我写个HTML"
54
+ - "Show me the HTML page" / "帮我查看HTML"
55
+ - "Open Browser to open page" / " 使用浏览器去打开文件"
56
+ - "open HTML file" / "打开HTML 文件"
57
+ - "I want to see a demo" / "给我演示一下"
58
+ - Any request for a game, animation, interactive component, or visual prototype
59
+
60
+ ## Core rule: Write files, don't paste code in chat
61
+
62
+ **NEVER** return the full HTML/CSS/JS as a chat message. Always write it to real files.
63
+
64
+ Users want to **see** it running — not read a code block.
65
+
66
+ ## Non-negotiable runtime rules
67
+
68
+ 1. **Always run dev servers in background**. Never run foreground commands that block the session.
69
+ 2. **Never assume a port** for framework dev servers. Parse the actual runtime output to detect it.
70
+ 3. **Call `get_preview_url`** After the server is reachable, call the `get_preview_url` tool with the detected port (and optional `path`). Buda opens the signed external preview in Local Browser. You may still print `http://localhost:PORT` in chat as a fallback.
71
+ 4. **Verify service health before announcing link**. Only print port + preview URL after a successful reachability check.
72
+ 5. **Always bind to `0.0.0.0`**, not `localhost` or `127.0.0.1`. This is required so the sandbox exposes the port to the external network, allowing users to open it in Local Browser. A server bound only to `127.0.0.1` is not reachable from outside the sandbox.
73
+ 5. **Restart means stop then start**. Kill previous process first, then launch a new one.
74
+ 6. **Use timeout-based polling**. Avoid infinite waits; fail fast with logs if startup is not ready.
75
+ 7. **Use a port between 3000 and 3999**. Always pick the preview port within the `3000`–`3999` range. If the chosen port is occupied, fall back to another free port in the same range.
76
+ 8. **Never hardcode working directory**. Derive paths relative to the project directory. Do not assume `/agent/` unless that is the actual project root.
77
+ 9. **Support multiple simultaneous dev servers**. PID/log files must be scoped per project (use a hash or sanitized project path), not a single global `/tmp/buda-preview.*`.
78
+ 10. **Read `buda.app.json` first**. If a `buda.app.json` exists in the project directory, read it to get the dev command, port, and other settings before falling back to defaults.
79
+
80
+ ## AI Browser vs Local Browser
81
+
82
+ - Use this skill and `get_preview_url` when the user wants to preview a local dev server or generated app. Buda opens that preview in **Local Browser**.
83
+ - Do not use AI Browser for sandbox localhost previews unless the user explicitly wants the AI-controlled CDP browser to visit the signed external preview URL.
84
+
85
+ ---
86
+
87
+ ## Step-by-step
88
+
89
+ ### 0. Check for `buda.app.json` (always do this first)
90
+
91
+ Before starting any server, check if a `buda.app.json` exists in the project directory:
92
+
93
+ ```bash
94
+ PROJECT_DIR="<absolute-path-to-project>"
95
+
96
+ if [ -f "$PROJECT_DIR/buda.app.json" ]; then
97
+ echo "Found buda.app.json, reading config..."
98
+ cat "$PROJECT_DIR/buda.app.json"
99
+ fi
100
+ ```
101
+
102
+ Schema: `/system/.agents/skills/app-builder/buda.app.schema.json`
103
+
104
+
105
+ Key fields to read for preview:
106
+
107
+ | Field | Description |
108
+ |---|---|
109
+ | `framework` | `"static"` \| `"vite"` \| `"next"` — determines server strategy |
110
+ | `port` | Dev server port (required for non-static) |
111
+ | `scripts.install` | Dependency install command (e.g. `bun install`) |
112
+ | `scripts.dev` | Dev server start command |
113
+
114
+
115
+ Example — Vite app:
116
+
117
+ ```json
118
+ {
119
+ "name": "my_app",
120
+ "version": "1.0.0",
121
+ "type": "web",
122
+ "description": "A Vite + React application",
123
+ "framework": "vite",
124
+ "port": 5173,
125
+ "scripts": {
126
+ "install": "bun install",
127
+ "dev": "./node_modules/.bin/vite --host 0.0.0.0",
128
+ "build": "./node_modules/.bin/tsc -b && ./node_modules/.bin/vite build",
129
+ "start": "./node_modules/.bin/vite preview --host 0.0.0.0"
130
+ }
131
+ }
132
+ ```
133
+
134
+ How to use it:
135
+
136
+ - `framework: "static"` → serve the project directory with `npx serve`, no install step needed.
137
+ - Otherwise → run `scripts.install` first, then `scripts.dev` as the start command.
138
+ - Use `port` as the expected port (still verify reachability with curl).
139
+ - If `buda.app.json` is absent, fall back to the standard detection logic below.
140
+
141
+ ---
142
+
143
+ ### Per-project runtime state files
144
+
145
+ To support multiple dev servers running simultaneously, scope PID/log/URL files to the project. Use a short hash of the project path:
146
+
147
+ ```bash
148
+ PROJECT_DIR="<absolute-path-to-project>"
149
+ PROJECT_HASH="$(echo "$PROJECT_DIR" | md5sum | cut -c1-8)"
150
+
151
+ PID_FILE="/tmp/buda-preview-${PROJECT_HASH}.pid"
152
+ LOG_FILE="/tmp/buda-preview-${PROJECT_HASH}.log"
153
+ URL_FILE="/tmp/buda-preview-${PROJECT_HASH}.url"
154
+ ```
155
+
156
+ Never use a shared global `/tmp/buda-preview.pid` — doing so would cause one project's server to clobber another's.
157
+
158
+ ---
159
+
160
+ ### Stop existing preview process for a project (required before restart)
161
+
162
+ ```bash
163
+ PROJECT_DIR="<absolute-path-to-project>"
164
+ PROJECT_HASH="$(echo "$PROJECT_DIR" | md5sum | cut -c1-8)"
165
+ PID_FILE="/tmp/buda-preview-${PROJECT_HASH}.pid"
166
+ URL_FILE="/tmp/buda-preview-${PROJECT_HASH}.url"
167
+
168
+ if [ -f "$PID_FILE" ] && kill -0 "$(cat "$PID_FILE")" 2>/dev/null; then
169
+ kill "$(cat "$PID_FILE")" 2>/dev/null || true
170
+ sleep 1
171
+ kill -9 "$(cat "$PID_FILE")" 2>/dev/null || true
172
+ fi
173
+ rm -f "$PID_FILE"
174
+
175
+ # Optional: kill by previous detected port if still occupied
176
+ if [ -f "$URL_FILE" ]; then
177
+ PORT="$(sed -E 's#.*:([0-9]+).*#\1#' "$URL_FILE")"
178
+ if [ -n "$PORT" ]; then
179
+ ss -ltnp "sport = :$PORT" 2>/dev/null \
180
+ | sed -nE 's/.*pid=([0-9]+).*/\1/p' \
181
+ | xargs -r kill 2>/dev/null || true
182
+ fi
183
+ fi
184
+ rm -f "$URL_FILE"
185
+ ```
186
+
187
+ Run this stop block whenever:
188
+ - user says "restart"
189
+ - you need to re-run a server command
190
+ - you suspect a stale preview process is still alive
191
+
192
+ ---
193
+
194
+ ### For static HTML pages (no framework needed)
195
+
196
+ Use this when the user asks for a simple page, game, animation, or visual demo.
197
+
198
+ **1. Write files**
199
+
200
+ Write to the actual project directory. Do **not** hardcode `/agent/preview/`. Use the real path where the project lives:
201
+
202
+ ```
203
+ <PROJECT_DIR>/index.html ← always required
204
+ <PROJECT_DIR>/style.css ← when styling is needed
205
+ <PROJECT_DIR>/script.js ← when JS logic is needed
206
+ ```
207
+
208
+ **2. Resolve start command and port**
209
+
210
+ ```bash
211
+ PROJECT_DIR="<absolute-path-to-project>"
212
+ PROJECT_HASH="$(echo "$PROJECT_DIR" | md5sum | cut -c1-8)"
213
+ PID_FILE="/tmp/buda-preview-${PROJECT_HASH}.pid"
214
+ LOG_FILE="/tmp/buda-preview-${PROJECT_HASH}.log"
215
+ URL_FILE="/tmp/buda-preview-${PROJECT_HASH}.url"
216
+ PORT=3000
217
+
218
+ # Read buda.app.json if present
219
+ if [ -f "$PROJECT_DIR/buda.app.json" ]; then
220
+ CFG_PORT="$(node -e "try{const c=require('$PROJECT_DIR/buda.app.json');process.stdout.write(String(c.port||''))}catch(e){}" 2>/dev/null)"
221
+ [ -n "$CFG_PORT" ] && PORT="$CFG_PORT"
222
+ fi
223
+
224
+ # Find a free port in 3000-3999 if chosen port is occupied
225
+ while ss -ltn "sport = :$PORT" 2>/dev/null | grep -q ":$PORT"; do
226
+ PORT=$((PORT + 1))
227
+ [ "$PORT" -gt 3999 ] && PORT=3000
228
+ done
229
+ ```
230
+
231
+ **3. Start the preview server**
232
+
233
+ ```bash
234
+ # Always stop old process first (restart-safe)
235
+ if [ -f "$PID_FILE" ] && kill -0 "$(cat "$PID_FILE")" 2>/dev/null; then
236
+ kill "$(cat "$PID_FILE")" 2>/dev/null || true
237
+ sleep 1
238
+ kill -9 "$(cat "$PID_FILE")" 2>/dev/null || true
239
+ fi
240
+ ss -ltnp "sport = :$PORT" 2>/dev/null \
241
+ | sed -nE 's/.*pid=([0-9]+).*/\1/p' \
242
+ | xargs -r kill 2>/dev/null || true
243
+
244
+ # Bind to 0.0.0.0 so the port is reachable from outside the sandbox
245
+ nohup npx serve "$PROJECT_DIR" -l "0.0.0.0:$PORT" > "$LOG_FILE" 2>&1 &
246
+ echo $! > "$PID_FILE"
247
+
248
+ # Wait until reachable
249
+ READY=0
250
+ for _ in $(seq 1 30); do
251
+ if ! kill -0 "$(cat "$PID_FILE")" 2>/dev/null; then
252
+ echo "Preview process exited before becoming ready. Last log lines:"
253
+ tail -n 40 "$LOG_FILE" 2>/dev/null || true
254
+ break
255
+ fi
256
+ if curl -fsS --connect-timeout 2 --max-time 10 \
257
+ -o /dev/null "http://127.0.0.1:$PORT/"; then
258
+ URL="http://localhost:$PORT/"
259
+ echo "$URL" > "$URL_FILE"
260
+ echo "Preview ready on port $PORT"
261
+ echo "$URL"
262
+ READY=1
263
+ break
264
+ fi
265
+ sleep 1
266
+ done
267
+ if [ "$READY" != 1 ]; then
268
+ echo "Preview did not become reachable within 30s (port $PORT). Check $LOG_FILE"
269
+ tail -n 40 "$LOG_FILE" 2>/dev/null || true
270
+ fi
271
+ ```
272
+
273
+ **4. Open preview**
274
+
275
+ Call `get_preview_url` with the detected port, for example:
276
+
277
+ ```json
278
+ { "port": 3000, "path": "/" }
279
+ ```
280
+
281
+ **5. Reply**
282
+
283
+ After writing files, starting the server, and calling `get_preview_url`, reply briefly:
284
+
285
+ ```
286
+ ✅ Preview launched!
287
+
288
+ Buda opened the preview in Local Browser.
289
+ ```
290
+
291
+ Then, ask the user if they'd like to deploy the web app — this feature is available on any purchased plan.
292
+
293
+ Do **not** paste the full source code unless the user asks.
294
+
295
+ ---
296
+
297
+ ### For Node.js / framework projects (React, Vite, Next.js, Express...)
298
+
299
+ Use this when the user asks for a React app, Express server, or any project with a `package.json`.
300
+
301
+ **1. Scaffold the project**
302
+
303
+ Create files under the actual project directory. Do **not** hardcode a working directory.
304
+
305
+ **2. Resolve start command**
306
+
307
+ ```bash
308
+ PROJECT_DIR="<absolute-path-to-project>"
309
+
310
+ # Priority 1: buda.app.json
311
+ DEV_CMD=""
312
+ INSTALL_CMD=""
313
+ if [ -f "$PROJECT_DIR/buda.app.json" ]; then
314
+ DEV_CMD="$(node -e "try{const c=require('$PROJECT_DIR/buda.app.json');process.stdout.write((c.scripts&&c.scripts.dev)||'')}catch(e){}" 2>/dev/null)"
315
+ INSTALL_CMD="$(node -e "try{const c=require('$PROJECT_DIR/buda.app.json');process.stdout.write((c.scripts&&c.scripts.install)||'')}catch(e){}" 2>/dev/null)"
316
+ fi
317
+
318
+ # Priority 2: package.json scripts.dev
319
+ if [ -z "$DEV_CMD" ] && [ -f "$PROJECT_DIR/package.json" ]; then
320
+ HAS_DEV="$(node -e "try{const p=require('$PROJECT_DIR/package.json');process.stdout.write(p.scripts&&p.scripts.dev?'yes':'')}catch(e){}" 2>/dev/null)"
321
+ [ "$HAS_DEV" = "yes" ] && DEV_CMD="bun run dev"
322
+ fi
323
+
324
+ # Priority 3: fallback
325
+ [ -z "$DEV_CMD" ] && DEV_CMD="bun run dev"
326
+ [ -z "$INSTALL_CMD" ] && INSTALL_CMD="bun install"
327
+
328
+ echo "Install: $INSTALL_CMD"
329
+ echo "Dev: $DEV_CMD"
330
+ ```
331
+
332
+ **3. Install and start**
333
+
334
+ ```bash
335
+ PROJECT_HASH="$(echo "$PROJECT_DIR" | md5sum | cut -c1-8)"
336
+ PID_FILE="/tmp/buda-preview-${PROJECT_HASH}.pid"
337
+ LOG_FILE="/tmp/buda-preview-${PROJECT_HASH}.log"
338
+ URL_FILE="/tmp/buda-preview-${PROJECT_HASH}.url"
339
+
340
+ cd "$PROJECT_DIR"
341
+ $INSTALL_CMD
342
+
343
+ # Always stop old process first (restart-safe)
344
+ if [ -f "$PID_FILE" ] && kill -0 "$(cat "$PID_FILE")" 2>/dev/null; then
345
+ kill "$(cat "$PID_FILE")" 2>/dev/null || true
346
+ sleep 1
347
+ kill -9 "$(cat "$PID_FILE")" 2>/dev/null || true
348
+ fi
349
+ rm -f "$URL_FILE"
350
+
351
+ nohup $DEV_CMD > "$LOG_FILE" 2>&1 &
352
+ echo $! > "$PID_FILE"
353
+
354
+ # Detect runtime URL from logs, then verify before announce
355
+ URL=""
356
+ for i in $(seq 1 60); do
357
+ URL="$(
358
+ sed -nE 's#.*(https?://(localhost|127\.0\.0\.1|0\.0\.0\.0):[0-9]+/?).*#\1#p' "$LOG_FILE" | tail -n 1
359
+ )"
360
+ if [ -n "$URL" ]; then
361
+ PORT="$(echo "$URL" | sed -E 's#.*:([0-9]+).*#\1#')"
362
+ if curl -fsS --connect-timeout 2 --max-time 10 -o /dev/null "http://127.0.0.1:$PORT/" \
363
+ || curl -fsS --connect-timeout 2 --max-time 10 -o /dev/null "$URL"; then
364
+ CANONICAL_URL="http://localhost:$PORT/"
365
+ echo "$CANONICAL_URL" > "$URL_FILE"
366
+ echo "Preview ready on port $PORT"
367
+ echo "$CANONICAL_URL"
368
+ break
369
+ fi
370
+ fi
371
+ sleep 1
372
+ done
373
+
374
+ # If no URL detected/verified, report failure with logs
375
+ if [ -z "$URL" ]; then
376
+ echo "Dev server did not become ready in time. Check $LOG_FILE"
377
+ tail -n 40 "$LOG_FILE" 2>/dev/null || true
378
+ fi
379
+ ```
380
+
381
+ Important:
382
+ - Do not output a preview link until a port is detected and reachable.
383
+ - Reply with the preview link as plain text only; do not wrap it in `<code>`, or any other element, so buda can intercept it and open the preview.
384
+ - If startup fails, share concise error + log file path.
385
+ - For Vite, `--strictPort` may be used when you need a fixed port; otherwise parse the actual port from logs.
386
+ - Never use `python3 http.server` as a web server.
387
+
388
+ **4. Keep reply short** — same as static case.
389
+
390
+ ---
391
+
392
+ ## Common output patterns the system detects
393
+
394
+ After the dev server starts (or restarts) successfully, check whether `scripts.dev` in `buda.app.json` matches the actual command used. If it differs, update it — if the file exists.
395
+
396
+ After **every** dev/static server start, always print preview metadata in bash output.
397
+ When the service restarts (manual restart, crash + restart, port switch), print it again.
398
+
399
+ Required output on each (re)start:
400
+ - `Preview time: 2026-04-14 10:32:11` (local time is fine)
401
+ - `http://localhost:3000` ← preferred plain link line for click/open
402
+
403
+ Compatible patterns the system can also detect:
404
+ - `http://localhost:3000`
405
+ - `Local: http://localhost:3000` (Vite/Next.js)
406
+ - `App listening on port 3000` (Express)
407
+ - `Serving HTTP on 0.0.0.0 port 3000`
408
+
409
+ Always make sure preview link output appears in bash logs for every (re)start, so users can click immediately.
410
+
411
+ If logs don't print a URL, use a fallback probe (bounded by timeout):
412
+
413
+ ```bash
414
+ for p in 3000 3001 4173 5173 8000 8080; do
415
+ if curl -fsS --connect-timeout 2 --max-time 10 -o /dev/null "http://127.0.0.1:$p/"; then
416
+ echo "Preview ready on port $p"
417
+ echo "http://localhost:$p/"
418
+ break
419
+ fi
420
+ done
421
+ ```
422
+
423
+ ## Choosing between static vs Node
424
+
425
+ | Situation | Use |
426
+ | ---------------------------------------------- | ------------------------------ |
427
+ | Simple page, game, animation, landing page | Static (npx serve) |
428
+ | User explicitly asks for React / Vue / Next.js | Node (bun run dev) |
429
+ | User asks for a backend / API | Node (Vite / Express / FastAPI)|
430
+ | Prototype with vanilla JS | Static (npx serve) |
431
+ | When in doubt | Ask user |
432
+
433
+ ## Updating the preview
434
+
435
+ If the user wants changes:
436
+ - Edit the file(s) directly
437
+ - No need to restart the server for static HTML (just refresh the page)
438
+ - For Node projects, hot reload usually handles it automatically
439
+
440
+ If the user explicitly asks to restart:
441
+ - Execute stop block first (kill old process and free old port)
442
+ - Run startup flow again
443
+ - Re-detect and re-verify port before replying with link
444
+
445
+ ## Tips
446
+
447
+ - For games: use canvas or simple DOM — no framework needed
448
+ - For landing pages: keep it self-contained in one HTML file when possible
449
+ - Don't run `python3 http.server` as a web server
450
+ - For complex projects: use Vite (`bun create vite`) for fast setup, always set `host: '0.0.0.0'` and `allowedHosts: true`
451
+ - **Every server must bind to `0.0.0.0`** — this is what makes the sandbox port reachable externally so the user can open it in Local Browser
452
+
453
+ ```js
454
+ // https://vite.dev/config/
455
+ export default defineConfig({
456
+ plugins: [react()],
457
+ server: {
458
+ host: '0.0.0.0', // required — bind to all interfaces, not just localhost
459
+ allowedHosts: true // required — allow sandbox external hostname
460
+ }
461
+ })
462
+ ```