Compare commits

...

2 Commits

Author SHA1 Message Date
Ben Brandt
becf1d4f0a Update to claude agent sdk 0.1.27 (#125)
Also simplifies the permission mode workaround so we don't have to
change the profile immediately, which could have raced with client
changes anwyay.
2025-10-27 12:34:43 +01:00
Guillaume Sabran
5491bb8dcc Allow for the package to be used as a dependency, while preserving existing behavior when run (#124)
This change will allow for this package to be used directly, without
launching a subprocess and communicating over stdio.

---------

Co-authored-by: Ben Brandt <benjamin.j.brandt@gmail.com>
2025-10-27 11:10:41 +00:00
6 changed files with 75 additions and 48 deletions

View File

@@ -1,5 +1,10 @@
# Changelog
## 0.7.0
- Allow importing from this package as a library in addition to running it as a CLI. Allows for easier integration into existing node applications.
- Update to @anthropic-ai/claude-agent-sdk@v0.1.27
## 0.6.10
- Provide `agentInfo` on initialization response.

22
package-lock.json generated
View File

@@ -1,17 +1,17 @@
{
"name": "@zed-industries/claude-code-acp",
"version": "0.6.10",
"version": "0.7.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@zed-industries/claude-code-acp",
"version": "0.6.10",
"version": "0.7.0",
"license": "Apache-2.0",
"dependencies": {
"@agentclientprotocol/sdk": "0.5.1",
"@anthropic-ai/claude-agent-sdk": "0.1.26",
"@anthropic-ai/claude-code": "2.0.26",
"@anthropic-ai/claude-agent-sdk": "0.1.27",
"@anthropic-ai/claude-code": "2.0.27",
"@modelcontextprotocol/sdk": "1.20.2",
"diff": "8.0.2",
"express": "5.1.0",
@@ -19,7 +19,7 @@
"uuid": "13.0.0"
},
"bin": {
"claude-code-acp": "dist/index.js"
"claude-code-acp": "dist/cli.js"
},
"devDependencies": {
"@anthropic-ai/sdk": "0.67.0",
@@ -49,9 +49,9 @@
}
},
"node_modules/@anthropic-ai/claude-agent-sdk": {
"version": "0.1.26",
"resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk/-/claude-agent-sdk-0.1.26.tgz",
"integrity": "sha512-daVGe5x6KOFy9DKyDojw15eljBP+tPx+spAyGll/Rp/B6t+NP0Oiwpaiib0afjbCRbqXkWEHUJPE3yDFrMcZlA==",
"version": "0.1.27",
"resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk/-/claude-agent-sdk-0.1.27.tgz",
"integrity": "sha512-HuMPW6spj2q8FODiP/WBCqUZAYGwDPoI1EpicP9KUXvuYk+2MZQYSaD7oiN6iNPupR2T5oJ2HY/D9OzjyCD2Mw==",
"license": "SEE LICENSE IN README.md",
"engines": {
"node": ">=18.0.0"
@@ -69,9 +69,9 @@
}
},
"node_modules/@anthropic-ai/claude-code": {
"version": "2.0.26",
"resolved": "https://registry.npmjs.org/@anthropic-ai/claude-code/-/claude-code-2.0.26.tgz",
"integrity": "sha512-bk/sxGdTEbI0N7g+pTwYq5CNUjdAcvIKXvf/x5oRV9q24b42uq3gijrZGycSbWmtYTIjbzFAHeWw5n7Ic43/6w==",
"version": "2.0.27",
"resolved": "https://registry.npmjs.org/@anthropic-ai/claude-code/-/claude-code-2.0.27.tgz",
"integrity": "sha512-Ml4tnBeJu+K7MUFLTg8q7U2BE39Vx2D+KI7t86QnFX/K90c58ekFDUUDnfAp1PqTe9vRms6vARJiWzNxrePinA==",
"license": "SEE LICENSE IN README.md",
"bin": {
"claude": "cli.js"

View File

@@ -4,9 +4,9 @@
"access": "public"
},
"bin": {
"claude-code-acp": "./dist/index.js"
"claude-code-acp": "./dist/cli.js"
},
"version": "0.6.10",
"version": "0.7.0",
"description": "An ACP-compatible coding agent powered by the Claude Code SDK (TypeScript)",
"main": "dist/index.js",
"type": "module",
@@ -18,7 +18,7 @@
],
"scripts": {
"build": "tsc",
"start": "node dist/index.js",
"start": "node dist/cli.js",
"dev": "npm run build && npm run start",
"lint": "eslint src --ext .ts",
"lint:fix": "eslint src --ext .ts --fix",
@@ -52,8 +52,8 @@
"license": "Apache-2.0",
"dependencies": {
"@agentclientprotocol/sdk": "0.5.1",
"@anthropic-ai/claude-agent-sdk": "0.1.26",
"@anthropic-ai/claude-code": "2.0.26",
"@anthropic-ai/claude-agent-sdk": "0.1.27",
"@anthropic-ai/claude-code": "2.0.27",
"@modelcontextprotocol/sdk": "1.20.2",
"diff": "8.0.2",
"express": "5.1.0",

View File

@@ -210,9 +210,10 @@ export class ClaudeAcpAgent implements Agent {
mcpServers,
systemPrompt,
settingSources: ["user", "project", "local"],
// If we want bypassPermissions to be an option, we have to start the session with it on.
// We change it immediately back to default below before returning the session.
permissionMode: IS_ROOT ? permissionMode : "bypassPermissions",
// If we want bypassPermissions to be an option, we have to allow it here.
// But it doesn't work in root mode, so we only activate it if it will work.
allowDangerouslySkipPermissions: !IS_ROOT,
permissionMode,
permissionPromptToolName: PERMISSION_TOOL_NAME,
stderr: (err) => console.error(err),
// note: although not documented by the types, passing an absolute path
@@ -258,10 +259,6 @@ export class ClaudeAcpAgent implements Agent {
const availableCommands = await getAvailableSlashCommands(q);
const models = await getAvailableModels(q);
// Change it back to default
if (!IS_ROOT) {
await q.setPermissionMode(permissionMode);
}
// Needs to happen after we return the session
setTimeout(() => {

26
src/cli.ts Normal file
View File

@@ -0,0 +1,26 @@
#!/usr/bin/env node
// Load managed settings and apply environment variables
import { loadManagedSettings, applyEnvironmentSettings } from "./utils.js";
const managedSettings = loadManagedSettings();
if (managedSettings) {
applyEnvironmentSettings(managedSettings);
}
// stdout is used to send messages to the client
// we redirect everything else to stderr to make sure it doesn't interfere with ACP
console.log = console.error;
console.info = console.error;
console.warn = console.error;
console.debug = console.error;
process.on("unhandledRejection", (reason, promise) => {
console.error("Unhandled Rejection at:", promise, "reason:", reason);
});
import { runAcp } from "./acp-agent.js";
runAcp();
// Keep process alive
process.stdin.resume();

View File

@@ -1,26 +1,25 @@
#!/usr/bin/env node
// Export the main agent class and utilities for library usage
export {
ClaudeAcpAgent,
runAcp,
toAcpNotifications,
streamEventToAcpNotifications,
} from "./acp-agent.js";
export {
loadManagedSettings,
applyEnvironmentSettings,
nodeToWebReadable,
nodeToWebWritable,
Pushable,
unreachable,
} from "./utils.js";
export {
createMcpServer,
createPermissionMcpServer,
PERMISSION_TOOL_NAME,
toolNames,
} from "./mcp-server.js";
export { toolInfoFromToolUse, planEntries, toolUpdateFromToolResult } from "./tools.js";
// Load managed settings and apply environment variables
import { loadManagedSettings, applyEnvironmentSettings } from "./utils.js";
const managedSettings = loadManagedSettings();
if (managedSettings) {
applyEnvironmentSettings(managedSettings);
}
// stdout is used to send messages to the client
// we redirect everything else to stderr to make sure it doesn't interfere with ACP
console.log = console.error;
console.info = console.error;
console.warn = console.error;
console.debug = console.error;
process.on("unhandledRejection", (reason, promise) => {
console.error("Unhandled Rejection at:", promise, "reason:", reason);
});
import { runAcp as runAcp } from "./acp-agent.js";
runAcp();
// Keep process alive
process.stdin.resume();
// Export types
export type { ClaudePlanEntry } from "./tools.js";