unrent
by stringcutter
Find the strings your AI code hangs by. Cut them before they snap.
- Closed AI services the code calls, with file and line, and the open source that replaces each one, ranked.
- Models that stop working: model ids the code selects that their vendor has retired, or will on an announced date, and the vendor's replacement.
- Open source AI the code already runs, and where it ranks in its field.
The CLI runs offline. No account. No upload. No telemetry.
Real output. One row per string, with its strongest location and how many more there are:
╎ cut |
A closed service with an open source replacement. The top of its ranking is on the row. |
│ held |
A closed service with no open source replacement in the catalog yet. |
┆ snapped |
A model id the code selects that its vendor has retired. Requests to it fail now. |
┆ snaps |
The same, on the date shown. |
│ runs |
Open source already in use, and where it ranks among its kind. |
--why shows every line behind one row, and what replaces it:
In a pipe or a file the same scan is a Markdown report that pastes straight into an issue or PR.
Install
uv tool install unrent # or: pipx install unrent
unrent .
Or once, without installing:
uvx unrent .
Python 3.11+. One dependency: PyYAML (the MCP server adds mcp). Large repos are read
on every core. With ripgrep on PATH it is about
twice as fast again: 6 s for 5,500 files, 14 s for 14,000 (13 s and 26 s without, on 4
cores). Same results either way.
Use
unrent . # the terminal view; Markdown in a pipe or file
unrent . --why openai # every location of one service, and what replaces it
unrent . --why gpt-4-turbo # every line that selects a retiring model
unrent . --as-of 2026-12-01 # judge retirements as of another day
unrent . -o report.md # the Markdown report
unrent . --format json -o r.json # everything, machine-readable
unrent . --top 5 # more alternatives per kind
unrent . --skip-tests # ignore test, spec and fixture code
unrent . --exclude "examples/" # .gitignore syntax; or a .unrentignore file
unrent catalog # what it knows
unrent . is short for unrent scan .. Colour follows NO_COLOR and FORCE_COLOR.
On Windows PowerShell, write reports with -o, not >. The redirect re-encodes the
file.
MCP
unrent as tools for Claude Code, Cursor, Copilot, or any agent that speaks MCP. The agent gets the facts; you decide what to swap.
claude mcp add unrent -- uvx --from "unrent[mcp]" unrent mcp
Other clients:
{
"mcpServers": {
"unrent": {
"command": "uvx",
"args": ["--from", "unrent[mcp]", "unrent", "mcp"]
}
}
}
| Tool | |
|---|---|
scan |
Closed services, models that stop working, open source in use, alternatives. The report as JSON. |
alternatives |
Best open source for a category or a closed service: "pinecone", "speech-to-text". |
standing |
Where one project ranks, overall and among its kind: "qdrant/qdrant". |
catalog |
What unrent recognises, and the signatures it looks for. |
Rankings come from this repo's main, refreshed weekly, not from the install. Cached
for six hours. When the fetch fails it uses the shipped snapshot and says so.
UNRENT_OFFLINE=1 never fetches. Only rankings come in. Your code never goes out.
For agents that use skills, npx skills add stringcutter/unrent adds a workflow on top:
check what unrent can't see, sweep for services outside the catalog, and write the report.
What it detects
357 closed AI services in 21 categories: LLM APIs, LLM gateways, embeddings, vector
databases, RAG platforms, document parsing, guardrails, classification and scoring, LLM
observability, model hosting, fine-tuning, speech-to-text, text-to-speech, voice agents,
image generation, web search, web scraping, browser automation, code sandboxes, agent
platforms, agent memory. 218 are written by hand; 139 hosted model providers come from
models.dev and are regenerated every week
(models-dev.yaml).
Models that stop working. 204 model retirements announced by OpenAI, Anthropic and
Google for their own APIs, with the date and the vendor's replacement, checked every
week against their deprecation pages
(retirements.yaml)
and shipped with each release.
A model id counts when a line selects it: a default, a config value, a model passed to
a call. The same id in a model menu, a price table or a check on what the user picked
is only counted. Azure OpenAI, Bedrock and Vertex keep their own schedules and are not
covered. On the golden corpus: precision 0.939, recall 0.886.
Services it does not know yet. Every scan also lists unknown_candidates: API hosts
and keys that no catalog entry explains and that look like a hosted AI API (a /v1/...
path, an api. or .ai host, a matching *_API_KEY). They are candidates to check, not
findings, and never counted.
89 open source projects: vector databases, inference servers, gateways, RAG frameworks and applications, document parsers, observability, evals, speech, scraping, agent memory.
Evidence it reads:
| Packages | Python (requirements, pyproject, setup.py/cfg, Pipfile, conda, extras like qdrant-client[fastembed]), npm and pnpm catalogs, Go, Cargo, Maven, Gradle, NuGet, RubyGems, Composer, pub, SwiftPM |
| Imports | Python (AST, notebooks), JavaScript/TypeScript (import, require, import(), npm:, jsr:) |
| Install commands | pip install, uv add, npm i, … in Dockerfiles, shell, CI, notebook cells |
| Container images | image: in compose and Kubernetes, ${VAR:-default}, Helm values, Dockerfile FROM |
| Code and config | API hosts, model ids, env vars, SDK symbols, CREATE EXTENSION, Terraform |
Every package name in the catalog exists in its registry. Checked weekly.
What it ignores
- Local servers behind a compatible SDK.
OpenAI(base_url="http://localhost:11434/v1")is Ollama, not OpenAI. - Lockfiles. Your dependencies' dependencies aren't yours.
- Comments and docs. Per-language comment syntax.
"/api/*"in a string is not a comment. - Ignored and vendored files.
.gitignorewith or without git. Submodules scanned.node_modulesnot. - Generic names.
task="transcribe"isn't Amazon.import textractisn't AWS. Yourperplexity.pyisn't Perplexity. - Open-weight models.
gpt-oss,deepseek-v3.2and Ollama tags aren't closed.
Also:
- Secrets are masked.
OPENAI_API_KEY=****. - Test-only findings are marked.
--skip-testsdrops them. - Model names alone don't count. A model id with no SDK, key, host or package behind it is listed apart, as closed models named in code.
- Vendor through vendor. Azure via
openai, Claude on Bedrock or Vertex viaanthropic: the report names the one you actually call. - Oversized files are listed, never skipped silently.
Every rule above has a test that fails without it.
Ranking
Pools live in catalog/alternatives.yaml. Re-ranked every Monday by a
GitHub Action that merges itself.
- Projects: GitHub stars gained in the last 90 days, from unrent's own weekly snapshots. Until four weeks exist: total stars. The report says which.
- Models: Hugging Face trending. Labs' own releases only, open licence, max two per lab.
- Open source only. OSI licence for code. Apache, MIT, BSD or CC-BY for weights.
Restricted weights are out, whatever the code licence. Archived projects and a year
without a push are out. Open core is marked: LiteLLM's
enterprise/or Langfuse'see/is not under the licence shown. - No silent rot. A renamed, archived or relicensed project blocks the auto-merge and waits for a human. A pool that empties or halves is not published.
The scanner reads the snapshot shipped with the release. New rankings come with new releases.
Contribute
The catalog is YAML. New service: catalog/services/. New alternative: a pool in
catalog/alternatives.yaml. False positive or miss: open an issue with the
line that fooled it. CONTRIBUTING.md.
Licence
Apache-2.0. unrent is made by stringcutter.
Metadata
Release files for unrent 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| unrent-0.2.0.tar.gz | 182.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| unrent-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 309.3 kB
Release files / unrent-0.2.0.tar.gz
| Download URL | unrent-0.2.0.tar.gz |
|---|---|
| Size | 182.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
7f3b24c5bf994d9a5d6e41e05617967f18b76836efb854a52f569cfaa4f0fc0a
|
|
BLAKE2b-256 checksum How to use checksums |
769ce2c8bd5169d89a41d588b4f5d1b4b9cda9ac1f84c1e9fb957856d36bae64
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 4, 2026.
Transparency logRelease files / unrent-0.2.0-py3-none-any.whl
| Download URL | unrent-0.2.0-py3-none-any.whl |
|---|---|
| Size | 126.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
189895c6c97edfba18e00ea4d03dd95505a3e6887b2f273b41da04bc998c236b
|
|
BLAKE2b-256 checksum How to use checksums |
daa3527f7a81bc52d3d2088425d781e2da6444e638c42b55aaa2154d3df70f85
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 4, 2026.
Transparency log