ctxoptimizer 0.4.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.
- ctxoptimizer-0.4.1/LICENSE +21 -0
- ctxoptimizer-0.4.1/NOTICE +13 -0
- ctxoptimizer-0.4.1/PKG-INFO +196 -0
- ctxoptimizer-0.4.1/README.md +157 -0
- ctxoptimizer-0.4.1/pyproject.toml +100 -0
- ctxoptimizer-0.4.1/pyproject.toml.orig +86 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/__init__.py +5 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/__main__.py +14 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/admin_security.py +130 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/analysis/__init__.py +1 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/analysis/baseline.py +69 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/analysis/break_even.py +49 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/analysis/drift.py +151 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/analysis/edits.py +148 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/analysis/markers.py +34 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/analysis/recommend.py +114 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/analysis/segments.py +57 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/analysis/session.py +62 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/analysis/state.py +239 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/analysis/tokens.py +62 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/analysis/waste.py +322 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/cli.py +873 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/config.py +512 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/dashboard/__init__.py +1 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/dashboard/api.py +537 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/dashboard/service.py +157 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/dashboard/static/.gitkeep +1 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/dashboard/templates/.gitkeep +1 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/dashboard/templates/doctor.html +46 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/dashboard/templates/live.html +91 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/dashboard/templates/overview.html +172 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/dashboard/templates/pricing.html +115 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/dashboard/templates/request.html +111 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/dashboard/templates/session.html +67 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/dashboard/templates/settings.html +79 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/dashboard/templates/table.html +56 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/dashboard/templates/transforms.html +118 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/dashboard/templates/waste.html +120 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/dashboard/views.py +429 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/data/cache_limits.json +23 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/data/default_config.toml +185 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/data/pricing.json +421 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/doctor.py +129 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/guard.py +139 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/ids.py +73 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/log.py +73 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/mcp.py +124 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/models.py +145 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/pipeline.py +126 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/profiles.py +152 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/providers/__init__.py +37 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/providers/anthropic.py +105 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/providers/base.py +191 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/providers/gemini.py +143 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/providers/ollama.py +133 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/providers/openai_chat.py +135 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/providers/openai_responses.py +121 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/proxy.py +665 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/routing.py +259 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/server.py +319 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/service.py +150 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/telemetry/__init__.py +1 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/telemetry/blobs.py +57 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/telemetry/expand.py +62 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/telemetry/pricing.py +168 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/telemetry/redact.py +53 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/telemetry/sse.py +145 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/telemetry/store.py +829 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/telemetry/usage.py +435 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/transforms/__init__.py +87 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/transforms/ansi.py +21 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/transforms/anthropic_cache.py +100 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/transforms/backref.py +74 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/transforms/base.py +93 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/transforms/cache_serve.py +146 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/transforms/dedupe_lines.py +69 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/transforms/eligibility.py +24 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/transforms/openai_hints.py +84 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/transforms/progress.py +52 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/transforms/stale_result_elision.py +109 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/transforms/truncate.py +100 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/transforms/volatile.py +177 -0
- ctxoptimizer-0.4.1/src/ctxoptimizer/transforms/whitespace.py +25 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Ahmed
|
|
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.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
ctxoptimizer
|
|
2
|
+
Copyright (c) 2026 Ahmed
|
|
3
|
+
|
|
4
|
+
ctxoptimizer is free and open-source software licensed under the MIT License.
|
|
5
|
+
See LICENSE.
|
|
6
|
+
|
|
7
|
+
Provider names (Anthropic, OpenAI, Google Gemini, Ollama, DeepSeek, OpenRouter,
|
|
8
|
+
OpenCode, Claude Code, Codex, Cursor, Aider, Cline and others) are trademarks of
|
|
9
|
+
their respective owners and are used only for descriptive compatibility. This
|
|
10
|
+
project is not affiliated with or endorsed by any provider.
|
|
11
|
+
|
|
12
|
+
Third-party components are distributed under their own licenses. See
|
|
13
|
+
THIRD_PARTY_LICENSES.md and the installed package metadata.
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ctxoptimizer
|
|
3
|
+
Version: 0.4.1
|
|
4
|
+
Summary: Local, deterministic cost optimizer for AI coding agents
|
|
5
|
+
Author: ahmed
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
License-File: NOTICE
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Requires-Dist: httpx[http2]>=0.27
|
|
11
|
+
Requires-Dist: jinja2>=3.1
|
|
12
|
+
Requires-Dist: orjson>=3.10
|
|
13
|
+
Requires-Dist: platformdirs>=4.2
|
|
14
|
+
Requires-Dist: pydantic>=2.7
|
|
15
|
+
Requires-Dist: starlette>=0.37
|
|
16
|
+
Requires-Dist: typer>=0.12
|
|
17
|
+
Requires-Dist: uvicorn>=0.30
|
|
18
|
+
Requires-Dist: coverage>=7 ; extra == 'dev'
|
|
19
|
+
Requires-Dist: hypothesis>=6.100 ; extra == 'dev'
|
|
20
|
+
Requires-Dist: mypy>=1.10 ; extra == 'dev'
|
|
21
|
+
Requires-Dist: pip-audit ; extra == 'dev'
|
|
22
|
+
Requires-Dist: pytest>=8 ; extra == 'dev'
|
|
23
|
+
Requires-Dist: pytest-asyncio>=0.23 ; extra == 'dev'
|
|
24
|
+
Requires-Dist: pytest-benchmark>=4 ; extra == 'dev'
|
|
25
|
+
Requires-Dist: pytest-cov>=5 ; extra == 'dev'
|
|
26
|
+
Requires-Dist: respx>=0.21 ; extra == 'dev'
|
|
27
|
+
Requires-Dist: ruff>=0.5 ; extra == 'dev'
|
|
28
|
+
Requires-Dist: google-re2>=1.1 ; extra == 're2'
|
|
29
|
+
Requires-Dist: tiktoken>=0.7 ; extra == 'tokens'
|
|
30
|
+
Requires-Python: >=3.11
|
|
31
|
+
Project-URL: Homepage, https://github.com/ahmed-dev25/ctxoptimizer
|
|
32
|
+
Project-URL: Repository, https://github.com/ahmed-dev25/ctxoptimizer
|
|
33
|
+
Project-URL: Issues, https://github.com/ahmed-dev25/ctxoptimizer/issues
|
|
34
|
+
Project-URL: Changelog, https://github.com/ahmed-dev25/ctxoptimizer/blob/main/CHANGELOG.md
|
|
35
|
+
Provides-Extra: dev
|
|
36
|
+
Provides-Extra: re2
|
|
37
|
+
Provides-Extra: tokens
|
|
38
|
+
Description-Content-Type: text/markdown
|
|
39
|
+
|
|
40
|
+
# ctxoptimizer
|
|
41
|
+
|
|
42
|
+
A local, deterministic cost optimizer for AI coding agents. It sits between your
|
|
43
|
+
agent and the LLM provider, measures real token usage and spend, explains why
|
|
44
|
+
prompt caching missed, and applies cache-safe payload reductions.
|
|
45
|
+
|
|
46
|
+
- **Local only** — binds to loopback; no telemetry leaves the machine.
|
|
47
|
+
- **Deterministic** — no LLM calls inside the proxy; every decision is a hash,
|
|
48
|
+
regex, counter or threshold.
|
|
49
|
+
- **Honest numbers** — provider-reported usage is ground truth; everything else
|
|
50
|
+
is labelled `est.` or `sim.`.
|
|
51
|
+
- **Fail-open** — invalid transforms retry with the original bytes; the proxy
|
|
52
|
+
never blocks traffic.
|
|
53
|
+
|
|
54
|
+
## Install
|
|
55
|
+
|
|
56
|
+
```powershell
|
|
57
|
+
uv tool install ctxoptimizer
|
|
58
|
+
# or: pipx install ctxoptimizer
|
|
59
|
+
ctxoptimizer run
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
If PyPI does not have the release yet, install from GitHub:
|
|
63
|
+
|
|
64
|
+
```powershell
|
|
65
|
+
uv tool install "git+https://github.com/ahmed-dev25/ctxoptimizer.git"
|
|
66
|
+
# or: pipx install "git+https://github.com/ahmed-dev25/ctxoptimizer.git"
|
|
67
|
+
ctxoptimizer run
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
From a checkout:
|
|
71
|
+
|
|
72
|
+
```powershell
|
|
73
|
+
uv sync --extra dev
|
|
74
|
+
uv run ctxoptimizer run
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
The startup banner prints the dashboard URL with a per-run admin token:
|
|
78
|
+
|
|
79
|
+
```text
|
|
80
|
+
dashboard: http://127.0.0.1:8787/_ctxoptimizer/?token=...
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Open that URL once; the token is stored as an `HttpOnly; SameSite=Strict`
|
|
84
|
+
cookie. The dashboard is also protected by a Host allowlist and CSRF checks.
|
|
85
|
+
|
|
86
|
+
## Quickstart
|
|
87
|
+
|
|
88
|
+
```powershell
|
|
89
|
+
ctxoptimizer env --shell powershell # bash | zsh | fish | powershell
|
|
90
|
+
ctxoptimizer status # health + counters
|
|
91
|
+
ctxoptimizer stats # recorded usage and cost
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Point a client at the printed base URL. See
|
|
95
|
+
[`docs/client-setup.md`](docs/client-setup.md) for Claude Code, OpenCode,
|
|
96
|
+
DeepSeek, OpenRouter, Gemini, Ollama, Codex and the other supported clients.
|
|
97
|
+
|
|
98
|
+
Default mode is `shadow`: everything is measured and simulated, while the
|
|
99
|
+
client's bytes are forwarded unchanged. Switch to `active` from the dashboard
|
|
100
|
+
(Settings), with `ctxoptimizer run --mode active`, or with
|
|
101
|
+
`x-ctxoptimizer-mode: active` per request.
|
|
102
|
+
|
|
103
|
+
## What it does
|
|
104
|
+
|
|
105
|
+
- Measures provider usage and cost for Anthropic, OpenAI Chat/Responses,
|
|
106
|
+
native Gemini, native Ollama and named OpenAI-compatible upstreams
|
|
107
|
+
(DeepSeek, OpenRouter, Gemini/Ollama compatibility, and custom gateways).
|
|
108
|
+
- Detects drift (tools/system/history/TTL/config/model) and waste W1–W8:
|
|
109
|
+
redundant re-reads, identical outputs, unbatched fan-out, runaway sessions,
|
|
110
|
+
recurring/param drift, edit churn and unused tool schemas.
|
|
111
|
+
- Applies deterministic transforms: ANSI/progress cleanup, line dedupe,
|
|
112
|
+
whitespace trim, signal-aware truncation, duplicate back-references,
|
|
113
|
+
byte-true `cache_serve`, opt-in stale-result elision, Anthropic
|
|
114
|
+
`cache_control` hints and OpenAI `prompt_cache_key`.
|
|
115
|
+
- Auto-quarantines a transform per session when fallback/drift guard counters
|
|
116
|
+
trip; the dashboard shows the history and lets you re-enable it.
|
|
117
|
+
- Provides `ctxoptimizer_expand` over MCP so an agent can retrieve any omitted
|
|
118
|
+
original from the local blob store.
|
|
119
|
+
- Serves a local dashboard: Overview, Live (SSE), Sessions, Requests + diff
|
|
120
|
+
viewer, Waste Opportunities with status controls, Transforms with hot
|
|
121
|
+
toggles/stats, Pricing editor, Settings and Doctor.
|
|
122
|
+
|
|
123
|
+
## Privacy
|
|
124
|
+
|
|
125
|
+
Payload capture defaults to `changed_blocks`; set it to `off` to store nothing.
|
|
126
|
+
Captured text stays in the per-user data directory, is redacted, and is bounded
|
|
127
|
+
by retention. `ctxoptimizer purge --all` wipes telemetry, blobs and findings. See
|
|
128
|
+
[`docs/privacy.md`](docs/privacy.md).
|
|
129
|
+
|
|
130
|
+
## Service
|
|
131
|
+
|
|
132
|
+
```powershell
|
|
133
|
+
ctxoptimizer service install # launchd / systemd --user / Windows scheduled task
|
|
134
|
+
ctxoptimizer service install --dry-run
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## Contributing
|
|
138
|
+
|
|
139
|
+
See [`CONTRIBUTING.md`](CONTRIBUTING.md) for development setup and gates. Report
|
|
140
|
+
vulnerabilities privately via [`SECURITY.md`](SECURITY.md); do not open a public
|
|
141
|
+
issue for a security problem.
|
|
142
|
+
|
|
143
|
+
## License
|
|
144
|
+
|
|
145
|
+
ctxoptimizer is free and open-source software licensed under the **MIT License**.
|
|
146
|
+
See [`LICENSE`](LICENSE) and [`NOTICE`](NOTICE).
|
|
147
|
+
|
|
148
|
+
## Updating
|
|
149
|
+
|
|
150
|
+
Use the package manager that installed ctxoptimizer:
|
|
151
|
+
|
|
152
|
+
```powershell
|
|
153
|
+
uv tool upgrade ctxoptimizer
|
|
154
|
+
# or
|
|
155
|
+
pipx upgrade ctxoptimizer
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
There is no built-in self-update command. PyPI releases are published with
|
|
159
|
+
Trusted Publishing and PEP 740 attestations. Source installs follow the GitHub
|
|
160
|
+
repository; downloaded wheels must be replaced manually. See
|
|
161
|
+
[`docs/updating.md`](docs/updating.md).
|
|
162
|
+
|
|
163
|
+
## Documentation
|
|
164
|
+
|
|
165
|
+
- [`SPEC.md`](SPEC.md) — authoritative specification
|
|
166
|
+
- [`docs/client-setup.md`](docs/client-setup.md) — per-client recipes
|
|
167
|
+
- [`docs/how-to-use.md`](docs/how-to-use.md) — complete install/run/update guide
|
|
168
|
+
- [`docs/provider-notes.md`](docs/provider-notes.md) — dated provider behavior
|
|
169
|
+
- [`docs/architecture.md`](docs/architecture.md) — component overview
|
|
170
|
+
- [`docs/privacy.md`](docs/privacy.md) — data handling and purge
|
|
171
|
+
- [`docs/faq.md`](docs/faq.md) — cache, savings, troubleshooting
|
|
172
|
+
- [`docs/test-report.md`](docs/test-report.md) — gates and test coverage summary
|
|
173
|
+
- [`docs/updating.md`](docs/updating.md) — package-manager upgrades and release artifacts
|
|
174
|
+
- [`docs/pypi-release.md`](docs/pypi-release.md) — PyPI Trusted Publishing setup
|
|
175
|
+
- [`docs/release-checklist.md`](docs/release-checklist.md) — release checklist
|
|
176
|
+
- [`docs/progress.md`](docs/progress.md) — build status and handoff notes
|
|
177
|
+
- [`CHANGELOG.md`](CHANGELOG.md)
|
|
178
|
+
- [`CONTRIBUTING.md`](CONTRIBUTING.md)
|
|
179
|
+
- [`SECURITY.md`](SECURITY.md)
|
|
180
|
+
- [`THIRD_PARTY_LICENSES.md`](THIRD_PARTY_LICENSES.md)
|
|
181
|
+
- [`docs/decisions/`](docs/decisions/) — architecture decision records
|
|
182
|
+
- [`AGENTS.md`](AGENTS.md) — coding and git workflow rules
|
|
183
|
+
|
|
184
|
+
## Development
|
|
185
|
+
|
|
186
|
+
```powershell
|
|
187
|
+
uv run ruff check .
|
|
188
|
+
uv run ruff format --check .
|
|
189
|
+
uv run mypy --strict src
|
|
190
|
+
uv run pytest -q
|
|
191
|
+
uv build --wheel
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
Supported Python: 3.11+. The package is built with `uv_build`; the test suite
|
|
195
|
+
uses a real fake upstream and recorded/documented fixtures. Live provider tests
|
|
196
|
+
are opt-in (`pytest -m live`) and require keys.
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
# ctxoptimizer
|
|
2
|
+
|
|
3
|
+
A local, deterministic cost optimizer for AI coding agents. It sits between your
|
|
4
|
+
agent and the LLM provider, measures real token usage and spend, explains why
|
|
5
|
+
prompt caching missed, and applies cache-safe payload reductions.
|
|
6
|
+
|
|
7
|
+
- **Local only** — binds to loopback; no telemetry leaves the machine.
|
|
8
|
+
- **Deterministic** — no LLM calls inside the proxy; every decision is a hash,
|
|
9
|
+
regex, counter or threshold.
|
|
10
|
+
- **Honest numbers** — provider-reported usage is ground truth; everything else
|
|
11
|
+
is labelled `est.` or `sim.`.
|
|
12
|
+
- **Fail-open** — invalid transforms retry with the original bytes; the proxy
|
|
13
|
+
never blocks traffic.
|
|
14
|
+
|
|
15
|
+
## Install
|
|
16
|
+
|
|
17
|
+
```powershell
|
|
18
|
+
uv tool install ctxoptimizer
|
|
19
|
+
# or: pipx install ctxoptimizer
|
|
20
|
+
ctxoptimizer run
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
If PyPI does not have the release yet, install from GitHub:
|
|
24
|
+
|
|
25
|
+
```powershell
|
|
26
|
+
uv tool install "git+https://github.com/ahmed-dev25/ctxoptimizer.git"
|
|
27
|
+
# or: pipx install "git+https://github.com/ahmed-dev25/ctxoptimizer.git"
|
|
28
|
+
ctxoptimizer run
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
From a checkout:
|
|
32
|
+
|
|
33
|
+
```powershell
|
|
34
|
+
uv sync --extra dev
|
|
35
|
+
uv run ctxoptimizer run
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
The startup banner prints the dashboard URL with a per-run admin token:
|
|
39
|
+
|
|
40
|
+
```text
|
|
41
|
+
dashboard: http://127.0.0.1:8787/_ctxoptimizer/?token=...
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Open that URL once; the token is stored as an `HttpOnly; SameSite=Strict`
|
|
45
|
+
cookie. The dashboard is also protected by a Host allowlist and CSRF checks.
|
|
46
|
+
|
|
47
|
+
## Quickstart
|
|
48
|
+
|
|
49
|
+
```powershell
|
|
50
|
+
ctxoptimizer env --shell powershell # bash | zsh | fish | powershell
|
|
51
|
+
ctxoptimizer status # health + counters
|
|
52
|
+
ctxoptimizer stats # recorded usage and cost
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Point a client at the printed base URL. See
|
|
56
|
+
[`docs/client-setup.md`](docs/client-setup.md) for Claude Code, OpenCode,
|
|
57
|
+
DeepSeek, OpenRouter, Gemini, Ollama, Codex and the other supported clients.
|
|
58
|
+
|
|
59
|
+
Default mode is `shadow`: everything is measured and simulated, while the
|
|
60
|
+
client's bytes are forwarded unchanged. Switch to `active` from the dashboard
|
|
61
|
+
(Settings), with `ctxoptimizer run --mode active`, or with
|
|
62
|
+
`x-ctxoptimizer-mode: active` per request.
|
|
63
|
+
|
|
64
|
+
## What it does
|
|
65
|
+
|
|
66
|
+
- Measures provider usage and cost for Anthropic, OpenAI Chat/Responses,
|
|
67
|
+
native Gemini, native Ollama and named OpenAI-compatible upstreams
|
|
68
|
+
(DeepSeek, OpenRouter, Gemini/Ollama compatibility, and custom gateways).
|
|
69
|
+
- Detects drift (tools/system/history/TTL/config/model) and waste W1–W8:
|
|
70
|
+
redundant re-reads, identical outputs, unbatched fan-out, runaway sessions,
|
|
71
|
+
recurring/param drift, edit churn and unused tool schemas.
|
|
72
|
+
- Applies deterministic transforms: ANSI/progress cleanup, line dedupe,
|
|
73
|
+
whitespace trim, signal-aware truncation, duplicate back-references,
|
|
74
|
+
byte-true `cache_serve`, opt-in stale-result elision, Anthropic
|
|
75
|
+
`cache_control` hints and OpenAI `prompt_cache_key`.
|
|
76
|
+
- Auto-quarantines a transform per session when fallback/drift guard counters
|
|
77
|
+
trip; the dashboard shows the history and lets you re-enable it.
|
|
78
|
+
- Provides `ctxoptimizer_expand` over MCP so an agent can retrieve any omitted
|
|
79
|
+
original from the local blob store.
|
|
80
|
+
- Serves a local dashboard: Overview, Live (SSE), Sessions, Requests + diff
|
|
81
|
+
viewer, Waste Opportunities with status controls, Transforms with hot
|
|
82
|
+
toggles/stats, Pricing editor, Settings and Doctor.
|
|
83
|
+
|
|
84
|
+
## Privacy
|
|
85
|
+
|
|
86
|
+
Payload capture defaults to `changed_blocks`; set it to `off` to store nothing.
|
|
87
|
+
Captured text stays in the per-user data directory, is redacted, and is bounded
|
|
88
|
+
by retention. `ctxoptimizer purge --all` wipes telemetry, blobs and findings. See
|
|
89
|
+
[`docs/privacy.md`](docs/privacy.md).
|
|
90
|
+
|
|
91
|
+
## Service
|
|
92
|
+
|
|
93
|
+
```powershell
|
|
94
|
+
ctxoptimizer service install # launchd / systemd --user / Windows scheduled task
|
|
95
|
+
ctxoptimizer service install --dry-run
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Contributing
|
|
99
|
+
|
|
100
|
+
See [`CONTRIBUTING.md`](CONTRIBUTING.md) for development setup and gates. Report
|
|
101
|
+
vulnerabilities privately via [`SECURITY.md`](SECURITY.md); do not open a public
|
|
102
|
+
issue for a security problem.
|
|
103
|
+
|
|
104
|
+
## License
|
|
105
|
+
|
|
106
|
+
ctxoptimizer is free and open-source software licensed under the **MIT License**.
|
|
107
|
+
See [`LICENSE`](LICENSE) and [`NOTICE`](NOTICE).
|
|
108
|
+
|
|
109
|
+
## Updating
|
|
110
|
+
|
|
111
|
+
Use the package manager that installed ctxoptimizer:
|
|
112
|
+
|
|
113
|
+
```powershell
|
|
114
|
+
uv tool upgrade ctxoptimizer
|
|
115
|
+
# or
|
|
116
|
+
pipx upgrade ctxoptimizer
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
There is no built-in self-update command. PyPI releases are published with
|
|
120
|
+
Trusted Publishing and PEP 740 attestations. Source installs follow the GitHub
|
|
121
|
+
repository; downloaded wheels must be replaced manually. See
|
|
122
|
+
[`docs/updating.md`](docs/updating.md).
|
|
123
|
+
|
|
124
|
+
## Documentation
|
|
125
|
+
|
|
126
|
+
- [`SPEC.md`](SPEC.md) — authoritative specification
|
|
127
|
+
- [`docs/client-setup.md`](docs/client-setup.md) — per-client recipes
|
|
128
|
+
- [`docs/how-to-use.md`](docs/how-to-use.md) — complete install/run/update guide
|
|
129
|
+
- [`docs/provider-notes.md`](docs/provider-notes.md) — dated provider behavior
|
|
130
|
+
- [`docs/architecture.md`](docs/architecture.md) — component overview
|
|
131
|
+
- [`docs/privacy.md`](docs/privacy.md) — data handling and purge
|
|
132
|
+
- [`docs/faq.md`](docs/faq.md) — cache, savings, troubleshooting
|
|
133
|
+
- [`docs/test-report.md`](docs/test-report.md) — gates and test coverage summary
|
|
134
|
+
- [`docs/updating.md`](docs/updating.md) — package-manager upgrades and release artifacts
|
|
135
|
+
- [`docs/pypi-release.md`](docs/pypi-release.md) — PyPI Trusted Publishing setup
|
|
136
|
+
- [`docs/release-checklist.md`](docs/release-checklist.md) — release checklist
|
|
137
|
+
- [`docs/progress.md`](docs/progress.md) — build status and handoff notes
|
|
138
|
+
- [`CHANGELOG.md`](CHANGELOG.md)
|
|
139
|
+
- [`CONTRIBUTING.md`](CONTRIBUTING.md)
|
|
140
|
+
- [`SECURITY.md`](SECURITY.md)
|
|
141
|
+
- [`THIRD_PARTY_LICENSES.md`](THIRD_PARTY_LICENSES.md)
|
|
142
|
+
- [`docs/decisions/`](docs/decisions/) — architecture decision records
|
|
143
|
+
- [`AGENTS.md`](AGENTS.md) — coding and git workflow rules
|
|
144
|
+
|
|
145
|
+
## Development
|
|
146
|
+
|
|
147
|
+
```powershell
|
|
148
|
+
uv run ruff check .
|
|
149
|
+
uv run ruff format --check .
|
|
150
|
+
uv run mypy --strict src
|
|
151
|
+
uv run pytest -q
|
|
152
|
+
uv build --wheel
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Supported Python: 3.11+. The package is built with `uv_build`; the test suite
|
|
156
|
+
uses a real fake upstream and recorded/documented fixtures. Live provider tests
|
|
157
|
+
are opt-in (`pytest -m live`) and require keys.
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "ctxoptimizer"
|
|
3
|
+
version = "0.4.1"
|
|
4
|
+
description = "Local, deterministic cost optimizer for AI coding agents"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
license = "MIT"
|
|
7
|
+
license-files = [
|
|
8
|
+
"LICENSE",
|
|
9
|
+
"NOTICE",
|
|
10
|
+
]
|
|
11
|
+
requires-python = ">=3.11"
|
|
12
|
+
classifiers = ["Programming Language :: Python :: 3"]
|
|
13
|
+
dependencies = [
|
|
14
|
+
"httpx[http2]>=0.27",
|
|
15
|
+
"jinja2>=3.1",
|
|
16
|
+
"orjson>=3.10",
|
|
17
|
+
"platformdirs>=4.2",
|
|
18
|
+
"pydantic>=2.7",
|
|
19
|
+
"starlette>=0.37",
|
|
20
|
+
"typer>=0.12",
|
|
21
|
+
"uvicorn>=0.30",
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
[[project.authors]]
|
|
25
|
+
name = "ahmed"
|
|
26
|
+
|
|
27
|
+
[project.optional-dependencies]
|
|
28
|
+
tokens = ["tiktoken>=0.7"]
|
|
29
|
+
re2 = ["google-re2>=1.1"]
|
|
30
|
+
dev = [
|
|
31
|
+
"coverage>=7",
|
|
32
|
+
"hypothesis>=6.100",
|
|
33
|
+
"mypy>=1.10",
|
|
34
|
+
"pip-audit",
|
|
35
|
+
"pytest>=8",
|
|
36
|
+
"pytest-asyncio>=0.23",
|
|
37
|
+
"pytest-benchmark>=4",
|
|
38
|
+
"pytest-cov>=5",
|
|
39
|
+
"respx>=0.21",
|
|
40
|
+
"ruff>=0.5",
|
|
41
|
+
]
|
|
42
|
+
|
|
43
|
+
[project.scripts]
|
|
44
|
+
ctxoptimizer = "ctxoptimizer.cli:app"
|
|
45
|
+
|
|
46
|
+
[project.urls]
|
|
47
|
+
Homepage = "https://github.com/ahmed-dev25/ctxoptimizer"
|
|
48
|
+
Repository = "https://github.com/ahmed-dev25/ctxoptimizer"
|
|
49
|
+
Issues = "https://github.com/ahmed-dev25/ctxoptimizer/issues"
|
|
50
|
+
Changelog = "https://github.com/ahmed-dev25/ctxoptimizer/blob/main/CHANGELOG.md"
|
|
51
|
+
|
|
52
|
+
[build-system]
|
|
53
|
+
requires = ["uv_build>=0.13.1,<0.14.0"]
|
|
54
|
+
build-backend = "uv_build"
|
|
55
|
+
|
|
56
|
+
[tool.ruff]
|
|
57
|
+
line-length = 100
|
|
58
|
+
target-version = "py311"
|
|
59
|
+
extend-exclude = ["SPEC.md"]
|
|
60
|
+
|
|
61
|
+
[tool.ruff.lint]
|
|
62
|
+
select = [
|
|
63
|
+
"E",
|
|
64
|
+
"F",
|
|
65
|
+
"I",
|
|
66
|
+
"B",
|
|
67
|
+
"UP",
|
|
68
|
+
"S",
|
|
69
|
+
"ASYNC",
|
|
70
|
+
"PERF",
|
|
71
|
+
"RUF",
|
|
72
|
+
]
|
|
73
|
+
|
|
74
|
+
[tool.ruff.lint.per-file-ignores]
|
|
75
|
+
"tests/**" = [
|
|
76
|
+
"S101",
|
|
77
|
+
"S104",
|
|
78
|
+
]
|
|
79
|
+
"scripts/**" = ["S101"]
|
|
80
|
+
|
|
81
|
+
[tool.mypy]
|
|
82
|
+
strict = true
|
|
83
|
+
python_version = "3.11"
|
|
84
|
+
mypy_path = "src"
|
|
85
|
+
files = ["src"]
|
|
86
|
+
plugins = ["pydantic.mypy"]
|
|
87
|
+
|
|
88
|
+
[tool.pytest.ini_options]
|
|
89
|
+
asyncio_mode = "auto"
|
|
90
|
+
testpaths = ["tests"]
|
|
91
|
+
markers = ["live: hits real provider APIs (needs keys)"]
|
|
92
|
+
addopts = "-m 'not live'"
|
|
93
|
+
|
|
94
|
+
[tool.coverage.run]
|
|
95
|
+
branch = true
|
|
96
|
+
source = ["ctxoptimizer"]
|
|
97
|
+
|
|
98
|
+
[tool.coverage.report]
|
|
99
|
+
show_missing = true
|
|
100
|
+
skip_covered = true
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "ctxoptimizer"
|
|
3
|
+
version = "0.4.1"
|
|
4
|
+
description = "Local, deterministic cost optimizer for AI coding agents"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
license = "MIT"
|
|
7
|
+
license-files = ["LICENSE", "NOTICE"]
|
|
8
|
+
requires-python = ">=3.11"
|
|
9
|
+
authors = [{ name = "ahmed" }]
|
|
10
|
+
classifiers = [
|
|
11
|
+
"Programming Language :: Python :: 3",
|
|
12
|
+
]
|
|
13
|
+
dependencies = [
|
|
14
|
+
"httpx[http2]>=0.27",
|
|
15
|
+
"jinja2>=3.1",
|
|
16
|
+
"orjson>=3.10",
|
|
17
|
+
"platformdirs>=4.2",
|
|
18
|
+
"pydantic>=2.7",
|
|
19
|
+
"starlette>=0.37",
|
|
20
|
+
"typer>=0.12",
|
|
21
|
+
"uvicorn>=0.30",
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
[project.optional-dependencies]
|
|
25
|
+
tokens = ["tiktoken>=0.7"]
|
|
26
|
+
re2 = ["google-re2>=1.1"]
|
|
27
|
+
dev = [
|
|
28
|
+
"coverage>=7",
|
|
29
|
+
"hypothesis>=6.100",
|
|
30
|
+
"mypy>=1.10",
|
|
31
|
+
"pip-audit",
|
|
32
|
+
"pytest>=8",
|
|
33
|
+
"pytest-asyncio>=0.23",
|
|
34
|
+
"pytest-benchmark>=4",
|
|
35
|
+
"pytest-cov>=5",
|
|
36
|
+
"respx>=0.21",
|
|
37
|
+
"ruff>=0.5",
|
|
38
|
+
]
|
|
39
|
+
|
|
40
|
+
[project.scripts]
|
|
41
|
+
ctxoptimizer = "ctxoptimizer.cli:app"
|
|
42
|
+
|
|
43
|
+
[project.urls]
|
|
44
|
+
Homepage = "https://github.com/ahmed-dev25/ctxoptimizer"
|
|
45
|
+
Repository = "https://github.com/ahmed-dev25/ctxoptimizer"
|
|
46
|
+
Issues = "https://github.com/ahmed-dev25/ctxoptimizer/issues"
|
|
47
|
+
Changelog = "https://github.com/ahmed-dev25/ctxoptimizer/blob/main/CHANGELOG.md"
|
|
48
|
+
|
|
49
|
+
[build-system]
|
|
50
|
+
requires = ["uv_build>=0.13.1,<0.14.0"]
|
|
51
|
+
build-backend = "uv_build"
|
|
52
|
+
|
|
53
|
+
[tool.ruff]
|
|
54
|
+
line-length = 100
|
|
55
|
+
target-version = "py311"
|
|
56
|
+
# SPEC.md is authoritative and must never be reformatted. Ruff formats Python
|
|
57
|
+
# code blocks inside Markdown files, which would rewrite it.
|
|
58
|
+
extend-exclude = ["SPEC.md"]
|
|
59
|
+
|
|
60
|
+
[tool.ruff.lint]
|
|
61
|
+
select = ["E", "F", "I", "B", "UP", "S", "ASYNC", "PERF", "RUF"]
|
|
62
|
+
|
|
63
|
+
[tool.ruff.lint.per-file-ignores]
|
|
64
|
+
"tests/**" = ["S101", "S104"]
|
|
65
|
+
"scripts/**" = ["S101"]
|
|
66
|
+
|
|
67
|
+
[tool.mypy]
|
|
68
|
+
strict = true
|
|
69
|
+
python_version = "3.11"
|
|
70
|
+
mypy_path = "src"
|
|
71
|
+
files = ["src"]
|
|
72
|
+
plugins = ["pydantic.mypy"]
|
|
73
|
+
|
|
74
|
+
[tool.pytest.ini_options]
|
|
75
|
+
asyncio_mode = "auto"
|
|
76
|
+
testpaths = ["tests"]
|
|
77
|
+
markers = ["live: hits real provider APIs (needs keys)"]
|
|
78
|
+
addopts = "-m 'not live'"
|
|
79
|
+
|
|
80
|
+
[tool.coverage.run]
|
|
81
|
+
branch = true
|
|
82
|
+
source = ["ctxoptimizer"]
|
|
83
|
+
|
|
84
|
+
[tool.coverage.report]
|
|
85
|
+
show_missing = true
|
|
86
|
+
skip_covered = true
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"""Module entry point for ``python -m ctxoptimizer``."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from ctxoptimizer.cli import app
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def main() -> None:
|
|
9
|
+
"""Run the command line interface."""
|
|
10
|
+
app()
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
if __name__ == "__main__":
|
|
14
|
+
main()
|