mirror of
https://github.com/agentclientprotocol/claude-agent-acp.git
synced 2026-10-27 04:30:59 +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:
|
||||
push:
|
||||
tags:
|
||||
- "v*.*.*"
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
publish-npm:
|
||||
build-binaries:
|
||||
name: Build (${{ matrix.target }})
|
||||
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
|
||||
permissions:
|
||||
contents: read
|
||||
@@ -22,15 +92,26 @@ jobs:
|
||||
- run: npm ci
|
||||
- run: npm run build
|
||||
- run: npm publish
|
||||
|
||||
release:
|
||||
name: Create Release
|
||||
runs-on: ubuntu-latest
|
||||
needs: [publish-npm]
|
||||
needs: [build-binaries, publish-npm]
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
|
||||
|
||||
- name: Download all artifacts
|
||||
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131
|
||||
with:
|
||||
path: artifacts
|
||||
merge-multiple: true
|
||||
|
||||
- name: Create Release
|
||||
id: create_release
|
||||
uses: softprops/action-gh-release@6da8fa9354ddfdc4aeace5fc48d7f679b5214090
|
||||
with:
|
||||
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
|
||||
```
|
||||
|
||||
#### 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
|
||||
|
||||
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
|
||||
const IS_ROOT = (process.geteuid?.() ?? process.getuid?.()) === 0;
|
||||
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 (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 = {
|
||||
"terminal-auth": {
|
||||
command: "node",
|
||||
args: [cliPath],
|
||||
command,
|
||||
args,
|
||||
label: "Claude Login",
|
||||
},
|
||||
};
|
||||
@@ -1231,9 +1245,12 @@ export class ClaudeAcpAgent implements Agent {
|
||||
// note: although not documented by the types, passing an absolute path
|
||||
// here works to find zed's managed node version.
|
||||
executable: process.execPath as any,
|
||||
...(process.env.CLAUDE_CODE_EXECUTABLE && {
|
||||
pathToClaudeCodeExecutable: process.env.CLAUDE_CODE_EXECUTABLE,
|
||||
}),
|
||||
executableArgs: isStaticBinary() ? ["--cli"] : undefined,
|
||||
...(process.env.CLAUDE_CODE_EXECUTABLE
|
||||
? { pathToClaudeCodeExecutable: process.env.CLAUDE_CODE_EXECUTABLE }
|
||||
: isStaticBinary()
|
||||
? { pathToClaudeCodeExecutable: process.execPath }
|
||||
: {}),
|
||||
disallowedTools,
|
||||
tools: { type: "preset", preset: "claude_code" },
|
||||
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