stan-ai-client 0.1.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,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Stanislav Kozlovski
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
@@ -0,0 +1,303 @@
1
+ Metadata-Version: 2.4
2
+ Name: stan-ai-client
3
+ Version: 0.1.1
4
+ Summary: Thin Python client for running Claude Code via the local claude executable.
5
+ Author: Stanislav Kozlovski
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/stanislavkozlovski/stan_ai_client
8
+ Project-URL: Repository, https://github.com/stanislavkozlovski/stan_ai_client
9
+ Project-URL: Issues, https://github.com/stanislavkozlovski/stan_ai_client/issues
10
+ Requires-Python: >=3.11
11
+ Description-Content-Type: text/markdown
12
+ License-File: LICENSE
13
+ Requires-Dist: jsonschema>=4.0
14
+ Provides-Extra: dev
15
+ Requires-Dist: build>=1.2; extra == "dev"
16
+ Requires-Dist: mypy>=1.10; extra == "dev"
17
+ Requires-Dist: pytest>=8.0; extra == "dev"
18
+ Requires-Dist: ruff>=0.5; extra == "dev"
19
+ Dynamic: license-file
20
+
21
+ # stan_ai_client
22
+
23
+ `stan_ai_client` is a thin Python wrapper around the local `claude` executable.
24
+
25
+ It does not call Anthropic APIs directly. Claude Code must already be installed and authenticated on the machine.
26
+
27
+ The library is intentionally small and pragmatic:
28
+
29
+ - `run_text()` for plain-text Claude output
30
+ - `run_json()` for `--output-format json`
31
+ - `run_structured()` for schema-validated structured output
32
+ - typed results
33
+ - structured exceptions
34
+ - local JSON Schema validation
35
+ - rate-limit parsing helpers
36
+ - stdlib logging
37
+
38
+ ## Why Use It
39
+
40
+ Use `stan_ai_client` when you want:
41
+
42
+ - a small Python API on top of Claude Code
43
+ - text mode and JSON mode without hand-rolling subprocess logic
44
+ - strongly guided structured output with local validation
45
+ - command metadata, typed JSON payloads, and normalized exceptions
46
+ - safe-by-default prompt logging behavior
47
+ - local automation that already depends on Claude Code being installed
48
+
49
+ Typical use cases:
50
+
51
+ - article summarization
52
+ - tagging or YAML generation
53
+ - one-shot repository or directory analysis
54
+ - local scripts that need Claude session metadata, cost, or duration
55
+
56
+ It is not a replacement for the Anthropic API SDK, and it is not trying to abstract multiple providers.
57
+
58
+ ## Install
59
+
60
+ ### From PyPI
61
+
62
+ ```bash
63
+ pip install stan-ai-client
64
+ ```
65
+
66
+ ### From a local checkout
67
+
68
+ ```bash
69
+ python3 -m venv .venv
70
+ source .venv/bin/activate
71
+ pip install -e ".[dev]"
72
+ ```
73
+
74
+ ### From GitHub
75
+
76
+ ```bash
77
+ pip install "git+https://github.com/<your-user>/stan_ai_client.git"
78
+ ```
79
+
80
+ ## Releases
81
+
82
+ - the package version lives in `pyproject.toml`
83
+ - every non-bot push or merge to `main` bumps patch automatically
84
+ - tags use `vX.Y.Z`
85
+ - `main` releases build and publish to PyPI automatically
86
+ - release commits are created by GitHub Actions as `chore: release vX.Y.Z [skip ci]`
87
+
88
+ ## Quickstart
89
+
90
+ ### 1. Install Claude Code
91
+
92
+ Make sure `claude` is already available on your machine and authenticated:
93
+
94
+ ```bash
95
+ claude --version
96
+ ```
97
+
98
+ ### 2. Run the smoke test
99
+
100
+ ```bash
101
+ python examples/smoke_test.py
102
+ ```
103
+
104
+ That runs one text-mode call and one JSON-mode call.
105
+
106
+ ## Minimal Usage
107
+
108
+ ### Text mode
109
+
110
+ ```python
111
+ from stan_ai_client import ClaudeCodeClient
112
+
113
+ client = ClaudeCodeClient()
114
+ result = client.run_text("Reply with the single word: ok")
115
+ print(result.text)
116
+ ```
117
+
118
+ ### JSON mode
119
+
120
+ ```python
121
+ from pathlib import Path
122
+
123
+ from stan_ai_client import ClaudeCodeClient, RunOptions
124
+
125
+ client = ClaudeCodeClient(
126
+ default_model="claude-opus-4-6",
127
+ default_effort="max",
128
+ default_timeout_seconds=180,
129
+ )
130
+
131
+ result = client.run_json(
132
+ "Summarize this article.",
133
+ options=RunOptions(
134
+ cwd=Path("."),
135
+ allowed_tools=("Read", "Glob", "Grep", "Bash"),
136
+ ),
137
+ )
138
+
139
+ print(result.payload.result)
140
+ print(result.payload.total_cost_usd)
141
+ print(result.payload.session_id)
142
+ ```
143
+
144
+ ### Structured mode
145
+
146
+ ```python
147
+ from stan_ai_client import ClaudeCodeClient, StructuredSchema
148
+
149
+ client = ClaudeCodeClient()
150
+
151
+ schema = StructuredSchema.from_dict(
152
+ {
153
+ "type": "object",
154
+ "properties": {
155
+ "summary": {"type": "string"},
156
+ "tags": {"type": "array", "items": {"type": "string"}},
157
+ },
158
+ "required": ["summary", "tags"],
159
+ "additionalProperties": False,
160
+ }
161
+ )
162
+
163
+ result = client.run_structured(
164
+ "Summarize this article and return tags.",
165
+ schema=schema,
166
+ )
167
+
168
+ print(result.structured_output["summary"])
169
+ print(result.payload.session_id)
170
+ print(result.payload.total_cost_usd)
171
+ ```
172
+
173
+ `run_structured()` validates the schema before Claude runs, requires `structured_output` in the response, and validates the returned object locally against the same schema.
174
+
175
+ ### Logging
176
+
177
+ ```python
178
+ import logging
179
+
180
+ from stan_ai_client import ClaudeCodeClient
181
+
182
+ logging.basicConfig(level=logging.INFO)
183
+ logger = logging.getLogger("my_app.claude")
184
+
185
+ client = ClaudeCodeClient(
186
+ logger=logger,
187
+ log_prompts=False,
188
+ )
189
+
190
+ client.run_text("Reply with the single word: ok")
191
+ ```
192
+
193
+ By default, logging includes execution metadata, not full prompt text. Set `log_prompts=True` only if you explicitly want prompts written to logs.
194
+
195
+ ### Error handling
196
+
197
+ ```python
198
+ from stan_ai_client import ClaudeCodeClient, ClaudeRateLimitError
199
+
200
+ client = ClaudeCodeClient()
201
+
202
+ try:
203
+ result = client.run_json("Summarize this repository.")
204
+ except ClaudeRateLimitError as exc:
205
+ print(exc.rate_limit.retry_after_seconds)
206
+ print(exc.rate_limit.reset_at)
207
+ ```
208
+
209
+ ## Public Surface
210
+
211
+ Top-level exports:
212
+
213
+ ```python
214
+ from stan_ai_client import (
215
+ __version__,
216
+ ClaudeCodeClient,
217
+ RunOptions,
218
+ TextRunResult,
219
+ JsonRunResult,
220
+ StructuredRunResult,
221
+ ClaudeJsonPayload,
222
+ CommandMetadata,
223
+ StructuredSchema,
224
+ ClaudeCodeError,
225
+ ClaudeExecutableNotFoundError,
226
+ ClaudeTimeoutError,
227
+ ClaudeProcessError,
228
+ ClaudeProtocolError,
229
+ ClaudeRateLimitError,
230
+ ClaudeSchemaValidationError,
231
+ ClaudeStructuredOutputMissingError,
232
+ ClaudeStructuredOutputValidationError,
233
+ RateLimitInfo,
234
+ parse_rate_limit_info,
235
+ )
236
+ ```
237
+
238
+ ## Supported Features
239
+
240
+ - text mode via `run_text()`
241
+ - JSON mode via `run_json()`
242
+ - structured mode via `run_structured()`
243
+ - prompts sent over stdin by default
244
+ - optional argv prompt mode
245
+ - per-call working directory control
246
+ - model, effort, timeout, environment, and session controls
247
+ - support for Claude CLI flags via typed `RunOptions`
248
+ - raw stdout and stderr preserved on results and errors
249
+ - opt-in stdlib logging with safe default prompt handling
250
+ - typed JSON payload parsing with unknown fields preserved in `extras`
251
+ - local input and output validation for structured mode
252
+ - rate-limit detection and reset-time parsing
253
+
254
+ ## Examples
255
+
256
+ - [examples/smoke_test.py](./examples/smoke_test.py)
257
+ - [examples/summarize_article.py](./examples/summarize_article.py)
258
+ - [examples/tag_article.py](./examples/tag_article.py)
259
+ - [examples/logging_demo.py](./examples/logging_demo.py)
260
+
261
+ ## Documentation
262
+
263
+ See [DOCS.md](./DOCS.md) for:
264
+
265
+ - full `RunOptions` reference
266
+ - logging behavior
267
+ - result types
268
+ - structured output usage
269
+ - exception model
270
+ - rate-limit handling
271
+ - session usage
272
+ - common patterns
273
+ - current limitations
274
+ - maintainer release flow
275
+
276
+ ## Notes
277
+
278
+ - prompts default to stdin instead of argv
279
+ - JSON mode always requests `--output-format json`
280
+ - structured mode always requests `--output-format json` and `--json-schema`
281
+ - text mode always requests `--output-format text`
282
+ - logging uses stdlib `logging`
283
+ - prompts are not written to logs unless `log_prompts=True`
284
+ - the library is sync-only in `0.1.x`
285
+ - streaming is intentionally out of scope right now
286
+
287
+ ## Current Limitations
288
+
289
+ - no streaming support
290
+ - no async API
291
+ - no built-in retry loop
292
+ - no standalone CLI wrapper command
293
+ - no first-class typed wrapper yet for every Claude Code flag
294
+ - structured mode accepts dict-backed JSON Schema objects only
295
+
296
+ For unsupported Claude Code flags, use `RunOptions(extra_args=...)`.
297
+
298
+ ## Development
299
+
300
+ ```bash
301
+ pytest
302
+ mypy src tests
303
+ ```
@@ -0,0 +1,283 @@
1
+ # stan_ai_client
2
+
3
+ `stan_ai_client` is a thin Python wrapper around the local `claude` executable.
4
+
5
+ It does not call Anthropic APIs directly. Claude Code must already be installed and authenticated on the machine.
6
+
7
+ The library is intentionally small and pragmatic:
8
+
9
+ - `run_text()` for plain-text Claude output
10
+ - `run_json()` for `--output-format json`
11
+ - `run_structured()` for schema-validated structured output
12
+ - typed results
13
+ - structured exceptions
14
+ - local JSON Schema validation
15
+ - rate-limit parsing helpers
16
+ - stdlib logging
17
+
18
+ ## Why Use It
19
+
20
+ Use `stan_ai_client` when you want:
21
+
22
+ - a small Python API on top of Claude Code
23
+ - text mode and JSON mode without hand-rolling subprocess logic
24
+ - strongly guided structured output with local validation
25
+ - command metadata, typed JSON payloads, and normalized exceptions
26
+ - safe-by-default prompt logging behavior
27
+ - local automation that already depends on Claude Code being installed
28
+
29
+ Typical use cases:
30
+
31
+ - article summarization
32
+ - tagging or YAML generation
33
+ - one-shot repository or directory analysis
34
+ - local scripts that need Claude session metadata, cost, or duration
35
+
36
+ It is not a replacement for the Anthropic API SDK, and it is not trying to abstract multiple providers.
37
+
38
+ ## Install
39
+
40
+ ### From PyPI
41
+
42
+ ```bash
43
+ pip install stan-ai-client
44
+ ```
45
+
46
+ ### From a local checkout
47
+
48
+ ```bash
49
+ python3 -m venv .venv
50
+ source .venv/bin/activate
51
+ pip install -e ".[dev]"
52
+ ```
53
+
54
+ ### From GitHub
55
+
56
+ ```bash
57
+ pip install "git+https://github.com/<your-user>/stan_ai_client.git"
58
+ ```
59
+
60
+ ## Releases
61
+
62
+ - the package version lives in `pyproject.toml`
63
+ - every non-bot push or merge to `main` bumps patch automatically
64
+ - tags use `vX.Y.Z`
65
+ - `main` releases build and publish to PyPI automatically
66
+ - release commits are created by GitHub Actions as `chore: release vX.Y.Z [skip ci]`
67
+
68
+ ## Quickstart
69
+
70
+ ### 1. Install Claude Code
71
+
72
+ Make sure `claude` is already available on your machine and authenticated:
73
+
74
+ ```bash
75
+ claude --version
76
+ ```
77
+
78
+ ### 2. Run the smoke test
79
+
80
+ ```bash
81
+ python examples/smoke_test.py
82
+ ```
83
+
84
+ That runs one text-mode call and one JSON-mode call.
85
+
86
+ ## Minimal Usage
87
+
88
+ ### Text mode
89
+
90
+ ```python
91
+ from stan_ai_client import ClaudeCodeClient
92
+
93
+ client = ClaudeCodeClient()
94
+ result = client.run_text("Reply with the single word: ok")
95
+ print(result.text)
96
+ ```
97
+
98
+ ### JSON mode
99
+
100
+ ```python
101
+ from pathlib import Path
102
+
103
+ from stan_ai_client import ClaudeCodeClient, RunOptions
104
+
105
+ client = ClaudeCodeClient(
106
+ default_model="claude-opus-4-6",
107
+ default_effort="max",
108
+ default_timeout_seconds=180,
109
+ )
110
+
111
+ result = client.run_json(
112
+ "Summarize this article.",
113
+ options=RunOptions(
114
+ cwd=Path("."),
115
+ allowed_tools=("Read", "Glob", "Grep", "Bash"),
116
+ ),
117
+ )
118
+
119
+ print(result.payload.result)
120
+ print(result.payload.total_cost_usd)
121
+ print(result.payload.session_id)
122
+ ```
123
+
124
+ ### Structured mode
125
+
126
+ ```python
127
+ from stan_ai_client import ClaudeCodeClient, StructuredSchema
128
+
129
+ client = ClaudeCodeClient()
130
+
131
+ schema = StructuredSchema.from_dict(
132
+ {
133
+ "type": "object",
134
+ "properties": {
135
+ "summary": {"type": "string"},
136
+ "tags": {"type": "array", "items": {"type": "string"}},
137
+ },
138
+ "required": ["summary", "tags"],
139
+ "additionalProperties": False,
140
+ }
141
+ )
142
+
143
+ result = client.run_structured(
144
+ "Summarize this article and return tags.",
145
+ schema=schema,
146
+ )
147
+
148
+ print(result.structured_output["summary"])
149
+ print(result.payload.session_id)
150
+ print(result.payload.total_cost_usd)
151
+ ```
152
+
153
+ `run_structured()` validates the schema before Claude runs, requires `structured_output` in the response, and validates the returned object locally against the same schema.
154
+
155
+ ### Logging
156
+
157
+ ```python
158
+ import logging
159
+
160
+ from stan_ai_client import ClaudeCodeClient
161
+
162
+ logging.basicConfig(level=logging.INFO)
163
+ logger = logging.getLogger("my_app.claude")
164
+
165
+ client = ClaudeCodeClient(
166
+ logger=logger,
167
+ log_prompts=False,
168
+ )
169
+
170
+ client.run_text("Reply with the single word: ok")
171
+ ```
172
+
173
+ By default, logging includes execution metadata, not full prompt text. Set `log_prompts=True` only if you explicitly want prompts written to logs.
174
+
175
+ ### Error handling
176
+
177
+ ```python
178
+ from stan_ai_client import ClaudeCodeClient, ClaudeRateLimitError
179
+
180
+ client = ClaudeCodeClient()
181
+
182
+ try:
183
+ result = client.run_json("Summarize this repository.")
184
+ except ClaudeRateLimitError as exc:
185
+ print(exc.rate_limit.retry_after_seconds)
186
+ print(exc.rate_limit.reset_at)
187
+ ```
188
+
189
+ ## Public Surface
190
+
191
+ Top-level exports:
192
+
193
+ ```python
194
+ from stan_ai_client import (
195
+ __version__,
196
+ ClaudeCodeClient,
197
+ RunOptions,
198
+ TextRunResult,
199
+ JsonRunResult,
200
+ StructuredRunResult,
201
+ ClaudeJsonPayload,
202
+ CommandMetadata,
203
+ StructuredSchema,
204
+ ClaudeCodeError,
205
+ ClaudeExecutableNotFoundError,
206
+ ClaudeTimeoutError,
207
+ ClaudeProcessError,
208
+ ClaudeProtocolError,
209
+ ClaudeRateLimitError,
210
+ ClaudeSchemaValidationError,
211
+ ClaudeStructuredOutputMissingError,
212
+ ClaudeStructuredOutputValidationError,
213
+ RateLimitInfo,
214
+ parse_rate_limit_info,
215
+ )
216
+ ```
217
+
218
+ ## Supported Features
219
+
220
+ - text mode via `run_text()`
221
+ - JSON mode via `run_json()`
222
+ - structured mode via `run_structured()`
223
+ - prompts sent over stdin by default
224
+ - optional argv prompt mode
225
+ - per-call working directory control
226
+ - model, effort, timeout, environment, and session controls
227
+ - support for Claude CLI flags via typed `RunOptions`
228
+ - raw stdout and stderr preserved on results and errors
229
+ - opt-in stdlib logging with safe default prompt handling
230
+ - typed JSON payload parsing with unknown fields preserved in `extras`
231
+ - local input and output validation for structured mode
232
+ - rate-limit detection and reset-time parsing
233
+
234
+ ## Examples
235
+
236
+ - [examples/smoke_test.py](./examples/smoke_test.py)
237
+ - [examples/summarize_article.py](./examples/summarize_article.py)
238
+ - [examples/tag_article.py](./examples/tag_article.py)
239
+ - [examples/logging_demo.py](./examples/logging_demo.py)
240
+
241
+ ## Documentation
242
+
243
+ See [DOCS.md](./DOCS.md) for:
244
+
245
+ - full `RunOptions` reference
246
+ - logging behavior
247
+ - result types
248
+ - structured output usage
249
+ - exception model
250
+ - rate-limit handling
251
+ - session usage
252
+ - common patterns
253
+ - current limitations
254
+ - maintainer release flow
255
+
256
+ ## Notes
257
+
258
+ - prompts default to stdin instead of argv
259
+ - JSON mode always requests `--output-format json`
260
+ - structured mode always requests `--output-format json` and `--json-schema`
261
+ - text mode always requests `--output-format text`
262
+ - logging uses stdlib `logging`
263
+ - prompts are not written to logs unless `log_prompts=True`
264
+ - the library is sync-only in `0.1.x`
265
+ - streaming is intentionally out of scope right now
266
+
267
+ ## Current Limitations
268
+
269
+ - no streaming support
270
+ - no async API
271
+ - no built-in retry loop
272
+ - no standalone CLI wrapper command
273
+ - no first-class typed wrapper yet for every Claude Code flag
274
+ - structured mode accepts dict-backed JSON Schema objects only
275
+
276
+ For unsupported Claude Code flags, use `RunOptions(extra_args=...)`.
277
+
278
+ ## Development
279
+
280
+ ```bash
281
+ pytest
282
+ mypy src tests
283
+ ```
@@ -0,0 +1,49 @@
1
+ [build-system]
2
+ requires = ["setuptools>=69"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "stan-ai-client"
7
+ version = "0.1.1"
8
+ description = "Thin Python client for running Claude Code via the local claude executable."
9
+ readme = "README.md"
10
+ requires-python = ">=3.11"
11
+ license = { text = "MIT" }
12
+ authors = [
13
+ {name = "Stanislav Kozlovski"},
14
+ ]
15
+ dependencies = [
16
+ "jsonschema>=4.0",
17
+ ]
18
+
19
+ [project.urls]
20
+ Homepage = "https://github.com/stanislavkozlovski/stan_ai_client"
21
+ Repository = "https://github.com/stanislavkozlovski/stan_ai_client"
22
+ Issues = "https://github.com/stanislavkozlovski/stan_ai_client/issues"
23
+
24
+ [project.optional-dependencies]
25
+ dev = [
26
+ "build>=1.2",
27
+ "mypy>=1.10",
28
+ "pytest>=8.0",
29
+ "ruff>=0.5",
30
+ ]
31
+
32
+ [tool.setuptools]
33
+ package-dir = {"" = "src"}
34
+
35
+ [tool.setuptools.packages.find]
36
+ where = ["src"]
37
+
38
+ [tool.pytest.ini_options]
39
+ testpaths = ["tests"]
40
+ pythonpath = ["src"]
41
+
42
+ [tool.mypy]
43
+ python_version = "3.11"
44
+ strict = true
45
+ warn_unused_configs = true
46
+
47
+ [[tool.mypy.overrides]]
48
+ module = ["jsonschema", "jsonschema.*"]
49
+ ignore_missing_imports = true
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,48 @@
1
+ from ._version import get_version
2
+ from .client import ClaudeCodeClient
3
+ from .exceptions import (
4
+ ClaudeCodeError,
5
+ ClaudeExecutableNotFoundError,
6
+ ClaudeProcessError,
7
+ ClaudeProtocolError,
8
+ ClaudeRateLimitError,
9
+ ClaudeSchemaValidationError,
10
+ ClaudeStructuredOutputMissingError,
11
+ ClaudeStructuredOutputValidationError,
12
+ ClaudeTimeoutError,
13
+ )
14
+ from .rate_limits import RateLimitInfo, parse_rate_limit_info
15
+ from .schema import StructuredSchema
16
+ from .types import (
17
+ ClaudeJsonPayload,
18
+ CommandMetadata,
19
+ JsonRunResult,
20
+ RunOptions,
21
+ StructuredRunResult,
22
+ TextRunResult,
23
+ )
24
+
25
+ __version__ = get_version()
26
+
27
+ __all__ = [
28
+ "__version__",
29
+ "ClaudeCodeClient",
30
+ "ClaudeCodeError",
31
+ "ClaudeExecutableNotFoundError",
32
+ "ClaudeJsonPayload",
33
+ "ClaudeProcessError",
34
+ "ClaudeProtocolError",
35
+ "ClaudeRateLimitError",
36
+ "ClaudeSchemaValidationError",
37
+ "ClaudeStructuredOutputMissingError",
38
+ "ClaudeStructuredOutputValidationError",
39
+ "ClaudeTimeoutError",
40
+ "CommandMetadata",
41
+ "JsonRunResult",
42
+ "RateLimitInfo",
43
+ "RunOptions",
44
+ "StructuredRunResult",
45
+ "StructuredSchema",
46
+ "TextRunResult",
47
+ "parse_rate_limit_info",
48
+ ]