Thin Python client for running Claude Code via the local claude executable.
Project description
stan_ai_client
stan_ai_client is a thin Python wrapper around the local claude executable.
It does not call Anthropic APIs directly. Claude Code must already be installed and authenticated on the machine.
The library is intentionally small and pragmatic:
run_text()for plain-text Claude outputrun_json()for--output-format jsonrun_structured()for schema-validated structured output- typed results
- structured exceptions
- local JSON Schema validation
- rate-limit parsing helpers
- stdlib logging
Why Use It
Use stan_ai_client when you want:
- a small Python API on top of Claude Code
- text mode and JSON mode without hand-rolling subprocess logic
- strongly guided structured output with local validation
- command metadata, typed JSON payloads, and normalized exceptions
- safe-by-default prompt logging behavior
- local automation that already depends on Claude Code being installed
Typical use cases:
- article summarization
- tagging or YAML generation
- one-shot repository or directory analysis
- local scripts that need Claude session metadata, cost, or duration
It is not a replacement for the Anthropic API SDK, and it is not trying to abstract multiple providers.
Install
From PyPI
pip install stan-ai-client
From a local checkout
python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
From GitHub
pip install "git+https://github.com/<your-user>/stan_ai_client.git"
Releases
- the package version lives in
pyproject.toml - every non-bot push or merge to
mainbumps patch automatically - tags use
vX.Y.Z mainreleases build and publish to PyPI automatically- release commits are created by GitHub Actions as
chore: release vX.Y.Z [skip ci]
Quickstart
1. Install Claude Code
Make sure claude is already available on your machine and authenticated:
claude --version
2. Run the smoke test
python examples/smoke_test.py
That runs one text-mode call and one JSON-mode call.
Minimal Usage
Text mode
from stan_ai_client import ClaudeCodeClient
client = ClaudeCodeClient()
result = client.run_text("Reply with the single word: ok")
print(result.text)
JSON mode
from pathlib import Path
from stan_ai_client import ClaudeCodeClient, RunOptions
client = ClaudeCodeClient(
default_model="claude-opus-4-6",
default_effort="max",
default_timeout_seconds=180,
)
result = client.run_json(
"Summarize this article.",
options=RunOptions(
cwd=Path("."),
allowed_tools=("Read", "Glob", "Grep", "Bash"),
),
)
print(result.payload.result)
print(result.payload.total_cost_usd)
print(result.payload.session_id)
Structured mode
from stan_ai_client import ClaudeCodeClient, StructuredSchema
client = ClaudeCodeClient()
schema = StructuredSchema.from_dict(
{
"type": "object",
"properties": {
"summary": {"type": "string"},
"tags": {"type": "array", "items": {"type": "string"}},
},
"required": ["summary", "tags"],
"additionalProperties": False,
}
)
result = client.run_structured(
"Summarize this article and return tags.",
schema=schema,
)
print(result.structured_output["summary"])
print(result.payload.session_id)
print(result.payload.total_cost_usd)
run_structured() validates the schema before Claude runs, requires structured_output in the response, and validates the returned object locally against the same schema.
Logging
import logging
from stan_ai_client import ClaudeCodeClient
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("my_app.claude")
client = ClaudeCodeClient(
logger=logger,
log_prompts=False,
)
client.run_text("Reply with the single word: ok")
By default, logging includes execution metadata, not full prompt text. Set log_prompts=True only if you explicitly want prompts written to logs.
Error handling
from stan_ai_client import ClaudeCodeClient, ClaudeRateLimitError
client = ClaudeCodeClient()
try:
result = client.run_json("Summarize this repository.")
except ClaudeRateLimitError as exc:
print(exc.rate_limit.retry_after_seconds)
print(exc.rate_limit.reset_at)
Public Surface
Top-level exports:
from stan_ai_client import (
__version__,
ClaudeCodeClient,
RunOptions,
TextRunResult,
JsonRunResult,
StructuredRunResult,
ClaudeJsonPayload,
CommandMetadata,
StructuredSchema,
ClaudeCodeError,
ClaudeExecutableNotFoundError,
ClaudeTimeoutError,
ClaudeProcessError,
ClaudeProtocolError,
ClaudeRateLimitError,
ClaudeSchemaValidationError,
ClaudeStructuredOutputMissingError,
ClaudeStructuredOutputValidationError,
RateLimitInfo,
parse_rate_limit_info,
)
Supported Features
- text mode via
run_text() - JSON mode via
run_json() - structured mode via
run_structured() - prompts sent over stdin by default
- optional argv prompt mode
- per-call working directory control
- model, effort, timeout, environment, and session controls
- support for Claude CLI flags via typed
RunOptions - raw stdout and stderr preserved on results and errors
- opt-in stdlib logging with safe default prompt handling
- typed JSON payload parsing with unknown fields preserved in
extras - local input and output validation for structured mode
- rate-limit detection and reset-time parsing
Examples
- examples/smoke_test.py
- examples/summarize_article.py
- examples/tag_article.py
- examples/logging_demo.py
Documentation
See DOCS.md for:
- full
RunOptionsreference - logging behavior
- result types
- structured output usage
- exception model
- rate-limit handling
- session usage
- common patterns
- current limitations
- maintainer release flow
Notes
- prompts default to stdin instead of argv
- JSON mode always requests
--output-format json - structured mode always requests
--output-format jsonand--json-schema - text mode always requests
--output-format text - logging uses stdlib
logging - prompts are not written to logs unless
log_prompts=True - the library is sync-only in
0.1.x - streaming is intentionally out of scope right now
Current Limitations
- no streaming support
- no async API
- no built-in retry loop
- no standalone CLI wrapper command
- no first-class typed wrapper yet for every Claude Code flag
- structured mode accepts dict-backed JSON Schema objects only
For unsupported Claude Code flags, use RunOptions(extra_args=...).
Development
pytest
mypy src tests
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file stan_ai_client-0.1.1.tar.gz.
File metadata
- Download URL: stan_ai_client-0.1.1.tar.gz
- Upload date:
- Size: 18.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d3fa894807467c5dfc51448f4188f033f8d45b0c88e6f12f2eae2a8ff92e8f4a
|
|
| MD5 |
6106d6704d65bde9256f7382da120cab
|
|
| BLAKE2b-256 |
f4ee2fab451849599eec171859ce509c9904eb9341f75b9ffc6f4b254828d975
|
Provenance
The following attestation bundles were made for stan_ai_client-0.1.1.tar.gz:
Publisher:
ci.yml on stanislavkozlovski/stan_ai_client
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
stan_ai_client-0.1.1.tar.gz -
Subject digest:
d3fa894807467c5dfc51448f4188f033f8d45b0c88e6f12f2eae2a8ff92e8f4a - Sigstore transparency entry: 1192082176
- Sigstore integration time:
-
Permalink:
stanislavkozlovski/stan_ai_client@c1e43715dd491309420419d20826714e7bc0acdb -
Branch / Tag:
refs/heads/main - Owner: https://github.com/stanislavkozlovski
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@c1e43715dd491309420419d20826714e7bc0acdb -
Trigger Event:
push
-
Statement type:
File details
Details for the file stan_ai_client-0.1.1-py3-none-any.whl.
File metadata
- Download URL: stan_ai_client-0.1.1-py3-none-any.whl
- Upload date:
- Size: 16.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
265fd2e0043419d3f1dd809718d7e83e571eae26553ab29de6ca0c7f41d9d06f
|
|
| MD5 |
e8d6dc9cf83d4d6c7bfce76168df499e
|
|
| BLAKE2b-256 |
baeb8ea80698cbd291742e5f1070d01cc81a19afe4009f81e39faa776c03079a
|
Provenance
The following attestation bundles were made for stan_ai_client-0.1.1-py3-none-any.whl:
Publisher:
ci.yml on stanislavkozlovski/stan_ai_client
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
stan_ai_client-0.1.1-py3-none-any.whl -
Subject digest:
265fd2e0043419d3f1dd809718d7e83e571eae26553ab29de6ca0c7f41d9d06f - Sigstore transparency entry: 1192082177
- Sigstore integration time:
-
Permalink:
stanislavkozlovski/stan_ai_client@c1e43715dd491309420419d20826714e7bc0acdb -
Branch / Tag:
refs/heads/main - Owner: https://github.com/stanislavkozlovski
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@c1e43715dd491309420419d20826714e7bc0acdb -
Trigger Event:
push
-
Statement type: