From e38694bd5757bb740608c0d017be2619c81ae268 Mon Sep 17 00:00:00 2001 From: ironerumi <39033099+ironerumi@users.noreply.github.com> Date: Tue, 10 Mar 2026 21:30:42 +0900 Subject: [PATCH 1/5] feat: add Factory Droid as built-in agent Register droid via droid-acp adapter at position 8 (after copilot). Also fixes missing cursor entry in skills/acpx/SKILL.md. Co-Authored-By: Claude Opus 4.6 --- README.md | 1 + agents/Droid.md | 5 +++++ agents/README.md | 2 ++ skills/acpx/SKILL.md | 2 ++ src/agent-registry.ts | 2 ++ test/agent-registry.test.ts | 1 + 6 files changed, 13 insertions(+) create mode 100644 agents/Droid.md diff --git a/README.md b/README.md index 71ee3613..4edf81c1 100644 --- a/README.md +++ b/README.md @@ -288,6 +288,7 @@ Built-ins: | `gemini` | native (`gemini --experimental-acp`) | [Gemini CLI](https://github.com/google/gemini-cli) | | `cursor` | native (`cursor-agent acp`) | [Cursor CLI](https://cursor.com/docs/cli/acp) | | `copilot` | native (`copilot --acp --stdio`) | [GitHub Copilot CLI](https://docs.github.com/copilot/how-tos/copilot-chat/use-copilot-chat-in-the-command-line) | +| `droid` | [droid-acp](https://github.com/kingsword09/droid-acp) | [Factory Droid](https://www.factory.ai) | | `kimi` | native (`kimi acp`) | [Kimi CLI](https://github.com/MoonshotAI/kimi-cli) | | `opencode` | `npx -y opencode-ai acp` | [OpenCode](https://opencode.ai) | | `kiro` | native (`kiro-cli acp`) | [Kiro CLI](https://kiro.dev) | diff --git a/agents/Droid.md b/agents/Droid.md new file mode 100644 index 00000000..1a5caf4d --- /dev/null +++ b/agents/Droid.md @@ -0,0 +1,5 @@ +# Droid + +- Built-in name: `droid` +- Default command: `npx droid-acp` +- Upstream: https://www.factory.ai diff --git a/agents/README.md b/agents/README.md index 28cb03ea..bbb85e3b 100644 --- a/agents/README.md +++ b/agents/README.md @@ -9,6 +9,7 @@ Built-in agents: - `gemini -> gemini --experimental-acp` - `cursor -> cursor-agent acp` - `copilot -> copilot --acp --stdio` +- `droid -> npx droid-acp` - `kimi -> kimi acp` - `opencode -> npx -y opencode-ai acp` - `kiro -> kiro-cli acp` @@ -20,6 +21,7 @@ Harness-specific docs in this directory: - [Gemini](Gemini.md): built-in `gemini -> gemini --experimental-acp` - [Cursor](Cursor.md): built-in `cursor -> cursor-agent acp` - [Copilot](Copilot.md): built-in `copilot -> copilot --acp --stdio` +- [Droid](Droid.md): built-in `droid -> npx droid-acp` - [Kimi](Kimi.md): built-in `kimi -> kimi acp` - [OpenCode](OpenCode.md): built-in `opencode -> npx -y opencode-ai acp` - [Kiro](Kiro.md): built-in `kiro -> kiro-cli acp` diff --git a/skills/acpx/SKILL.md b/skills/acpx/SKILL.md index fb96ea01..ba84fc73 100644 --- a/skills/acpx/SKILL.md +++ b/skills/acpx/SKILL.md @@ -81,7 +81,9 @@ Friendly agent names resolve to commands: - `kiro` -> `kiro-cli acp` - `pi` -> `npx pi-acp` - `kilocode` -> `npx -y @kilocode/cli acp` +- `cursor` -> `cursor-agent acp` - `qwen` -> `qwen --acp` +- `droid` -> `npx droid-acp` Rules: diff --git a/src/agent-registry.ts b/src/agent-registry.ts index 0e1dd855..8857e5ee 100644 --- a/src/agent-registry.ts +++ b/src/agent-registry.ts @@ -2,6 +2,7 @@ const ACP_ADAPTER_PACKAGE_RANGES = { pi: "^0.0.22", codex: "^0.9.5", claude: "^0.21.0", + droid: "^0.6.1", } as const; export const AGENT_REGISTRY: Record = { @@ -12,6 +13,7 @@ export const AGENT_REGISTRY: Record = { gemini: "gemini --experimental-acp", cursor: "cursor-agent acp", copilot: "copilot --acp --stdio", + droid: `npx droid-acp@${ACP_ADAPTER_PACKAGE_RANGES.droid}`, kimi: "kimi acp", opencode: "npx -y opencode-ai acp", kiro: "kiro-cli acp", diff --git a/test/agent-registry.test.ts b/test/agent-registry.test.ts index 4a30dc79..80c19515 100644 --- a/test/agent-registry.test.ts +++ b/test/agent-registry.test.ts @@ -29,6 +29,7 @@ test("listBuiltInAgents preserves the required built-in example order", () => { "cursor", "copilot", ]); + assert.equal(agents[7], "droid"); }); test("default agent is codex", () => { From 9add191a5fb11aad871487c30978115d87889618 Mon Sep 17 00:00:00 2001 From: ironerumi <39033099+ironerumi@users.noreply.github.com> Date: Tue, 10 Mar 2026 23:51:05 +0900 Subject: [PATCH 2/5] refactor: switch droid to native ACP command Use official `droid exec --output-format acp` instead of community droid-acp adapter. Factory's native command is the supported path. Co-Authored-By: Claude Opus 4.6 --- README.md | 2 +- agents/Droid.md | 2 +- agents/README.md | 4 ++-- skills/acpx/SKILL.md | 2 +- src/agent-registry.ts | 3 +-- 5 files changed, 6 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 4edf81c1..64b29209 100644 --- a/README.md +++ b/README.md @@ -288,7 +288,7 @@ Built-ins: | `gemini` | native (`gemini --experimental-acp`) | [Gemini CLI](https://github.com/google/gemini-cli) | | `cursor` | native (`cursor-agent acp`) | [Cursor CLI](https://cursor.com/docs/cli/acp) | | `copilot` | native (`copilot --acp --stdio`) | [GitHub Copilot CLI](https://docs.github.com/copilot/how-tos/copilot-chat/use-copilot-chat-in-the-command-line) | -| `droid` | [droid-acp](https://github.com/kingsword09/droid-acp) | [Factory Droid](https://www.factory.ai) | +| `droid` | native (`droid exec --output-format acp`) | [Factory Droid](https://www.factory.ai) | | `kimi` | native (`kimi acp`) | [Kimi CLI](https://github.com/MoonshotAI/kimi-cli) | | `opencode` | `npx -y opencode-ai acp` | [OpenCode](https://opencode.ai) | | `kiro` | native (`kiro-cli acp`) | [Kiro CLI](https://kiro.dev) | diff --git a/agents/Droid.md b/agents/Droid.md index 1a5caf4d..644f19fe 100644 --- a/agents/Droid.md +++ b/agents/Droid.md @@ -1,5 +1,5 @@ # Droid - Built-in name: `droid` -- Default command: `npx droid-acp` +- Default command: `droid exec --output-format acp` - Upstream: https://www.factory.ai diff --git a/agents/README.md b/agents/README.md index bbb85e3b..14dc17c1 100644 --- a/agents/README.md +++ b/agents/README.md @@ -9,7 +9,7 @@ Built-in agents: - `gemini -> gemini --experimental-acp` - `cursor -> cursor-agent acp` - `copilot -> copilot --acp --stdio` -- `droid -> npx droid-acp` +- `droid -> droid exec --output-format acp` - `kimi -> kimi acp` - `opencode -> npx -y opencode-ai acp` - `kiro -> kiro-cli acp` @@ -21,7 +21,7 @@ Harness-specific docs in this directory: - [Gemini](Gemini.md): built-in `gemini -> gemini --experimental-acp` - [Cursor](Cursor.md): built-in `cursor -> cursor-agent acp` - [Copilot](Copilot.md): built-in `copilot -> copilot --acp --stdio` -- [Droid](Droid.md): built-in `droid -> npx droid-acp` +- [Droid](Droid.md): built-in `droid -> droid exec --output-format acp` - [Kimi](Kimi.md): built-in `kimi -> kimi acp` - [OpenCode](OpenCode.md): built-in `opencode -> npx -y opencode-ai acp` - [Kiro](Kiro.md): built-in `kiro -> kiro-cli acp` diff --git a/skills/acpx/SKILL.md b/skills/acpx/SKILL.md index ba84fc73..53d969fc 100644 --- a/skills/acpx/SKILL.md +++ b/skills/acpx/SKILL.md @@ -83,7 +83,7 @@ Friendly agent names resolve to commands: - `kilocode` -> `npx -y @kilocode/cli acp` - `cursor` -> `cursor-agent acp` - `qwen` -> `qwen --acp` -- `droid` -> `npx droid-acp` +- `droid` -> `droid exec --output-format acp` Rules: diff --git a/src/agent-registry.ts b/src/agent-registry.ts index 8857e5ee..99d88348 100644 --- a/src/agent-registry.ts +++ b/src/agent-registry.ts @@ -2,7 +2,6 @@ const ACP_ADAPTER_PACKAGE_RANGES = { pi: "^0.0.22", codex: "^0.9.5", claude: "^0.21.0", - droid: "^0.6.1", } as const; export const AGENT_REGISTRY: Record = { @@ -13,7 +12,7 @@ export const AGENT_REGISTRY: Record = { gemini: "gemini --experimental-acp", cursor: "cursor-agent acp", copilot: "copilot --acp --stdio", - droid: `npx droid-acp@${ACP_ADAPTER_PACKAGE_RANGES.droid}`, + droid: "droid exec --output-format acp", kimi: "kimi acp", opencode: "npx -y opencode-ai acp", kiro: "kiro-cli acp", From f900f4b8ad5dc145749c3278412d270b33a6d976 Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Tue, 10 Mar 2026 23:48:01 -0400 Subject: [PATCH 3/5] docs: fix acpx skill built-in order --- skills/acpx/SKILL.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/skills/acpx/SKILL.md b/skills/acpx/SKILL.md index 02a2c593..99a30ca5 100644 --- a/skills/acpx/SKILL.md +++ b/skills/acpx/SKILL.md @@ -71,19 +71,19 @@ If prompt text is omitted and stdin is piped, `acpx` reads prompt text from stdi Friendly agent names resolve to commands: +- `pi` -> `npx pi-acp` +- `openclaw` -> `openclaw acp` - `codex` -> `npx @zed-industries/codex-acp` - `claude` -> `npx -y @zed-industries/claude-agent-acp` -- `copilot` -> `copilot --acp --stdio` - `gemini` -> `gemini --acp` -- `openclaw` -> `openclaw acp` +- `cursor` -> `cursor-agent acp` +- `copilot` -> `copilot --acp --stdio` +- `droid` -> `droid exec --output-format acp` - `kimi` -> `kimi acp` - `opencode` -> `npx -y opencode-ai acp` - `kiro` -> `kiro-cli acp` -- `pi` -> `npx pi-acp` - `kilocode` -> `npx -y @kilocode/cli acp` -- `cursor` -> `cursor-agent acp` - `qwen` -> `qwen --acp` -- `droid` -> `droid exec --output-format acp` Rules: From aae9b53269dd5c01871f8d125394c96d838a741d Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Wed, 11 Mar 2026 00:26:09 -0400 Subject: [PATCH 4/5] test: lock full built-in agent order --- test/agent-registry.test.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/test/agent-registry.test.ts b/test/agent-registry.test.ts index 80c19515..f5b16d41 100644 --- a/test/agent-registry.test.ts +++ b/test/agent-registry.test.ts @@ -20,7 +20,7 @@ test("resolveAgentCommand returns raw value for unknown agents", () => { test("listBuiltInAgents preserves the required built-in example order", () => { const agents = listBuiltInAgents(); assert.deepEqual(agents, Object.keys(AGENT_REGISTRY)); - assert.deepEqual(agents.slice(0, 7), [ + assert.deepEqual(agents, [ "pi", "openclaw", "codex", @@ -28,8 +28,13 @@ test("listBuiltInAgents preserves the required built-in example order", () => { "gemini", "cursor", "copilot", + "droid", + "kimi", + "opencode", + "kiro", + "kilocode", + "qwen", ]); - assert.equal(agents[7], "droid"); }); test("default agent is codex", () => { From 709cbb381bf5f285258076625a2d41575b9e7dcd Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Wed, 11 Mar 2026 00:26:44 -0400 Subject: [PATCH 5/5] test: cover droid built-in resolution --- test/integration.test.ts | 65 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/test/integration.test.ts b/test/integration.test.ts index 31b89e61..3e18083d 100644 --- a/test/integration.test.ts +++ b/test/integration.test.ts @@ -72,6 +72,33 @@ test("integration: built-in cursor agent resolves to cursor-agent acp", async () }); }); +test("integration: built-in droid agent resolves to droid exec --output-format acp", async () => { + await withTempHome(async (homeDir) => { + const cwd = await fs.mkdtemp(path.join(os.tmpdir(), "acpx-integration-cwd-")); + const fakeBinDir = await fs.mkdtemp(path.join(os.tmpdir(), "acpx-fake-droid-")); + + try { + await writeFakeDroidAgent(fakeBinDir); + + const result = await runCli( + ["--approve-all", "--cwd", cwd, "--format", "quiet", "droid", "exec", "echo hello"], + homeDir, + { + env: { + PATH: `${fakeBinDir}${path.delimiter}${process.env.PATH ?? ""}`, + }, + }, + ); + + assert.equal(result.code, 0, result.stderr); + assert.match(result.stdout, /hello/); + } finally { + await fs.rm(fakeBinDir, { recursive: true, force: true }); + await fs.rm(cwd, { recursive: true, force: true }); + } + }); +}); + test("integration: exec forwards model, allowed-tools, and max-turns in session/new _meta", async () => { await withTempHome(async (homeDir) => { const cwd = await fs.mkdtemp(path.join(os.tmpdir(), "acpx-integration-cwd-")); @@ -1529,6 +1556,44 @@ async function writeFakeCursorAgent(binDir: string): Promise { ); } +async function writeFakeDroidAgent(binDir: string): Promise { + if (process.platform === "win32") { + await fs.writeFile( + path.join(binDir, "droid.cmd"), + [ + "@echo off", + "setlocal", + 'if /I "%~1"=="exec" shift', + 'if /I "%~1"=="--output-format" shift', + 'if /I "%~1"=="acp" shift', + `"${process.execPath}" "${MOCK_AGENT_PATH}" %*`, + "", + ].join("\r\n"), + { encoding: "utf8" }, + ); + return; + } + + await fs.writeFile( + path.join(binDir, "droid"), + [ + "#!/bin/sh", + 'if [ "$1" = "exec" ]; then', + " shift", + "fi", + 'if [ "$1" = "--output-format" ]; then', + " shift", + "fi", + 'if [ "$1" = "acp" ]; then', + " shift", + "fi", + `exec "${process.execPath}" "${MOCK_AGENT_PATH}" "$@"`, + "", + ].join("\n"), + { encoding: "utf8", mode: 0o755 }, + ); +} + async function withTempHome(run: (homeDir: string) => Promise): Promise { const tempHome = await fs.mkdtemp(path.join(os.tmpdir(), "acpx-integration-home-")); try {