以 Node.js 實作的 Ralph 迭代式 AI 開發迴圈工具,透過 GitHub Copilot SDK 與事件串流,讓 AI 依照同一個任務反覆迭代,直到達成完成條件或達到限制。
Create release 會提供跨平台的獨立可執行檔,下載後放到 PATH 即可使用。
Apple Silicon 請用 arm64,Intel 請用 x64(可用 uname -m 確認)。
# Apple Silicon (M1/M2/M3)
curl -L -o copilot-ralph https://github.com/doggy8088/copilot-ralph/releases/latest/download/copilot-ralph-macos-arm64
# Intel
# curl -L -o copilot-ralph https://github.com/doggy8088/copilot-ralph/releases/latest/download/copilot-ralph-macos-x64
chmod +x copilot-ralph
sudo mv copilot-ralph /usr/local/bin/curl -L -o copilot-ralph https://github.com/doggy8088/copilot-ralph/releases/latest/download/copilot-ralph-linux-x64
chmod +x copilot-ralph
sudo mv copilot-ralph /usr/local/bin/$dest = "$env:LOCALAPPDATA\\copilot-ralph"
New-Item -ItemType Directory -Force -Path $dest | Out-Null
Invoke-WebRequest -Uri "https://github.com/doggy8088/copilot-ralph/releases/latest/download/copilot-ralph.exe" -OutFile "$dest\\copilot-ralph.exe"
[Environment]::SetEnvironmentVariable("Path", $env:Path + ";$dest", "User")若出現「已損毀」、「無法開啟,因為無法驗證開發者」或直接被系統 killed,多半是檔案帶有 quarantine 屬性或尚未被 macOS 放行。
請先走 官方安全流程(推薦):
- 於 Finder 對檔案按右鍵 → 打開,或
- 到 系統設定 → 隱私權與安全性,在底部按 仍要打開
若上述方式仍無法執行,再使用以下方式移除 quarantine(屬於繞過 Gatekeeper):
xattr -d com.apple.quarantine /path/to/copilot-ralph
chmod +x /path/to/copilot-ralph- Node.js 18 或以上版本
- Bun(建置與測試用)
- npm 或 yarn
- GitHub Copilot 帳號與授權(需要有效的 Copilot 訂閱)
-
複製或下載專案
git clone <repository-url> cd copilot-ralph-node
-
安裝相依套件
npm install
-
執行型別檢查
npm run typecheck
-
執行單元測試
bun run test或使用 watch 模式進行開發:
bun run test:watch
使用 tsx 直接執行 TypeScript 原始碼(無需先建置):
npm run dev -- run "請加上單元測試"-
建置專案
bun run build
建置後的檔案會輸出至
dist/目錄。 -
執行建置後的 CLI
node dist/cli-entry.js run "請加上單元測試"
# 指定迭代次數與完成短語
node dist/cli-entry.js run --max-iterations 3 --promise "Task complete!" "修正登入流程"
# 讀取 Markdown 或文字檔案作為 prompt
node dist/cli-entry.js run task.md在開發期間,你可以將此工具安裝為全域指令,這樣就能在任何目錄直接使用 copilot-ralph 指令。
npm i -g @willh/copilot-ralph這是最適合開發階段的方法,程式碼修改後會立即生效,無需重新安裝。
# 1. 先建置專案
bun run build
# 2. 建立全域符號連結
npm link
# 3. 現在可以在任何目錄執行
copilot-ralph run "你的任務"解除安裝:
# 在專案目錄下執行
npm unlink
# 或者在任何目錄執行
npm unlink -g @willh/copilot-ralph這個方法會實際安裝到全域,適合測試正式安裝後的行為。
# 1. 先建置專案
bun run build
# 2. 全域安裝(從當前目錄)
npm install -g .
# 3. 現在可以在任何目錄執行
copilot-ralph run "你的任務"解除安裝:
npm uninstall -g @willh/copilot-ralph- 使用
npm link後,每次修改原始碼都需要重新執行bun run build,才能讓全域指令使用到最新的程式碼。 - 如果遇到權限問題(Windows 需要管理員權限,macOS/Linux 可能需要
sudo),請以管理員身份執行終端機。 - 開發完成後記得解除連結,避免與正式發布的版本衝突。
- CLI 解析參數與 prompt,組成
LoopConfig。 - 依設定建立 Copilot SDK Client 並啟動 session。
- 啟動
LoopEngine,進入迭代迴圈。 - 每輪迭代傳送 prompt,讀取 SDK 事件串流(文字、工具呼叫、錯誤)。
- 偵測完成短語(promise)或達到條件後結束。
- 輸出摘要與退出碼。
完整細節可參考 docs/運作流程詳解.md。
- 迭代式 AI 迴圈執行
- 事件串流即時輸出
- 完成短語(promise)偵測
- 工具呼叫事件顯示
- 逾時與取消處理
copilot-ralph run "<你的任務描述>"--max-iterations:最大迭代次數(預設 10)--timeout:最大執行時間(預設 30m)--promise:完成短語(預設任務完成!🥇)--model:模型名稱(預設gpt-5-mini)--working-dir:工作目錄(預設.)--streaming:是否開啟串流(預設true)--system-prompt:自訂系統提示(可為文字、Markdown 或 .txt 檔案)--system-prompt-file:系統提示模板檔案路徑(支援{{PROMISE}};與--system-prompt同時使用時會被忽略)--system-prompt-mode:append或replace(搭配--system-prompt或--system-prompt-file)--log-level:debug、info、warn、error--session-id:指定 Copilot session ID 以便在下一次執行時延續上下文--dry-run:僅顯示設定,不執行迴圈--azure-endpoint:Azure OpenAI 端點 URL--azure-api-key:Azure OpenAI API 金鑰--azure-api-version:Azure OpenAI API 版本(預設2024-10-21)--azure-wire-api:API 格式,completions或responses(預設completions)
Copilot Ralph 支援「自帶金鑰」(Bring Your Own Key, BYOK)模式,讓你可以使用自己的 Azure OpenAI、OpenAI 或 Anthropic API,而非預設的 GitHub Copilot API。
AZURE_OPENAI_ENDPOINT 是你的 Azure OpenAI 資源端點 URL,格式如下:
https://<your-resource-name>.openai.azure.com/
範例:
| 資源名稱 | 端點 URL |
|---|---|
my-openai |
https://my-openai.openai.azure.com/ |
contoso-ai |
https://contoso-ai.openai.azure.com/ |
duotify-ai-coding-agent |
https://duotify-ai-coding-agent.openai.azure.com/ |
注意:結尾的
/可加可不加,系統會自動處理。
你可以在 Azure Portal 的 Azure OpenAI 資源頁面 → 「Keys and Endpoint」找到此端點。
在 Azure OpenAI 中,Deployment Name 就是 --model 參數的值。當你在 Azure Portal 建立模型部署時設定的名稱,就是要傳入 --model 的值。
例如:
- 如果你在 Azure 建立了一個名為
gpt-4o-deployment的部署,則使用--model gpt-4o-deployment - 如果部署名稱是
my-gpt-4o,則使用--model my-gpt-4o
將金鑰存放在環境變數中,避免在命令列中暴露敏感資訊。
# 設定環境變數
export AZURE_OPENAI_ENDPOINT="https://your-resource.openai.azure.com/"
export AZURE_OPENAI_API_KEY="your-api-key"
export AZURE_OPENAI_API_VERSION="2024-10-21" # 可選,預設為 2024-10-21
export AZURE_OPENAI_WIRE_API="completions" # 可選,預設為 completions
# 執行命令(--model 填入你的 deployment name)
copilot-ralph run --model your-deployment-name "請幫我加上單元測試"Windows PowerShell:
$env:AZURE_OPENAI_ENDPOINT = "https://your-resource.openai.azure.com/"
$env:AZURE_OPENAI_API_KEY = "your-api-key"
$env:AZURE_OPENAI_API_VERSION = "2024-10-21"
$env:AZURE_OPENAI_WIRE_API = "completions"
copilot-ralph run --model your-deployment-name "請幫我加上單元測試"Windows CMD:
set AZURE_OPENAI_ENDPOINT=https://your-resource.openai.azure.com/
set AZURE_OPENAI_API_KEY=your-api-key
set AZURE_OPENAI_API_VERSION=2024-10-21
set AZURE_OPENAI_WIRE_API=completions
copilot-ralph run --model your-deployment-name "請幫我加上單元測試"copilot-ralph run \
--model your-deployment-name \
--azure-endpoint "https://your-resource.openai.azure.com/" \
--azure-api-key "your-api-key" \
--azure-api-version "2024-10-21" \
--azure-wire-api "completions" \
"請幫我加上單元測試"注意:CLI 參數的優先順序高於環境變數。
如果你要使用 Azure OpenAI 的 Responses API(而非傳統的 Chat Completions API),請將 wireApi 設為 responses:
# 環境變數方式
export AZURE_OPENAI_WIRE_API="responses"
# 或 CLI 參數方式
copilot-ralph run \
--model your-deployment-name \
--azure-endpoint "https://your-resource.openai.azure.com/" \
--azure-api-key "your-api-key" \
--azure-wire-api "responses" \
"請幫我加上單元測試"| wireApi 值 | 說明 |
|---|---|
completions |
使用 Chat Completions API(預設) |
responses |
使用 Responses API |
如果你在程式碼中直接使用 SDK,可以透過 withProvider 或 ProviderConfig 設定自訂 provider。
import { newCopilotClient, withModel, withProvider } from "@willh/copilot-ralph";
// 使用 Chat Completions API(預設)
const client = newCopilotClient(
withModel("your-deployment-name"), // deployment name
withProvider({
type: "azure",
baseUrl: "https://your-resource.openai.azure.com/",
apiKey: "your-api-key",
wireApi: "completions", // 可選,預設為 "completions"
azure: {
apiVersion: "2024-10-21" // 可選,預設為 "2024-10-21"
}
})
);import { newCopilotClient, withModel, withProvider } from "@willh/copilot-ralph";
// 使用 Responses API
const client = newCopilotClient(
withModel("your-deployment-name"), // deployment name
withProvider({
type: "azure",
baseUrl: "https://your-resource.openai.azure.com/",
apiKey: "your-api-key",
wireApi: "responses", // 使用 Responses API
azure: {
apiVersion: "2024-10-21"
}
})
);import { newCopilotClient, withModel, withProvider } from "@willh/copilot-ralph";
const client = newCopilotClient(
withModel("gpt-4o"),
withProvider({
type: "openai",
baseUrl: "https://api.openai.com/v1",
apiKey: "sk-your-openai-api-key"
})
);import { newCopilotClient, withModel, withProvider } from "@willh/copilot-ralph";
const client = newCopilotClient(
withModel("claude-sonnet-4-20250514"),
withProvider({
type: "anthropic",
baseUrl: "https://api.anthropic.com",
apiKey: "your-anthropic-api-key"
})
);某些服務需要使用 Bearer Token 而非 API Key:
import { newCopilotClient, withModel, withProvider } from "@willh/copilot-ralph";
const client = newCopilotClient(
withModel("your-model"),
withProvider({
type: "openai",
baseUrl: "https://your-custom-endpoint.com/v1",
bearerToken: "your-bearer-token" // 會設定 Authorization: Bearer header
})
);對於本地運行的模型(如 Ollama),API Key 是可選的:
import { newCopilotClient, withModel, withProvider } from "@willh/copilot-ralph";
const client = newCopilotClient(
withModel("llama3.2"),
withProvider({
type: "openai",
baseUrl: "http://localhost:11434/v1"
// apiKey 可省略
})
);| 參數 | 類型 | 必填 | 說明 |
|---|---|---|---|
type |
"openai" | "azure" | "anthropic" |
否 | Provider 類型,預設為 "openai" |
baseUrl |
string |
是 | API 端點 URL |
apiKey |
string |
否 | API 金鑰(本地模型可省略) |
bearerToken |
string |
否 | Bearer Token,優先於 apiKey |
wireApi |
"completions" | "responses" |
否 | API 格式(僅 openai/azure),預設 "completions" |
azure.apiVersion |
string |
否 | Azure API 版本,預設 "2024-10-21" |
| 環境變數 | CLI 參數 | 說明 |
|---|---|---|
AZURE_OPENAI_ENDPOINT |
--azure-endpoint |
Azure OpenAI 端點 URL |
AZURE_OPENAI_API_KEY |
--azure-api-key |
Azure OpenAI API 金鑰 |
AZURE_OPENAI_API_VERSION |
--azure-api-version |
Azure API 版本(預設 2024-10-21) |
AZURE_OPENAI_WIRE_API |
--azure-wire-api |
API 格式:completions 或 responses(預設 completions) |
系統訊息模板會要求模型在任務完全完成時輸出:
<promise>{你的完成短語}</promise>
只有當 AI 回覆中精準包含該字串(大小寫與字元完全一致)時,才會被視為完成信號。未輸出 promise 並不代表失敗,可能只是達到 --max-iterations 或 timeout。
0:完成1:失敗2:取消3:逾時4:達到最大迭代次數(保留)
- 運作流程詳解:
docs/運作流程詳解.md
# 型別檢查
npm run typecheck
# 執行測試
bun run test
# 測試 watch 模式(開發時使用)
bun run test:watch
# 建置專案
bun run build
# 開發模式執行
npm run dev -- run "<你的任務>"
# 版本號碼更新
npm run bump