Metadata-Version: 2.4
Name: spendwall
Version: 0.1.1
Summary: Spendwall SDK — local-first agent spend firewall
Author: Spendwall
License-Expression: Apache-2.0
Project-URL: Homepage, https://github.com/catancs/spendwall
Project-URL: Repository, https://github.com/catancs/spendwall
Project-URL: Issues, https://github.com/catancs/spendwall/issues
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: requests>=2.28
Requires-Dist: requests-unixsocket>=0.3; sys_platform != "win32"
Requires-Dist: pywin32>=306; sys_platform == "win32"
Provides-Extra: openai
Requires-Dist: openai>=1.0; extra == "openai"
Provides-Extra: anthropic
Requires-Dist: anthropic>=0.21; extra == "anthropic"
Provides-Extra: all
Requires-Dist: openai>=1.0; extra == "all"
Requires-Dist: anthropic>=0.21; extra == "all"
Provides-Extra: dev
Requires-Dist: pytest>=7; extra == "dev"
Requires-Dist: pytest-asyncio>=0.21; extra == "dev"
Requires-Dist: responses>=0.23; extra == "dev"
Dynamic: license-file

# spendwall (Python)

## Quick start

```python
from spendwall import SpendwallClient

# Zero config: socket and token are auto-discovered from ~/.spendwall
# (override with SPENDWALL_DIR / SPENDWALL_SOCKET / SPENDWALL_TOKEN).
client = SpendwallClient()
```

## Daemon lifecycle

Zero-install by default: the client lazily auto-spawns the daemon on the first
call if none is running, and the daemon self-initializes its data dir.

```python
from spendwall import ensure_daemon, SpendwallClient

# Just use it — the daemon is spawned + self-initialized on the first call.
client = SpendwallClient()

# Or manage it explicitly: reuse a healthy daemon, or spawn one (binary via
# SPENDWALL_DAEMON_BIN, the bundled wheel, or PATH).
ensure_daemon()
```

Opt out of auto-spawn with `SPENDWALL_AUTOSPAWN=0` (or `SpendwallClient(auto_spawn=False)`).
With it disabled, a down daemon fails open in observe/advisory modes and
raises `DaemonNotRunningError` in enforce mode.

`~/.spendwall/auth.toml` is machine-managed — the daemon self-generates its
bearer token on first run; don't edit it.

### Compatibility window

The SDK checks the daemon's version from `/v1/about` on first use and refuses a
daemon whose SemVer **major** is more than 2 away from the SDK's (in either
direction) — raising `SpendwallVersionMismatch`, which fail-open clients
(observe/advisory) swallow and enforce surfaces. If the daemon advertises a
deprecation notice, the SDK emits a `warnings.warn`. (Pre-1.0 every version is
major 0, so the window is always satisfied today.)

## Provider wrappers

```python
import openai
import spendwall.openai as sw

client = openai.OpenAI(api_key="sk-...")
client = sw.wrap(client, mode="enforce")

# Now every client.chat.completions.create(...) is observed by spendwalld.
```
