pyclaudecli 1.0.1__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: pyclaudecli
3
- Version: 1.0.1
3
+ Version: 1.0.2
4
4
  Summary: Python library wrapping the Claude Code CLI: prompts, background agents, auth, MCP, plugins, and more
5
5
  Author-email: Suriya Ravichandran <suriyaravichandran@itrendsolution.com>
6
6
  License: MIT
@@ -37,6 +37,7 @@ It's a thin wrapper, not a reimplementation — every call runs the real `claude
37
37
  - [Install](#install)
38
38
  - [Quickstart](#quickstart)
39
39
  - [Setup](#setup)
40
+ - [Authentication](#authentication)
40
41
  - [Command-line usage](#command-line-usage)
41
42
  - [Errors](#errors)
42
43
  - [`build_flags`](#build_flags)
@@ -80,6 +81,94 @@ claude = ClaudeCLI(
80
81
  )
81
82
  ```
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
+
83
172
  ## Command-line usage
84
173
 
85
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.
@@ -222,6 +311,9 @@ claude.rm(session_id) # delete a stopped session
222
311
  claude.auth_status() # {"loggedIn": True, "email": "...", ...}
223
312
  claude.auth_status(as_json=False) # human-readable text instead
224
313
 
314
+ # Interactive OAuth: prints the sign-in URL, then reads the pasted code from stdin
315
+ claude.auth_login()
316
+
225
317
  # Non-interactive login: supply the code yourself
226
318
  claude.auth_login(code="123456")
227
319
 
@@ -231,6 +323,9 @@ claude.auth_login(code_provider=lambda url: fetch_code_from_my_browser(url))
231
323
  # Route the printed sign-in URL/output somewhere other than stdout
232
324
  claude.auth_login(on_output=lambda chunk: log.info(chunk), console=True, timeout=120)
233
325
 
326
+ claude.auth_login(sso=True) # enterprise SSO
327
+ claude.auth_login(email="you@example.com") # pre-fill the account
328
+
234
329
  claude.auth_logout()
235
330
  claude.setup_token() # interactive; sets up a long-lived auth token
236
331
  ```
@@ -14,6 +14,7 @@ It's a thin wrapper, not a reimplementation — every call runs the real `claude
14
14
  - [Install](#install)
15
15
  - [Quickstart](#quickstart)
16
16
  - [Setup](#setup)
17
+ - [Authentication](#authentication)
17
18
  - [Command-line usage](#command-line-usage)
18
19
  - [Errors](#errors)
19
20
  - [`build_flags`](#build_flags)
@@ -57,6 +58,94 @@ claude = ClaudeCLI(
57
58
  )
58
59
  ```
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
+
60
149
  ## Command-line usage
61
150
 
62
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.
@@ -199,6 +288,9 @@ claude.rm(session_id) # delete a stopped session
199
288
  claude.auth_status() # {"loggedIn": True, "email": "...", ...}
200
289
  claude.auth_status(as_json=False) # human-readable text instead
201
290
 
291
+ # Interactive OAuth: prints the sign-in URL, then reads the pasted code from stdin
292
+ claude.auth_login()
293
+
202
294
  # Non-interactive login: supply the code yourself
203
295
  claude.auth_login(code="123456")
204
296
 
@@ -208,6 +300,9 @@ claude.auth_login(code_provider=lambda url: fetch_code_from_my_browser(url))
208
300
  # Route the printed sign-in URL/output somewhere other than stdout
209
301
  claude.auth_login(on_output=lambda chunk: log.info(chunk), console=True, timeout=120)
210
302
 
303
+ claude.auth_login(sso=True) # enterprise SSO
304
+ claude.auth_login(email="you@example.com") # pre-fill the account
305
+
211
306
  claude.auth_logout()
212
307
  claude.setup_token() # interactive; sets up a long-lived auth token
213
308
  ```
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "pyclaudecli"
7
- version = "1.0.1"
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"
@@ -3,7 +3,7 @@
3
3
  from .client import ClaudeCLI, build_flags
4
4
  from .exceptions import ClaudeCLIError, ClaudeNotFoundError, ClaudeTimeoutError
5
5
 
6
- __version__ = "1.0.1"
6
+ __version__ = "1.0.2"
7
7
 
8
8
  __all__ = [
9
9
  "ClaudeCLI",
File without changes
File without changes