claude-code-acp 0.2.0__tar.gz → 0.3.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,441 @@
1
+ Metadata-Version: 2.4
2
+ Name: claude-code-acp
3
+ Version: 0.3.1
4
+ Summary: ACP-compatible agent for Claude Code (Python version)
5
+ Project-URL: Homepage, https://github.com/yazelin/claude-code-acp-py
6
+ Project-URL: Repository, https://github.com/yazelin/claude-code-acp-py
7
+ Project-URL: Issues, https://github.com/yazelin/claude-code-acp-py/issues
8
+ Author: yazelin
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: acp,agent,anthropic,claude,claude-code,python
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Requires-Python: >=3.10
20
+ Requires-Dist: agent-client-protocol>=0.7.0
21
+ Requires-Dist: claude-agent-sdk>=0.1.29
22
+ Description-Content-Type: text/markdown
23
+
24
+ # Claude Code ACP (Python)
25
+
26
+ [![PyPI](https://img.shields.io/pypi/v/claude-code-acp)](https://pypi.org/project/claude-code-acp/)
27
+ [![Python](https://img.shields.io/pypi/pyversions/claude-code-acp)](https://pypi.org/project/claude-code-acp/)
28
+ [![License](https://img.shields.io/github/license/yazelin/claude-code-acp-py)](https://github.com/yazelin/claude-code-acp-py/blob/main/LICENSE)
29
+
30
+ **Python implementation of ACP (Agent Client Protocol) for Claude Code.**
31
+
32
+ This package bridges the [Claude Agent SDK](https://github.com/anthropics/claude-agent-sdk-python) with the [Agent Client Protocol (ACP)](https://agentclientprotocol.com/), providing two ways to use Claude:
33
+
34
+ 1. **ACP Server** - Connect Claude to any ACP-compatible editor (Zed, Neovim, JetBrains, etc.)
35
+ 2. **Python Client** - Event-driven API for building Python applications with Claude
36
+
37
+ ## Features
38
+
39
+ - **Uses Claude CLI subscription** - No API key needed, uses your existing Claude subscription
40
+ - **Full ACP protocol support** - Compatible with Zed, Neovim, and other ACP clients
41
+ - **Bidirectional communication** - Permission requests, tool calls, streaming responses
42
+ - **Event-driven Python API** - Decorator-based handlers for easy integration
43
+ - **Session management** - Create, fork, resume, list sessions
44
+ - **Multiple permission modes** - default, acceptEdits, plan, bypassPermissions
45
+
46
+ ## Installation
47
+
48
+ ```bash
49
+ pip install claude-code-acp
50
+ ```
51
+
52
+ Or with uv:
53
+
54
+ ```bash
55
+ uv tool install claude-code-acp
56
+ ```
57
+
58
+ ## Requirements
59
+
60
+ - Python 3.10+
61
+ - Claude CLI installed and authenticated (`claude /login`)
62
+
63
+ ---
64
+
65
+ ## Components
66
+
67
+ | Class | Type | Description |
68
+ |-------|------|-------------|
69
+ | `ClaudeAcpAgent` | ACP Server | For editors (Zed, Neovim) to connect |
70
+ | `ClaudeClient` | Python API | Event-driven wrapper (uses agent internally) |
71
+ | `AcpClient` | ACP Client | Connect to any ACP agent via subprocess |
72
+
73
+ ---
74
+
75
+ ## Usage 1: ACP Server for Editors
76
+
77
+ Run as an ACP server to connect Claude to your editor:
78
+
79
+ ```bash
80
+ claude-code-acp
81
+ ```
82
+
83
+ ### Zed Editor
84
+
85
+ Add to your Zed `settings.json`:
86
+
87
+ ```json
88
+ {
89
+ "agent_servers": {
90
+ "Claude Code Python": {
91
+ "type": "custom",
92
+ "command": "claude-code-acp",
93
+ "args": [],
94
+ "env": {}
95
+ }
96
+ }
97
+ }
98
+ ```
99
+
100
+ Then open the Agent Panel (`Ctrl+?` / `Cmd+?`) and select "Claude Code Python" from the `+` menu.
101
+
102
+ ### Other Editors
103
+
104
+ Any [ACP-compatible client](https://agentclientprotocol.com/overview/clients) can connect by spawning `claude-code-acp` as a subprocess and communicating via stdio.
105
+
106
+ ---
107
+
108
+ ## Usage 2: Python Event-Driven API
109
+
110
+ Use `ClaudeClient` for building Python applications with Claude:
111
+
112
+ ```python
113
+ import asyncio
114
+ from claude_code_acp import ClaudeClient
115
+
116
+ async def main():
117
+ client = ClaudeClient(cwd=".")
118
+
119
+ @client.on_text
120
+ async def handle_text(text: str):
121
+ """Called for each text chunk from Claude."""
122
+ print(text, end="", flush=True)
123
+
124
+ @client.on_tool_start
125
+ async def handle_tool_start(tool_id: str, name: str, input: dict):
126
+ """Called when Claude starts using a tool."""
127
+ print(f"\n🔧 {name}")
128
+
129
+ @client.on_tool_end
130
+ async def handle_tool_end(tool_id: str, status: str, output):
131
+ """Called when a tool completes."""
132
+ icon = "✅" if status == "completed" else "❌"
133
+ print(f" {icon}")
134
+
135
+ @client.on_permission
136
+ async def handle_permission(name: str, input: dict) -> bool:
137
+ """Called when Claude needs permission. Return True to allow."""
138
+ print(f"🔐 Permission requested: {name}")
139
+ return True # or prompt user
140
+
141
+ @client.on_complete
142
+ async def handle_complete():
143
+ """Called when the query completes."""
144
+ print("\n--- Done ---")
145
+
146
+ # Send a query
147
+ response = await client.query("Create a hello.py file that prints Hello World")
148
+ print(f"\nFull response: {response}")
149
+
150
+ asyncio.run(main())
151
+ ```
152
+
153
+ ### Event Handlers
154
+
155
+ | Decorator | Arguments | Description |
156
+ |-----------|-----------|-------------|
157
+ | `@client.on_text` | `(text: str)` | Streaming text chunks from Claude |
158
+ | `@client.on_thinking` | `(text: str)` | Thinking/reasoning blocks |
159
+ | `@client.on_tool_start` | `(tool_id, name, input)` | Tool execution started |
160
+ | `@client.on_tool_end` | `(tool_id, status, output)` | Tool execution completed |
161
+ | `@client.on_permission` | `(name, input) -> bool` | Permission request (return True/False) |
162
+ | `@client.on_error` | `(exception)` | Error occurred |
163
+ | `@client.on_complete` | `()` | Query completed |
164
+
165
+ ### Client Methods
166
+
167
+ ```python
168
+ # Start a new session
169
+ session_id = await client.start_session()
170
+
171
+ # Send a query (returns full response text)
172
+ response = await client.query("Your prompt here")
173
+
174
+ # Set permission mode
175
+ await client.set_mode("acceptEdits") # or "default", "plan", "bypassPermissions"
176
+ ```
177
+
178
+ ---
179
+
180
+ ## Usage 3: ACP Client (Connect to Any Agent)
181
+
182
+ Use `AcpClient` to connect to any ACP-compatible agent:
183
+
184
+ ```python
185
+ import asyncio
186
+ from claude_code_acp import AcpClient
187
+
188
+ async def main():
189
+ # Connect to claude-code-acp (Python version)
190
+ client = AcpClient(command="claude-code-acp")
191
+
192
+ # Or connect to the TypeScript version
193
+ # client = AcpClient(command="npx", args=["@zed-industries/claude-code-acp"])
194
+
195
+ # Or any other ACP agent
196
+ # client = AcpClient(command="my-custom-agent")
197
+
198
+ @client.on_text
199
+ async def handle_text(text: str):
200
+ print(text, end="", flush=True)
201
+
202
+ @client.on_tool_start
203
+ async def handle_tool(tool_id: str, name: str, input: dict):
204
+ print(f"\n🔧 {name}")
205
+
206
+ @client.on_permission
207
+ async def handle_permission(name: str, input: dict, options: list) -> str:
208
+ """Return option_id: 'allow', 'reject', or 'allow_always'"""
209
+ print(f"🔐 Permission: {name}")
210
+ return "allow"
211
+
212
+ @client.on_complete
213
+ async def handle_complete():
214
+ print("\n--- Done ---")
215
+
216
+ async with client:
217
+ response = await client.prompt("What files are here?")
218
+
219
+ asyncio.run(main())
220
+ ```
221
+
222
+ ### Connect to Different Agents
223
+
224
+ ```python
225
+ from claude_code_acp import AcpClient
226
+
227
+ # Connect to our Claude ACP server
228
+ claude = AcpClient(command="claude-code-acp")
229
+
230
+ # Connect to Gemini CLI
231
+ gemini = AcpClient(command="gemini", args=["--experimental-acp"])
232
+
233
+ # Connect to TypeScript version
234
+ ts_claude = AcpClient(command="npx", args=["@zed-industries/claude-code-acp"])
235
+ ```
236
+
237
+ ### AcpClient vs ClaudeClient
238
+
239
+ | Feature | `ClaudeClient` | `AcpClient` |
240
+ |---------|---------------|-------------|
241
+ | Uses | Claude Agent SDK directly | Any ACP agent via subprocess |
242
+ | Connection | In-process | Subprocess + stdio |
243
+ | Agents | Claude only | Any ACP-compatible agent |
244
+ | Use case | Simple Python apps | Multi-agent, testing, flexibility |
245
+
246
+ ### Tested Agents
247
+
248
+ | Agent | Command | Status |
249
+ |-------|---------|--------|
250
+ | claude-code-acp (this package) | `claude-code-acp` | ✅ Works |
251
+ | Gemini CLI | `gemini --experimental-acp` | ✅ Works |
252
+ | TypeScript version | `npx @zed-industries/claude-code-acp` | ✅ Compatible |
253
+
254
+ ---
255
+
256
+ ## Architecture
257
+
258
+ ```
259
+ ┌──────────────────────────────────────────────────────────────────────────────┐
260
+ │ claude-code-acp Package │
261
+ ├──────────────────────────────────────────────────────────────────────────────┤
262
+ │ │
263
+ │ ACP SERVER (for editors) ACP CLIENT (for Python apps) │
264
+ │ ───────────────────────── ──────────────────────────── │
265
+ │ │
266
+ │ ┌─────────────┐ ┌─────────────┐ │
267
+ │ │ Zed/Neovim │ │ Your Python │ │
268
+ │ │ Editor │ │ App │ │
269
+ │ └──────┬──────┘ └──────┬──────┘ │
270
+ │ │ │ │
271
+ │ │ ACP │ uses │
272
+ │ ▼ ▼ │
273
+ │ ┌──────────────────┐ ┌─────────────────┐ │
274
+ │ │ ClaudeAcpAgent │ │ AcpClient │───┐ │
275
+ │ │ (ACP Server) │ │ (ACP Client) │ │ │
276
+ │ └────────┬─────────┘ └────────┬────────┘ │ │
277
+ │ │ │ │ can connect to │
278
+ │ │ │ ACP │ any ACP agent │
279
+ │ ▼ ▼ │ │
280
+ │ ┌──────────────────┐ ┌─────────────────┐ │ │
281
+ │ │ ClaudeClient │ │ claude-code-acp│◄─┘ │
282
+ │ │ (Python wrapper) │ │ Gemini CLI │ │
283
+ │ └────────┬─────────┘ │ Other agents │ │
284
+ │ │ └─────────────────┘ │
285
+ │ │ │
286
+ │ ▼ │
287
+ │ ┌──────────────────┐ │
288
+ │ │ Claude Agent SDK │ │
289
+ │ └────────┬─────────┘ │
290
+ │ │ │
291
+ │ ▼ │
292
+ │ ┌──────────────────┐ │
293
+ │ │ Claude CLI │ │
294
+ │ │ (Subscription) │ │
295
+ │ └──────────────────┘ │
296
+ │ │
297
+ └──────────────────────────────────────────────────────────────────────────────┘
298
+ ```
299
+
300
+ ---
301
+
302
+ ## What We Built
303
+
304
+ This project combines two official SDKs to create a complete Python solution:
305
+
306
+ ### Integrated Components
307
+
308
+ | Component | Source | Purpose |
309
+ |-----------|--------|---------|
310
+ | [Agent Client Protocol SDK](https://github.com/anthropics/agent-client-protocol) | Anthropic | ACP server/client protocol implementation |
311
+ | [Claude Agent SDK](https://github.com/anthropics/claude-agent-sdk-python) | Anthropic | Claude CLI wrapper with streaming support |
312
+
313
+ ### Our Contributions
314
+
315
+ 1. **ClaudeAcpAgent** (`agent.py`)
316
+ - Bridges Claude Agent SDK with ACP protocol
317
+ - Converts Claude messages to ACP session updates
318
+ - Handles bidirectional permission requests
319
+ - Session management (create, fork, resume, list)
320
+
321
+ 2. **ClaudeClient** (`client.py`)
322
+ - Event-driven Python API with decorators
323
+ - Smart text deduplication for streaming
324
+ - Simple permission handling
325
+ - Clean async/await interface
326
+
327
+ 3. **ACP Server Entry Point**
328
+ - Standalone `claude-code-acp` command
329
+ - Direct integration with Zed and other ACP clients
330
+ - No configuration needed
331
+
332
+ ### Why This Package?
333
+
334
+ | Approach | API Key | Subscription | ACP Support | Event-Driven |
335
+ |----------|---------|--------------|-------------|--------------|
336
+ | Anthropic API directly | ✅ Required | ❌ | ❌ | ❌ |
337
+ | Claude Agent SDK | ❌ | ✅ Uses CLI | ❌ | Partial |
338
+ | **claude-code-acp** | ❌ | ✅ Uses CLI | ✅ Full | ✅ Full |
339
+
340
+ ---
341
+
342
+ ## Examples
343
+
344
+ ### Simple Chat
345
+
346
+ ```python
347
+ import asyncio
348
+ from claude_code_acp import ClaudeClient
349
+
350
+ async def main():
351
+ client = ClaudeClient()
352
+
353
+ @client.on_text
354
+ async def on_text(text):
355
+ print(text, end="")
356
+
357
+ while True:
358
+ user_input = input("\nYou: ")
359
+ if user_input.lower() == "quit":
360
+ break
361
+ await client.query(user_input)
362
+
363
+ asyncio.run(main())
364
+ ```
365
+
366
+ ### File Operations with Permission Control
367
+
368
+ ```python
369
+ import asyncio
370
+ from claude_code_acp import ClaudeClient
371
+
372
+ async def main():
373
+ client = ClaudeClient(cwd="/path/to/project")
374
+
375
+ @client.on_text
376
+ async def on_text(text):
377
+ print(text, end="")
378
+
379
+ @client.on_permission
380
+ async def on_permission(name, input):
381
+ response = input(f"Allow '{name}'? [y/N]: ")
382
+ return response.lower() == "y"
383
+
384
+ await client.query("Refactor the main.py file to use async/await")
385
+
386
+ asyncio.run(main())
387
+ ```
388
+
389
+ ### Auto-approve Mode
390
+
391
+ ```python
392
+ import asyncio
393
+ from claude_code_acp import ClaudeClient
394
+
395
+ async def main():
396
+ client = ClaudeClient(cwd=".")
397
+
398
+ # Bypass all permission checks
399
+ await client.set_mode("bypassPermissions")
400
+
401
+ @client.on_text
402
+ async def on_text(text):
403
+ print(text, end="")
404
+
405
+ await client.query("Create a complete Flask app with tests")
406
+
407
+ asyncio.run(main())
408
+ ```
409
+
410
+ ---
411
+
412
+ ## Development
413
+
414
+ ```bash
415
+ # Clone
416
+ git clone https://github.com/yazelin/claude-code-acp-py
417
+ cd claude-code-acp-py
418
+
419
+ # Install dependencies
420
+ uv sync
421
+
422
+ # Run locally
423
+ uv run claude-code-acp
424
+
425
+ # Run tests
426
+ uv run python -c "from claude_code_acp import ClaudeClient; print('OK')"
427
+ ```
428
+
429
+ ---
430
+
431
+ ## Related Projects
432
+
433
+ - [claude-code-acp](https://github.com/zed-industries/claude-code-acp) - TypeScript version by Zed Industries
434
+ - [agent-client-protocol](https://github.com/anthropics/agent-client-protocol) - ACP specification and SDKs
435
+ - [claude-agent-sdk-python](https://github.com/anthropics/claude-agent-sdk-python) - Official Claude Agent SDK
436
+
437
+ ---
438
+
439
+ ## License
440
+
441
+ MIT