Repository: https://github.com/yanowo/agent-process-guard Stars: 14 | Language: PowerShell / Bash | License: MIT 最後更新: 2026-06-10


1. 專案概覽 (Project Overview)

1.1 這個工具解決什麼問題?

當 AI 編碼代理(如 Codex、Claude Code)在終端機執行指令時,經常遭遇兩個根本問題:

  1. 阻塞 (Blocking):代理啟動了一個開發伺服器(如 npm run dev),該指令永遠不會結束,導致代理卡住無法繼續後續任務。
  2. 孤兒程序 (Orphaned Processes):代理啟動了背景程序但忘記清理,導致埠號被佔用、記憶體洩漏,甚至影響後續任務的執行。

Process Guard (程序守衛) 是一個跨代理 (cross-agent) 的終端機程序衛生 (terminal process hygiene) 技能,它將終端機指令的執行轉化為一個完整的生命週期管理流程。

1.2 設計哲學

Process Guard 採用了幾個關鍵設計原則:

  • 分類優先 (Classify First):在執行任何指令之前,先將其分類為「有限指令」、「長期執行指令」或「互動式指令」。
  • 最小公分母 (Common Denominator):只使用 Agent Skills 的通用格式(SKILL.md + scripts/ + references/),確保 Codex 和 Claude Code 都能直接使用。
  • 程序組清理 (Process Group Cleanup):停止程序時不只殺死父程序 (parent PID),而是遞迴清理整個程序樹 (process tree)。
  • 就緒檢查 (Readiness Check):程序活著不代表已就緒;必須通過 HTTP 健康檢查、TCP 埠監聽、自定義探測或日誌比對來確認。

1.3 專案結構

 1agent-process-guard/
 2├── SKILL.md                              # 技能定義(YAML frontmatter + 完整規範)
 3├── LICENSE                               # MIT 授權
 4├── README.md                             # 英文說明(含多語系連結)
 5├── README.zh-TW.md                       # 繁體中文說明
 6├── README.zh-CN.md                       # 簡體中文說明
 7├── README.ja.md                          # 日文說明
 8├── README.ko.md                          # 韓文說明
 9├── scripts/
10│   ├── install.sh / install.ps1          # 安裝腳本
11│   ├── guarded-run.sh / .ps1             # 有限指令守護執行
12│   ├── start-managed-process.sh / .ps1   # 啟動受管理程序
13│   ├── stop-managed-process.sh / .ps1    # 停止受管理程序
14│   ├── with-managed-process.sh / .ps1    # 一次性臨時程序(自動清理)
15│   ├── status-managed-processes.sh / .ps1 # 檢視所有受管理程序狀態
16│   └── cleanup-managed-processes.sh / .ps1 # 清理所有受管理程序
17└── references/
18    ├── AGENTS.md.snippet                 # Codex 持久指令片段
19    ├── CLAUDE.md.snippet                 # Claude Code 持久指令片段
20    ├── install.md                        # 安裝指南
21    ├── examples.md                       # 各語言範例
22    ├── long-running-patterns.md          # 長期執行指令分類參考
23    ├── platforms.md                      # 平台差異說明
24    └── troubleshooting.md               # 疑難排解

2. 核心架構 (Core Architecture)

2.1 指令生命週期 (Command Lifecycle)

Process Guard 的核心運作流程是將每一條終端機指令送入一個標準化的生命週期管理。


flowchart TD
    A["收到終端機指令"] --> B{"指令分類\n(Command Classification)"}

    B -->|"有限指令\n(Finite)"| C["guarded-run.sh\n設定 timeout 執行"]
    B -->|"長期執行\n(Long-running)"| D{"需要多步驟檢查?"}
    B -->|"互動式\n(Interactive)"| E["拒絕執行\n除非使用者明確要求"]

    D -->|"否(單一檢查)"| F["with-managed-process.sh\n自動啟動 → 檢查 → 清理"]
    D -->|"是(多步驟)"| G["start-managed-process.sh\n啟動並追蹤 PID"]

    C --> H["等待完成或 timeout"]
    F --> I["執行檢查指令"]
    G --> J["執行多個檢查步驟"]

    H --> K["回報結果"]
    I --> L["自動停止程序"]
    J --> M["stop-managed-process.sh\n手動停止"]

    L --> N["回報終端機衛生狀態\n(Terminal Hygiene Report)"]
    M --> N
    K --> N

    style A fill:#e1f5fe
    style B fill:#fff3e0
    style E fill:#ffcdd2
    style N fill:#c8e6c9

2.2 程序狀態管理 (Process State Management)

所有受管理程序的狀態都儲存在 .agent-run/ 目錄下,提供統一的追蹤介面。


flowchart LR
    subgraph ".agent-run/ 目錄結構"
        direction TB
        L["logs/\n程序日誌"]
        P["pids/\n程序 PID 檔"]
        M["meta/\n程序元資料"]
    end

    subgraph "日誌檔案"
        L1["web.log"]
        L2["api.log"]
        L3["worker.log"]
    end

    subgraph "PID 檔案"
        P1["web.pid → 12345"]
        P2["api.pid → 12346"]
        P3["worker.pid → 12347"]
    end

    subgraph "Meta 檔案"
        M1["web.env\nNAME=web\nPID=12345\nPORT=3000\n..."]
    end

    L --- L1
    L --- L2
    L --- L3
    P --- P1
    P --- P2
    P --- P3
    M --- M1

    style L fill:#e3f2fd
    style P fill:#fce4ec
    style M fill:#f3e5f5

每個受管理程序會產生三個檔案:

檔案類型路徑範例內容
日誌 (Log).agent-run/logs/web.log程序的 stdout + stderr 輸出
PID 檔.agent-run/pids/web.pid程序 ID,用於存活檢查與清理
元資料 (Meta).agent-run/meta/web.env名稱、PID、埠號、健康檢查 URL、啟動指令、工作目錄、啟動時間

2.3 就緒檢查優先序 (Readiness Check Priority)

Process Guard 不把「程序活著」等同於「程序已就緒」。它按照以下優先順序使用最強的就緒信號 (readiness signal):

優先序檢查方式適用場景參數
1HTTP Health URLHTTP/RPC 服務--health-url
2TCP 埠監聽有網路監聽的服務--port
3自定義探測指令無網路介面的程序--ready-command
4日誌比對 (Log Pattern)程序會印出已就緒訊息--ready-log-pattern

2.4 程序清理策略 (Cleanup Strategy)

許多開發工具(Next.js、Vite、Python reloader、Cargo watch 等)在啟動時會衍生子程序 (child processes)。只殺死父程序會留下孤兒。Process Guard 的清理策略:

  1. 程序組終止 (Process Group Termination):使用 setsid 建立獨立的 session,然後對整個程序組發送 SIGTERM
  2. 遞迴子程序清理:用 pgrep -P 找出所有子程序,遞迴停止。
  3. 強制終止 (Force Kill):若 SIGTERM 在寬限期 (grace period) 後仍未生效,發送 SIGKILL

3. 安裝與設定 (Installation & Setup)

3.1 自動安裝

最簡單的方式是使用內建安裝腳本,同時安裝到 Codex 和 Claude Code:

使用者層級安裝 (User-level)

1# 同時安裝到 Codex 和 Claude Code
2./scripts/install.sh --target both --scope user

專案層級安裝 (Repository-level)

1# 只在當前專案生效
2./scripts/install.sh --target both --scope project

PowerShell

1.\scripts\install.ps1 -Target both -Scope user
2.\scripts\install.ps1 -Target both -Scope project

3.2 手動安裝

將整個 process-guard/ 資料夾複製到對應位置:

工具層級路徑
Codex使用者~/.agents/skills/process-guard/
Codex專案.agents/skills/process-guard/
Claude Code使用者~/.claude/skills/process-guard/
Claude Code專案.claude/skills/process-guard/

3.3 強制執行模式 (Strict Enforcement)

若希望代理在每次執行指令時都自動遵守 Process Guard 規範,可將持久指令片段 (persistent instruction snippet) 貼入代理設定:

  • Codex:將 references/AGENTS.md.snippet 貼入 ~/.codex/AGENTS.md 或專案根目錄的 AGENTS.md
  • Claude Code:將 references/CLAUDE.md.snippet 貼入 ~/.claude/CLAUDE.md 或專案根目錄的 CLAUDE.md

3.4 解析技能目錄 (Resolve Skill Directory)

在腳本中使用 Process Guard 前,需先解析安裝路徑:

 1PROCESS_GUARD_DIR="${CLAUDE_SKILL_DIR:-}"
 2if [ -z "$PROCESS_GUARD_DIR" ]; then
 3  for d in \
 4    .agents/skills/process-guard \
 5    .claude/skills/process-guard \
 6    "$HOME/.agents/skills/process-guard" \
 7    "$HOME/.claude/skills/process-guard"; do
 8    if [ -f "$d/SKILL.md" ]; then PROCESS_GUARD_DIR="$d"; break; fi
 9  done
10fi
11[ -n "$PROCESS_GUARD_DIR" ] || { echo "process-guard skill directory not found" >&2; exit 1; }

3.5 自訂執行目錄

預設的程序狀態目錄是 .agent-run/,可透過環境變數覆蓋:

1export PROCESS_GUARD_RUN_DIR=".my-run"

4. 使用方式與程式碼範例 (Usage & Code Examples)

4.1 範例一:有限指令守護執行 (Guarded Finite Commands)

最基本的使用場景——執行測試、建置等預期會結束的指令,加上 timeout 保護。

 1# 執行 npm test,120 秒後若未完成則強制終止
 2"$PROCESS_GUARD_DIR/scripts/guarded-run.sh" --timeout 120 -- npm test
 3
 4# 執行 Python 測試,180 秒 timeout
 5"$PROCESS_GUARD_DIR/scripts/guarded-run.sh" --timeout 180 -- pytest
 6
 7# 執行 Cargo 測試,並記錄日誌
 8"$PROCESS_GUARD_DIR/scripts/guarded-run.sh" --timeout 300 --log-name cargo-test -- cargo test
 9
10# 執行 Go 測試
11"$PROCESS_GUARD_DIR/scripts/guarded-run.sh" --timeout 120 -- go test ./...

運作原理

  1. 若系統有 timeout 指令(GNU coreutils),直接使用 timeout --preserve-status --kill-after=5s
  2. 若沒有,則手動 fork 指令並啟動一個 watcher,在 timeout 時間到後發送 SIGTERM,5 秒後若仍未結束則 SIGKILL
  3. 可選擇使用 --log-name 將輸出同時寫入 .agent-run/logs/<name>.once.log

4.2 範例二:一次性臨時伺服器 (Temporary Server with Auto-Cleanup)

這是最推薦的模式——啟動開發伺服器、執行檢查、自動清理,全部在一條指令內完成。

1# 啟動 Next.js 開發伺服器 → 等待 port 3000 就緒 → 執行 curl 檢查 → 自動停止
2"$PROCESS_GUARD_DIR/scripts/with-managed-process.sh" \
3  --name next-web \
4  --command "pnpm dev --host 127.0.0.1 --port 3000" \
5  --port 3000 \
6  --timeout 60 \
7  -- \
8  "curl -fsS http://127.0.0.1:3000 >/dev/null"
1# 啟動 FastAPI 伺服器 → 等待 health endpoint 回應 → 檢查 → 自動停止
2"$PROCESS_GUARD_DIR/scripts/with-managed-process.sh" \
3  --name fastapi \
4  --command "uvicorn app.main:app --host 127.0.0.1 --port 8000" \
5  --health-url "http://127.0.0.1:8000/health" \
6  --timeout 60 \
7  -- \
8  "curl -fsS http://127.0.0.1:8000/health >/dev/null"

運作原理

  1. 呼叫 start-managed-process.sh 啟動程序
  2. 等待就緒(透過 --port--health-url
  3. 執行 -- 後面的檢查指令
  4. 無論檢查成功或失敗,都會用 cleanup trap 停止程序
  5. 這避免了「檢查失敗後忘記停止伺服器」的常見問題

4.3 範例三:多步驟長期程序管理 (Multi-Step Long-Running Process)

當需要對一個長期執行的程序進行多次檢查時,手動控制啟動與停止。

 1# 第一步:啟動 API 伺服器
 2"$PROCESS_GUARD_DIR/scripts/start-managed-process.sh" \
 3  --name api \
 4  --command "uvicorn app.main:app --host 127.0.0.1 --port 8000" \
 5  --health-url "http://127.0.0.1:8000/health" \
 6  --timeout 60
 7
 8# 第二步:執行多個檢查
 9curl -fsS http://127.0.0.1:8000/health
10curl -fsS http://127.0.0.1:8000/api/v1/status
11"$PROCESS_GUARD_DIR/scripts/guarded-run.sh" --timeout 60 -- pytest tests/integration/
12
13# 第三步:檢視所有受管理程序狀態
14"$PROCESS_GUARD_DIR/scripts/status-managed-processes.sh"
15
16# 第四步:停止程序
17"$PROCESS_GUARD_DIR/scripts/stop-managed-process.sh" --name api

無埠號的 Worker 程序

 1# 啟動一個沒有網路介面的 Python worker,用日誌比對確認就緒
 2"$PROCESS_GUARD_DIR/scripts/start-managed-process.sh" \
 3  --name worker \
 4  --command "python worker.py" \
 5  --ready-log-pattern "ready|started|connected" \
 6  --timeout 60
 7
 8# 檢視狀態
 9"$PROCESS_GUARD_DIR/scripts/status-managed-processes.sh"
10
11# 停止
12"$PROCESS_GUARD_DIR/scripts/stop-managed-process.sh" --name worker

4.4 Docker / Kubernetes 安全模式

Process Guard 嚴格禁止前景執行 Docker 指令(會永遠阻塞):

 1# 正確做法:detached 模式 + 有限檢查 + 清理
 2docker compose up -d
 3curl -fsS http://127.0.0.1:3000/health
 4docker compose down
 5
 6# 錯誤做法(永遠不要這樣做):
 7# docker compose up       ← 會永遠阻塞
 8# kubectl logs -f pod/x   ← 會永遠追蹤
 9
10# 正確做法:有限擷取
11kubectl logs --tail=200 pod/name

4.5 測試監聽模式轉換 (Test Watcher Conversion)

Process Guard 要求將 watch 模式測試轉為有限模式:

原始指令 (Watch Mode)轉換後 (Finite Mode)
vitest --watchvitest run
jest --watchjest --runInBand
pytest-watchpytest
cargo watch -x testcargo test
npm run test:watch檢查 package.json 找到有限測試指令

5. 技術細節深度解析 (Technical Deep Dive)

5.1 指令分類決策樹 (Command Classification)

Process Guard 的分類不依賴程式語言,而是依據執行期行為 (runtime behavior)


flowchart TD
    START["收到指令"] --> Q1{"是否開啟 shell/REPL?\nbash, python, node, irb..."}
    Q1 -->|"是"| INTERACTIVE["互動式 (Interactive)\n→ 拒絕,除非使用者明確要求"]

    Q1 -->|"否"| Q2{"是否綁定埠號或\n維持長期連線?"}
    Q2 -->|"是"| LONGRUN["長期執行 (Long-running)\n→ 受管理背景程序"]

    Q2 -->|"否"| Q3{"是否監聽檔案變動\n或自動重載?"}
    Q3 -->|"是"| LONGRUN

    Q3 -->|"否"| Q4{"是否為 worker/daemon/\nbot/miner/indexer/scheduler?"}
    Q4 -->|"是"| LONGRUN

    Q4 -->|"否"| Q5{"是否追蹤日誌\n(tail -f)?"}
    Q5 -->|"是"| LONGRUN

    Q5 -->|"否"| FINITE["有限指令 (Finite)\n→ guarded-run + timeout"]

    style INTERACTIVE fill:#ffcdd2
    style LONGRUN fill:#fff9c4
    style FINITE fill:#c8e6c9

5.2 guarded-run.sh 實作剖析

guarded-run.sh 的核心邏輯有兩條路徑:

路徑 A — 系統有 timeout 指令 (GNU coreutils)

1timeout --preserve-status --kill-after=5s "${TIMEOUT_SECONDS}s" "$@"
  • --preserve-status:保留原始指令的 exit code(而非回傳 timeout 的 exit code 124)
  • --kill-after=5sSIGTERM 後 5 秒若仍未結束,發送 SIGKILL

路徑 B — 系統沒有 timeout(如 macOS 預設)

手動 fork 指令,啟動一個 watcher 程序計時,時間到後手動 kill

5.3 start-managed-process.sh 實作剖析

這是最複雜的腳本,主要流程:

  1. 驗證輸入:檢查名稱格式(只允許 [A-Za-z0-9._-])、埠號格式
  2. 衝突檢查:若同名程序已在執行,拒絕啟動;若目標埠號已被佔用,拒絕啟動(不會自動殺死不明程序)
  3. 啟動程序:優先使用 setsid 建立獨立 session(方便後續程序組清理),若不可用則直接 fork
  4. 就緒等待:每秒輪詢 (polling) 就緒條件,最多等待 --timeout
  5. 失敗處理:若程序在就緒前就結束 (exit),印出最後 120 行日誌供除錯

埠號監聽偵測的多重降級 (Fallback Chain)

1lsof → ss → netstat → Python socket

腳本會依序嘗試這些工具,確保在各種 Linux/macOS 環境下都能運作。

5.4 kill_tree 遞迴清理

 1kill_tree() {
 2  local pid="$1"
 3  # 1. 程序組終止
 4  kill -TERM -"$pid" 2>/dev/null || true
 5  kill -TERM "$pid" 2>/dev/null || true
 6  sleep "$GRACE_SECONDS"
 7
 8  # 2. 遞迴子程序清理
 9  children="$(pgrep -P "$pid" 2>/dev/null || true)"
10  for child in $children; do
11    kill_tree "$child" || true
12  done
13
14  # 3. 強制終止
15  kill -KILL -"$pid" 2>/dev/null || true
16  kill -KILL "$pid" 2>/dev/null || true
17}

這個函式的關鍵設計:

  • 同時嘗試程序組 (-pid) 和個別程序 (pid) 的終止
  • 使用 pgrep -P 遞迴找出所有子程序
  • SIGTERM(優雅關閉),再 SIGKILL(強制關閉)

5.5 安全防護機制

防護項目機制
Timeout 保護有限指令必須設定 timeout,防止無預期的永久等待
埠號衝突保護不自動殺死不明程序,改為報告衝突
殭屍程序偵測 (Zombie Detection)ps -o stat= 檢查程序狀態,排除 Z 狀態的殭屍程序
名稱格式驗證程序名稱只允許 [A-Za-z0-9._-],防止路徑注入 (path injection)
禁止廣範殺死嚴禁 killall nodepkill python 等可能殺死使用者其他程序的指令

6. 與生態系的關係 (Ecosystem Relationships)

6.1 支援的 AI 編碼代理

代理工具整合方式技能路徑
Codex (OpenAI)Agent Skills 格式~/.agents/skills/process-guard/.agents/skills/process-guard/
Claude Code (Anthropic)Claude Skills 格式~/.claude/skills/process-guard/.claude/skills/process-guard/

Process Guard 刻意只使用兩個平台共通的格式(SKILL.md + scripts/ + references/),不依賴任何平台特有功能(如 Claude Code 的 allowed-tools 或 Codex 特有的設定)。

6.2 支援的語言與框架

Process Guard 是語言無關 (language-agnostic) 的。它透過行為分類來處理任何語言的指令:

語言/框架有限指令範例長期執行指令範例
Node.js / Next.jsnpm test, pnpm buildpnpm dev, next dev, vite
Python / FastAPIpytest, python scripts/migrate.pyuvicorn app:app, flask run, streamlit run
Rustcargo test, cargo buildcargo run --bin server, cargo watch
Gogo test ./...go run ./cmd/server, air
Java / Springmvn testmvn spring-boot:run, gradle bootRun
.NETdotnet testdotnet run, dotnet watch
PHPphp artisan testphp artisan serve, php artisan queue:work
Dockerdocker compose builddocker compose up(需用 -d detached)

6.3 與其他工具的互動

  • .agent-run/ 狀態目錄:是統一的程序追蹤格式,Codex 和 Claude Code 共用。可透過 PROCESS_GUARD_RUN_DIR 環境變數分開。
  • CI/CD:可在 CI 環境中使用 guarded-run 確保測試指令有 timeout 保護。
  • Docker:不取代 Docker 的程序管理,而是確保代理不會用前景模式啟動 Docker 服務。

7. 優缺點分析 (Strengths & Limitations)

7.1 優勢 (Strengths)

項目說明
跨平台一致性同一套 skill 同時支援 Codex 和 Claude Code,安裝路徑不同但行為一致
雙系統腳本每個功能都提供 Bash (.sh) 和 PowerShell (.ps1) 版本,涵蓋 Linux/macOS/Windows
防禦性設計埠號衝突不自動殺死不明程序、殭屍程序偵測、名稱格式驗證、禁止廣範 kill
多重就緒檢查四種就緒偵測方式(HTTP、TCP、自定義指令、日誌比對),按優先序選用
程序樹清理使用 setsid + 遞迴 pgrep + 分級 kill(TERM → KILL),不會遺漏子程序
零依賴只需要 Bash/PowerShell + 基本系統工具(lsof/ss/curl),無需額外安裝
多語系文件README 提供英文、繁體中文、簡體中文、日文、韓文五種語言

7.2 限制 (Limitations)

項目說明
無圖形介面純 CLI 工具,無法管理需要 GUI 的應用程式
單機限制狀態儲存在本地 .agent-run/,不支援多機或分散式程序管理
手動分類模糊指令(如 cargo runpython main.py)需要人工或代理判斷是有限還是長期執行
輪詢就緒就緒檢查採每秒輪詢 (polling) 而非事件驅動 (event-driven),高延遲環境下可能需要調高 timeout
無程序重啟程序崩潰時不會自動重啟(不是 supervisor/systemd 的替代品)
PowerShell 依賴Windows 環境需要 PowerShell,且部分功能(如 setsid 程序組管理)在 Windows 上的行為不同

7.3 適用場景 vs 不適用場景

適用不適用
AI 編碼代理(Codex、Claude Code)的日常開發任務生產環境的程序管理(請用 systemd、supervisor、PM2)
開發伺服器的臨時啟停長期執行的生產服務
CI/CD 中的 timeout 保護容器編排(請用 Docker Compose、Kubernetes)
防止代理阻塞和資源洩漏多機分散式程序管理

附錄:常用指令速查表

場景指令
有限指令 + timeoutguarded-run.sh --timeout 120 -- <cmd>
臨時伺服器 + 自動清理with-managed-process.sh --name <n> --command "<cmd>" --port <p> --timeout 60 -- "<check>"
啟動受管理程序start-managed-process.sh --name <n> --command "<cmd>" --health-url <url> --timeout 60
停止受管理程序stop-managed-process.sh --name <n>
檢視所有程序狀態status-managed-processes.sh
清理所有程序cleanup-managed-processes.sh
安裝到兩個代理install.sh --target both --scope user

本教學基於 yanowo/agent-process-guard 撰寫,最後更新:2026-06-10