Metadata-Version: 2.4
Name: mullm
Version: 1.0.0
Summary: Local-first LLM router. 96.4% cost reduction. Free tier first.
Author: muLLM Contributors
License-Expression: Apache-2.0
Project-URL: Homepage, https://github.com/mybrainrunslinux/mullm
Project-URL: Repository, https://github.com/mybrainrunslinux/mullm
Project-URL: Bug Tracker, https://github.com/mybrainrunslinux/mullm/issues
Keywords: llm,router,ai,cost-optimization,ollama,local-first
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Programming Language :: Python :: 3.15
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
License-File: NOTICE
Requires-Dist: fastapi<1.0,>=0.116
Requires-Dist: uvicorn[standard]<1.0,>=0.50
Requires-Dist: pydantic<3.0,>=2.10
Requires-Dist: pydantic-settings<3.0,>=2.6
Requires-Dist: httpx<1.0,>=0.27
Requires-Dist: python-multipart<1.0,>=0.0.20
Requires-Dist: anthropic<1.0,>=0.50
Requires-Dist: openai<3.0,>=1.60
Requires-Dist: psutil<7.0,>=6.0
Requires-Dist: numpy<3.0,>=2.1
Requires-Dist: Pillow<14.0,>=13.0
Requires-Dist: rich<15.0,>=13.0
Requires-Dist: structlog<26.0,>=24.0
Requires-Dist: python-dotenv<2.0,>=1.0
Requires-Dist: keyring<26.0,>=25.0
Requires-Dist: tomli>=2.0; python_version < "3.11"
Provides-Extra: gpu
Requires-Dist: pynvml<12.0,>=11.0; extra == "gpu"
Provides-Extra: classifier
Requires-Dist: transformers<5.0,>=4.44; extra == "classifier"
Requires-Dist: torch<3.0,>=2.3; extra == "classifier"
Provides-Extra: google
Requires-Dist: google-genai<3.0,>=1.0; extra == "google"
Provides-Extra: notifications
Requires-Dist: apprise<2.0,>=1.9; extra == "notifications"
Provides-Extra: auth
Requires-Dist: authlib<2.0,>=1.3; extra == "auth"
Requires-Dist: itsdangerous<3.0,>=2.1; extra == "auth"
Provides-Extra: redis
Requires-Dist: redis<6.0,>=5.0; extra == "redis"
Provides-Extra: studio
Requires-Dist: pillow<14.0,>=13.0; extra == "studio"
Requires-Dist: imageio-ffmpeg<1.0,>=0.5; extra == "studio"
Requires-Dist: kokoro<1.0,>=0.9; extra == "studio"
Requires-Dist: soundfile<1.0,>=0.12; extra == "studio"
Provides-Extra: sentence-transformers
Requires-Dist: sentence-transformers<4.0,>=3.0; extra == "sentence-transformers"
Provides-Extra: vector-cache
Requires-Dist: chromadb<2.0,>=1.0; extra == "vector-cache"
Requires-Dist: requests>=2.33.0; extra == "vector-cache"
Requires-Dist: urllib3>=2.6.3; extra == "vector-cache"
Provides-Extra: cuda128
Requires-Dist: torch==2.7.0; extra == "cuda128"
Requires-Dist: torchvision; extra == "cuda128"
Requires-Dist: torchaudio; extra == "cuda128"
Provides-Extra: cuda-nightly
Provides-Extra: tts
Requires-Dist: kokoro<1.0,>=0.9; extra == "tts"
Requires-Dist: soundfile<1.0,>=0.12; extra == "tts"
Provides-Extra: dev
Requires-Dist: pytest<10.0,>=9.0.3; extra == "dev"
Requires-Dist: pytest-asyncio<2.0,>=1.3; extra == "dev"
Requires-Dist: pytest-cov<8.0,>=5.0; extra == "dev"
Requires-Dist: httpx>=0.27; extra == "dev"
Requires-Dist: playwright<2.0,>=1.48; extra == "dev"
Requires-Dist: ruff<1.0,>=0.8; extra == "dev"
Provides-Extra: security
Requires-Dist: bandit[toml]<2.0,>=1.8; extra == "security"
Requires-Dist: pip-audit<3.0,>=2.7; extra == "security"
Provides-Extra: all
Requires-Dist: mullm[classifier,dev,google,gpu,security,sentence-transformers,studio,vector-cache]; extra == "all"
Dynamic: license-file

<div align="center">

# mμ|LLM

### Cost-Optimal LLM Routing — 96.4% cheaper than cloud-only

[![License: Apache 2.0](https://img.shields.io/badge/License-Apache%202.0-green?style=for-the-badge)](https://www.apache.org/licenses/LICENSE-2.0)
[![Python 3.11+](https://img.shields.io/badge/Python-3.11%2B-blue?style=for-the-badge&logo=python&logoColor=white)](https://www.python.org)
[![Release](https://img.shields.io/github/v/release/mybrainrunslinux/mullm?style=for-the-badge&logo=github)](https://github.com/mybrainrunslinux/mullm/releases/latest)
[![Cost Reduction](https://img.shields.io/badge/Cost%20Reduction-96.4%25-F59E0B?style=for-the-badge)](#-benchmark-results)
[![HumanEval](https://img.shields.io/badge/HumanEval-100%25%20pass%401-brightgreen?style=for-the-badge)](#-benchmark-results)
[![RouterBench AIQ](https://img.shields.io/badge/RouterBench%20AIQ-0.6673%20SOTA-purple?style=for-the-badge)](#-benchmark-results)

[![Platform](https://img.shields.io/badge/Platform-Linux%20%7C%20macOS%20%7C%20Windows-lightgrey?style=for-the-badge)](#-quick-start)
[![Backends](https://img.shields.io/badge/Local-TabbyAPI%20%7C%20vLLM%20%7C%20llama.cpp%20%7C%20Ollama-94A3B8?style=for-the-badge)](#-supported-providers)
[![Security checks](https://img.shields.io/github/actions/workflow/status/mybrainrunslinux/mullm/security.yml?branch=main&style=for-the-badge&label=Security)](https://github.com/mybrainrunslinux/mullm/actions/workflows/security.yml)
[![Release checks](https://img.shields.io/github/actions/workflow/status/mybrainrunslinux/mullm/release-dry-run.yml?branch=main&style=for-the-badge&label=Release%20checks)](https://github.com/mybrainrunslinux/mullm/actions/workflows/release-dry-run.yml)
[![CI](https://img.shields.io/github/actions/workflow/status/mybrainrunslinux/mullm/ci.yml?branch=main&style=for-the-badge&label=CI)](https://github.com/mybrainrunslinux/mullm/actions/workflows/ci.yml)

**[GitHub](https://github.com/mybrainrunslinux/mullm)** · **[Quick Start](#-quick-start)** · **[Benchmarks](#-benchmark-results)** · **[Providers](#-supported-providers)**

</div>

---

## 💡 The Case in One Line

<div align="center">

> **$27.87 actual spend vs $772 cloud-only baseline — across 15,363 production queries over 22 days.**
>
> 87.5% of queries resolved at $0.00. 100% HumanEval pass@1 at $0.00. RouterBench AIQ 0.6673 — highest published.

</div>

---

## 🏛️ Four-Tier Architecture

**mμ|LLM** routes every query through four escalating tiers, short-circuiting the moment an answer is found. Cost accumulates only if cheaper tiers can't satisfy the query.

![muLLM four-tier routing architecture](docs/tier-routing.svg)

**The classifier** — DeBERTa-v3-small (44 MB) — reads the query once and predicts tier + intent category before any LLM is invoked. Tier 0 overhead: **<1 ms**.

---

## Software Factory: from specification to evidence

Build small, dependent tasks with local inference, protected executable tests, bounded repair loops, and a human handoff when the worker needs help. Inspect the work on a flat operations board, or switch on the animated 3D factory.

[![The muLLM Software Factory](docs/media/factory-tour.gif)](docs/SOFTWARE_FACTORY.md)

**[How it works](docs/SOFTWARE_FACTORY.md)** · **[Watch the tour](docs/media/factory-tour.webm)** · **[Spec → working game: evidence](docs/evidence/peg-bloom/README.md)** · **[Try Peg Bloom](examples/factory-peg-bloom/README.md)**

Build several projects together and see which need a human: [three marketing workspaces, their contracts, repairs, and review evidence](docs/evidence/marketing/README.md). Executable checks establish technical behavior; a separate product gate asks whether the result is useful and usable.

The Peg Bloom case study includes model-generated source, independent checks for three puzzle boards and 63 legal jumps, browser validation, failed attempts, diagnostic guidance, and an artifact hash. An accepted artifact means its configured checks passed; the evidence makes that claim inspectable.

---

## 🚀 Quick Start

Start muLLM on port **6856**, configure your providers, and open the web UI.
Use a virtual environment with Python 3.11 or newer.

### Path 1 — Install the package

```bash
python -m venv .venv
# Linux / macOS:
source .venv/bin/activate
# Windows PowerShell instead: .venv\Scripts\Activate.ps1
python -m pip install --upgrade mullm
mullm-server
```

Open the setup URL printed by the server. It uses HTTPS when a local certificate
is available. The first interactive start opens setup automatically; installation
itself starts no process. Set `MULLM_OPEN_BROWSER=0` for headless operation.

**Windows with local inference:** connect your existing Ollama, TabbyAPI, vLLM,
or llama.cpp runner in `/setup`. **Mac with API keys only:** add your provider
keys and leave local inference disabled; MLX and model downloads are optional.

Use `/chat` for queries and `/factory` to follow projects, tasks, and human
requests. The optional `/classifier` page previews local Kev.js inference.
[Factory guide](docs/SOFTWARE_FACTORY.md) · [Upgrade and configuration guide](docs/UPGRADING.md).

The core install needs no separate constraints download. SQLite is the default
cache. ChromaDB is an opt-in extra with unresolved advisories; see [Security](SECURITY.md).

### Optional installs, modes, and key storage

The base package includes the router, web UI, CLI, SQLite semantic cache, and cloud-provider clients. Add only the capabilities you need:

| Install | Adds |
|---|---|
| `pip install "mullm[studio]"` | Studio media helpers, local TTS, audio, and video support |
| `pip install "mullm[classifier]"` | Transformers + PyTorch for the trained DeBERTa classifier |
| `pip install "mullm[gpu]"` | NVIDIA GPU/VRAM monitoring |
| `pip install "mullm[auth]"` | OAuth/OIDC support for a remotely exposed UI |
| `pip install "mullm[sentence-transformers]"` | Local embedding models |
| `pip install "mullm[vector-cache]"` | Optional ChromaDB cache; SQLite remains the safer dependency-free default |
| `pip install "mullm[dev]"` | Developer tests, coverage, linting, and browser-test tools |
| `pip install "mullm[google]"` | Current `google-genai` SDK |
| `pip install "mullm[notifications]"` | Apprise adapters for factory notifications |


The setup page separates installs from feature toggles. **Single User** keeps private workstation defaults; **Team / Proxy** configures a stricter shared-gateway posture. Studio, 3D, Game Studio, ComfyUI, benchmarks, experimental backends, and research/developer features can be enabled independently. Some changes require a restart.

Provider keys can be saved to the OS keychain (recommended), Unix `pass`, or a local `.env` file with owner-only permissions. **Best available** selects the OS keychain when usable and otherwise falls back to `.env`. For containers and Kubernetes, inject keys through environment variables or mounted secrets rather than baking them into the image.

### Path 2 — Rootless Podman

```bash
git clone https://github.com/mybrainrunslinux/mullm.git && cd mullm
podman build -t localhost/mullm:local .
podman volume create mullm-data
podman run --name mullm --replace -d \
  -p 127.0.0.1:6856:6856 \
  -v mullm-data:/data:Z \
  -e MULLM_REMOTE_ACCESS=true \
  localhost/mullm:local
```

This is a single muLLM container; run Ollama or another compatible inference backend separately. See [Deployment](docs/DEPLOYMENT.md) for secrets, persistent state, and remote access.

### Path 3 — Source / development

```bash
git clone https://github.com/mybrainrunslinux/mullm && cd mullm
python -m pip install -e ".[dev]"
cp config/mullm.toml.example mullm.toml   # configure providers as needed
mullm-server
```

For local generation, configure a supported inference runner in `/setup`.
Ollama is one option (`ollama pull qwen3-coder:30b`); TabbyAPI, vLLM,
llama.cpp, and MLX are also supported. Deterministic lookups need no model.

---

## 🚢 Production Deployment

```bash
# 1. Configure authentication and headless startup
export MULLM_DEV_MODE=false
export MULLM_API_KEY="your-long-random-server-token"
export MULLM_OPEN_BROWSER=0
# Add cloud provider keys through your normal secret store

# 2. Start muLLM
mullm-server

# 3. Verify
mullm --status
```

For concrete systemd, Podman, Kubernetes, and multi-replica guidance, see [Deployment](docs/DEPLOYMENT.md).

---

## 🖥️ CLI Reference

```bash
mullm "your question"                          # auto-route
mullm-server                                   # start server on :6856
mullm --status                                 # health check
mullm --cost                                   # session cost summary
mullm --stream "tell me a story"               # SSE streaming
mullm --model claude-haiku-5-5 "summarize X"   # force a specific model
mullm --tier cloud_full "complex question"     # force a specific tier
```

---

## 🌐 Supported Providers

The tier router directly supports Anthropic, OpenAI, Google, DeepSeek, GLM,
and Cerebras. Additional providers have backend/gateway integrations; these
are not all interchangeable with the tier router. Keys are optional.
Model documentation reviewed 2026-11-05; account availability varies.

| Provider | Models Available | Pricing Tier |
|---|---|---|
| **Anthropic** | Haiku / Sonnet / Opus 5.5 · Fable 5.1 | Low → High |
| **OpenAI** | GPT-6 Luna / Astra · GPT-6.1 Sol / Terra | Low → High |
| **Google** | Gemini 3.5 Flash-Lite · 3.8 Flash · 4 Argon | Low → High |
| **DeepSeek** | V4.1 Flash (`deepseek-flash`) · V4 Pro | Low |
| **Cerebras** | GPT OSS 120B · Qwen 3.8 27B | Low |
| **Mistral** | Mistral Small · Large | Low → Medium |
| **Cohere** | Command A+ | Account dependent |
| **Perplexity** | Agent API / Sonar | Token and tool charges |
| **OpenRouter** | All models via unified API | Varies |
| **Venice** | Privacy-preserving inference | Low |
| **GLM (Z.AI)** | GLM 5.3 · Flash · FlashX | Low |
| **xAI** | Grok 4.7 | Medium |
| **IBM / Venice** | Operator-configured model IDs | Account dependent |
| **Ollama** | Any local model | **$0** |
| **ExLlamaV2** | Quantized GPTQ/EXL2 | **$0** |
| **llama.cpp** | GGUF models | **$0** |
| **MLX** | Apple Silicon optimized | **$0** |

The router escalates through providers in cost order. Budget hard-stop at a configurable threshold prevents runaway spend.

---

## 💻 Hardware Compatibility

mμ|LLM scales from a laptop to a workstation. The local tier performance scales with your hardware; Tiers 0, 1, and 3 are hardware-independent.

| GPU / RAM | Recommended Model | Backend | Expected tok/s |
|---|---|---|---|
| RTX 5090 / 32 GB VRAM | qwen3-coder:30b (Q4) | Ollama / ExLlamaV2 | ~60–80 |
| RTX 4090 / 24 GB VRAM | qwen3-coder:30b (Q4) | Ollama / ExLlamaV2 | ~40–55 |
| RTX 4080 / 16 GB VRAM | qwen2.5-coder:14b (Q8) | Ollama | ~45–60 |
| RTX 3080 / 10 GB VRAM | qwen2.5-coder:7b (Q8) | Ollama | ~35–50 |
| Apple M3 Max / 128 GB | qwen3-coder:30b (Q4) | MLX | ~30–45 |
| Apple M2 Pro / 32 GB | qwen2.5-coder:14b (Q6) | MLX | ~25–35 |
| CPU only / 32 GB RAM | qwen2.5-coder:7b (Q4) | llama.cpp | ~5–12 |
| CPU only / 16 GB RAM | qwen2.5-coder:3b (Q8) | llama.cpp | ~8–18 |

> Models are pulled automatically on first use when Ollama is the backend. For ExLlamaV2, MLX, and llama.cpp, point `MULLM_OLLAMA_BASE_URL` at their compatible API endpoint.

---

## 🧩 Module System

Each module is independently toggleable. Disable what you don't need to reduce dependencies and startup time.

| Module | Toggle | Description |
|---|---|---|
| **Groundtruth LUT** | always on | AST arithmetic, date/time, HTTP codes, Big-O, Git one-liners |
| **Semantic Cache** | `MULLM_SEMANTIC_CACHE_BACKEND=sqlite` | Dependency-free SQLite cosine cache by default; set `chroma` and install `mullm[vector-cache]` only if you explicitly want ChromaDB |
| **DeBERTa Classifier** | `MULLM_CLASSIFIER_MODEL_PATH=<dir>` | 44 MB fine-tuned intent classifier; falls back to rule-based if unset |
| **Local Ollama** | `MULLM_OLLAMA_BASE_URL=<url>` | Any Ollama-compatible endpoint |
| **Cloud Fallback** | set any `MULLM_*_API_KEY` | Only providers with keys are used |
| **Budget Guard** | `MULLM_BUDGET_HARD=<$>` | Hard-stops cloud calls above threshold |
| **Privacy Mode** | `MULLM_LOG_QUERY_CONTENT=false` | Strips query content from scoring log |
| **Split Routing** | POST `/query/split` | Decomposes multi-part prompts, parallel execution |
| **SSE Streaming** | GET `/query/stream` | Server-Sent Events from local Ollama |
| **OpenAI Compat** | POST `/v1/chat/completions` | Drop-in replacement for OpenAI clients |
| **Dashboard** | GET `/api/dashboard` | Real-time cost, tier distribution, query stats |
| **System Stats** | GET `/api/system` | CPU, RAM, GPU, VRAM, loaded model info |

---

## ⚙️ Configuration

All environment variables are prefixed `MULLM_`. Copy `.env.example` to `.env` and set only what you need.

<details>
<summary>Full environment variable reference</summary>

| Variable | Default | Description |
|---|---|---|
| `MULLM_PORT` | `6856` | Server port (MULM on keypad) |
| `MULLM_DEV_MODE` | `true` | Disable auth, enable /docs |
| `MULLM_API_KEY` | _(unset)_ | Bearer token for production |
| `MULLM_OLLAMA_BASE_URL` | `http://localhost:11434` | Ollama endpoint |
| `MULLM_OLLAMA_MODEL` | `qwen3-coder:30b` | Local generation model |
| `MULLM_OLLAMA_EMBED_MODEL` | `nomic-embed-text` | Embedding model for semantic cache |
| `MULLM_ANTHROPIC_API_KEY` | _(unset)_ | Anthropic API key |
| `MULLM_OPENAI_API_KEY` | _(unset)_ | OpenAI API key |
| `MULLM_GOOGLE_API_KEY` | _(unset)_ | Google Gemini API key |
| `MULLM_PREFERRED_CLOUD_PROVIDER` | `anthropic` | `anthropic` / `openai` / `google` |
| `MULLM_BUDGET_WARN` | `7.00` | Log warning above this cost ($) |
| `MULLM_BUDGET_MODERATE` | `10.00` | Prefer local tier above this ($) |
| `MULLM_BUDGET_HARD` | `50.00` | Block all cloud calls above this ($) |
| `MULLM_SEMANTIC_CACHE_BACKEND` | `sqlite` | Semantic cache backend: `sqlite`, `chroma`, or `off` |
| `MULLM_CACHE_COSINE_THRESHOLD` | `0.98` | Semantic cache similarity floor |
| `MULLM_LOG_QUERY_CONTENT` | `true` | Set `false` for privacy mode |
| `MULLM_DATA_RETENTION_DAYS` | `90` | Auto-purge scoring log entries |
| `MULLM_CLASSIFIER_MODEL_PATH` | _(unset)_ | DeBERTa model dir; empty = rule-based |

</details>

---

## 🔌 API Reference

**Base URL:** `http://localhost:6856`

### Core endpoints

```bash
# Route a query through all tiers
POST /query
{"content": "what is 2+2"}

# Split multi-part query, parallel execution
POST /query/split
{"content": "summarize X and then write tests for Y"}

# SSE streaming from local Ollama
GET /query/stream?content=tell+me+a+story

# Health check (Ollama + semantic cache availability)
GET /health

# Dashboard stats (cost, tier distribution, query counts)
GET /api/dashboard

# Live system stats (CPU, RAM, GPU, VRAM, loaded model)
GET /api/system
```

### OpenAI-compatible endpoints

```bash
POST /v1/chat/completions   # drop-in replacement
GET  /v1/models             # model list
```

<details>
<summary>Example query response</summary>

```bash
curl -X POST http://localhost:6856/query \
  -H "Content-Type: application/json" \
  -d '{"content": "what is 2+2"}'
```

```json
{
  "response": "4",
  "tier": "groundtruth",
  "cost": 0.0,
  "latency_ms": 0.3,
  "model_used": "groundtruth-lut",
  "cached": false
}
```

</details>

---

## 🎯 Intent Categories

The classifier assigns every query to one of eight categories, each with a default routing strategy.

| Category | Description | Default Tier |
|---|---|---|
| `code` | Programming, debugging, refactoring | Local (complexity-gated) |
| `deploy` | Docker, CI/CD, infrastructure | Local |
| `research` | Explanations, papers, analysis | Local / Cloud |
| `lookup` | Facts, definitions, unit conversions | Cache / Groundtruth |
| `note` | Summarise, remember, to-do | Local |
| `creative` | Writing, stories, brainstorming | Local |
| `conversation` | General chat | Local |
| `vision` | Image and photo analysis | Local (vision model) |

---

## 🔬 Research

**mμ|LLM** is informed by ongoing research. The manuscript and evaluation methodology are still under critical review; no preprint is currently published.

### Key claims (verified on production data)

- **96.4% cost reduction** — $27.87 vs $772 baseline, N = 15,363 queries, 22 days
- **87.5% free-tier resolution** — Tiers 0–2 combined, zero cloud spend
- **100% HumanEval pass@1 at $0.00** — local tier only, no cloud escalation
- **RouterBench AIQ 0.6673** — highest published score on this benchmark at time of submission
- **DeBERTa-v3-small (44 MB)** classifier achieves production-grade intent classification
- Four-tier waterfall architecture generalizes to any local + cloud backend combination

Citation details will be added when the manuscript is ready for publication.

---

## 📊 Benchmark Results

All results from a 22-day production run on real developer queries (N = 15,363). No cherry-picking, no synthetic benchmarks for the cost numbers.

| Benchmark | Result | Notes |
|---|---|---|
| **Actual spend** | $27.87 | 22-day production run |
| **Cloud-only baseline** | $772.00 | Same queries, cloud-only |
| **Cost reduction** | **96.4%** | $744.13 saved |
| **Free-tier resolution** | **87.5%** | Tier 0 + Tier 1 + Tier 2 |
| **HumanEval pass@1** | **100%** | At $0.00 (local tier only) |
| **MMLU accuracy** | ≥ cloud parity | Via quality-gated escalation |
| **RouterBench AIQ** | **0.6673** | Highest published score |
| **Production queries** | 15,363 | 22 days, real developer workload |
| **Tier 0 latency** | < 1 ms | Groundtruth LUT, no model |
| **Local tier latency** | ~ 5 s | 30B model, consumer GPU |
| **Classifier size** | 44 MB | DeBERTa-v3-small, fine-tuned |
| **Cloud providers** | 16 | See provider grid below |

<details>
<summary>📈 Tier distribution breakdown</summary>

| Tier | Name | Queries Handled | Cost Per Query |
|---|---|---|---|
| Tier 0 | Groundtruth LUT | ~15% | $0.0000 |
| Tier 1 | Semantic Cache | ~35% | $0.0000 |
| Tier 2 | Local 30B Model | ~37.5% | $0.0000 |
| Tier 3 | Cloud API | ~12.5% | varies |

87.5% of all queries cost nothing. Cloud is invoked only when the local tier fails a quality gate.

</details>

---

## 🤝 Contributing

Contributions are welcome. Please open an issue before starting large changes.

```bash
git clone https://github.com/mybrainrunslinux/mullm.git
cd mullm
pip install -e .[all]
npx playwright test              # 59 free tests (no API calls)
npx playwright test --grep @spend  # paid cloud tests (explicit opt-in)
```

**Guidelines:**
- Tests must never spend money by default — cloud tests go behind `--grep @spend`
- Use Podman over Docker for container-based tests
- Cost accuracy matters — real API keys, real money
- Local-first — default to the cheapest capable tier

---

## 📄 License & Credits

**License:** [Apache 2.0](LICENSE)

**Built by [0101 Technology](https://0101technology.com)**

mμ|LLM is a research project and production system developed at 0101 Technology. The tardigrade mascot was chosen for its resilience — surviving extremes, running anywhere, needing nothing external.

---

<div align="center">

**[GitHub](https://github.com/mybrainrunslinux/mullm)** · **[0101technology.com](https://0101technology.com)** · **[Apache 2.0](LICENSE)**

*Cost-optimal LLM routing. Local-first. Microscopic spend.*

muLLM is developed and stewarded by **0101 Technology LLC** (Oregon, USA). See [NOTICE](NOTICE).

</div>

[Runtime privacy, deadlines, and model verification](docs/RUNTIME_GUARDS.md) · [Software Factory mode](docs/SOFTWARE_FACTORY.md).
[Current models and custom classifiers](docs/MODELS.md) · [Upgrade guide](docs/UPGRADING.md).

Software Factory: `mullm --factory factory.toml` — [configuration and acceptance gates](docs/SOFTWARE_FACTORY.md).
