# patent **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. [![downloads](https://img.shields.io/crates/d/patent.svg)](https://crates.io/crates/patent) [![docs.rs](https://docs.rs/patent/badge.svg)](https://docs.rs/patent) [![CI](https://github.com/r14dd/patent/actions/workflows/ci.yml/badge.svg)](https://github.com/r14dd/patent/actions/workflows/ci.yml) [![GitHub stars](https://img.shields.io/github/stars/r14dd/patent?style=flat&logo=github)](https://github.com/r14dd/patent/stargazers) [![license: MIT OR Apache-2.0](https://img.shields.io/badge/license-MIT%20OR%20Apache--2.0-blue.svg)](#license)

patent in action

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. ```bash cargo install patent ``` ```bash 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 ```bash # 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](https://crates.io/crates/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](https://ollama.com) model 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** — `--fast` skips 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`. - **Fully local & private** — no data leaves your machine; embeddings and the LLM both run locally. - **Never fails loud** — Ollama down, or the model not pulled? 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 ```bash cargo install patent ``` ### From source ```bash git clone https://github.com/r14dd/patent.git cd patent cargo install --path . ``` ### Prerequisites **Rust** (stable 1.80+) via [rustup](https://rustup.rs). **Ollama** (optional, recommended) — powers the AI verdict. Skip it and use `--fast`, or just let `patent` fall back to a similarity-only verdict: ```bash # 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 ``` **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×): ```bash # macOS / Linux export GITHUB_TOKEN=ghp_your_token_here ``` ```powershell # 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 `downloading the embedding model…` notice. It's cached under your OS cache directory (e.g. `~/Library/Caches/patent` on macOS, `~/.cache/patent` on Linux, `%LOCALAPPDATA%\patent` on Windows), so it's a one-time download shared across every directory you run from. ## Usage ```bash # 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 # Keep more matches after ranking patent "async runtime for rust" --limit 100 ``` ### Options | Flag | Description | Default | |---|---|---| | `--fast` | Skip the Ollama verdict for an instant, search-only result | — | | `--json` | Print JSON to stdout instead of the TUI | — | | `--model ` | Ollama model for the verdict | `qwen2.5` | | `--limit ` | Max matches to keep after ranking | `50` | | `--completions ` | Generate shell completions and exit | — | ### Shell completions ```bash # 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 Ollama │ ▼ TUI or JSON ``` 1. **Parse** — extracts keywords, selects relevant sources based on the idea 2. **Search** — fans out to selected sources concurrently; a failing source is skipped and retried once, never fatal 3. **Rank** — embeds the idea and each match description with AllMiniLM-L6-V2, sorts by cosine similarity, keeps the top N 4. **Verdict** — sends the ranked matches to a local Ollama model that classifies the space and identifies gaps (or, with `--fast`, derives the level straight from the similarity data) 5. **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 # Ollama prompt + response parsing ├── ollama.rs # minimal Ollama 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 ```bash 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](https://github.com/charmbracelet/vhs): ```bash vhs demo.tape # writes demo.gif ``` ### Adding a new source 1. Create `src/sources/your_source.rs` implementing the `SourceAdapter` trait 2. Add the variant to `Source` in `src/model.rs` 3. Register it in `sources::build_source` and `sources::detect_sources` 4. Add wiremock integration tests in `tests/sources.rs` ## License Licensed under either of [MIT](LICENSE-MIT) or [Apache-2.0](LICENSE-APACHE) at your option.