stargaze
Cache and search your GitHub stars from the terminal. Pure Rust. Single binary. No cloud.
A small Rust CLI that pulls your starred GitHub repos into a local embedded database, lets you keyword-search them (README text included), and exposes the same cache to AI agents as an MCP server. No daemon, no cloud, no C dependencies.
Why
The GitHub starred-repos list is a shoebox of bookmarks with no real retrieval. Once you've starred more than a few hundred repos, finding "that one Postgres CLI I saw last month" means scrolling. stargaze turns your stars into a queryable local corpus that survives across machines, runs offline, and plugs into Claude / Cursor / any MCP-speaking agent.
Install
From crates.io:
From source:
Needs Rust 1.76+. Everything is pure Rust — no libsqlite3, no openssl, no C toolchain. The release binary is fully static (aside from libc).
Prebuilt binaries for Linux / macOS / Windows are attached to every tagged release.
Quick start
# one-time: give stargaze a token to talk to the GitHub API
# pull down your stars
# ...and their READMEs (slower, pulls 1 request per repo)
# search across the cache — now includes README text
# run as an MCP server so agents can query your stars
Commands
| Command | What it does |
|---|---|
stargaze sync [--user <login>] [--with-readmes] [--concurrency N] [--prune] |
Fetch all starred repos via the GitHub API and upsert into the local cache. --with-readmes also pulls each repo's README in parallel. --prune removes locally cached repos that are no longer starred. |
stargaze readmes [--force] [--concurrency N] |
Fetch READMEs for already-cached repos. Skips repos with a cached README unless --force. Useful after a plain sync. |
stargaze search <query> [--lang <L>] [--topic <T>] [--limit N] |
Substring match across full_name, description, language, topics, and cached README text. Ranks by weighted hit count × log(stars). Cold queries run in parallel via rayon; repeat queries hit an LRU cache. |
stargaze show <owner/name> |
Pretty-print the full cached JSON record for a repo. |
stargaze stats |
Total cached count, last sync time, top languages. |
stargaze list [--limit N] |
List all cached repos sorted by stargazer count. |
stargaze serve |
Run a Model Context Protocol stdio server over the cache. Exposes search_stars, show_star, list_stars, and stats as MCP tools. |
stargaze api [--bind 127.0.0.1:7879] [--api-key <k>] [--threads N] |
Run an HTTP JSON API over the cache. Same read-only surface as the CLI and MCP. Bearer-token auth is optional. |
Global flags:
--db <path>— override the database file (default:$XDG_DATA_HOME/stargaze/stars.redb)--token <pat>— pass a GitHub PAT explicitly instead of reading the env var
Storage
One file. Default location:
- Linux:
~/.local/share/stargaze/stars.redb - macOS:
~/Library/Application Support/com.bkataru.stargaze/stars.redb - Windows:
%APPDATA%\bkataru\stargaze\data\stars.redb
Backed by redb — a pure-Rust embedded key-value store with ACID transactions. Each starred repo is stored as a JSON blob keyed by owner/name; a separate meta table tracks last-sync timestamp and count. README text is included in the same record (truncated to 64 KiB to keep the file lean).
Three equivalent surfaces: CLI, MCP, HTTP API
Every read-only operation is reachable from all three surfaces. You pick the one that matches your client:
| Operation | CLI | MCP tool | HTTP |
|---|---|---|---|
| Health check | — | — | GET /api/v1/health |
| Stats (cached count + last sync) | stargaze stats |
stats |
GET /api/v1/stats |
| Keyword search | stargaze search <q> |
search_stars |
GET /api/v1/search?q=…&lang=…&topic=…&limit=… |
| Top-N by stars | stargaze list --limit N |
list_stars |
GET /api/v1/list?limit=N |
| Show one repo | stargaze show owner/name |
show_star |
GET /api/v1/stars/:owner/:name |
| Sync | stargaze sync |
not exposed (mutating) | not exposed (mutating) |
| Fetch READMEs | stargaze readmes |
not exposed (mutating) | not exposed (mutating) |
All three surfaces dispatch through the same RepoIndex + Database handles, so search results are identical across them. Mutating operations (sync, readmes) are intentionally CLI-only for now.
HTTP API
# optionally require a bearer token:
Backed by tiny_http (pure Rust, blocking, no tokio). Thread pool size configurable via --threads. CORS is enabled (Access-Control-Allow-Origin: *) so you can hit it from localhost web UIs.
MCP server mode
stargaze serve runs a Model Context Protocol stdio server that exposes the local cache as a structured tool set. Any MCP-compatible client (Claude Desktop, Cursor, custom agents) can query your starred repos as typed data.
Example Claude Desktop config (claude_desktop_config.json):
Tools exposed:
| Tool | Arguments | Returns |
|---|---|---|
search_stars |
query, lang?, topic?, limit? |
Ranked search hits with score, name, description, language, stars, topics, url |
show_star |
full_name |
Full cached record for one repo |
list_stars |
limit? |
Repos sorted by stargazer count |
stats |
— | Cache size + last sync metadata |
The implementation is hand-rolled JSON-RPC 2.0 over stdio — no tokio, no external MCP library — so the binary stays single-static and cold-starts instantly.
Auth
stargaze sync needs a GitHub token (any classic PAT or fine-grained token with read access to public metadata will do). Resolution order:
--token <pat>flagGH_TOKENenvironment variableGITHUB_TOKENenvironment variable
The easiest bootstrap if you already use the gh CLI:
stargaze never shells out — all HTTP traffic goes through ureq with rustls (pure-Rust TLS).
Scheduled sync
systemd timer (Linux)
~/.config/systemd/user/stargaze-sync.service:
[Unit]
Description=stargaze — refresh GitHub stars cache
[Service]
Type=oneshot
Environment="GH_TOKEN=%h/.config/stargaze/token"
ExecStart=%h/.cargo/bin/stargaze sync --with-readmes --prune
~/.config/systemd/user/stargaze-sync.timer:
[Unit]
Description=Weekly stargaze sync
[Timer]
OnCalendar=weekly
Persistent=true
[Install]
WantedBy=timers.target
Enable it once: systemctl --user enable --now stargaze-sync.timer.
launchd (macOS)
~/Library/LaunchAgents/com.bkataru.stargaze.plist:
Label com.bkataru.stargaze
ProgramArguments
/usr/local/bin/stargaze
sync
--with-readmes
--prune
StartInterval 604800
EnvironmentVariables
GH_TOKENghp_…
Load: launchctl load ~/Library/LaunchAgents/com.bkataru.stargaze.plist.
GitHub Actions (run in the cloud, commit the cache)
See .github/workflows/ci.yml for the reusable CI pattern. A weekly sync workflow that commits the cache back to a private repo is straightforward: cargo install stargaze && stargaze sync --with-readmes && git add stars.redb && git commit && git push.
Benchmarks
stargaze ships with a full criterion bench suite:
Workloads covered:
| Bench group | Parameters |
|---|---|
index_build |
100, 1k, 3k, 10k synthetic repos |
search_cold |
same sizes, one cold search per iteration |
search_warm |
3k repos, LRU pre-primed |
search_with_filters |
lang / topic / combined filter fast-paths |
indexed_repo_score |
per-repo score function microbench |
parse_link_next |
Link header walker |
repo_from_api |
JSON payload → Repo conversion |
End-to-end wall-clock via hyperfine:
Tests
Around 108 tests across unit + integration + live tiers:
Live tests are gated on GH_TOKEN / GITHUB_TOKEN being present; if missing they short-circuit with a skip message instead of failing. The CI pipeline runs them on every push to main using the repo's own workflow token.
Full breakdown:
| Layer | File | Count |
|---|---|---|
| Unit — parsing / index / MCP / API | src/lib.rs |
parse_link_next, Repo::from_api, IndexedRepo, score, truncate, resolve_token, MCP handlers, HTTP router, query-string parser (~66 tests) |
| Integration — redb | tests/store.rs |
upsert / load / meta / retain / idempotency (13 tests) |
| Integration — search | tests/search.rs |
filters / ranking / cache / large corpora (14 tests) |
| Integration — parse | tests/parse.rs |
edge-case payloads + Link headers (9 tests) |
| Live — GitHub API | tests/live.rs |
pagination, README fetch, parallel batch, mini sync (6 tests, #[ignore]) |
Comparison: stargaze vs miantiao-me/github-stars
Both projects address the same frustration. They make very different architectural choices.
| Capability | stargaze |
miantiao-me/github-stars |
|---|---|---|
| Language | Rust | TypeScript / JavaScript |
| Runtime requirement | Single static binary | Node.js v22 + pnpm + Cloudflare account |
| Storage | Local redb file | Cloudflare R2 bucket |
| Auth | GH_TOKEN env var |
GH_TOKEN + Cloudflare API keys + MCP API key |
| Offline use | ✅ full cache lives on disk | ❌ requires Cloudflare |
| Pagination of stars API | ✅ Link-header driven, generic | ✅ page counter |
| README extraction | ✅ --with-readmes, rayon-parallel |
✅ single-threaded loop |
| Scheduled refresh | ✅ systemd / launchd / cron / GH Actions examples | ✅ weekly GH Actions cron |
| Search — keyword | ✅ substring + BM25-ish scoring over name/desc/topics/lang/README, LRU-cached | ❌ delegates everything to Cloudflare AutoRAG |
| Search — semantic | 🔜 v0.3 via fastembed (tracked) |
✅ Cloudflare AutoRAG embeddings |
| Language / topic filters | ✅ | ❌ |
| Stats / list / show commands | ✅ | ❌ |
| Prune stale entries | ✅ --prune |
❌ |
| MCP tool server | ✅ stargaze serve over stdio |
✅ Cloudflare Worker HTTP |
| MCP transport | stdio — works with Claude Desktop out-of-the-box | HTTP — requires deployment + API key management |
| HTTP JSON API | ✅ stargaze api — tiny_http, pure Rust, optional bearer auth |
(Cloudflare Worker is the only interface) |
| Equivalent surfaces | ✅ CLI + MCP + HTTP all dispatch through the same index | ❌ only MCP |
| Parallelism | rayon par_iter for search + README batch |
single-threaded JS |
| Test coverage | 88 hermetic + 6 live | none committed |
| Benchmarks | criterion (7 groups) + hyperfine docs | none |
| Cold-start | ~1 ms (binary) | Worker cold-start + network round-trip |
| License | MIT | MIT |
The short version: stargaze is local-first, CI-tested, and runs anywhere Rust compiles. miantiao-me/github-stars offloads everything interesting (storage, embeddings, hosting) to Cloudflare. Different axes, same goal.
Roadmap
- v0.1 (current): sync, parallel README fetch, search with LRU cache, MCP stdio server, HTTP JSON API server, 108 tests, criterion benches, GH Actions CI + release workflow.
- v0.2:
stargaze diff --since DATE— delta of additions/removals (already schema-ready viastarred_at). - v0.3:
fastembed-rslocal embeddings + cosine-similarity semantic search (stargaze semantic <query>). - v0.4: export formats (markdown, opml, csv),
stargaze categorizeheuristic grouping,stargaze open <name>launcher.
License
MIT. See LICENSE.