A prior-art search for your code ideas. Stop building what already exists — find the state of the art in seconds, without leaving the terminal.
Give patent a plain-English dev-tool idea and it searches 11 open-source
registries — crates.io, npm, PyPI, GitHub, Docker Hub, and more — ranks the
matches with local semantic search, and writes an honest verdict on whether the
space is Open, Crowded, or Saturated. Everything runs on your
machine.
cargo install patent
patent "interactive cli to kill whatever's on a port"
Like a patent search, but for code. A patent search finds prior art — it never certifies absence. Neither does this.
Why
- Prevent wasted effort — find out something already exists before you spend a month rebuilding it.
- Find inspiration & benchmarks — see the closest prior art, ranked, so you know exactly what you'd have to beat.
- Competitive analysis — survey an entire ecosystem in one command instead of tab-hopping across a dozen registries.
Quick demo
# A crowded space — lots of prior art, ranked by relevance
patent "distributed key-value store in rust"
# Pipe structured output into your own tooling
patent "react component for infinite scroll" --json | jq .
# Skip the AI verdict for an instant, search-only result
patent "kubernetes log viewer" --fast
Features
- Search the entire developer ecosystem at once — 11 registries (crates.io, npm, PyPI, GitHub, Go, Maven, NuGet, RubyGems, Docker Hub, VS Code Marketplace, Hacker News) in a single command.
- It searches the right places automatically — mention "rust" and it hits crates.io; mention "docker" and it hits Docker Hub. GitHub and Hacker News (both language-agnostic) are always searched; with no language signal it falls back to a broad sweep across the largest registries.
- Relevance you can trust — local embeddings (AllMiniLM-L6-V2 via fastembed) rank every match by cosine similarity to your idea, so the closest prior art floats to the top.
- An honest verdict, not hype — a local Ollama model
(or any OpenAI-compatible API via
--api-base) classifies the space as Open / Crowded / Saturated and names the gaps you could fill. It can prove something exists; it never claims something doesn't. - Instant mode —
--fastskips the LLM and gives you the ranked list immediately, with a saturation level derived straight from the similarity data. - See it, don't parse it — an interactive TUI with scrollable, filterable,
sortable matches, a detail popup for any result, mouse support, and one-key
URL opening. Need machine output?
--json. - Local-first & private — embeddings always run on your machine, and the
verdict uses a local LLM by default; point
--api-baseat a cloud API only if you want to. - Never fails loud — LLM down, model not pulled, or a cloud API rejecting the request? Results still render, ranked by similarity, without an AI verdict. A source fails? It's skipped (and shown as "not reached"), never fatal.
Install
From crates.io
cargo install patent
From source
git clone https://github.com/r14dd/patent.git
cd patent
cargo install --path .
Prerequisites
Rust (stable 1.80+) via rustup.
Ollama (optional, recommended) — powers the AI verdict. Skip it and use
--fast, or just let patent fall back to a similarity-only verdict:
# macOS
brew install ollama
# Linux
curl -fsSL https://ollama.com/install.sh | sh
# Windows (or download the installer from https://ollama.com/download)
winget install Ollama.Ollama
# Then (any platform):
ollama pull qwen2.5
ollama serve
Cloud or OpenAI-compatible API (alternative to Ollama) — point patent at
any server that speaks the OpenAI chat API with --api-base, plus --api-key
(or the OPENAI_API_KEY env var):
# OpenAI
patent "vector database" --api-base https://api.openai.com/v1 --model gpt-4o-mini --api-key sk-...
# OpenRouter
patent "vector database" --api-base https://openrouter.ai/api/v1 --model openai/gpt-4o-mini --api-key sk-or-...
# Local LM Studio / llama.cpp / vLLM (usually no key needed)
patent "vector database" --api-base http://localhost:1234/v1 --model your-model
GitHub token (optional) — the unauthenticated GitHub search API is limited to 10 requests/minute. Set a token to raise that to 30 requests/minute (3×):
# macOS / Linux
export GITHUB_TOKEN=ghp_your_token_here
# Windows (PowerShell)
$env:GITHUB_TOKEN = "ghp_your_token_here"
First run — patent downloads a small (80 MB) embedding model the first
time it ranks results. You'll see a one-time /Library/Caches/patentdownloading the embedding model…
notice. It's cached under your OS cache directory (e.g. `on macOS,~/.cache/patenton Linux,%LOCALAPPDATA%\patent` on Windows), so
it's a one-time download shared across every directory you run from.
Usage
# Basic search — opens the interactive TUI
patent "CLI tool that kills whatever's on a port"
# Instant, search-only result — no model warm-up, no inference wait
patent "CLI tool that kills whatever's on a port" --fast
# Structured JSON output for scripting
patent "react component for infinite scroll" --json | jq .
# Use a smaller/faster Ollama model
patent "kubernetes log viewer" --model qwen2.5:3b
# Use a cloud LLM instead of local Ollama
patent "kubernetes log viewer" --api-base https://api.openai.com/v1 --model gpt-4o-mini
# Keep more matches after ranking
patent "async runtime for rust" --limit 100
Options
| Flag | Description | Default |
|---|---|---|
--fast |
Skip the LLM verdict for an instant, search-only result | — |
--json |
Print JSON to stdout instead of the TUI | — |
--model <MODEL> |
LLM model for the verdict | qwen2.5 (Ollama) |
--api-base <URL> |
Use an OpenAI-compatible API (base URL ending in /v1) instead of Ollama |
— |
--api-key <KEY> |
API key for --api-base (or set OPENAI_API_KEY) |
— |
--limit <N> |
Max matches to keep after ranking | 50 |
--completions <SHELL> |
Generate shell completions and exit | — |
Shell completions
# Bash
patent --completions bash >> ~/.bashrc
# Zsh
patent --completions zsh >> ~/.zshrc
# Fish
patent --completions fish > ~/.config/fish/completions/patent.fish
# PowerShell
patent --completions powershell >> $PROFILE
TUI keybindings
| Key | Action |
|---|---|
↑ / k |
Scroll up |
↓ / j |
Scroll down |
g / Home |
Jump to top |
G / End |
Jump to bottom |
/ |
Filter matches |
s |
Cycle sort (similarity / popularity / name) |
m |
Show more / show less |
Enter |
Show match details (full description, popularity, URL) |
o |
Open selected match in browser |
? |
Help overlay |
q |
Quit |
The mouse works too — scroll with the wheel, click a row to select it. Press
? inside the TUI for the full keybinding reference.
How it works
idea ──► parse keywords
│
├──► fan out to sources (concurrent, with retry)
│ │
│ ▼
│ dedup matches
│ │
▼ ▼
load model ──► rank by cosine similarity
│
▼
verdict via LLM
│
▼
TUI or JSON
- Parse — extracts keywords, selects relevant sources based on the idea
- Search — fans out to selected sources concurrently; a failing source is skipped and retried once, never fatal
- Rank — embeds the idea and each match description with AllMiniLM-L6-V2, sorts by cosine similarity, keeps the top N
- Verdict — sends the ranked matches to an LLM (local Ollama by default, or
an OpenAI-compatible API via
--api-base) that classifies the space and identifies gaps (or, with--fast, derives the level straight from the similarity data) - Output — interactive TUI (default) or structured JSON (
--json)
The embedding model loads concurrently with source searches, so the model-load latency is hidden behind network I/O.
The integrity rule
patent can prove something exists. It can never prove something
doesn't — it only searched some sources. Every verdict is scoped to "what was
found in the sources checked," and a clean result means keep looking, not
start building.
The sources-checked list is always displayed for transparency, and sources that were selected but failed to respond are surfaced as "not reached" — so a thin result is never mistaken for "nothing out there."
Architecture
src/
├── lib.rs # library root
├── model.rs # Query, Match, Source, Verdict, Saturation
├── sources/
│ ├── mod.rs # trait Source, search_all fan-out, dedup, retry
│ ├── crates_io.rs # crates.io API
│ ├── github.rs # GitHub search API
│ ├── npm.rs # npm registry API
│ ├── pypi.rs # PyPI search (HTML scraping)
│ ├── hacker_news.rs # HN Algolia API
│ ├── go.rs # Go package search
│ ├── maven.rs # Maven Central API
│ ├── nuget.rs # NuGet API
│ ├── rubygems.rs # RubyGems API
│ ├── docker_hub.rs # Docker Hub API
│ └── vscode.rs # VS Code Marketplace API
├── rank.rs # fastembed embeddings + cosine similarity
├── verdict.rs # LLM prompt + response parsing
├── llm.rs # trait Llm (verdict backend interface)
├── ollama.rs # Llm impl: native Ollama client
├── openai.rs # Llm impl: OpenAI-compatible chat client
└── tui.rs # TUI state machine
src/bin/patent/
��── main.rs # CLI entry point, pipeline wiring
├── cli.rs # clap argument parsing
└── tui.rs # ratatui rendering + event loop
Lib/bin split: the testable core is the library; the binary is a thin CLI/TUI shell.
Development
cargo fmt --all --check # formatting (CI-enforced)
cargo clippy --all-targets -- -D warnings # lint (CI-enforced)
cargo test # unit + wiremock integration tests
cargo build --release # optimized build
The README demo GIF is generated with vhs:
vhs demo.tape # writes demo.gif
Adding a new source
- Create
src/sources/your_source.rsimplementing theSourceAdaptertrait - Add the variant to
Sourceinsrc/model.rs - Register it in
sources::build_sourceandsources::detect_sources - Add wiremock integration tests in
tests/sources.rs
Comments