# Local Server

> Auto-start a local development server before sharing a localhost URL with the user. Use this skill PROACTIVELY whenever (1) the user asks to test, preview, open, or access a local frontend / web app / website ("幫我開啟本地端", "本地測試", "我要看", "give me the local link", "open it locally", "let me try it"), OR (2) you are about to give the user a `http://localhost:...` link. Never hand out a localhost URL without first verifying the server is actually running. Covers static sites (vanilla HTML/JS, no build), Vite, Next.js, CRA, Python static sites, and similar.

- Skill: `alanpai/local-server` (Agent Skill)
- Install (CLI): `npx skillmds@latest add alanpai/local-server`
- Raw SKILL.md: https://api.skillmd.com/api/skills/alanpai/local-server/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- Author: AlanPai (https://skillmd.com/u/alanpai)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/alanpai/local-server

---


# local-server — 自動啟本地 server

## 觸發時機（必須主動觸發，不等使用者要求）

**任一條件成立就執行：**

1. 使用者語意表達「想看本地版」「測試一下」「打開來看」「給我連結試試」「跑起來」「本地端」等
2. 你準備在對話中給出 `http://localhost:<port>` 形式的連結
3. 使用者明示 `/local-server` 或 `/serve` 等指令
4. 已給過連結但使用者反應「打不開 / 連不上」→ 重新驗證並重啟

**不要做的事：**
- 不要在沒驗證 server 已起來前就把連結貼給使用者
- 不要因為「我覺得使用者自己會跑」就跳過——使用者已經明確說過想要這個自動化

## 工作流程

### Step 1 — 檢查目前是否已有 server 跑著

對常見埠依序試打（preferred: 8000, 5173, 3000, 4321, 8080）：

```bash
for port in 8000 5173 3000 4321 8080; do
  code=$(curl -s -o /dev/null -w "%{http_code}" --max-time 1 "http://localhost:$port/" 2>/dev/null)
  if [ "$code" = "200" ] || [ "$code" = "301" ] || [ "$code" = "302" ]; then
    echo "FOUND $port $code"
    break
  fi
done
```

**有命中 → 跳到 Step 4**（直接給連結，不要重複啟 server）。

### Step 2 — 偵測專案型態，選對啟動指令

讀工作目錄下的 `package.json`（若有）：

| 偵測到 | 啟動指令 | 預設埠 |
|---|---|---|
| `package.json` 有 `scripts.dev` 且 deps 含 `vite` | `npm run dev` | 5173 |
| `package.json` 有 `scripts.dev` 且 deps 含 `next` | `npm run dev` | 3000 |
| `package.json` 有 `scripts.start`（CRA / react-scripts） | `npm start` | 3000 |
| `package.json` 有 `scripts.dev`（其他） | `npm run dev` | 看 log |
| 沒 `package.json`、根目錄有 `index.html` | `npx serve -p 8000 .` | 8000 |
| 純 Python 靜態 | `python -m http.server 8000`（Windows 上若是 WindowsApps stub 改 `npx serve`） | 8000 |

**Windows 注意：** `C:\Users\<u>\AppData\Local\Microsoft\WindowsApps\python.exe` 是 Microsoft Store stub，跑會 exit 49。優先用 `npx serve`。

### Step 3 — 背景啟動 + 等待就緒

用 Bash 的 `run_in_background: true` 啟動（不要前景，會卡住）：

```
Bash(command="npx serve -p 8000 .", run_in_background=true)
```

然後**輪詢直到就緒**（單一通知模式，注意 timeout）：

```bash
until curl -s -o /dev/null -w "%{http_code}" http://localhost:8000/ | grep -qE "200|301|302"; do
  sleep 0.3
done
echo "READY"
```

如果 30 秒內沒就緒：
- 讀 background task 的 output 找錯誤（埠衝突 / 缺套件 / 寫死路徑錯誤）
- 報告錯誤給使用者，**不要假裝成功**

### Step 4 — 把連結交給使用者

格式：

> Server 已啟動 → http://localhost:<port>
>
> （若有特定頁面）建議直接打開 http://localhost:<port>/<path>

順便：
- 若這個 server 是新啟的，提一句「跑在背景，要關掉跟我說一聲」
- 若是沿用之前的，提一句「沿用既有 server」

### Step 5 — 後續維護

- 同一 session 內**不要重啟**已經健康的 server
- 若使用者改了程式碼，靜態站需要重新整理瀏覽器；Vite/Next 有 HMR 不用重啟
- 使用者明確說「停掉 server / 關掉」→ 用 `TaskStop` 收掉背景任務

## 反例（不要這樣做）

❌ 直接說「請執行 `npx serve -p 8000 .` 然後打開 http://localhost:8000」
   → 使用者要的就是自動化，這違背 skill 目的

❌ 啟動後不驗證就貼連結
   → 啟動失敗（埠佔用 / 缺依賴）使用者會打不開

❌ 同 session 重複 spawn 多個 server
   → 浪費埠 + 混淆

## 常見 troubleshooting

| 症狀 | 原因 | 解法 |
|---|---|---|
| `EADDRINUSE :::8000` | 埠被占（可能是上次沒收掉的 task） | 換埠或先 `TaskStop` 舊的 |
| 瀏覽器 404 但 server 有起 | 路徑大小寫 / `index.html` 不在根 | 確認檔案位置或補 `--single` |
| `python: command not found` 或 exit 49 | Windows Store stub | 改 `npx serve` |
| Fetch ES module 失敗 | 用 `file://` 打開了 | 必須走 http://，這就是 server 存在的意義 |

