tokensaver-egress
Capture HTTPS traffic from your AI agents (Claude Code, Cursor, n8n, …) and send audits to the TokenSaver control plane.
You run a small proxy on your machine. Your tools talk to the proxy; the proxy talks to Anthropic / OpenAI / … and reports what happened to TokenSaver (Flux IA).
Your agent ──HTTPS──► tokensaver-egress ──► api.anthropic.com / …
│
└── audits ──► api.tokensaver.fr → Flux IA
Architecture (client only)
tokensaver-egress is a lightweight client-side HTTPS proxy. It does not embed TokenSaver business logic, databases, or admin console.
| Runs locally (this package) | Runs on TokenSaver SaaS (platform.tokensaver.fr) |
|---|---|
| Listen / MITM / forward HTTPS | Ingest, Flux IA, storage |
| Optional body capture (auth headers masked) | Governance policies (cache, RAG, compression, PII, routing) |
Ship audits + call policy APIs with your ts_… key |
Catalogue enforce, quotas, dashboards |
You need an API key from the control plane. Default ingest: https://api.tokensaver.fr/api/v1/egress/ingest.
How it works (principles)
These are the design ideas behind the product — enough to use it safely, without exposing internal control-plane details.
-
Runs next to the agent, not in the cloud
The proxy is a separate process on the laptop, CI runner, or pod where Claude Code / Cursor / your agent runs. TokenSaver SaaS never terminates your LLM TLS for you. -
Traffic still goes to the real provider
Anthropic, OpenAI, etc. remain the destination. Egress sits in the middle only for observation (and optional governance hooks). Uninstall or unsetHTTPS_PROXYand your tools talk to providers directly again. -
Metadata first; plaintext stays local by default
By default the proxy reports observability facts to TokenSaver (destination host, timing, sizes, and — with MITM — model / token usage when available). Full request/response bodies are off unless you opt in (EGRESS_CAPTURE_BODIES). Auth headers are masked when bodies are captured. -
Three visibility levels (you choose)
- Explicit proxy — point
HTTPS_PROXYat egress: see that a call happened (host, latency, bytes). TLS content stays opaque. - MITM (opt-in) — trust a local CA once: for known LLM hosts, egress can read what is needed for richer audits (model, tokens, tool names) and for SaaS policies.
- Transparent (Linux, advanced) — network-level redirect so clients need not set proxy env (harder to “forget” the proxy). Still metadata-oriented unless you also enable MITM where applicable.
- Explicit proxy — point
-
SaaS decides policy; the proxy asks and applies
Cache, compression, PII handling, catalogue allow/deny, model preferences, etc. are configured on your API key in the control plane. The local proxy fetches effective settings and may call TokenSaver APIs during a request; it does not hard-code your organisation’s rules in the package. -
Streaming stays interactive
When MITM is on, responses are still streamed to the agent in real time. Audits are built along the way — you should not feel a “buffer everything then reply” delay for normal chat. -
Fail soft by default
If the control plane is briefly unreachable, capture/forward typically continues (audits may be dropped or policies skipped depending on options). Stricter “block if SaaS is down” behaviour is available for enforcement scenarios — opt in deliberately. -
Your key is the trust boundary
TOKENSAVER_API_KEYauthenticates ingest and policy calls. Without a valid key the proxy can still forward traffic locally, but nothing useful appears in Flux IA.
Install
pip install -U tokensaver-egress
tokensaver-egress setup # interactive wizard (recommended)
Or open the menu with a bare tokensaver-egress in a terminal (TTY).
Requires Python ≥ 3.10 and a TokenSaver API key (ts_…) from platform.tokensaver.fr.
Easiest path: guided setup
tokensaver-egress setup
The wizard walks you through:
- API key (
TOKENSAVER_API_KEY) - Ingest URL (default: production TokenSaver)
- MITM on/off + create the local CA if needed
- Trust instructions (and optional macOS keychain trust)
- Body capture on/off
- Port (default
8888) - Claude Code skills (CCR / onboarding) if missing — no
tokensaver-clirequired - Saves
~/.tokensaver-egress/env+client-env.sh, then offers to start the proxy
In another terminal:
source ~/.tokensaver-egress/client-env.sh
claude # or your agent
Next time you can run tokensaver-egress → Start proxy now, or:
source ~/.tokensaver-egress/env
tokensaver-egress serve
5-minute setup (manual MITM)
MITM mode can see model, tokens, and tool names. You must trust a local certificate once.
1. Configure TokenSaver
export TOKENSAVER_API_KEY=ts_your_key_here
export TOKENSAVER_INGEST_URL=https://api.tokensaver.fr/api/v1/egress/ingest
2. Create the local CA (once)
tokensaver-egress init-ca
# Writes: ~/.tokensaver-egress/ca/ca.crt
Trust that CA on this Mac (system keychain), then tell Node (Claude Code) to use it:
# macOS — trust the CA (admin password)
sudo security add-trusted-cert -d -r trustRoot \
-k /Library/Keychains/System.keychain \
"$HOME/.tokensaver-egress/ca/ca.crt"
# Every terminal where you run Claude Code / Node agents
export NODE_EXTRA_CA_CERTS="$HOME/.tokensaver-egress/ca/ca.crt"
3. Start the proxy
EGRESS_MITM_ENABLED=true tokensaver-egress serve --port 8888
Leave this terminal open. You should see something like listening on …8888.
4. Point your tools at the proxy
In another terminal:
export HTTPS_PROXY=http://127.0.0.1:8888
export HTTP_PROXY=http://127.0.0.1:8888
export NODE_EXTRA_CA_CERTS="$HOME/.tokensaver-egress/ca/ca.crt"
# Example: Claude Code
claude
5. Check Flux IA
Open platform.tokensaver.fr → Flux IA / egress flows. New calls should appear within seconds.
Everyday commands
| Command | What it does |
|---|---|
tokensaver-egress |
Interactive menu (TTY) or help |
tokensaver-egress setup |
Guided setup (API key, CA, Claude skills, options, start) |
tokensaver-egress install-skills |
Install Claude Code skills to ~/.claude/skills/tokensaver-router |
tokensaver-egress unproxy |
Clear HTTPS_PROXY / HTTP_PROXY in your shell (after stop) |
tokensaver-egress serve |
Start proxy on 0.0.0.0:8888 (loads ~/.tokensaver-egress/env) |
tokensaver-egress serve --port 8890 |
Use another port |
tokensaver-egress init-ca |
(Re)generate the MITM CA |
Ctrl+C |
Stop serve |
If the port is busy:
✖ Cannot listen on 0.0.0.0:8888 (Address already in use).
Try: tokensaver-egress serve --port 8889
Stop whatever is on 8888 (often another egress), or pick a free port and update HTTPS_PROXY.
Claude Code skills (no CLI needed)
tokensaver-egress install-skills
# or: tokensaver-egress install-skills --force
Installs ~/.claude/skills/tokensaver-router (same plugin as tokensaver-cli): CCR, onboarding, MCP helpers. Restart Claude Code after install.
After Ctrl+C — clear the proxy in client shells
Stopping egress does not unset env vars in other terminals. If pip / curl still try localhost:8888:
source ~/.tokensaver-egress/client-unproxy.sh
# or:
eval "$(tokensaver-egress unproxy --sh)"
# or:
unset HTTPS_PROXY HTTP_PROXY
Then retry your install.
Examples
A. Claude Code (full capture)
# Terminal A — proxy
export TOKENSAVER_API_KEY=ts_…
export TOKENSAVER_INGEST_URL=https://api.tokensaver.fr/api/v1/egress/ingest
EGRESS_MITM_ENABLED=true EGRESS_CAPTURE_BODIES=1 \
tokensaver-egress serve --port 8888
# Terminal B — agent
export HTTPS_PROXY=http://127.0.0.1:8888
export HTTP_PROXY=http://127.0.0.1:8888
export NODE_EXTRA_CA_CERTS="$HOME/.tokensaver-egress/ca/ca.crt"
claude
EGRESS_CAPTURE_BODIES=1 stores request/response bodies in TokenSaver (auth headers are masked). Omit it if you only want metadata (host, latency, tokens).
B. One-shot curl through the proxy
# Proxy already running with MITM + CA trusted
export HTTPS_PROXY=http://127.0.0.1:8888
curl -sS https://api.anthropic.com/v1/messages \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "content-type: application/json" \
-d '{"model":"claude-haiku-4-5-20251001","max_tokens":32,"messages":[{"role":"user","content":"ping"}]}'
C. Metadata only (no TLS decrypt)
No CA trust needed. You still see host / bytes / latency, not model tokens.
export TOKENSAVER_API_KEY=ts_…
export TOKENSAVER_INGEST_URL=https://api.tokensaver.fr/api/v1/egress/ingest
tokensaver-egress serve --port 8888
# Client
export HTTPS_PROXY=http://127.0.0.1:8888
export HTTP_PROXY=http://127.0.0.1:8888
D. Local TokenSaver backend (dev)
export TOKENSAVER_API_KEY=ts_…
export TOKENSAVER_INGEST_URL=http://localhost:8000/api/v1/egress/ingest
EGRESS_MITM_ENABLED=true tokensaver-egress serve --port 8888
Modes (simple)
| Mode | How you enable it | What you get |
|---|---|---|
| Explicit | HTTPS_PROXY → proxy |
Host, size, latency |
| MITM | + EGRESS_MITM_ENABLED=true + trusted CA |
Model, tokens, tools, optional bodies |
| Transparent | Linux TPROXY (advanced) | No proxy env on the client; metadata only |
Most people want MITM + explicit proxy (sections above).
Mental model: explicit = “I opted this shell in”; MITM = “I also trust a local cert so TokenSaver can enrich the audit”; transparent = “the network forces traffic through the proxy” (ops / lock-down setups).
Transparent (Linux only):
sudo EGRESS_PORT=8888 ./scripts/tproxy-setup.sh up
tokensaver-egress serve --transparent --port 8888
Useful environment variables
| Variable | Meaning |
|---|---|
TOKENSAVER_API_KEY |
Your ts_… key (required to ship audits) |
TOKENSAVER_INGEST_URL |
SaaS default: https://api.tokensaver.fr/api/v1/egress/ingest |
EGRESS_MITM_ENABLED |
true = decrypt known LLM hosts |
EGRESS_CAPTURE_BODIES |
1 = store bodies in Flux IA |
EGRESS_ENFORCE_ENABLED |
1 = block non-approved catalogue assets |
TOKENSAVER_NO_BANNER |
1 = hide the ASCII logo |
NODE_EXTRA_CA_CERTS |
Path to ca.crt for Node / Claude Code |
Troubleshooting
| Symptom | Fix |
|---|---|
pip install -U stays on an old version |
pip install -U --no-cache-dir tokensaver-egress |
| TLS / certificate errors in Claude Code | Trust ca.crt and set NODE_EXTRA_CA_CERTS |
| Nothing in Flux IA | Check TOKENSAVER_API_KEY + TOKENSAVER_INGEST_URL; watch proxy logs |
| Port already in use | tokensaver-egress serve --port 8889 (update HTTPS_PROXY) |
| Want quieter startup | TOKENSAVER_NO_BANNER=1 tokensaver-egress serve |
Security
- Run MITM only on machines you control. The CA can decrypt traffic you route through the proxy.
HTTPS_PROXYis easy to unset — it is not a hard security boundary. For lock-down, seek8s/networkpolicy.example.yaml/ transparent mode.- Bodies are optional; auth headers are masked unless you opt into raw headers.
Related
| Package | Role |
|---|---|
tokensaver-cli |
Route Claude Code / Cursor through TokenSaver APIs |
tokensaver-sdk |
Python SDK |
| TokenSaver platform | Control plane (Flux IA, policies, keys) |
License
MIT © TokenSaver
Release files for tokensaver-egress 0.1.13
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| tokensaver_egress-0.1.13.tar.gz | 100.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| tokensaver_egress-0.1.13-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 203.9 kB
Release files / tokensaver_egress-0.1.13.tar.gz
| Download URL | tokensaver_egress-0.1.13.tar.gz |
|---|---|
| Size | 100.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
e1e8c0d05963f4af2d6c7fbc01e07f0faaa5074a8e5011fe35c3c55aaf9ae04f
|
|
BLAKE2b-256 checksum How to use checksums |
04dd352ba980a9c094815fc427fdf38f162eb1204229eee7adc37efd78af4479
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.16
|
Release files / tokensaver_egress-0.1.13-py3-none-any.whl
| Download URL | tokensaver_egress-0.1.13-py3-none-any.whl |
|---|---|
| Size | 103.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
8e335b09c4e1398095a01f12adf596f93fad7361ad62f35ae36359d83cba5d13
|
|
BLAKE2b-256 checksum How to use checksums |
06fb038dbfb2ffd60c2d78e0450d2a546ecb55fd3c8526c0d81f72e297a09381
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.16
|