pyclaudecli 1.0.0__tar.gz → 1.0.2__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.
- pyclaudecli-1.0.2/PKG-INFO +424 -0
- pyclaudecli-1.0.2/README.md +401 -0
- {pyclaudecli-1.0.0 → pyclaudecli-1.0.2}/pyproject.toml +1 -1
- {pyclaudecli-1.0.0 → pyclaudecli-1.0.2}/src/pyclaudecli/__init__.py +1 -1
- pyclaudecli-1.0.0/PKG-INFO +0 -94
- pyclaudecli-1.0.0/README.md +0 -71
- {pyclaudecli-1.0.0 → pyclaudecli-1.0.2}/.gitignore +0 -0
- {pyclaudecli-1.0.0 → pyclaudecli-1.0.2}/LICENSE +0 -0
- {pyclaudecli-1.0.0 → pyclaudecli-1.0.2}/src/pyclaudecli/__main__.py +0 -0
- {pyclaudecli-1.0.0 → pyclaudecli-1.0.2}/src/pyclaudecli/_process.py +0 -0
- {pyclaudecli-1.0.0 → pyclaudecli-1.0.2}/src/pyclaudecli/client.py +0 -0
- {pyclaudecli-1.0.0 → pyclaudecli-1.0.2}/src/pyclaudecli/exceptions.py +0 -0
- {pyclaudecli-1.0.0 → pyclaudecli-1.0.2}/tests/test_usage.py +0 -0
|
@@ -0,0 +1,424 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: pyclaudecli
|
|
3
|
+
Version: 1.0.2
|
|
4
|
+
Summary: Python library wrapping the Claude Code CLI: prompts, background agents, auth, MCP, plugins, and more
|
|
5
|
+
Author-email: Suriya Ravichandran <suriyaravichandran@itrendsolution.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Keywords: anthropic,automation,claude,claude-code,cli,sdk,wrapper
|
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Classifier: Operating System :: OS Independent
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
21
|
+
Requires-Python: >=3.8
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
|
|
24
|
+
# pyclaudecli
|
|
25
|
+
|
|
26
|
+
[](https://pypi.org/project/pyclaudecli/)
|
|
27
|
+
[](https://pypi.org/project/pyclaudecli/)
|
|
28
|
+
[](LICENSE)
|
|
29
|
+
[](https://pypi.org/project/pyclaudecli/)
|
|
30
|
+
|
|
31
|
+
A Python library that wraps the [Claude Code](https://claude.com/claude-code) CLI (`claude`) so you can drive it from Python instead of shelling out by hand: one-shot prompts, JSON/streaming output, background agents, authentication, MCP servers, plugins, and the rest of the CLI's surface.
|
|
32
|
+
|
|
33
|
+
It's a thin wrapper, not a reimplementation — every call runs the real `claude` binary, so it always reflects whatever version, auth, and config you have installed locally.
|
|
34
|
+
|
|
35
|
+
## Contents
|
|
36
|
+
|
|
37
|
+
- [Install](#install)
|
|
38
|
+
- [Quickstart](#quickstart)
|
|
39
|
+
- [Setup](#setup)
|
|
40
|
+
- [Authentication](#authentication)
|
|
41
|
+
- [Command-line usage](#command-line-usage)
|
|
42
|
+
- [Errors](#errors)
|
|
43
|
+
- [`build_flags`](#build_flags)
|
|
44
|
+
- [Every method, with an example](#every-method-with-an-example)
|
|
45
|
+
- [Development](#development)
|
|
46
|
+
- [License](#license)
|
|
47
|
+
|
|
48
|
+
## Install
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
pip install pyclaudecli
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Requires the `claude` CLI itself to be installed and on `PATH` (see the [Claude Code docs](https://claude.com/claude-code)).
|
|
55
|
+
|
|
56
|
+
## Quickstart
|
|
57
|
+
|
|
58
|
+
```python
|
|
59
|
+
from pyclaudecli import ClaudeCLI
|
|
60
|
+
|
|
61
|
+
claude = ClaudeCLI()
|
|
62
|
+
|
|
63
|
+
# One-shot prompt
|
|
64
|
+
print(claude.prompt("Summarize this repo's README.", model="haiku"))
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Setup
|
|
68
|
+
|
|
69
|
+
```python
|
|
70
|
+
from pyclaudecli import ClaudeCLI
|
|
71
|
+
|
|
72
|
+
# Defaults: binary="claude" on PATH, inherited cwd/env, no timeout
|
|
73
|
+
claude = ClaudeCLI()
|
|
74
|
+
|
|
75
|
+
# Pointing at a specific binary/project, with a default timeout for every call
|
|
76
|
+
claude = ClaudeCLI(
|
|
77
|
+
"claude",
|
|
78
|
+
cwd="/path/to/project",
|
|
79
|
+
env={"ANTHROPIC_API_KEY": "sk-ant-..."},
|
|
80
|
+
timeout=120,
|
|
81
|
+
)
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Authentication
|
|
85
|
+
|
|
86
|
+
`claude` handles auth itself, so `pyclaudecli` just drives it. You have two options.
|
|
87
|
+
|
|
88
|
+
### API key
|
|
89
|
+
|
|
90
|
+
Pass the key through the environment — either inherited from your shell or set per client:
|
|
91
|
+
|
|
92
|
+
```python
|
|
93
|
+
from pyclaudecli import ClaudeCLI
|
|
94
|
+
|
|
95
|
+
claude = ClaudeCLI(env={"ANTHROPIC_API_KEY": "sk-ant-..."})
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### OAuth login (paste the code)
|
|
99
|
+
|
|
100
|
+
`auth_login()` runs `claude auth login`, prints the sign-in URL, waits for the CLI's
|
|
101
|
+
"Paste code here" prompt, and writes your code back to it. With no arguments it reads the
|
|
102
|
+
code from stdin, so this is the whole interactive flow:
|
|
103
|
+
|
|
104
|
+
```python
|
|
105
|
+
from pyclaudecli import ClaudeCLI
|
|
106
|
+
|
|
107
|
+
claude = ClaudeCLI()
|
|
108
|
+
|
|
109
|
+
if not claude.auth_status().get("loggedIn"):
|
|
110
|
+
# Prints the sign-in URL, then asks: "Paste the code from the browser here:"
|
|
111
|
+
exit_code = claude.auth_login()
|
|
112
|
+
print("login exit code:", exit_code)
|
|
113
|
+
|
|
114
|
+
print(claude.auth_status()) # {"loggedIn": True, "email": "you@example.com", ...}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
To capture the URL yourself (open it in a browser, send it to a chat, log it) and paste the
|
|
118
|
+
code back without stdin, use `on_output` plus `code_provider`:
|
|
119
|
+
|
|
120
|
+
```python
|
|
121
|
+
import re
|
|
122
|
+
|
|
123
|
+
URL_RE = re.compile(r"https://\S+")
|
|
124
|
+
login_url = None
|
|
125
|
+
|
|
126
|
+
def capture(chunk: str) -> None:
|
|
127
|
+
global login_url
|
|
128
|
+
print(chunk, end="", flush=True) # or log.info(chunk)
|
|
129
|
+
if login_url is None:
|
|
130
|
+
match = URL_RE.search(chunk)
|
|
131
|
+
if match:
|
|
132
|
+
login_url = match.group(0)
|
|
133
|
+
|
|
134
|
+
def supply_code(url: str) -> str:
|
|
135
|
+
# `url` is the sign-in URL pyclaudecli found in the CLI's output.
|
|
136
|
+
# Open it however you like, then return the code the browser shows.
|
|
137
|
+
print(f"\nOpen this URL and approve the login:\n{url}\n")
|
|
138
|
+
return input("Paste code here: ").strip()
|
|
139
|
+
|
|
140
|
+
claude.auth_login(
|
|
141
|
+
on_output=capture,
|
|
142
|
+
code_provider=supply_code,
|
|
143
|
+
console=True, # --console: force the URL/console flow instead of opening a browser
|
|
144
|
+
timeout=300, # how long to wait for the "Paste code here" prompt
|
|
145
|
+
)
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Fully non-interactive — when the code already came from somewhere else (a queue, a
|
|
149
|
+
browser-automation step, an operator pasting it into your own UI):
|
|
150
|
+
|
|
151
|
+
```python
|
|
152
|
+
claude.auth_login(code="123456")
|
|
153
|
+
|
|
154
|
+
# Or fetch it programmatically from the printed sign-in URL
|
|
155
|
+
claude.auth_login(code_provider=lambda url: fetch_code_from_my_browser(url))
|
|
156
|
+
|
|
157
|
+
# Enterprise SSO, or pre-filling the account
|
|
158
|
+
claude.auth_login(sso=True)
|
|
159
|
+
claude.auth_login(email="you@example.com")
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
`auth_login()` returns the CLI's exit code (`0` on success) and raises `ClaudeTimeoutError`
|
|
163
|
+
if the login prompt never appears within `timeout` seconds.
|
|
164
|
+
|
|
165
|
+
Signing out, and long-lived tokens for CI:
|
|
166
|
+
|
|
167
|
+
```python
|
|
168
|
+
claude.auth_logout()
|
|
169
|
+
claude.setup_token() # interactive; sets up a long-lived auth token
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## Command-line usage
|
|
173
|
+
|
|
174
|
+
The package also installs a minimal `pyclaudecli` command (and `python -m pyclaudecli`) for quick one-off prompts — for anything beyond that, use `ClaudeCLI` directly.
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
pyclaudecli "What's 2+2?" # defaults to model "haiku"
|
|
178
|
+
pyclaudecli --model sonnet "Explain this diff"
|
|
179
|
+
pyclaudecli -m sonnet "Explain this diff"
|
|
180
|
+
|
|
181
|
+
python -m pyclaudecli "Hello, Claude!"
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## Errors
|
|
185
|
+
|
|
186
|
+
All CLI failures raise `ClaudeCLIError` (or `ClaudeNotFoundError` / `ClaudeTimeoutError`), carrying `returncode`, `stdout`, `stderr`, and `cmd`.
|
|
187
|
+
|
|
188
|
+
```python
|
|
189
|
+
from pyclaudecli import ClaudeCLI, ClaudeCLIError, ClaudeNotFoundError, ClaudeTimeoutError
|
|
190
|
+
|
|
191
|
+
claude = ClaudeCLI()
|
|
192
|
+
|
|
193
|
+
try:
|
|
194
|
+
claude.prompt("Do something", model="haiku", timeout=30)
|
|
195
|
+
except ClaudeTimeoutError as exc:
|
|
196
|
+
print("timed out:", exc.cmd)
|
|
197
|
+
except ClaudeNotFoundError as exc:
|
|
198
|
+
print("claude binary not on PATH:", exc)
|
|
199
|
+
except ClaudeCLIError as exc:
|
|
200
|
+
print(exc.returncode, exc.stdout, exc.stderr)
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
## `build_flags`
|
|
204
|
+
|
|
205
|
+
The helper `ClaudeCLI` uses internally to turn a `{python_name: value}` dict into CLI flags — handy if you're composing your own `extra_flags` or calling `.run()` directly. `None`/`False` are omitted, `True` becomes a bare flag, lists/tuples repeat the flag followed by each value, and anything else becomes the flag plus `str(value)`.
|
|
206
|
+
|
|
207
|
+
```python
|
|
208
|
+
from pyclaudecli import build_flags
|
|
209
|
+
|
|
210
|
+
build_flags({"model": "haiku", "verbose": True, "quiet": False, "add_dir": ["a", "b"]})
|
|
211
|
+
# ["--model", "haiku", "--verbose", "--add-dir", "a", "b"]
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
## Every method, with an example
|
|
215
|
+
|
|
216
|
+
All examples assume:
|
|
217
|
+
|
|
218
|
+
```python
|
|
219
|
+
from pyclaudecli import ClaudeCLI
|
|
220
|
+
|
|
221
|
+
claude = ClaudeCLI()
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### Raw / internal
|
|
225
|
+
|
|
226
|
+
```python
|
|
227
|
+
# .run() — lowest-level call; returns a CommandResult(returncode, stdout, stderr)
|
|
228
|
+
result = claude.run(["--version"], check=False)
|
|
229
|
+
print(result.returncode, result.stdout)
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### Version / health
|
|
233
|
+
|
|
234
|
+
```python
|
|
235
|
+
claude.version() # "claude --version" -> "1.2.3"
|
|
236
|
+
claude.doctor() # "claude doctor" -> health-check report
|
|
237
|
+
claude.update() # "claude update" -> checks for and installs updates
|
|
238
|
+
|
|
239
|
+
claude.install() # "claude install" (latest default)
|
|
240
|
+
claude.install("stable") # "claude install stable"
|
|
241
|
+
claude.install("1.2.3", force=True) # "claude install 1.2.3 --force"
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
### Prompting
|
|
245
|
+
|
|
246
|
+
```python
|
|
247
|
+
# One-shot prompt -> plain text
|
|
248
|
+
claude.prompt("Summarize this repo's README.", model="haiku")
|
|
249
|
+
|
|
250
|
+
# Structured result (cost, session id, etc.)
|
|
251
|
+
result = claude.prompt_json("What's 2+2?", model="haiku")
|
|
252
|
+
print(result["result"], result["total_cost_usd"])
|
|
253
|
+
|
|
254
|
+
# Live streaming events
|
|
255
|
+
for event in claude.prompt_stream("Write a haiku about tests.", model="haiku"):
|
|
256
|
+
print(event["type"])
|
|
257
|
+
|
|
258
|
+
# Full option surface
|
|
259
|
+
claude.prompt(
|
|
260
|
+
"Refactor this function for clarity.",
|
|
261
|
+
model="sonnet",
|
|
262
|
+
output_format="json",
|
|
263
|
+
system_prompt="You are a terse senior engineer.",
|
|
264
|
+
append_system_prompt="Always answer in bullet points.",
|
|
265
|
+
allowed_tools=["Read", "Edit"],
|
|
266
|
+
disallowed_tools=["Bash"],
|
|
267
|
+
add_dir=["../shared-lib"],
|
|
268
|
+
permission_mode="acceptEdits",
|
|
269
|
+
mcp_config=["./mcp.json"],
|
|
270
|
+
settings="./claude-settings.json",
|
|
271
|
+
resume="session-id-123",
|
|
272
|
+
fork_session=True,
|
|
273
|
+
effort="high",
|
|
274
|
+
fallback_model="haiku",
|
|
275
|
+
max_budget_usd=0.50,
|
|
276
|
+
json_schema='{"type": "object"}',
|
|
277
|
+
betas=["some-beta-flag"],
|
|
278
|
+
no_session_persistence=True,
|
|
279
|
+
dangerously_skip_permissions=False,
|
|
280
|
+
restricted=True,
|
|
281
|
+
input_text="piped stdin content",
|
|
282
|
+
timeout=60,
|
|
283
|
+
extra_flags={"worktree": True}, # anything without a named parameter
|
|
284
|
+
)
|
|
285
|
+
|
|
286
|
+
# continue_session=True appends --continue (keeps typing in the latest session)
|
|
287
|
+
claude.prompt("And now add tests for it.", continue_session=True)
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
### Background sessions ("agents")
|
|
291
|
+
|
|
292
|
+
```python
|
|
293
|
+
session_id = claude.start_background("Refactor the auth module", model="sonnet")
|
|
294
|
+
|
|
295
|
+
claude.list_agents() # all sessions, as a list of dicts
|
|
296
|
+
claude.list_agents(all=True, cwd="/repo") # include finished ones, scoped to a project
|
|
297
|
+
|
|
298
|
+
claude.attach(session_id) # interactive; requires a real TTY
|
|
299
|
+
claude.logs(session_id) # raw terminal snapshot
|
|
300
|
+
claude.logs(session_id, strip_ansi=True) # best-effort plain text
|
|
301
|
+
|
|
302
|
+
claude.stop(session_id) # stop, keep state
|
|
303
|
+
claude.respawn(session_id) # restart one stopped session
|
|
304
|
+
claude.respawn(all=True) # restart every stopped session
|
|
305
|
+
claude.rm(session_id) # delete a stopped session
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
### Auth
|
|
309
|
+
|
|
310
|
+
```python
|
|
311
|
+
claude.auth_status() # {"loggedIn": True, "email": "...", ...}
|
|
312
|
+
claude.auth_status(as_json=False) # human-readable text instead
|
|
313
|
+
|
|
314
|
+
# Interactive OAuth: prints the sign-in URL, then reads the pasted code from stdin
|
|
315
|
+
claude.auth_login()
|
|
316
|
+
|
|
317
|
+
# Non-interactive login: supply the code yourself
|
|
318
|
+
claude.auth_login(code="123456")
|
|
319
|
+
|
|
320
|
+
# Or fetch the code programmatically from the printed sign-in URL
|
|
321
|
+
claude.auth_login(code_provider=lambda url: fetch_code_from_my_browser(url))
|
|
322
|
+
|
|
323
|
+
# Route the printed sign-in URL/output somewhere other than stdout
|
|
324
|
+
claude.auth_login(on_output=lambda chunk: log.info(chunk), console=True, timeout=120)
|
|
325
|
+
|
|
326
|
+
claude.auth_login(sso=True) # enterprise SSO
|
|
327
|
+
claude.auth_login(email="you@example.com") # pre-fill the account
|
|
328
|
+
|
|
329
|
+
claude.auth_logout()
|
|
330
|
+
claude.setup_token() # interactive; sets up a long-lived auth token
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
### MCP servers
|
|
334
|
+
|
|
335
|
+
```python
|
|
336
|
+
claude.mcp_list()
|
|
337
|
+
claude.mcp_get("sentry")
|
|
338
|
+
|
|
339
|
+
claude.mcp_add("sentry", "https://mcp.sentry.dev/mcp", transport="http")
|
|
340
|
+
claude.mcp_add(
|
|
341
|
+
"local-tool", "node", "server.js",
|
|
342
|
+
transport="stdio", env=["API_KEY=abc"], scope="project",
|
|
343
|
+
)
|
|
344
|
+
|
|
345
|
+
claude.mcp_add_json("sentry", {"type": "http", "url": "https://mcp.sentry.dev/mcp"})
|
|
346
|
+
claude.mcp_add_from_claude_desktop(scope="user")
|
|
347
|
+
|
|
348
|
+
claude.mcp_remove("sentry", scope="project")
|
|
349
|
+
claude.mcp_login("sentry") # interactive OAuth
|
|
350
|
+
claude.mcp_logout("sentry")
|
|
351
|
+
claude.mcp_reset_project_choices()
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
### Plugins
|
|
355
|
+
|
|
356
|
+
```python
|
|
357
|
+
claude.plugin_list()
|
|
358
|
+
claude.plugin_list(as_json=True)
|
|
359
|
+
|
|
360
|
+
claude.plugin_install("some-plugin", yes=True)
|
|
361
|
+
claude.plugin_install("some-plugin@my-marketplace", scope="user", as_json=True)
|
|
362
|
+
|
|
363
|
+
claude.plugin_uninstall("some-plugin", yes=True, prune=True)
|
|
364
|
+
claude.plugin_enable("some-plugin")
|
|
365
|
+
claude.plugin_disable("some-plugin")
|
|
366
|
+
claude.plugin_disable(all=True) # disable every plugin
|
|
367
|
+
|
|
368
|
+
claude.plugin_update("some-plugin", yes=True)
|
|
369
|
+
claude.plugin_details("some-plugin")
|
|
370
|
+
claude.plugin_validate("./my-plugin", strict=True, as_json=True)
|
|
371
|
+
claude.plugin_prune(dry_run=True)
|
|
372
|
+
|
|
373
|
+
claude.plugin_marketplace_list()
|
|
374
|
+
claude.plugin_marketplace_add("https://github.com/org/marketplace-repo")
|
|
375
|
+
claude.plugin_marketplace_remove("marketplace-name")
|
|
376
|
+
claude.plugin_marketplace_update() # update all
|
|
377
|
+
claude.plugin_marketplace_update("marketplace-name")
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
### Project state
|
|
381
|
+
|
|
382
|
+
```python
|
|
383
|
+
claude.project_purge() # purge state for the current project
|
|
384
|
+
claude.project_purge("/path/to/repo") # or for a specific path
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
### Auto mode
|
|
388
|
+
|
|
389
|
+
```python
|
|
390
|
+
claude.auto_mode_config() # effective classifier config, as a dict
|
|
391
|
+
claude.auto_mode_defaults() # shipped default rules, as a dict
|
|
392
|
+
claude.auto_mode_reset() # remove custom rules from user settings
|
|
393
|
+
claude.auto_mode_critique() # AI feedback on your custom rules
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
### Misc
|
|
397
|
+
|
|
398
|
+
```python
|
|
399
|
+
claude.import_config("cursor", dry_run=True, yes=True) # source: codex, gemini, or cursor
|
|
400
|
+
|
|
401
|
+
claude.ultrareview() # review the current branch
|
|
402
|
+
claude.ultrareview("main") # review against a base branch
|
|
403
|
+
claude.ultrareview(482, as_json=True, post=True) # review a PR, post results, get JSON
|
|
404
|
+
|
|
405
|
+
# Long-running server: returns a Popen handle, doesn't block
|
|
406
|
+
gateway = claude.start_gateway(config="./gateway.json")
|
|
407
|
+
...
|
|
408
|
+
gateway.terminate()
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
See `ClaudeCLI`'s docstrings for the exact CLI flags behind each method — it covers every top-level `claude` command (`auth`, `mcp`, `plugin`, `project`, `agents`/background sessions, `auto-mode`, `doctor`, `update`, `install`, `import`, `ultrareview`, `gateway`) plus the main prompt flags. Anything not exposed as a named parameter can still be passed through via each method's `extra_flags` dict.
|
|
412
|
+
|
|
413
|
+
## Development
|
|
414
|
+
|
|
415
|
+
```bash
|
|
416
|
+
git clone https://github.com/Suriya-Ravichandran/pyclaudecli.git
|
|
417
|
+
cd pyclaudecli
|
|
418
|
+
pip install -e .
|
|
419
|
+
pytest
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
## License
|
|
423
|
+
|
|
424
|
+
MIT
|
|
@@ -0,0 +1,401 @@
|
|
|
1
|
+
# pyclaudecli
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/pyclaudecli/)
|
|
4
|
+
[](https://pypi.org/project/pyclaudecli/)
|
|
5
|
+
[](LICENSE)
|
|
6
|
+
[](https://pypi.org/project/pyclaudecli/)
|
|
7
|
+
|
|
8
|
+
A Python library that wraps the [Claude Code](https://claude.com/claude-code) CLI (`claude`) so you can drive it from Python instead of shelling out by hand: one-shot prompts, JSON/streaming output, background agents, authentication, MCP servers, plugins, and the rest of the CLI's surface.
|
|
9
|
+
|
|
10
|
+
It's a thin wrapper, not a reimplementation — every call runs the real `claude` binary, so it always reflects whatever version, auth, and config you have installed locally.
|
|
11
|
+
|
|
12
|
+
## Contents
|
|
13
|
+
|
|
14
|
+
- [Install](#install)
|
|
15
|
+
- [Quickstart](#quickstart)
|
|
16
|
+
- [Setup](#setup)
|
|
17
|
+
- [Authentication](#authentication)
|
|
18
|
+
- [Command-line usage](#command-line-usage)
|
|
19
|
+
- [Errors](#errors)
|
|
20
|
+
- [`build_flags`](#build_flags)
|
|
21
|
+
- [Every method, with an example](#every-method-with-an-example)
|
|
22
|
+
- [Development](#development)
|
|
23
|
+
- [License](#license)
|
|
24
|
+
|
|
25
|
+
## Install
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
pip install pyclaudecli
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Requires the `claude` CLI itself to be installed and on `PATH` (see the [Claude Code docs](https://claude.com/claude-code)).
|
|
32
|
+
|
|
33
|
+
## Quickstart
|
|
34
|
+
|
|
35
|
+
```python
|
|
36
|
+
from pyclaudecli import ClaudeCLI
|
|
37
|
+
|
|
38
|
+
claude = ClaudeCLI()
|
|
39
|
+
|
|
40
|
+
# One-shot prompt
|
|
41
|
+
print(claude.prompt("Summarize this repo's README.", model="haiku"))
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Setup
|
|
45
|
+
|
|
46
|
+
```python
|
|
47
|
+
from pyclaudecli import ClaudeCLI
|
|
48
|
+
|
|
49
|
+
# Defaults: binary="claude" on PATH, inherited cwd/env, no timeout
|
|
50
|
+
claude = ClaudeCLI()
|
|
51
|
+
|
|
52
|
+
# Pointing at a specific binary/project, with a default timeout for every call
|
|
53
|
+
claude = ClaudeCLI(
|
|
54
|
+
"claude",
|
|
55
|
+
cwd="/path/to/project",
|
|
56
|
+
env={"ANTHROPIC_API_KEY": "sk-ant-..."},
|
|
57
|
+
timeout=120,
|
|
58
|
+
)
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Authentication
|
|
62
|
+
|
|
63
|
+
`claude` handles auth itself, so `pyclaudecli` just drives it. You have two options.
|
|
64
|
+
|
|
65
|
+
### API key
|
|
66
|
+
|
|
67
|
+
Pass the key through the environment — either inherited from your shell or set per client:
|
|
68
|
+
|
|
69
|
+
```python
|
|
70
|
+
from pyclaudecli import ClaudeCLI
|
|
71
|
+
|
|
72
|
+
claude = ClaudeCLI(env={"ANTHROPIC_API_KEY": "sk-ant-..."})
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### OAuth login (paste the code)
|
|
76
|
+
|
|
77
|
+
`auth_login()` runs `claude auth login`, prints the sign-in URL, waits for the CLI's
|
|
78
|
+
"Paste code here" prompt, and writes your code back to it. With no arguments it reads the
|
|
79
|
+
code from stdin, so this is the whole interactive flow:
|
|
80
|
+
|
|
81
|
+
```python
|
|
82
|
+
from pyclaudecli import ClaudeCLI
|
|
83
|
+
|
|
84
|
+
claude = ClaudeCLI()
|
|
85
|
+
|
|
86
|
+
if not claude.auth_status().get("loggedIn"):
|
|
87
|
+
# Prints the sign-in URL, then asks: "Paste the code from the browser here:"
|
|
88
|
+
exit_code = claude.auth_login()
|
|
89
|
+
print("login exit code:", exit_code)
|
|
90
|
+
|
|
91
|
+
print(claude.auth_status()) # {"loggedIn": True, "email": "you@example.com", ...}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
To capture the URL yourself (open it in a browser, send it to a chat, log it) and paste the
|
|
95
|
+
code back without stdin, use `on_output` plus `code_provider`:
|
|
96
|
+
|
|
97
|
+
```python
|
|
98
|
+
import re
|
|
99
|
+
|
|
100
|
+
URL_RE = re.compile(r"https://\S+")
|
|
101
|
+
login_url = None
|
|
102
|
+
|
|
103
|
+
def capture(chunk: str) -> None:
|
|
104
|
+
global login_url
|
|
105
|
+
print(chunk, end="", flush=True) # or log.info(chunk)
|
|
106
|
+
if login_url is None:
|
|
107
|
+
match = URL_RE.search(chunk)
|
|
108
|
+
if match:
|
|
109
|
+
login_url = match.group(0)
|
|
110
|
+
|
|
111
|
+
def supply_code(url: str) -> str:
|
|
112
|
+
# `url` is the sign-in URL pyclaudecli found in the CLI's output.
|
|
113
|
+
# Open it however you like, then return the code the browser shows.
|
|
114
|
+
print(f"\nOpen this URL and approve the login:\n{url}\n")
|
|
115
|
+
return input("Paste code here: ").strip()
|
|
116
|
+
|
|
117
|
+
claude.auth_login(
|
|
118
|
+
on_output=capture,
|
|
119
|
+
code_provider=supply_code,
|
|
120
|
+
console=True, # --console: force the URL/console flow instead of opening a browser
|
|
121
|
+
timeout=300, # how long to wait for the "Paste code here" prompt
|
|
122
|
+
)
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Fully non-interactive — when the code already came from somewhere else (a queue, a
|
|
126
|
+
browser-automation step, an operator pasting it into your own UI):
|
|
127
|
+
|
|
128
|
+
```python
|
|
129
|
+
claude.auth_login(code="123456")
|
|
130
|
+
|
|
131
|
+
# Or fetch it programmatically from the printed sign-in URL
|
|
132
|
+
claude.auth_login(code_provider=lambda url: fetch_code_from_my_browser(url))
|
|
133
|
+
|
|
134
|
+
# Enterprise SSO, or pre-filling the account
|
|
135
|
+
claude.auth_login(sso=True)
|
|
136
|
+
claude.auth_login(email="you@example.com")
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
`auth_login()` returns the CLI's exit code (`0` on success) and raises `ClaudeTimeoutError`
|
|
140
|
+
if the login prompt never appears within `timeout` seconds.
|
|
141
|
+
|
|
142
|
+
Signing out, and long-lived tokens for CI:
|
|
143
|
+
|
|
144
|
+
```python
|
|
145
|
+
claude.auth_logout()
|
|
146
|
+
claude.setup_token() # interactive; sets up a long-lived auth token
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## Command-line usage
|
|
150
|
+
|
|
151
|
+
The package also installs a minimal `pyclaudecli` command (and `python -m pyclaudecli`) for quick one-off prompts — for anything beyond that, use `ClaudeCLI` directly.
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
pyclaudecli "What's 2+2?" # defaults to model "haiku"
|
|
155
|
+
pyclaudecli --model sonnet "Explain this diff"
|
|
156
|
+
pyclaudecli -m sonnet "Explain this diff"
|
|
157
|
+
|
|
158
|
+
python -m pyclaudecli "Hello, Claude!"
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## Errors
|
|
162
|
+
|
|
163
|
+
All CLI failures raise `ClaudeCLIError` (or `ClaudeNotFoundError` / `ClaudeTimeoutError`), carrying `returncode`, `stdout`, `stderr`, and `cmd`.
|
|
164
|
+
|
|
165
|
+
```python
|
|
166
|
+
from pyclaudecli import ClaudeCLI, ClaudeCLIError, ClaudeNotFoundError, ClaudeTimeoutError
|
|
167
|
+
|
|
168
|
+
claude = ClaudeCLI()
|
|
169
|
+
|
|
170
|
+
try:
|
|
171
|
+
claude.prompt("Do something", model="haiku", timeout=30)
|
|
172
|
+
except ClaudeTimeoutError as exc:
|
|
173
|
+
print("timed out:", exc.cmd)
|
|
174
|
+
except ClaudeNotFoundError as exc:
|
|
175
|
+
print("claude binary not on PATH:", exc)
|
|
176
|
+
except ClaudeCLIError as exc:
|
|
177
|
+
print(exc.returncode, exc.stdout, exc.stderr)
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
## `build_flags`
|
|
181
|
+
|
|
182
|
+
The helper `ClaudeCLI` uses internally to turn a `{python_name: value}` dict into CLI flags — handy if you're composing your own `extra_flags` or calling `.run()` directly. `None`/`False` are omitted, `True` becomes a bare flag, lists/tuples repeat the flag followed by each value, and anything else becomes the flag plus `str(value)`.
|
|
183
|
+
|
|
184
|
+
```python
|
|
185
|
+
from pyclaudecli import build_flags
|
|
186
|
+
|
|
187
|
+
build_flags({"model": "haiku", "verbose": True, "quiet": False, "add_dir": ["a", "b"]})
|
|
188
|
+
# ["--model", "haiku", "--verbose", "--add-dir", "a", "b"]
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
## Every method, with an example
|
|
192
|
+
|
|
193
|
+
All examples assume:
|
|
194
|
+
|
|
195
|
+
```python
|
|
196
|
+
from pyclaudecli import ClaudeCLI
|
|
197
|
+
|
|
198
|
+
claude = ClaudeCLI()
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### Raw / internal
|
|
202
|
+
|
|
203
|
+
```python
|
|
204
|
+
# .run() — lowest-level call; returns a CommandResult(returncode, stdout, stderr)
|
|
205
|
+
result = claude.run(["--version"], check=False)
|
|
206
|
+
print(result.returncode, result.stdout)
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### Version / health
|
|
210
|
+
|
|
211
|
+
```python
|
|
212
|
+
claude.version() # "claude --version" -> "1.2.3"
|
|
213
|
+
claude.doctor() # "claude doctor" -> health-check report
|
|
214
|
+
claude.update() # "claude update" -> checks for and installs updates
|
|
215
|
+
|
|
216
|
+
claude.install() # "claude install" (latest default)
|
|
217
|
+
claude.install("stable") # "claude install stable"
|
|
218
|
+
claude.install("1.2.3", force=True) # "claude install 1.2.3 --force"
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
### Prompting
|
|
222
|
+
|
|
223
|
+
```python
|
|
224
|
+
# One-shot prompt -> plain text
|
|
225
|
+
claude.prompt("Summarize this repo's README.", model="haiku")
|
|
226
|
+
|
|
227
|
+
# Structured result (cost, session id, etc.)
|
|
228
|
+
result = claude.prompt_json("What's 2+2?", model="haiku")
|
|
229
|
+
print(result["result"], result["total_cost_usd"])
|
|
230
|
+
|
|
231
|
+
# Live streaming events
|
|
232
|
+
for event in claude.prompt_stream("Write a haiku about tests.", model="haiku"):
|
|
233
|
+
print(event["type"])
|
|
234
|
+
|
|
235
|
+
# Full option surface
|
|
236
|
+
claude.prompt(
|
|
237
|
+
"Refactor this function for clarity.",
|
|
238
|
+
model="sonnet",
|
|
239
|
+
output_format="json",
|
|
240
|
+
system_prompt="You are a terse senior engineer.",
|
|
241
|
+
append_system_prompt="Always answer in bullet points.",
|
|
242
|
+
allowed_tools=["Read", "Edit"],
|
|
243
|
+
disallowed_tools=["Bash"],
|
|
244
|
+
add_dir=["../shared-lib"],
|
|
245
|
+
permission_mode="acceptEdits",
|
|
246
|
+
mcp_config=["./mcp.json"],
|
|
247
|
+
settings="./claude-settings.json",
|
|
248
|
+
resume="session-id-123",
|
|
249
|
+
fork_session=True,
|
|
250
|
+
effort="high",
|
|
251
|
+
fallback_model="haiku",
|
|
252
|
+
max_budget_usd=0.50,
|
|
253
|
+
json_schema='{"type": "object"}',
|
|
254
|
+
betas=["some-beta-flag"],
|
|
255
|
+
no_session_persistence=True,
|
|
256
|
+
dangerously_skip_permissions=False,
|
|
257
|
+
restricted=True,
|
|
258
|
+
input_text="piped stdin content",
|
|
259
|
+
timeout=60,
|
|
260
|
+
extra_flags={"worktree": True}, # anything without a named parameter
|
|
261
|
+
)
|
|
262
|
+
|
|
263
|
+
# continue_session=True appends --continue (keeps typing in the latest session)
|
|
264
|
+
claude.prompt("And now add tests for it.", continue_session=True)
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
### Background sessions ("agents")
|
|
268
|
+
|
|
269
|
+
```python
|
|
270
|
+
session_id = claude.start_background("Refactor the auth module", model="sonnet")
|
|
271
|
+
|
|
272
|
+
claude.list_agents() # all sessions, as a list of dicts
|
|
273
|
+
claude.list_agents(all=True, cwd="/repo") # include finished ones, scoped to a project
|
|
274
|
+
|
|
275
|
+
claude.attach(session_id) # interactive; requires a real TTY
|
|
276
|
+
claude.logs(session_id) # raw terminal snapshot
|
|
277
|
+
claude.logs(session_id, strip_ansi=True) # best-effort plain text
|
|
278
|
+
|
|
279
|
+
claude.stop(session_id) # stop, keep state
|
|
280
|
+
claude.respawn(session_id) # restart one stopped session
|
|
281
|
+
claude.respawn(all=True) # restart every stopped session
|
|
282
|
+
claude.rm(session_id) # delete a stopped session
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
### Auth
|
|
286
|
+
|
|
287
|
+
```python
|
|
288
|
+
claude.auth_status() # {"loggedIn": True, "email": "...", ...}
|
|
289
|
+
claude.auth_status(as_json=False) # human-readable text instead
|
|
290
|
+
|
|
291
|
+
# Interactive OAuth: prints the sign-in URL, then reads the pasted code from stdin
|
|
292
|
+
claude.auth_login()
|
|
293
|
+
|
|
294
|
+
# Non-interactive login: supply the code yourself
|
|
295
|
+
claude.auth_login(code="123456")
|
|
296
|
+
|
|
297
|
+
# Or fetch the code programmatically from the printed sign-in URL
|
|
298
|
+
claude.auth_login(code_provider=lambda url: fetch_code_from_my_browser(url))
|
|
299
|
+
|
|
300
|
+
# Route the printed sign-in URL/output somewhere other than stdout
|
|
301
|
+
claude.auth_login(on_output=lambda chunk: log.info(chunk), console=True, timeout=120)
|
|
302
|
+
|
|
303
|
+
claude.auth_login(sso=True) # enterprise SSO
|
|
304
|
+
claude.auth_login(email="you@example.com") # pre-fill the account
|
|
305
|
+
|
|
306
|
+
claude.auth_logout()
|
|
307
|
+
claude.setup_token() # interactive; sets up a long-lived auth token
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
### MCP servers
|
|
311
|
+
|
|
312
|
+
```python
|
|
313
|
+
claude.mcp_list()
|
|
314
|
+
claude.mcp_get("sentry")
|
|
315
|
+
|
|
316
|
+
claude.mcp_add("sentry", "https://mcp.sentry.dev/mcp", transport="http")
|
|
317
|
+
claude.mcp_add(
|
|
318
|
+
"local-tool", "node", "server.js",
|
|
319
|
+
transport="stdio", env=["API_KEY=abc"], scope="project",
|
|
320
|
+
)
|
|
321
|
+
|
|
322
|
+
claude.mcp_add_json("sentry", {"type": "http", "url": "https://mcp.sentry.dev/mcp"})
|
|
323
|
+
claude.mcp_add_from_claude_desktop(scope="user")
|
|
324
|
+
|
|
325
|
+
claude.mcp_remove("sentry", scope="project")
|
|
326
|
+
claude.mcp_login("sentry") # interactive OAuth
|
|
327
|
+
claude.mcp_logout("sentry")
|
|
328
|
+
claude.mcp_reset_project_choices()
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
### Plugins
|
|
332
|
+
|
|
333
|
+
```python
|
|
334
|
+
claude.plugin_list()
|
|
335
|
+
claude.plugin_list(as_json=True)
|
|
336
|
+
|
|
337
|
+
claude.plugin_install("some-plugin", yes=True)
|
|
338
|
+
claude.plugin_install("some-plugin@my-marketplace", scope="user", as_json=True)
|
|
339
|
+
|
|
340
|
+
claude.plugin_uninstall("some-plugin", yes=True, prune=True)
|
|
341
|
+
claude.plugin_enable("some-plugin")
|
|
342
|
+
claude.plugin_disable("some-plugin")
|
|
343
|
+
claude.plugin_disable(all=True) # disable every plugin
|
|
344
|
+
|
|
345
|
+
claude.plugin_update("some-plugin", yes=True)
|
|
346
|
+
claude.plugin_details("some-plugin")
|
|
347
|
+
claude.plugin_validate("./my-plugin", strict=True, as_json=True)
|
|
348
|
+
claude.plugin_prune(dry_run=True)
|
|
349
|
+
|
|
350
|
+
claude.plugin_marketplace_list()
|
|
351
|
+
claude.plugin_marketplace_add("https://github.com/org/marketplace-repo")
|
|
352
|
+
claude.plugin_marketplace_remove("marketplace-name")
|
|
353
|
+
claude.plugin_marketplace_update() # update all
|
|
354
|
+
claude.plugin_marketplace_update("marketplace-name")
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
### Project state
|
|
358
|
+
|
|
359
|
+
```python
|
|
360
|
+
claude.project_purge() # purge state for the current project
|
|
361
|
+
claude.project_purge("/path/to/repo") # or for a specific path
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
### Auto mode
|
|
365
|
+
|
|
366
|
+
```python
|
|
367
|
+
claude.auto_mode_config() # effective classifier config, as a dict
|
|
368
|
+
claude.auto_mode_defaults() # shipped default rules, as a dict
|
|
369
|
+
claude.auto_mode_reset() # remove custom rules from user settings
|
|
370
|
+
claude.auto_mode_critique() # AI feedback on your custom rules
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
### Misc
|
|
374
|
+
|
|
375
|
+
```python
|
|
376
|
+
claude.import_config("cursor", dry_run=True, yes=True) # source: codex, gemini, or cursor
|
|
377
|
+
|
|
378
|
+
claude.ultrareview() # review the current branch
|
|
379
|
+
claude.ultrareview("main") # review against a base branch
|
|
380
|
+
claude.ultrareview(482, as_json=True, post=True) # review a PR, post results, get JSON
|
|
381
|
+
|
|
382
|
+
# Long-running server: returns a Popen handle, doesn't block
|
|
383
|
+
gateway = claude.start_gateway(config="./gateway.json")
|
|
384
|
+
...
|
|
385
|
+
gateway.terminate()
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
See `ClaudeCLI`'s docstrings for the exact CLI flags behind each method — it covers every top-level `claude` command (`auth`, `mcp`, `plugin`, `project`, `agents`/background sessions, `auto-mode`, `doctor`, `update`, `install`, `import`, `ultrareview`, `gateway`) plus the main prompt flags. Anything not exposed as a named parameter can still be passed through via each method's `extra_flags` dict.
|
|
389
|
+
|
|
390
|
+
## Development
|
|
391
|
+
|
|
392
|
+
```bash
|
|
393
|
+
git clone https://github.com/Suriya-Ravichandran/pyclaudecli.git
|
|
394
|
+
cd pyclaudecli
|
|
395
|
+
pip install -e .
|
|
396
|
+
pytest
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
## License
|
|
400
|
+
|
|
401
|
+
MIT
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "pyclaudecli"
|
|
7
|
-
version = "1.0.
|
|
7
|
+
version = "1.0.2"
|
|
8
8
|
description = "Python library wrapping the Claude Code CLI: prompts, background agents, auth, MCP, plugins, and more"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.8"
|
pyclaudecli-1.0.0/PKG-INFO
DELETED
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.5
|
|
2
|
-
Name: pyclaudecli
|
|
3
|
-
Version: 1.0.0
|
|
4
|
-
Summary: Python library wrapping the Claude Code CLI: prompts, background agents, auth, MCP, plugins, and more
|
|
5
|
-
Author-email: Suriya Ravichandran <suriyaravichandran@itrendsolution.com>
|
|
6
|
-
License: MIT
|
|
7
|
-
License-File: LICENSE
|
|
8
|
-
Keywords: anthropic,automation,claude,claude-code,cli,sdk,wrapper
|
|
9
|
-
Classifier: Development Status :: 3 - Alpha
|
|
10
|
-
Classifier: Intended Audience :: Developers
|
|
11
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
-
Classifier: Operating System :: OS Independent
|
|
13
|
-
Classifier: Programming Language :: Python :: 3
|
|
14
|
-
Classifier: Programming Language :: Python :: 3 :: Only
|
|
15
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
16
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
17
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
-
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
21
|
-
Requires-Python: >=3.8
|
|
22
|
-
Description-Content-Type: text/markdown
|
|
23
|
-
|
|
24
|
-
# pyclaudecli
|
|
25
|
-
|
|
26
|
-
A Python library that wraps the [Claude Code](https://claude.com/claude-code) CLI (`claude`) so you can drive it from Python instead of shelling out by hand: one-shot prompts, JSON/streaming output, background agents, authentication, MCP servers, plugins, and the rest of the CLI's surface.
|
|
27
|
-
|
|
28
|
-
It's a thin wrapper, not a reimplementation — every call runs the real `claude` binary, so it always reflects whatever version, auth, and config you have installed locally.
|
|
29
|
-
|
|
30
|
-
## Install
|
|
31
|
-
|
|
32
|
-
```bash
|
|
33
|
-
pip install pyclaudecli
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
Requires the `claude` CLI itself to be installed and on `PATH` (see the [Claude Code docs](https://claude.com/claude-code)).
|
|
37
|
-
|
|
38
|
-
## Quickstart
|
|
39
|
-
|
|
40
|
-
```python
|
|
41
|
-
from pyclaudecli import ClaudeCLI
|
|
42
|
-
|
|
43
|
-
claude = ClaudeCLI()
|
|
44
|
-
|
|
45
|
-
# One-shot prompt
|
|
46
|
-
print(claude.prompt("Summarize this repo's README.", model="haiku"))
|
|
47
|
-
|
|
48
|
-
# Structured result (cost, session id, etc.)
|
|
49
|
-
result = claude.prompt_json("What's 2+2?", model="haiku")
|
|
50
|
-
print(result["result"], result["total_cost_usd"])
|
|
51
|
-
|
|
52
|
-
# Live streaming events
|
|
53
|
-
for event in claude.prompt_stream("Write a haiku about tests.", model="haiku"):
|
|
54
|
-
print(event["type"])
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
## Background agents
|
|
58
|
-
|
|
59
|
-
```python
|
|
60
|
-
session_id = claude.start_background("Refactor the auth module", model="sonnet")
|
|
61
|
-
claude.list_agents()
|
|
62
|
-
claude.logs(session_id, strip_ansi=True)
|
|
63
|
-
claude.stop(session_id)
|
|
64
|
-
claude.rm(session_id)
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
## Auth
|
|
68
|
-
|
|
69
|
-
```python
|
|
70
|
-
claude.auth_status() # {"loggedIn": True, "email": "...", ...}
|
|
71
|
-
|
|
72
|
-
# Prints the sign-in URL, then forwards the pasted code to finish login
|
|
73
|
-
claude.auth_login()
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
## MCP servers and plugins
|
|
77
|
-
|
|
78
|
-
```python
|
|
79
|
-
claude.mcp_add("sentry", "https://mcp.sentry.dev/mcp", transport="http")
|
|
80
|
-
claude.mcp_list()
|
|
81
|
-
|
|
82
|
-
claude.plugin_install("some-plugin", yes=True)
|
|
83
|
-
claude.plugin_list(as_json=True)
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
See `ClaudeCLI`'s docstrings for the full method list — it covers every top-level `claude` command (`auth`, `mcp`, `plugin`, `project`, `agents`/background sessions, `auto-mode`, `doctor`, `update`, `install`, `import`, `ultrareview`, `gateway`) plus the main prompt flags. Anything not exposed as a named parameter can still be passed through via each method's `extra_flags` dict.
|
|
87
|
-
|
|
88
|
-
## Errors
|
|
89
|
-
|
|
90
|
-
All CLI failures raise `ClaudeCLIError` (or `ClaudeNotFoundError` / `ClaudeTimeoutError`), carrying `returncode`, `stdout`, and `stderr`.
|
|
91
|
-
|
|
92
|
-
## License
|
|
93
|
-
|
|
94
|
-
MIT
|
pyclaudecli-1.0.0/README.md
DELETED
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
# pyclaudecli
|
|
2
|
-
|
|
3
|
-
A Python library that wraps the [Claude Code](https://claude.com/claude-code) CLI (`claude`) so you can drive it from Python instead of shelling out by hand: one-shot prompts, JSON/streaming output, background agents, authentication, MCP servers, plugins, and the rest of the CLI's surface.
|
|
4
|
-
|
|
5
|
-
It's a thin wrapper, not a reimplementation — every call runs the real `claude` binary, so it always reflects whatever version, auth, and config you have installed locally.
|
|
6
|
-
|
|
7
|
-
## Install
|
|
8
|
-
|
|
9
|
-
```bash
|
|
10
|
-
pip install pyclaudecli
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
Requires the `claude` CLI itself to be installed and on `PATH` (see the [Claude Code docs](https://claude.com/claude-code)).
|
|
14
|
-
|
|
15
|
-
## Quickstart
|
|
16
|
-
|
|
17
|
-
```python
|
|
18
|
-
from pyclaudecli import ClaudeCLI
|
|
19
|
-
|
|
20
|
-
claude = ClaudeCLI()
|
|
21
|
-
|
|
22
|
-
# One-shot prompt
|
|
23
|
-
print(claude.prompt("Summarize this repo's README.", model="haiku"))
|
|
24
|
-
|
|
25
|
-
# Structured result (cost, session id, etc.)
|
|
26
|
-
result = claude.prompt_json("What's 2+2?", model="haiku")
|
|
27
|
-
print(result["result"], result["total_cost_usd"])
|
|
28
|
-
|
|
29
|
-
# Live streaming events
|
|
30
|
-
for event in claude.prompt_stream("Write a haiku about tests.", model="haiku"):
|
|
31
|
-
print(event["type"])
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
## Background agents
|
|
35
|
-
|
|
36
|
-
```python
|
|
37
|
-
session_id = claude.start_background("Refactor the auth module", model="sonnet")
|
|
38
|
-
claude.list_agents()
|
|
39
|
-
claude.logs(session_id, strip_ansi=True)
|
|
40
|
-
claude.stop(session_id)
|
|
41
|
-
claude.rm(session_id)
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
## Auth
|
|
45
|
-
|
|
46
|
-
```python
|
|
47
|
-
claude.auth_status() # {"loggedIn": True, "email": "...", ...}
|
|
48
|
-
|
|
49
|
-
# Prints the sign-in URL, then forwards the pasted code to finish login
|
|
50
|
-
claude.auth_login()
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
## MCP servers and plugins
|
|
54
|
-
|
|
55
|
-
```python
|
|
56
|
-
claude.mcp_add("sentry", "https://mcp.sentry.dev/mcp", transport="http")
|
|
57
|
-
claude.mcp_list()
|
|
58
|
-
|
|
59
|
-
claude.plugin_install("some-plugin", yes=True)
|
|
60
|
-
claude.plugin_list(as_json=True)
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
See `ClaudeCLI`'s docstrings for the full method list — it covers every top-level `claude` command (`auth`, `mcp`, `plugin`, `project`, `agents`/background sessions, `auto-mode`, `doctor`, `update`, `install`, `import`, `ultrareview`, `gateway`) plus the main prompt flags. Anything not exposed as a named parameter can still be passed through via each method's `extra_flags` dict.
|
|
64
|
-
|
|
65
|
-
## Errors
|
|
66
|
-
|
|
67
|
-
All CLI failures raise `ClaudeCLIError` (or `ClaudeNotFoundError` / `ClaudeTimeoutError`), carrying `returncode`, `stdout`, and `stderr`.
|
|
68
|
-
|
|
69
|
-
## License
|
|
70
|
-
|
|
71
|
-
MIT
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|