mirror of
https://github.com/agentclientprotocol/claude-agent-acp.git
synced 2026-10-27 12:40:32 +00:00
Add single-file executable using bun (#332)
This adds a single-file executable using bun. The trick is to use a separate flag for ACP `--acp` and spawn the regular `cli.js` bundled by the Agent SDK if no flags are passed. This was, we can pass ourselves as pathToClaudeCodeExecutable.
This commit is contained in:
89
.github/workflows/publish.yml
vendored
89
.github/workflows/publish.yml
vendored
@@ -1,11 +1,81 @@
|
|||||||
name: Publish Package to npmjs
|
name: Publish and Release
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
tags:
|
tags:
|
||||||
- "v*.*.*"
|
- "v*.*.*"
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
publish-npm:
|
build-binaries:
|
||||||
|
name: Build (${{ matrix.target }})
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
timeout-minutes: 15
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
fail-fast: true
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- target: bun-linux-x64
|
||||||
|
artifact: claude-agent-acp-linux-x64
|
||||||
|
archive: claude-agent-acp-linux-x64.tar.gz
|
||||||
|
- target: bun-linux-arm64
|
||||||
|
artifact: claude-agent-acp-linux-arm64
|
||||||
|
archive: claude-agent-acp-linux-arm64.tar.gz
|
||||||
|
- target: bun-linux-x64-musl
|
||||||
|
artifact: claude-agent-acp-linux-x64-musl
|
||||||
|
archive: claude-agent-acp-linux-x64-musl.tar.gz
|
||||||
|
- target: bun-linux-arm64-musl
|
||||||
|
artifact: claude-agent-acp-linux-arm64-musl
|
||||||
|
archive: claude-agent-acp-linux-arm64-musl.tar.gz
|
||||||
|
- target: bun-darwin-x64
|
||||||
|
artifact: claude-agent-acp-darwin-x64
|
||||||
|
archive: claude-agent-acp-darwin-x64.zip
|
||||||
|
- target: bun-darwin-arm64
|
||||||
|
artifact: claude-agent-acp-darwin-arm64
|
||||||
|
archive: claude-agent-acp-darwin-arm64.zip
|
||||||
|
- target: bun-windows-x64
|
||||||
|
artifact: claude-agent-acp-windows-x64.exe
|
||||||
|
archive: claude-agent-acp-windows-x64.zip
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
|
||||||
|
|
||||||
|
- uses: oven-sh/setup-bun@3d267786b128fe76c2f16a390aa2448b815359f3
|
||||||
|
with:
|
||||||
|
bun-version: latest
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: bun install
|
||||||
|
|
||||||
|
- name: Build binary
|
||||||
|
run: |
|
||||||
|
bun build src/static-entry.ts \
|
||||||
|
--compile \
|
||||||
|
--target ${{ matrix.target }} \
|
||||||
|
--define 'process.env.CLAUDE_AGENT_ACP_IS_SINGLE_FILE_BUN="true"' \
|
||||||
|
--outfile ${{ matrix.artifact }}
|
||||||
|
|
||||||
|
- name: Compress binary
|
||||||
|
run: |
|
||||||
|
if [[ "${{ matrix.archive }}" == *.zip ]]; then
|
||||||
|
zip ${{ matrix.archive }} ${{ matrix.artifact }}
|
||||||
|
else
|
||||||
|
tar czf ${{ matrix.archive }} ${{ matrix.artifact }}
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Upload artifact
|
||||||
|
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f
|
||||||
|
with:
|
||||||
|
name: ${{ matrix.archive }}
|
||||||
|
path: ${{ matrix.archive }}
|
||||||
|
|
||||||
|
publish-npm:
|
||||||
|
name: Publish to npm
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: [build-binaries]
|
||||||
|
if: startsWith(github.ref, 'refs/tags/')
|
||||||
environment: release # Optional: for enhanced security
|
environment: release # Optional: for enhanced security
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
@@ -22,15 +92,26 @@ jobs:
|
|||||||
- run: npm ci
|
- run: npm ci
|
||||||
- run: npm run build
|
- run: npm run build
|
||||||
- run: npm publish
|
- run: npm publish
|
||||||
|
|
||||||
release:
|
release:
|
||||||
|
name: Create Release
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: [publish-npm]
|
needs: [build-binaries, publish-npm]
|
||||||
|
if: startsWith(github.ref, 'refs/tags/')
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
|
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
|
||||||
|
|
||||||
|
- name: Download all artifacts
|
||||||
|
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131
|
||||||
|
with:
|
||||||
|
path: artifacts
|
||||||
|
merge-multiple: true
|
||||||
|
|
||||||
- name: Create Release
|
- name: Create Release
|
||||||
id: create_release
|
|
||||||
uses: softprops/action-gh-release@6da8fa9354ddfdc4aeace5fc48d7f679b5214090
|
uses: softprops/action-gh-release@6da8fa9354ddfdc4aeace5fc48d7f679b5214090
|
||||||
with:
|
with:
|
||||||
generate_release_notes: true
|
generate_release_notes: true
|
||||||
|
files: artifacts/*
|
||||||
|
|||||||
@@ -48,6 +48,11 @@ You can then use `claude-agent-acp` as a regular ACP agent:
|
|||||||
ANTHROPIC_API_KEY=sk-... claude-agent-acp
|
ANTHROPIC_API_KEY=sk-... claude-agent-acp
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Single-file executable
|
||||||
|
|
||||||
|
Pre-built single-file binaries are available on the [Releases](https://github.com/zed-industries/claude-agent-acp/releases) page for Linux, macOS, and Windows.
|
||||||
|
These binaries bundle everything needed and don't require Node.js.
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
Apache-2.0
|
Apache-2.0
|
||||||
|
|||||||
@@ -230,6 +230,10 @@ export type ToolUseCache = {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function isStaticBinary(): boolean {
|
||||||
|
return process.env.CLAUDE_AGENT_ACP_IS_SINGLE_FILE_BUN !== undefined;
|
||||||
|
}
|
||||||
|
|
||||||
// Bypass Permissions doesn't work if we are a root/sudo user
|
// Bypass Permissions doesn't work if we are a root/sudo user
|
||||||
const IS_ROOT = (process.geteuid?.() ?? process.getuid?.()) === 0;
|
const IS_ROOT = (process.geteuid?.() ?? process.getuid?.()) === 0;
|
||||||
const ALLOW_BYPASS = !IS_ROOT || !!process.env.IS_SANDBOX;
|
const ALLOW_BYPASS = !IS_ROOT || !!process.env.IS_SANDBOX;
|
||||||
@@ -264,12 +268,22 @@ export class ClaudeAcpAgent implements Agent {
|
|||||||
|
|
||||||
// If client supports terminal-auth capability, use that instead.
|
// If client supports terminal-auth capability, use that instead.
|
||||||
if (request.clientCapabilities?._meta?.["terminal-auth"] === true) {
|
if (request.clientCapabilities?._meta?.["terminal-auth"] === true) {
|
||||||
const cliPath = fileURLToPath(import.meta.resolve("@anthropic-ai/claude-agent-sdk/cli.js"));
|
let command: string;
|
||||||
|
let args: string[];
|
||||||
|
|
||||||
|
if (isStaticBinary()) {
|
||||||
|
command = process.execPath;
|
||||||
|
args = ["--cli"];
|
||||||
|
} else {
|
||||||
|
const cliPath = fileURLToPath(import.meta.resolve("@anthropic-ai/claude-agent-sdk/cli.js"));
|
||||||
|
command = "node";
|
||||||
|
args = [cliPath];
|
||||||
|
}
|
||||||
|
|
||||||
authMethod._meta = {
|
authMethod._meta = {
|
||||||
"terminal-auth": {
|
"terminal-auth": {
|
||||||
command: "node",
|
command,
|
||||||
args: [cliPath],
|
args,
|
||||||
label: "Claude Login",
|
label: "Claude Login",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -1231,9 +1245,12 @@ export class ClaudeAcpAgent implements Agent {
|
|||||||
// note: although not documented by the types, passing an absolute path
|
// note: although not documented by the types, passing an absolute path
|
||||||
// here works to find zed's managed node version.
|
// here works to find zed's managed node version.
|
||||||
executable: process.execPath as any,
|
executable: process.execPath as any,
|
||||||
...(process.env.CLAUDE_CODE_EXECUTABLE && {
|
executableArgs: isStaticBinary() ? ["--cli"] : undefined,
|
||||||
pathToClaudeCodeExecutable: process.env.CLAUDE_CODE_EXECUTABLE,
|
...(process.env.CLAUDE_CODE_EXECUTABLE
|
||||||
}),
|
? { pathToClaudeCodeExecutable: process.env.CLAUDE_CODE_EXECUTABLE }
|
||||||
|
: isStaticBinary()
|
||||||
|
? { pathToClaudeCodeExecutable: process.execPath }
|
||||||
|
: {}),
|
||||||
disallowedTools,
|
disallowedTools,
|
||||||
tools: { type: "preset", preset: "claude_code" },
|
tools: { type: "preset", preset: "claude_code" },
|
||||||
hooks: {
|
hooks: {
|
||||||
|
|||||||
7
src/static-entry.ts
Normal file
7
src/static-entry.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
if (process.argv.includes("--cli")) {
|
||||||
|
process.argv = process.argv.filter((arg) => arg !== "--cli");
|
||||||
|
// @ts-expect-error -- no types
|
||||||
|
await import("@anthropic-ai/claude-agent-sdk/cli.js");
|
||||||
|
} else {
|
||||||
|
await import("./index.js");
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user