npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

repolex

v0.11.1

Published

Local SQLite index of your codebase with grep-fast lookups and AI-synthesized architecture/endpoint/schema summaries, exposed to Claude Code via MCP.

Downloads

1,913

Readme

Repolex

Repolex builds a structured index of your codebase once, so every developer's Claude can answer "where does billing live?" in one tool call instead of grepping for ten minutes.

What you get: 27 MCP tools (search_code, find_symbol, find_references, find_callers, get_symbol_body, find_definition_at, get_test_for, get_routes_for_controller, list_endpoints, get_db_table, ...), AI-synthesized architecture/domains/endpoints/db_tables/integrations, per-row staleness flags so the model knows when synth data is behind your edits, and a single SQLite file you can commit to a private git repo and share with your team.

It runs locally. Without --mode anthropic-api or hybrid, your code never leaves the machine.

60-second quick start

npm install -g repolex
repolex setup --register-clients
repolex index myapp --path .
# Restart Claude Code so it loads the new MCP server.

Now ask Claude "where does billing live in this repo?" and it'll call mcp__repolex__list_files, mcp__repolex__find_symbol, and friends instead of running ten grep -r commands.

--register-clients writes the MCP entry into ~/.claude.json for you. Use --no-register-clients to wire it up yourself.

For AI-synthesized architecture summaries (optional, see below):

export ANTHROPIC_API_KEY=sk-...
repolex synthesize myapp --max-cost 10

Requirements

  • Node 20+
  • git
  • repomix (npm install -g repomix) for snapshotting source
  • Optional: an Anthropic API key for AI synthesis (anthropic-api or hybrid mode)
  • Optional: syft for full techstack SBOM detection. The native parser handles most cases without it.

Run repolex doctor to verify your environment.

What it does

Repolex turns a checkout of your code into a queryable SQLite database with FTS5 search, symbol extraction, and (optionally) AI-generated architecture summaries. Then it exposes that database through the Model Context Protocol so Claude Code can query it directly with 23 typed tools.

The model:

  1. Index once. repolex index runs repomix to snapshot the repo, extracts symbols (classes/functions/methods with line numbers), categorizes files by template (Rails / React-TS), and writes everything to ~/.repolex/db/<name>.sqlite.
  2. Synthesize once (optional). repolex synthesize calls Claude Sonnet to produce repo-level architecture, domains, endpoints, db_tables, and integrations. Results live in the same SQLite.
  3. Serve forever. repolex mcp (auto-spawned by Claude Code) reads from the SQLite and answers tool calls. No re-indexing needed for queries.
  4. Refresh incrementally. repolex refresh re-runs repomix and only re-processes files whose hash changed. Synthesis only re-runs for changed files.

The killer detail: the SQLite is small (47 MB on a 5621-file Rails repo, 27 MB on a 2868-file TypeScript repo) and portable. Push it to a private git repo, your teammates repolex pull, and their Claude is already up to speed without spending another cent on synthesis.

Supported languages and frameworks

Templates auto-detect file categorization. Symbol extractors pull classes, methods, functions, and constants out of source.

| Language | Files indexed | Symbols extracted | Notes | |---|---|---|---| | Ruby | yes | yes | Module/class nesting tracked. Produces FQNs like Api::V1::AddressesController#create. | | TypeScript / TSX | yes | yes | Classes, interfaces, types, functions, arrow components, forwardRef/memo HOCs, React.FC<Props> typed components, export default class. | | JavaScript / JSX / MJS / CJS | yes | yes | Same patterns as TypeScript. | | Python | yes | partial | Top-level classes and defs only. No nesting, no FQNs. | | Go, Java, Kotlin, C#, PHP, Swift, Rust, Scala, Erlang, Elixir | yes | no | Files indexed and searchable; symbol table is empty. Use search_code and find_references for these. |

Templates shipped today: rails and react-ts. Auto-detected from Gemfile/config/application.rb (Rails) and react in package.json plus tsconfig.json (React-TS). Next.js, Django, Go, Rust, and Laravel are detected but not shipped yet (you'll get a clear "not shipped" error and a --template hint). Pass --template <name> to use a specific template.

All commands

| Command | Purpose | |---|---| | repolex setup | First-time config; optionally registers MCP entry and installs hooks | | repolex index [name] | Snapshot + index a local checkout (auto-derives name from git remote) | | repolex refresh [name] | Re-run snapshot, re-process changed files only | | repolex synthesize <name> | Run the 5 reasoning AI synthesizers (domains, architecture, endpoints, db_tables, integrations) | | repolex add <name> <snapshot.json> | Index from an existing repomix JSON snapshot | | repolex list <name> | Print indexed files (filterable by --category / --domain) | | repolex status <name> | Print indexed/synthesized/cost JSON | | repolex doctor | Diagnose env (node version, git, repomix, claude CLI, syft, config) | | repolex mcp [names...] | Start MCP server (default for Claude Code; serves all repos by default) | | repolex serve [names...] | Alias for mcp | | repolex push <name> | Push DB + manifest to shared git repo (admin/ci role) | | repolex pull <name> | Pull DB + manifest from shared git repo, verify SHA, atomic swap | | repolex sync [name] | Pull + verify DB is readable | | repolex prune <name> | Remove failed synthesis entries and orphaned citations | | repolex techstack <name> | Detect/rebuild tech stack (syft + curated map + registry + AI) | | repolex remove <name> | Delete DB, WAL, manifest, origin marker, MCP entry from ~/.claude.json | | repolex hello [name] | Smoke-test the MCP wiring end-to-end without restarting Claude Code |

Add --help to any command to see all flags.

setup

repolex setup [--mode <claude-code|anthropic-api|hybrid>] [--role <admin|ci|consumer>]
              [--shared-from <git-url>] [--non-interactive] [--force]
              [--register-clients|--no-register-clients]
              [--enable-hooks] [--hooks-scope <project|user>]

Writes ~/.repolex/config.json. Refuses to overwrite an existing config (would lose shared_index, repos, and any custom keys); pass --force to replace.

--mode controls where AI calls go:

  • claude-code (default when no ANTHROPIC_API_KEY): goes through the local claude CLI's subscription
  • anthropic-api (default when key is present in TTY): direct Anthropic API + Batches (50% off)
  • hybrid: reasoning passes via claude CLI; reserved for future API-bound work

--role gates writes to the shared index:

  • admin / ci: can push
  • consumer: read-only (default)

--register-clients walks ~/.repolex/db/*.sqlite and writes a Claude Code MCP entry per repo into ~/.claude.json (default in TTY, off in CI). --no-register-clients opts out.

--enable-hooks installs the optional PreToolUse hook (see below). --hooks-scope project (default) writes to <cwd>/.claude/settings.local.json; user writes to ~/.claude/settings.json.

# Solo dev, no shared index
repolex setup --register-clients

# Consumer onboarding from existing shared index
repolex setup --shared-from [email protected]:yourorg/repolex-data.git --non-interactive

# Admin building the shared index
repolex setup --mode hybrid --role admin --shared-from [email protected]:yourorg/repolex-data.git --non-interactive

index

repolex index [name] [--path <path>] [--template <rails|react-ts>] [--ignore <glob,glob>]
              [--no-claudemd]

Runs repomix on --path (default .), feeds the snapshot into the indexer, writes a per-repo <repo>/CLAUDE.md block (suppress with --no-claudemd).

Name resolution: explicit positional > GitHub remote (github-owner-repo) > path.basename. Bitbucket / GitLab / self-hosted git URLs fall through to basename; pass an explicit name for stability.

# In your project root
repolex index

# Explicit name + path
repolex index myapp --path ~/code/my-rails-app

# Force a template
repolex index myapp --template rails --path .

# Skip noise the .gitignore doesn't catch
repolex index myapp --ignore "vendor/**,**/__pycache__/**"

Gotchas:

  • The --max-cost, --no-confirm, --sync, --resume flags are accepted but no-op for the first index. Use them on refresh for incremental runs.
  • is reserved / must start with a letter/digit errors come from the repo-name validator. Names must match [a-zA-Z0-9][a-zA-Z0-9_.-]* and be 64 chars or fewer.
  • A repo name binds to its git origin URL via <db>.origin. Re-indexing the same name from a different origin throws "already bound to a different origin".

refresh

repolex refresh [name] [--path <path>] [--template <name>]
                [--max-cost <usd>] [--no-confirm] [--sync] [--resume]

Re-runs repomix and re-processes only files whose content hash changed since the last index. Cheap, run after every meaningful edit.

repolex refresh myapp
repolex refresh myapp --path ~/code/my-rails-app

refresh also drops any previously-indexed files that now match the secret-shaped pattern set in 0.6.5 (e.g. an .env.production you indexed before upgrading).

synthesize

repolex synthesize <name> [--max-cost <usd>] [--path <path>] [--no-claudemd]

Runs the 5 reasoning synthesizers (Sonnet, fixed call count each): domains > architecture > endpoints > db_tables > integrations. Each synthesizer reads a deterministic context built from the index (file paths, categories, symbols) at call time, so the call count is fixed regardless of repo size.

--max-cost caps spend in USD (default 25). Only enforces in anthropic-api and hybrid modes; in claude-code mode every call reports $0 against your subscription, so the ceiling is informational.

--path makes the post-synth CLAUDE.md block reflect the freshly-synthesized counts (instead of the zeros index wrote pre-synthesis).

--max-files is accepted for backward compatibility but is a no-op as of 0.8 (will be removed in 1.0). The pipeline no longer makes a per-file AI pass.

# 5 reasoning synthesizers (works in any mode)
repolex synthesize myapp --path .

# With a $10 cost ceiling (only enforced in anthropic-api / hybrid modes)
repolex synthesize myapp --max-cost 10 --path .

Cost rough estimates (Batches API, Sonnet for reasoning, fixed 5-call shape):

  • Any repo size: ~$0.05 to $0.20

repolex status <name> shows total_cost_usd. repolex prune <name> clears failed synthesis entries.

list

repolex list <name> [--category <c>] [--domain <d>]

Prints indexed files as a JSON array. Always passes a name explicitly; there is no silent fallback to a "default" repo.

repolex list myapp
repolex list myapp --category controller
repolex list myapp --domain billing

status

repolex status <name>

Prints { files_indexed, last_refresh, pending_synthesis_calls, total_cost_usd, indexed }. Exits non-zero when no index exists for that name (still prints valid JSON for jq pipes).

doctor

repolex doctor

Checks: node version, git, repomix, claude CLI (optional), syft (optional), config validity, ~/.repolex/db/ existence, indexed repos. Exits non-zero if any required check fails.

mcp / serve

repolex mcp [names...] [--no-sync]
repolex serve [names...]   # alias

Starts the MCP server over stdio. With no args, serves every .sqlite in ~/.repolex/db/. With one name, single-repo mode (repo arg defaults to it on every tool call). With multiple names, the agent must pass repo on each call.

--no-sync skips the startup auto-pull and disables the periodic background sync (only relevant when shared_index.auto_sync_on_mcp_start is set in config).

You generally won't run this yourself: Claude Code spawns it via the entry written to ~/.claude.json by setup --register-clients or pull --register.

push

repolex push <name> [--path <path>] [--message <msg>]

Checkpoints the WAL, copies ~/.repolex/db/<name>.sqlite to <shared-repo>/db/, writes a manifest with the file's sha256 to <shared-repo>/manifests/, commits and pushes. Only runs in admin / ci roles.

git clone [email protected]:yourorg/repolex-data.git ~/repolex-data
repolex push myapp --path ~/repolex-data
repolex push myapp --path ~/repolex-data --message "myapp index after Q4 schema migration"

pull

repolex pull <name> [--no-register] [--skip-verify]

Fetches/clones the configured shared_index.git_url, verifies the manifest's sha256 matches the cloned SQLite, then atomically swaps it in at ~/.repolex/db/<name>.sqlite.

--register (default off as of 0.6.4) wires the pulled repo into ~/.claude.json. Default-off because a malicious shared-index repo could otherwise inject arbitrary MCP servers into your config on a single pull. Pass --register to opt in.

--skip-verify bypasses the sha256 check. Only use it for known-good pre-0.6.4 shared indexes that don't have a manifest. NOT recommended otherwise.

repolex pull myapp
repolex pull myapp --register     # also write the MCP entry
repolex pull myapp --skip-verify  # legacy escape hatch

sync

repolex sync <name> [--no-fetch]

pull plus a sanity-check SELECT COUNT(*) FROM files. --no-fetch uses the local cached shared dir without hitting git.

remove

repolex remove <name> [--keep-config]

Deletes ~/.repolex/db/<name>.sqlite{,-wal,-shm}, the manifest, the .origin marker, AND the mcpServers[<name>] entry from ~/.claude.json. Pass --keep-config to skip the MCP-entry removal.

Does NOT remove the optional PreToolUse hook (it's project-scoped, not tied to a repo name) or the per-repo CLAUDE.md block (we don't know which on-disk project the DB came from after the SQLite is gone). Edit those by hand.

prune

repolex prune <name>

Removes failed synthesis call rows and orphaned citation rows. Run after a synthesize that aborted mid-batch.

techstack

repolex techstack <name> [--path <path>] [--rebuild] [--no-ai] [--syft-path <path>]

Runs the techstack pipeline: syft SBOM generation (optional, falls back to native parser) > curated map > package registry lookups > optional AI categorization for unknowns.

repolex techstack myapp --path .
repolex techstack myapp --rebuild --no-ai   # skip the AI tier

add

repolex add <name> <snapshot.json> [--path <path>] [--template <t>] [--branch <label>] [--no-claudemd]

Indexes from an existing repomix JSON file. Useful when you've already snapshotted (e.g. in CI) and want to skip the repomix step.

repomix --style json --output snapshot.json .
repolex add myapp snapshot.json --path .

Auto-registering with MCP clients (Claude Code, Cursor, Claude Desktop)

repolex setup --register-clients writes a single consolidated mcpServers.repolex entry into the matching IDE config. The entry has no embedded repo names; repolex serve auto-discovers every .sqlite file under ~/.repolex/db/ at startup, so one entry serves current and future indexed repos. The bare flag targets Claude Code only; pass a comma-separated list to register additional editors:

repolex setup --register-clients                       # Claude Code only
repolex setup --register-clients=cursor,claude-desktop # Cursor + Claude Desktop too
repolex setup --register-clients=all                   # every supported client

Supported clients today: claude-code (~/.claude.json), cursor (~/.cursor/mcp.json), claude-desktop (the platform-specific Claude Desktop config). Each writes the same shape:

{
  "mcpServers": {
    "repolex": {
      "command": "repolex",
      "args": ["serve"],
      "env": {}
    }
  }
}

If a pre-0.6.8 install left per-repo entries (mcpServers.myapp, etc.), they're migrated to the consolidated entry on first run; the migration is one-shot.

Every write is atomic (rename) and creates a .repolex.bak.<timestamp> sibling before any overwrite. The registrar refuses to follow symlinks at the target path, refuses to write through invalid JSON, and validates the repo name to block path-traversal.

--no-register-clients skips the write. In CI / non-TTY environments, the default is also off, and setup prints a one-line stderr notice so you know the entry was NOT written: Skipped Claude Code MCP registration (non-interactive default for CI safety). Re-run with --register-clients to wire repolex into ~/.claude.json after indexing. Suppress by passing --no-register-clients explicitly, or override with --register-clients.

repolex pull <name> --register ensures the consolidated entry exists in Claude Code after a successful pull. The default for pull is off (a malicious shared-index repo could otherwise inject arbitrary MCP entries on a single command).

To undo: repolex remove <name> deletes the index files. The consolidated mcpServers.repolex entry is left in place because it still serves the rest of your indexed repos. To remove the consolidated entry entirely, edit ~/.claude.json by hand. The --keep-config flag is preserved for back-compat with pre-0.6.8 per-repo entries.

To smoke-test the wiring end-to-end without restarting your editor, run repolex hello [name]. It spawns repolex serve in a subprocess and runs initialize + tools/list + prompts/list + a couple of tool calls; exit 0 means the MCP entry will work once Claude Code reloads.

The optional PreToolUse hook

repolex setup --enable-hooks installs an advisory PreToolUse hook into <cwd>/.claude/settings.local.json (or ~/.claude/settings.json with --hooks-scope user). When Claude is about to run grep -r ..., rg ..., or find ... -name ... and an index exists in ~/.repolex/db/, the hook prints a decision: continue payload nudging Claude to try mcp__repolex__search_code or mcp__repolex__find_references first.

It never blocks. Plain grep -v, find -type f, etc. are not matched. The hook never sends data anywhere; it's a local-only stderr advisory.

Kill switch: export REPOLEX_HOOKS=0 silences it without uninstalling. To uninstall, edit <project>/.claude/settings.local.json (or ~/.claude/settings.json) and remove the PreToolUse entry whose command contains the # repolex-hook marker.

AI synthesis (optional)

repolex synthesize runs the 5 reasoning synthesizers. As of 0.8 each one reads a deterministic context built straight from the index (files + symbols), so there is no per-file AI pass and the call count is fixed regardless of repo size.

| Synthesizer | What it produces | Cost shape | |---|---|---| | domains | Business areas (e.g. billing, users) with file lists | Fixed small N, Sonnet | | architecture | High-level repo prose for get_architecture | 1 to a few calls, Sonnet | | endpoints | HTTP routes + their controllers/handlers | Fixed small N, Sonnet | | db_tables | Tables, columns, foreign keys | Fixed small N, Sonnet | | integrations | External services the repo talks to | Fixed small N, Sonnet |

When to run:

  • After the first index, to populate the AI tools (get_architecture, list_domains, list_endpoints, get_db_table, list_integrations)
  • After a meaningful refactor or schema change
  • Not after every refresh (architecture / domains / endpoints don't auto-rerun)

Cost ceilings: --max-cost <usd> aborts when the running total crosses the threshold. Only enforces in anthropic-api and hybrid modes; in claude-code mode all calls report $0 (subscription billing). The fixed 5-call shape costs little either way.

repolex_status MCP tool returns total_cost_usd and pending_synthesis_calls.

Sharing the index with your team

Push the index to a private git repo. Teammates pull a single SQLite (typically 27 to 47 MB; the manifest sidecar is around 1 KB) instead of running another $15 synthesize.

Admin (one person, has API key):

git clone [email protected]:yourorg/repolex-data.git ~/repolex-data
cd ~/code/myapp
repolex setup --mode hybrid --role admin --shared-from [email protected]:yourorg/repolex-data.git --non-interactive
repolex index myapp
repolex synthesize myapp --max-cost 15 --path .
repolex push myapp --path ~/repolex-data

Consumer (everyone else, no API key required):

repolex setup --shared-from [email protected]:yourorg/repolex-data.git --non-interactive
repolex pull myapp --register   # opt in to the MCP entry write
# Restart Claude Code; the new tools are live.

pull integrity check: as of 0.6.4, every shared index has a manifest with the SQLite's sha256 written at push time. repolex pull recomputes the sha and refuses to swap on mismatch (or on a missing manifest). --skip-verify is the escape hatch for legacy unsigned (pre-0.6.4) shared indexes; do not use it as a habit.

Auto-sync: when the MCP server starts, it pulls the latest from the shared repo (set shared_index.auto_sync_on_mcp_start: true in config). It also re-pulls in the background every auto_sync_interval_seconds seconds. The atomic swap means in-flight tool calls finish reading the old DB; new calls land on the new one.

Roles:

  • admin / ci can push
  • consumer cannot push (CLI errors out before touching git)

Privacy and security

  • Local-first by default. Without --mode anthropic-api or hybrid, your code never leaves the machine. Indexing, symbol extraction, and FTS5 search all run locally. The only network calls in default mode are git operations against your own remotes.

  • Auto-ignored at index time, regardless of your .gitignore (as of 0.6.5):

    • .env, .env.local, .env.production, .env.dev (and any .env.* except .env.example, .env.sample, .env.template)
    • .npmrc, .netrc, .pgpass
    • id_rsa*, id_ed25519*
    • *.pem, *.key, *.p12, *.pfx
    • Rails: config/master.key, config/credentials.yml.enc, config/credentials/*.key
    • Cloud: .aws/credentials, service-account*.json, *.kubeconfig

    Even if a secret-shaped file is committed to git, repolex skips it before insert. repolex refresh also removes any previously-indexed files that match these patterns.

  • The PreToolUse hook script (dist/hooks/repolex-hook.js) never sends data anywhere. It's a local stderr advisory.

  • The hook does NOT echo your bash command back to Claude in the systemMessage (closed in 0.6.4 to prevent prompt-injection re-introduction via teammate-crafted commands).

  • Pulled shared indexes are SHA-verified by default. --skip-verify is opt-in.

  • Synthesizer-emitted file paths are validated before SQL insert: .., absolute paths, and non-string entries are dropped.

  • client-registrar and hook-template refuse to write through symlinks (lstat guard before open).

  • Repo names are validated against [a-zA-Z0-9][a-zA-Z0-9_.-]* (max 64 chars) before any path is built from them.

  • git_url values for shared-index repos go through a scheme allowlist before any git clone/git fetch (V-01). Allowed: https://, http://, ssh://, git+ssh://, scp-like (git@host:owner/repo.git). Leading - is rejected (defense against argv injection). The validator rejects exotic schemes like ext:: or file:// outright. Every git invocation also passes the URL after a -- separator as defense in depth. repolex doctor surfaces a [FAIL] shared_index for any pre-V-01 config that points at a now-disallowed URL.

  • REPOLEX_HOME (and the legacy REPODEX_HOME) sandboxes the registrar (V-02). When set, every IDE config the registrar writes lives under that dir instead of the user's home; CI runs and tests that scope REPOLEX_HOME=/tmp/foo no longer accidentally mutate the user's real ~/.claude.json.

If you find a security issue, please open a GitHub issue or contact the author directly.

Where things live

  • ~/.repolex/config.json: global config (AI mode, role, shared_index.git_url)
  • ~/.repolex/db/<name>.sqlite: index + WAL + shm
  • ~/.repolex/db/<name>.sqlite.origin: origin URL marker (collision detection)
  • ~/.repolex/db/<name>.sqlite.manifest: local manifest
  • ~/.repolex/shared/<name>/: cloned shared-index repo (after first pull)
  • ~/.claude.json: MCP entries written by --register-clients
  • <project>/.claude/settings.local.json: PreToolUse hook (project scope)
  • <project>/CLAUDE.md: per-repo block (between <!-- repolex:start --> markers)

Override the home dir: export REPOLEX_HOME=/some/path before any command. The legacy REPODEX_HOME and ~/.repodex paths still work for users who upgraded from pre-0.5.x.

Don't commit ~/.repolex/ to git; commit the shared-index repo, not the home dir.

Troubleshooting

| Symptom | Cause | Fix | |---|---|---| | repolex: command not found | Global npm bin not on PATH | Open a new terminal; check npm bin -g; ensure that dir is in $PATH | | Repository path does not exist: <path> | Bad --path | Pass an absolute path or cd into the repo first | | Repo name "..." is reserved / must start with a letter/digit | Name validator | Use a name matching [a-zA-Z0-9][a-zA-Z0-9_.-]*, max 64 chars | | Repo name "..." already bound to a different origin | Two checkouts colliding on the same name | Use a different positional name OR repolex remove <name> first | | Could not auto-detect a categorization template | No Rails / React-TS signals | Pass --template rails or --template react-ts explicitly | | Detected nextjs but repolex doesn't ship a nextjs template yet | Detector found a framework but no template ships for it | Pass --template react-ts (or rails) explicitly | | No symbol matching "X" from find_symbol | Wrong tool for substring/regex | Try find_references (substring across symbols) or search_code (FTS5 phrase) | | is_stale: true on a synthesizer row | File hash changed since last synthesize | Run repolex refresh <name> then repolex synthesize <name> | | No <X> data yet. Run repolex synthesize | Synthesis hasn't been run for that table | repolex synthesize <name> (costs apply in API/hybrid modes) | | Pulled SQLite SHA does not match manifest | Tampering / partial force-push / mid-flight write | Investigate the shared-index repo; re-push from admin; do NOT --skip-verify blindly | | pull worked but Claude doesn't see the tools | MCP entry missing OR Claude Code wasn't restarted | Pass --register on pull, or run repolex setup --register-clients; restart Claude Code | | Index seems too small | Secret-filter or .gitignore excluding more than expected | Run repolex list <name> to see what landed; check the secret patterns in 0.6.5 | | Auto-config didn't write ~/.claude.json | --register-clients not passed (CI default is off) | Re-run repolex setup --register-clients or repolex pull <name> --register | | Hook doesn't fire | REPOLEX_HOOKS=0 set, OR no .sqlite in ~/.repolex/db/ | unset REPOLEX_HOOKS; ensure repolex_status shows the index | | repolex remove left orphan CLAUDE.md block | Block lives in the source repo, not in ~/.repolex/ | Edit <project>/CLAUDE.md and delete lines between <!-- repolex:start --> ... <!-- repolex:end --> | | --max-cost exceeded mid-synth | The first synthesizer already crossed the ceiling | Inspect synthesis_call_log rows; repolex prune <name>; raise --max-cost | | status shows indexed: false after pull | Manifest verification likely failed; check stderr | Read the stderr line from the failed pull; investigate the shared-index repo | | syft not found warning during techstack | syft binary missing | brew install syft (or skip; the native fallback covers most package managers) | | Cannot push: role is consumer (read-only) | Wrong role in config | repolex setup --role admin --force --non-interactive | | repomix failed for <path> | repomix missing or out of date | npm install -g repomix; verify with repolex doctor |

FAQ

Does this work without an API key? Yes. With --mode claude-code (the default when no ANTHROPIC_API_KEY is set), you get FTS5 search, symbol extraction, file categorization, and 27 MCP tools for free. AI synthesis runs through the local claude CLI's subscription if you have it installed; otherwise just don't run synthesize and the search/symbol tools still work.

Does my code leave my machine? Only when you opt in to --mode anthropic-api or hybrid AND run synthesize. Indexing, refresh, search, and symbol extraction are all local. The PreToolUse hook is local-only.

Will this work with Cursor / Cline / Continue / other MCP clients? The auto-registration path (--register-clients, pull --register, remove) writes to ~/.claude.json (Claude Code only). Other MCP clients can use repolex by pointing them at the repolex serve <name> command manually. The MCP server itself is client-agnostic.

Does it support Python / Go / Rust / Java / ...? All those file types are indexed and searchable via search_code and find_references. Symbol extraction (find_symbol, find_callers) is reliable for Ruby, TypeScript, JavaScript, and partial for Python (top-level only). Other languages return empty symbol tables today.

What's a "domain"? AI-extracted business areas (e.g. billing, users, inventory) with file lists attached. Populated by the domains synthesizer. Use list_domains, deep_dive_domain, list_files_in_domain from the MCP side.

How big does my repo's index grow? From dogfood tests: a 5621-file Rails monorepo produces a 47 MB SQLite; a 2868-file TypeScript app produces 27 MB. The shared push is just the SQLite + a small manifest.

Should I commit ~/.repolex/ to git? No. Commit the shared-index git repo (whatever you set as --shared-from), not your ~/.repolex/ home dir. The home dir is per-machine; the shared-index repo is the team artifact.

What if my repo is on Bitbucket / GitLab / self-hosted git? Auto-naming from the git remote is GitHub-only as of 0.6.3 (github-owner-repo). Other hosts fall through to path.basename, which is fine but unstable across renames. Pass repolex index <name> explicitly for non-GitHub repos.

Does it index node_modules? No. Repomix's snapshot tool ignores node_modules, build artifacts, and standard noise out of the box. You can add more patterns with --ignore "vendor/**,**/__pycache__/**".

How is this different from Sourcegraph / Glean / LSPs? Local-first, no server to install, ships in a single npm install. AI-synthesized architecture/domains/endpoints (no other tool gives Claude a list_domains / get_endpoint). Index ships via git as a single SQLite (27 to 47 MB on the dogfood repos), so onboarding a new dev is repolex pull instead of "wait six hours for it to re-index your monorepo." Trade-off: symbol extraction is pattern-based, not LSP-based, so it's cheaper and works without a language server but is less precise on dynamic constructs.

License

MIT. Copyright 2026 Cris Nahine.

Contributing

Issues and PRs welcome at https://github.com/crisnahine/repolex (currently a private repo; the URL works for users with access).

See also

  • docs/ADVANCED.md: full reference. Every MCP tool with input/output shapes, every CLI flag, edge cases per tool, schema, recovery procedures, performance tuning.
  • CHANGELOG.md: what's new in 0.6.x.