spyglass-search/spyglass
A personal search engine: Create a searchable library from your personal documents, interests, and more!
Slowing — last commit 10mo ago
weakest axiscopyleft license (AGPL-3.0) — review compatibility
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓Last commit 10mo ago
- ✓7 active contributors
- ✓AGPL-3.0 licensed
Show all 8 evidence items →Show less
- ✓CI configured
- ✓Tests present
- ⚠Slowing — last commit 10mo ago
- ⚠Concentrated ownership — top contributor handles 51% of recent commits
- ⚠AGPL-3.0 is copyleft — check downstream compatibility
What would change the summary?
- →Use as dependency Concerns → Mixed if: relicense under MIT/Apache-2.0 (rare for established libs)
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Forkable" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/spyglass-search/spyglass)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/spyglass-search/spyglass on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: spyglass-search/spyglass
Generated by RepoPilot · 2026-05-09 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/spyglass-search/spyglass shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
WAIT — Slowing — last commit 10mo ago
- Last commit 10mo ago
- 7 active contributors
- AGPL-3.0 licensed
- CI configured
- Tests present
- ⚠ Slowing — last commit 10mo ago
- ⚠ Concentrated ownership — top contributor handles 51% of recent commits
- ⚠ AGPL-3.0 is copyleft — check downstream compatibility
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live spyglass-search/spyglass
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/spyglass-search/spyglass.
What it runs against: a local clone of spyglass-search/spyglass — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in spyglass-search/spyglass | Confirms the artifact applies here, not a fork |
| 2 | License is still AGPL-3.0 | Catches relicense before you depend on it |
| 3 | Default branch main exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 344 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of spyglass-search/spyglass. If you don't
# have one yet, run these first:
#
# git clone https://github.com/spyglass-search/spyglass.git
# cd spyglass
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of spyglass-search/spyglass and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "spyglass-search/spyglass(\\.git)?\\b" \\
&& ok "origin remote is spyglass-search/spyglass" \\
|| miss "origin remote is not spyglass-search/spyglass (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(AGPL-3\\.0)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"AGPL-3\\.0\"" package.json 2>/dev/null) \\
&& ok "license is AGPL-3.0" \\
|| miss "license drift — was AGPL-3.0 at generation time"
# 3. Default branch
git rev-parse --verify main >/dev/null 2>&1 \\
&& ok "default branch main exists" \\
|| miss "default branch main no longer exists"
# 4. Critical files exist
test -f "Cargo.toml" \\
&& ok "Cargo.toml" \\
|| miss "missing critical file: Cargo.toml"
test -f "apps/desktop-client/src/main.tsx" \\
&& ok "apps/desktop-client/src/main.tsx" \\
|| miss "missing critical file: apps/desktop-client/src/main.tsx"
test -f "apps/desktop-client/src/glue.ts" \\
&& ok "apps/desktop-client/src/glue.ts" \\
|| miss "missing critical file: apps/desktop-client/src/glue.ts"
test -f "apps/desktop-client/src/pages/search/SearchPage.tsx" \\
&& ok "apps/desktop-client/src/pages/search/SearchPage.tsx" \\
|| miss "missing critical file: apps/desktop-client/src/pages/search/SearchPage.tsx"
test -f "apps/desktop-client/src/bindings/ClientInvoke.ts" \\
&& ok "apps/desktop-client/src/bindings/ClientInvoke.ts" \\
|| miss "missing critical file: apps/desktop-client/src/bindings/ClientInvoke.ts"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 344 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~314d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/spyglass-search/spyglass"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
Spyglass is a desktop personal search engine (macOS/Windows/Linux via Tauri) that indexes documents, websites, and online content sources you explicitly choose, storing indexed data locally for instant full-text search without SEO spam. Built in Rust with a TypeScript frontend, it crawls and indexes content from local folders, 'lenses' (curated web collections), Google Calendar/Drive, GitHub, Reddit, and Wikipedia—creating a personal searchable library that runs entirely on-device. Monorepo structure: crates/ contains modular Rust libraries (entities, migrations, shared, spyglass core engine, lens/LLM/processor/RPC/searcher subsystems), while apps/tauri is the Tauri desktop wrapper and apps/desktop-client/ contains the TypeScript/Vite frontend (src/bindings auto-generated from Rust via Tauri, src/assets for UI). CI workflows in .github/workflows/. Desktop-client uses Vite with PostCSS, Prettier, ESLint.
👥Who it's for
Power users and developers frustrated with Google Search quality who want to build custom searchable indexes of documentation (Rust/Go docs, game wikis), personal files, and curated web content. Also useful for researchers, knowledge workers, and anyone who wants to cut through SEO spam by indexing only trusted sources.
🌱Maturity & risk
⚠️ No longer in active development (README states clearly). Last release was v2023.4.1. The codebase is feature-complete for what it does (supports major integrations: Google Calendar/Drive, GitHub, Reddit), has CI/CD via GitHub Actions (rust.yml, frontend-check.yml, publish.yml), and includes Docker support. However, it is effectively abandoned—no active maintenance or new features.
High risk for production use: project is explicitly discontinued (README warning), so no bug fixes or security patches will be released. Large Rust dependency surface (Cargo.toml workspace with 10+ crates including candle ML library, jsonrpsee, reqwest). Tauri desktop framework adds OS-specific binary compatibility concerns. No visible test suite mentioned in file structure suggests testing coverage is unclear.
Active areas of work
Nothing—project is abandoned. Last commits likely months ago (v2023.4.1 release). No active PRs, issues, or development indicated.
🚀Get running
Clone and set up: git clone https://github.com/spyglass-search/spyglass.git && cd spyglass. Install Rust (via rustup) and Node.js. Run make dev (uses Makefile.dev.template) to start the development environment, or follow Makefile.toml for Rust-cargo-make tasks. Frontend is at apps/desktop-client with npm install && npm run dev.
Daily commands:
From root: make dev (reads Makefile.dev.template). Or manually: (1) cargo build --release (Rust backend), (2) cd apps/desktop-client && npm install && npm run dev (frontend with Vite dev server), (3) Tauri binds them via apps/tauri. See .env.template for required environment setup (likely API keys for Google, GitHub, Reddit).
🗺️Map of the codebase
Cargo.toml— Workspace root configuration defining all member crates and shared dependencies; essential for understanding the monorepo structure and build system.apps/desktop-client/src/main.tsx— Frontend entry point for the Tauri desktop application; required reading to understand the React/TypeScript application bootstrap.apps/desktop-client/src/glue.ts— Bridge between TypeScript frontend and Rust backend via Tauri IPC; critical for understanding the async command/event system.apps/desktop-client/src/pages/search/SearchPage.tsx— Core search UI component orchestrating the primary user workflow; demonstrates how frontend renders results and interacts with backend.apps/desktop-client/src/bindings/ClientInvoke.ts— Type-safe interface definitions for all Tauri IPC invocations; essential for understanding the frontend-backend contract..github/workflows/rust.yml— CI/CD pipeline for Rust crate builds and tests; reveals build validation strategy and supported platforms.VERSION.json— Central version management for coordinating releases across Rust and TypeScript components.
🛠️How to make changes
Add a New Search Result Field to UI
- Define the new field in the Rust backend SearchResult struct (in one of the crates, likely spyglass-searcher or entities). Update the serialization. (
crates/entities/src/lib.rs (inferred—update SearchResult struct)) - Add the field to the TypeScript binding to match the Rust type. (
apps/desktop-client/src/bindings/SearchResult.ts) - Update the DocumentResultItem component to render the new field conditionally. (
apps/desktop-client/src/pages/search/DocumentResultItem.tsx) - Optionally add CSS classes for styling the new field in index.css. (
apps/desktop-client/src/index.css)
Add a New Settings Form
- Create a new form component in the forms directory, extending the pattern used in PathField or Toggle. (
apps/desktop-client/src/components/forms/YourNewField.tsx) - Add the setting option type in bindings if it's a new SettingOpts variant. (
apps/desktop-client/src/bindings/SettingOpts.ts) - Integrate the form component into UserSettingsPage or ConnectionManager depending on scope. (
apps/desktop-client/src/pages/settings/UserSettingsPage.tsx) - Wire up the Tauri IPC call in glue.ts to save/load the setting from the backend. (
apps/desktop-client/src/glue.ts)
Add a New Backend IPC Command
- Define the command handler in the Rust backend (likely in crates/spyglass or crates/spyglass-rpc). (
crates/spyglass-rpc/src/lib.rs (inferred—implement command handler)) - Add the Tauri command decorator and serialize the response. (
apps/tauri/src/main.rs (inferred—register Tauri command)) - Create/update the TypeScript binding and request/response types. (
apps/desktop-client/src/bindings/ClientInvoke.ts) - Add the IPC invocation function to glue.ts for frontend consumption. (
apps/desktop-client/src/glue.ts) - Call the new IPC function from your React component. (
apps/desktop-client/src/pages/search/SearchPage.tsx (example))
Add a New Lens Type or Lens Configuration Option
- Define the lens structure/schema in the Rust backend (likely crates/spyglass-lens or entities). (
crates/spyglass-lens/src/lib.rs (inferred)) - Add the new lens type to the InstallableLens or LensType bindings. (
apps/desktop-client/src/bindings/InstallableLens.ts) - Create a UI component or form fields in LensManager to handle configuration of the new lens type. (
apps/desktop-client/src/pages/settings/LensManager.tsx) - Add validation and serialization logic via IPC to persist the lens configuration. (
apps/desktop-client/src/glue.ts)
🔧Why these technologies
- Tauri — Cross-platform desktop framework (Windows, mac
🪤Traps & gotchas
Tauri platform-specific builds: Desktop binaries require separate builds for macOS (Intel/ARM), Windows, Linux; see published .dmg/.msi/.AppImage in releases. Environment variables critical: .env.template indicates Google API keys, GitHub tokens, Reddit credentials required to enable data sources—missing these silently disables features. Candle version pinning: tokenizers version (0.19) must match Candle's (0.8) or embedding/LLM features break. TypeScript bindings auto-generated: src/bindings/*.ts generated from Rust types via Tauri—manual edits will be overwritten on rebuild. No Gmail support yet (checkbox unchecked in README), so don't expect to index emails. Discourse-based docs at docs.spyglass.fyi may be offline—project abandoned.
🏗️Architecture
💡Concepts to learn
- Full-text search indexing — Spyglass's core function is building local, queryable indexes of content; understanding inverted indices and BM25 ranking is essential to modifying crates/spyglass-searcher.
- Web crawling and HTML parsing — The processor pipeline (crates/spyglass-processor) crawls URLs and extracts text; knowing robots.txt, sitemaps, and respectful crawling patterns is necessary to extend data sources.
- Tauri IPC (Inter-Process Communication) — Bridge between Rust backend (apps/tauri) and TypeScript frontend (apps/desktop-client); all data flows through Tauri's JSON-RPC protocol, visible in src/bindings/.
- Semantic embeddings / vector search — crates/spyglass-llm uses Candle for embeddings; understanding how text is vectorized enables debugging or customizing semantic (not just keyword) search.
- Plugin/Lens architecture — Spyglass abstracts content sources as pluggable 'Lenses' (crates/spyglass-lens); understanding the trait/interface pattern is required to add new sources (Google Drive, GitHub, etc.).
- Tokio async runtime — Rust backend uses Tokio throughout for concurrent crawling and indexing; non-blocking I/O is critical to performance when fetching many URLs or handling many search queries.
- Database migrations (SQLx) — crates/migrations/ manages the local database schema; understanding how data is persisted locally (indexed documents, metadata, settings) requires reading migration files.
🔗Related repos
meilisearch/meilisearch— Drop-in full-text search engine similar to Spyglass's indexing backbone, but self-hosted and API-driven rather than desktop-focused.typesense/typesense— Another alternative personal/self-hosted search engine with similar indexing goals; compare approach to Spyglass's Rust-based design.tauri-apps/tauri— The desktop framework powering Spyglass; contributes to cross-platform (macOS/Windows/Linux) binary builds.huggingface/candle— ML inference library used by Spyglass for embeddings and LLM features (crates/spyglass-llm); critical for semantic search.wikimedia/mediawiki— One of Spyglass's indexable sources (Wikipedia); understanding MediaWiki API helps extend wiki-lens support.
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add GitHub Actions workflow for desktop client (Node/TypeScript) linting and build verification
The repo has a frontend-check.yml workflow but examining the desktop client structure at apps/desktop-client/, there's evidence of ESLint config (.eslintrc.js), Prettier config (.prettierrc), and TypeScript bindings, yet no dedicated CI step that validates the Node build before Tauri compilation. This prevents catching frontend regressions early and ensures the desktop client dependencies are properly managed.
- [ ] Create
.github/workflows/desktop-client-check.ymlthat runsnpm ci && npm run lint && npm run buildin theapps/desktop-client/directory - [ ] Reference the existing
.prettierrc,eslint.config.js, andpackage.jsonscripts to ensure proper linting configuration - [ ] Verify the workflow triggers on pushes to relevant paths (
apps/desktop-client/**,Cargo.lockchanges that affect Tauri bindings) - [ ] Ensure the workflow runs on multiple Node versions (16, 18, 20) to catch compatibility issues early
Add type definitions export validation test for TypeScript bindings
The repo auto-generates TypeScript bindings at apps/desktop-client/src/bindings/ from Rust (ChatMessage.ts, SearchResult.ts, etc.). Currently there's no validation that these generated types are syntactically correct, properly exported, or match their Rust counterparts. A test would prevent stale or malformed binding files from reaching production.
- [ ] Create
apps/desktop-client/src/bindings/__tests__/bindings.test.tsto validate all.tsfiles in the bindings directory export proper types - [ ] Use TypeScript compiler API or
tsc --noEmitto verify type definitions compile without errors - [ ] Add assertions that critical bindings (SearchResult.ts, ChatMessage.ts, UserConnection.ts, etc.) export the expected interfaces
- [ ] Integrate this test into the
frontend-check.ymlworkflow (or new desktop-client workflow) to run before desktop builds
Add missing ESLint configuration for consistent TypeScript/React standards in desktop client
The apps/desktop-client/eslint.config.js exists but likely needs stricter rules for a growing desktop codebase with many React components. There's a .prettierrc for formatting but no evidence of comprehensive linting rules (e.g., no unused imports, no console statements in production, proper hook dependencies). This is especially important given the complexity of bindings and state management.
- [ ] Review and enhance
apps/desktop-client/eslint.config.jsto add rules for: unused variables, import sorting, React hooks (eslint-plugin-react-hooks), and TypeScript-specific rules - [ ] Add ESLint rules that enforce no console/debugger statements in non-development code
- [ ] Create
.eslintignorefile (or update existing) to excludedist/and auto-generated bindings if they have known linting issues - [ ] Document the linting standards in
apps/desktop-client/README.mdor top-level contributing guide for new contributors
🌿Good first issues
- Write integration tests for crates/spyglass-searcher query parsing and ranking—test suite appears thin given no tests/ directory visible in file list. Start with boolean operators and phrase queries.
- Add missing data source: Implement a Lens for Hacker News (popular with developers) following the pattern in crates/spyglass-processor/ for existing sources like Reddit. Requires HTTP fetching, parsing, and Lens struct.
- Document the Tauri IPC protocol: Create a schema or guide showing RPC calls from apps/desktop-client to apps/tauri backend (see ClientInvoke.ts bindings). Currently only TypeScript bindings exist, no spec.
⭐Top contributors
Click to expand
Top contributors
- @a5huynh — 51 commits
- @travolin — 38 commits
- @fosfomycin — 5 commits
- @DrChat — 3 commits
- @LillySchramm — 1 commits
📝Recent commits
Click to expand
Recent commits
498fb08— Update README.md (a5huynh)dcd6f55— Add document Q&A to the debug utility (#561) (travolin)69e5d7e— Vec documents updates (#560) (travolin)f3f0762— Update model to use cuda when available (#559) (travolin)093bc21— feature: llm-a-rama, basic llm integration using candle (#558) (a5huynh)766839b— Add paging to results (#557) (travolin)160174f— Bugfix lens search (#556) (travolin)2749a0a— Add Concat Context (#555) (travolin)fc3518c— Embedding segment index (#553) (travolin)1451863— bugfix: add missing startup/updater popups (#554) (a5huynh)
🔒Security observations
- High · Outdated and Potentially Vulnerable Dependencies —
Cargo.toml - workspace.dependencies. The project uses several dependencies with known vulnerabilities or outdated versions. Notable examples: reqwest 0.11.7 (released 2021, current is 0.12+), tokenizers 0.19 with 'onig' feature enabled (regex parsing library with historical CVEs), and candle ecosystem at 0.8 (older version). These versions may contain unpatched security issues. Fix: Audit and upgrade all dependencies to their latest stable versions. Run 'cargo audit' to identify known CVEs. Test thoroughly after upgrades to ensure compatibility. - High · Project No Longer in Active Development —
README.md. The README explicitly states '⚠️ NO LONGER IN ACTIVE DEVELOPMENT ⚠️'. This means security vulnerabilities will not be patched, and the application poses a significant risk in production or security-sensitive environments. Fix: Do not deploy this application in production environments. If in use, migrate to actively maintained alternatives or establish an internal security audit and patching process. - High · Exposed Ports in Docker Configuration —
docker-compose.yml - services.web.ports and services.api-server.ports. The docker-compose.yml exposes ports 8080 (web) and 4664 (api-server) directly without any documented authentication, rate limiting, or network isolation. This allows direct access from any network interface. Fix: Implement network isolation using Docker networks, add authentication/authorization middleware, implement rate limiting, and document required security controls. Consider binding to localhost only if not needed externally. - Medium · Potential Secrets in Environment Template —
.env.template (content not provided). The presence of .env.template suggests the application uses environment variables for configuration, including potentially sensitive data. However, no actual .env file is visible in the provided structure, indicating proper separation of secrets, but this requires discipline in execution. Fix: Ensure .env is in .gitignore (appears to be correct based on .gitignore presence). Document all required environment variables in .env.template without exposing actual values. Use secret management systems in production (e.g., HashiCorp Vault, cloud provider secrets). - Medium · Tauri Desktop Application Security Considerations —
apps/desktop-client/src - Frontend TypeScript/React components and bindings. The project includes a Tauri desktop application (apps/tauri) with IPC bridges to Rust backends. Tauri applications can have XSS or command injection vulnerabilities if the frontend improperly handles user input or untrusted data passed between frontend and backend. Fix: Implement strict input validation and output encoding in all IPC handlers. Audit all bindings in apps/desktop-client/src/bindings for secure serialization. Use Content Security Policy headers. Validate all user actions before passing to backend. - Medium · Missing Security Headers Configuration —
dockerfiles/web.Dockerfile (content not provided), web service configuration. No visible configuration for HTTP security headers (Content-Security-Policy, X-Frame-Options, X-Content-Type-Options, etc.) in the web service exposed on port 8080. Fix: Configure security headers in the web server (nginx/Apache) or application framework. Implement CSP to prevent XSS attacks, X-Frame-Options to prevent clickjacking, and HSTS for HTTPS enforcement. - Medium · Lack of HTTPS Configuration —
docker-compose.yml. Docker compose exposes ports 8080 and 4664 without TLS/SSL configuration. There is no indication of HTTPS enforcement or certificate management. Fix: Deploy behind a reverse proxy (nginx, traefik) with SSL/TLS termination. Use Let's Encrypt for certificate automation. Enforce HTTPS redirection. Enable HSTS headers. - Low · Verbose Logging Enabled —
Cargo.toml - log, tracing, tracing-subscriber dependencies. The workspace dependencies include 'log' and 'tracing-subscriber' with 'env-filter' and 'std' features, which could expose sensitive information in logs if not properly configured. Fix: Implement log filtering to prevent sensitive data (API keys, PII, internal paths) from being
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.