The Problem
Developers using LLM‑backed tools pay premium rates for every request, even when the prompt is trivial (e.g., a quick JSON format or a short arithmetic query). Those “simple” calls dominate usage—often 60‑70 % of traffic—yet they are routed to costly models, inflating cloud bills without adding value.
What This Does
nadirclaw installs a local, OpenAI‑compatible proxy that classifies each incoming prompt and forwards it to the cheapest model that meets a configurable complexity threshold. The classifier lives in nadirclaw/classifier.py and is invoked by the request handler in nadirclaw/server.py. Model pools are defined in nadirclaw/routing.py; they are loaded from the YAML configuration created by the wizard in nadirclaw/setup.py.
The package also includes a “context optimizer” (nadirclaw/optimize.py) that strips unnecessary whitespace, JSON boiler‑plate, and tool‑schema noise before dispatch, cutting input tokens by up to 70 % with no semantic loss. Budget tracking, alerting, and reporting live in nadirclaw/budget.py and nadirclaw/report.py, exposing a simple dashboard via the same HTTP server.
How It Is Wired
Execution starts at the CLI entry point nadirclaw/cli.py. The serve command (line 42) calls nadirclaw/server.serve(), which constructs a FastAPI app and registers /v1/chat/completions. When a request arrives, the handler chat_completions (line 1094) performs these steps:
- Logging & filesystem –
_log_requestcreateslog_dir(filesystem write). - Classification –
_msg(called 56 places) runs the embedding model; its result is cached inSessionCache(used by 17 callers). - Routing –
select_from_pool(innadirclaw/routing.py, called 14 times) picks a model tier based on the classifier score. - Context optimization –
optimize_messages(called 39 times) trims the payload; it currently opens files without a context manager (nadirclaw/credentials.py). - Outbound request –
_make_request(called 25 times) builds the HTTP call to the target provider. No timeout is set, so the request can block indefinitely. - Budget accounting –
recordandincupdate in‑memory counters;budget._send_webhookmay issue a webhook (network call).
The most central modules are nadirclaw/server (7 inbound, 16 outbound imports, instability 0.7) and nadirclaw/routing (9 inbound, 2 outbound, instability 0.18). Changing server.py ripples through 40 functions and touches the database, filesystem, and external APIs, making it a high‑impact area.
How To Use It
# Clone and install dependencies
git clone https://github.com/moses-y/NadirClaw
cd NadirClaw
pip install . # uses pyproject.toml; no lockfile is present
# Optional container build
docker build -t nadirclaw .
# Run the interactive setup wizard
python -m nadirclaw.cli setup
# Start the proxy
python -m nadirclaw.cli serve --verbose
Configuration lives in the .env file generated by the wizard (.env.example shows required keys). The server listens on http://localhost:8856; point any OpenAI‑compatible client at http://localhost:8856/v1.
Real‑World Use
A CI/CD pipeline that runs nadirclaw serve as a sidecar can route all openai.ChatCompletion.create calls from a code‑assistant tool. Simple prompts such as “format this JSON” are automatically sent to gemini‑flash (≈ $0.0002 per call), while complex refactoring requests fall back to claude‑sonnet. Budget alerts from nadirclaw/budget.py can abort runs when daily caps are exceeded.
Code Health & Issues
- High – GitHub Actions use tag references (
pypa/gh-action-pypi-publish@release/v1). Pin to a commit SHA. - High – No lockfile alongside
pyproject.toml; builds are non‑reproducible. Generate and commitpoetry.lock(or similar). - High – Wildcard CORS (
allow_origins=["*"]) combined with credentials innadirclaw/server.py. Restrict to explicit origins. - Medium – GitHub token permissions are not declared in
.github/workflows/ci.yml. Addpermissions: contents: read. - Medium – Dependabot/Renovate not configured; add
.github/dependabot.yml. - Medium – Docker base image (
python:3.11-slim) not pinned by digest. Use@sha256:…. - Medium – No dependency‑vulnerability scan in CI; add
dependency-review-actionorosv-scanner. - Medium – Outbound HTTP calls lack a timeout. Supply
timeout=inrequestscalls. - Medium –
checkoutstep keeps the token; setpersist-credentials: false. - Medium – Container runs as root; create a non‑root
USER.
Additional observations: the repository includes a full test suite (30 files) and CI, but the absence of a lockfile and the high‑risk CORS setting are the most immediate production concerns.
The Bottom Line
NadirClaw delivers a functional, well‑tested proxy that can cut LLM costs by 40‑70 % with minimal client changes. Its architecture is clear, but the core server module is large and deeply nested, and several security‑hardening steps (CORS, lockfile, pinned images) are missing. Teams comfortable managing Docker and Python dependencies can adopt it quickly; they should address the high‑severity findings before deploying to production.