Metadata-Version: 2.4
Name: shutapp
Version: 2.4.0
Summary: Model-agnostic PII firewall for LLM apps: scan/redact/rescan/verify SDK + a local Claude Code redaction proxy (`shutapp claude`).
Author: Shutapp
License: MIT
Keywords: pii,privacy,llm,openai,anthropic,redaction,prompt-injection
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Security
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: httpx<1.0,>=0.27
Requires-Dist: rfc8785<1.0,>=0.1
Requires-Dist: cryptography>=42
Requires-Dist: pyyaml<7.0,>=6.0
Requires-Dist: aiohttp<4.0,>=3.9
Requires-Dist: tomlkit<1.0,>=0.12
Provides-Extra: dev
Requires-Dist: pytest>=8; extra == "dev"

# shutapp — the model-agnostic PII firewall

Three lines. Any LLM.

```python
from shutapp import Shutapp

g = Shutapp(api_key="shu_live_...")
safe, session = g.scan("My email is john@acme.com")

# ...send `safe` to any LLM using your own provider key...

final = g.unscan(response_text, session)
```

Or the 2-line auto-wrap for OpenAI / Anthropic:

```python
from openai import OpenAI
from shutapp import guard
client = guard(OpenAI())          # every .chat.completions.create call is now protected
```

```python
from anthropic import Anthropic
from shutapp import guard
client = guard(Anthropic())       # every .messages.create call is now protected
```

## Run Claude Code privately — `shutapp claude`

The same package ships a local CLI that wraps **Claude Code** so secrets are
redacted before they ever reach Anthropic:

```bash
pip install shutapp
shutapp claude            # launches Claude Code through a local redaction proxy
```

`shutapp claude` starts a localhost proxy and runs the real `claude` through it,
so API keys and other secrets are swapped for reversible placeholders on the way
out and restored locally — Anthropic only ever sees redacted text. It works with
both **API-key** and **Claude Max/Pro subscription** logins: on a subscription it
auto-bridges your OAuth through the proxy (your credentials never leave your
machine except to Anthropic, exactly as Claude Code already sends them).
Requires Claude Code's `claude` on your PATH.

### Local chat history is redacted too

The model never receives a raw secret: the proxy re-redacts the entire
conversation (including replayed history) on every API call. But Claude Code
also writes your raw typed prompt to its own local transcript files
(`~/.claude/projects/.../*.jsonl`) for `--resume`. `shutapp claude` runs a
real-time history redactor that rewrites those secrets to the same placeholder
the model saw, and does a guaranteed final pass when Claude exits. Opt out with
`shutapp claude --no-history-scrub` (the model stays protected either way).

Already have older transcripts with secrets in them? Clean them up:

```bash
shutapp history scrub --dry-run   # report only
shutapp history scrub             # redact transcripts from the last 7 days
shutapp history scrub --all       # redact every transcript
```

```bash
shutapp status            # version, vault dir, detector count
shutapp session list      # value-free session stats
shutapp detectors list    # the bundled detector registry
shutapp verify rcpt.json  # offline receipt verification
```

## What it does

1. Sends your prompt text to the Shutapp API, which replaces PII with reversible
   placeholders like `[EMAIL_ADDRESS_1]`, `[PHONE_NUMBER_1]`, `[API_KEY_1]`.
2. You send the redacted text to **any** LLM using **your own** key.
   Shutapp never sees your LLM key and never sees the response.
3. You call `unscan(...)` to restore the original values in the LLM's response.

After every scan Shutapp prints a one-line receipt to your terminal:

```
[shutapp] scan ok · 12ms · EMAIL_ADDRESS x1, PHONE_NUMBER x1 · rcpt_8f3a2b
```

## Install (from PyPI, later)

```bash
pip install shutapp
```

## Install (from this monorepo, right now)

```bash
pip install -e ./packages/sdk-python
```

## Config

`Shutapp(api_key, base_url, receipts, receipt_format, timeout)`

* `receipts`: `"stderr"` (default), `"stdout"`, `"silent"`, or a callable
  `fn(receipt_dict)` for custom logging.
* `receipt_format`: `"line"` or `"block"`.
* `base_url`: override for self-hosted Shutapp (e.g. `http://localhost:8080`).
