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

find-refs

v0.1.1

Published

Exhaustive, position-based cross-file find-references via the language server (TypeScript/JavaScript + Python). Waits for project load before answering, so a cold run never silently undercounts.

Readme

find-refs

Exhaustive, exact cross-file find-references for a symbol, driven by the real language server — not a textual heuristic. You give it a file and a 1-based caret position; it returns every reference to the symbol under that caret, across the whole project.

Supported languages:

The language servers and the TypeScript compiler are bundled as dependencies of this package. npm install reproduces a working toolchain resolved from this package's own node_modules — independent of the global engine install and the node version in use, so it survives a node version bump and is transferable to another machine. (It still needs a node on PATH: the bundled servers run on Node — their shebang is #!/usr/bin/env node.)

Why this exists

The off-the-shelf options for a scriptable "find all references" all have a gap:

  • lsp-cli is archived, and it returns cold results — it queries the server before project indexing finishes, so it can confidently undercount.
  • MCP-only language tools can't be called from a plain shell / script.
  • SCIP indexes are great for storage but ship no references-query CLI — you'd build the query layer yourself.
  • ctags / grep-ast / ripgrep are textual: they match by name, so they miss aliased imports and renamed re-exports, and they over-match unrelated symbols that share a name.

This tool is position-based (it asks the server about the symbol at an exact caret, not a name string) and it waits for the project to finish loading before it trusts the answer — closing the cold-undercount hole that the naive approaches share.

Install

npm install -g find-refs      # puts `find-refs` on your PATH

Or run it without installing:

npx find-refs <file> <line> <col>

Or from source:

git clone https://github.com/rahimi/find-refs.git
cd find-refs && npm install && npm install -g .

Usage

find-refs <file> <line> <col>
  • line and col are 1-based.
  • col is the caret on the symbol (point it at the identifier you care about). Most editors show line:col in the status bar; pointing at the symbol's declaration works well. You can query from any reference too — the result is the same set.

Output:

  • stdout — one reference per line, as path:line:col (paths relative to the detected project root, sorted).
  • stderr — a one-line summary: N references in M files via SERVER (ready=…, Xs) and, if relevant, an environment warning.

Example:

$ find-refs src/concierge/state.ts 180 14
src/concierge/state.ts:180:14
...
# stderr: 87 references in 10 files  via typescript-language-server  (ready=progress, 4.2s)

The project root is auto-detected by walking up for tsconfig.json / package.json (TS/JS) or pyrightconfig.json / pyproject.toml / setup.py / setup.cfg (Python), falling back to the nearest .git then the file's directory.

Behavior notes

The readiness gate prevents cold undercount. Before reading references, the tool waits for the server's project-load signal — a $/progress beginend cycle. For tsserver this means advertising capabilities.window.workDoneProgress and answering the server's window/workDoneProgress/create request, so the "Initializing" progress fires; for Python it settles and falls back if no progress is reported. It then polls until the reference count is stable across two consecutive queries. The summary's ready= field tells you which path was taken (progress, no-progress, or timeout).

The env-guard keeps a partial result from lying. References silently undercount when the project can't resolve its own imports (an uninstalled repo). When the environment looks absent — no node_modules for a JS/TS project, no .venv/venv/.tox/$VIRTUAL_ENV for Python — the tool prints a warning to stderr. It never blocks; a normal installed project produces no warning, so the warning's presence is meaningful.

TypeScript lib resolution. For tsserver, the tool prefers the target repo's node_modules/typescript/lib/tsserver.js (so it analyzes with the project's own TypeScript version), and falls back to this package's bundled typescript otherwise.

Adding a language

The dispatch lives in one place in find-refs.mjs (the ext === … block). To add a language:

  1. Add the language server as a dependency in package.json (so it lands in node_modules/.bin and is bundled).
  2. Add an extension branch that sets ROOT (root-marker detection), SERVER (resolveServer("<bin-name>")), SERVER_NAME, and the LSP LANGID.
  3. If the server needs an env to resolve imports, extend the env-health guard so a partial result still warns.

Everything else — the LSP handshake, the readiness gate, the references query, and the output format — is language-agnostic and unchanged.

Using it with an AI coding agent (Claude Code)

find-refs is built to be an agent tool: it gives the agent exact references where grep is a fuzzy proxy that can silently miss a call site. Three small bits of wiring make an agent actually reach for it.

1. Allowlist it so it never prompts — in ~/.claude/settings.json:

{ "permissions": { "allow": ["Bash(find-refs *)"] } }

2. Make the agent aware it exists — a line in your CLAUDE.md:

find-refs <file> <line> <col> returns a symbol's exact cross-file references (TS/JS + Python) — exhaustive where grep is fuzzy, which misses call sites.

3. Nudge at the moment of reach (optional, the strongest anchor) — a PreToolUse hook on the Grep tool. When the agent greps a bare identifier inside a code repo, the hook injects a one-line "prefer find-refs for exact references" note via hookSpecificOutput.additionalContext (exit 0 — it never blocks the grep). Keep it smart so it isn't noisy: only fire on identifier-shaped patterns, gate to repos with a tsconfig.json / package.json / pyproject.toml, and debounce per-symbol per session. Register it:

{ "hooks": { "PreToolUse": [
  { "matcher": "Grep", "hooks": [
    { "type": "command", "command": "~/.claude/hooks/grep-to-nav.sh" } ] } ] } }

License

MIT — see LICENSE.