repopick
Offline · Deterministic · Zero dependencies

Pick the files
that matter.

Every other tool in this space packs your whole repository into one giant prompt. repopick does the opposite: give it a task in plain English and it returns the smallest set of files that actually answers it — ranked, explained, and capped to a budget you choose.

Quickstart

No config file. No index build. No API key. One command.

Run it without installing

npx repopick . --task "fix the checkout bug"

Or install it globally

npm install -g repopick

repopick ~/code/my-app --task "how does payments work" --format md --out context.md

Then feed the digest to your model

# context.md now contains only the files that matter, in dependency order,
# with each file's reason for being there written at the top.
5-minute check: clone any repository, run npx repopick . --task "what does this project do" --top 15, and read the ranked list at the top of the output. If the first five files aren't the ones you'd open first, tell us — that is a bug report we care about.

How it works

Seven stages. All local. All deterministic. Same input, same answer, every time.

Walk, parse, graph, PageRank, rank, budget, output
The pipeline. No network calls, no embeddings, no API keys at any stage.
  1. WalkWalks the tree, honours .gitignore plus .repopickignore, skips vendored code, lockfiles, binaries and build output.
  2. ParseExtracts imports and top-level symbols with regexes — no tree-sitter, no native builds. Works across JavaScript/TypeScript, Python, Go, Rust, Ruby, Java, C/C++, PHP and more.
  3. GraphBuilds a repository-wide import graph and resolves relative, extensionless, aliased, Python-relative and cross-package imports.
  4. PageRankRuns PageRank over the graph so files that many modules depend on rise to the top.
  5. RankBlends PageRank, task-keyword matching, distance from an entry point, git recency and per-kind weights (tests, docs and styles are down-weighted unless you asked for them).
  6. BudgetGreedily fills a token ceiling — default 32,000 tokens, estimated at 4 characters per token.
  7. OutputText, Markdown, JSON or a self-contained HTML context card.

Why this is different

Task-conditioned

Most tools need you to hand-write globs. repopick takes a sentence and ranks by relevance to it.

Explainable

Every selected file carries its reason: entry point, imported by 104 files, matches task. You can audit the selection.

Zero dependencies

Plain ES modules on the Node you already have. A tool you npx once should not install a tree.

Output formats

One selection, four ways to consume it.

FormatCommandUse it for
textrepopick . --task "..."A ranked table in the terminal. Default.
mdrepopick . --format md --out context.mdA prompt-ready digest with file contents.
jsonrepopick . --format jsonMachine-readable selection for agents and CI.
htmlrepopick . --format html --out card.htmlA shareable context card. No JS, no remote assets.
The repopick HTML context card showing files selected, tokens and context reduction
The HTML card: a real screenshot of generated output, not a mockup.

CLI reference

Everything the tool accepts.

FlagDescriptionDefault
[path]Repository to analyse.
-t, --task <text>Free-text task; boosts keyword-matching filesnone
-b, --budget <n>Token budget for the selection32000
-n, --top <n>Maximum files to select40
-f, --format <fmt>text | md | json | htmltext
-o, --out <file>Write to a file instead of stdoutstdout
-e, --explainShow why each file was pickedoff
--entry <path>Force a file to be an entry point (repeatable)
--kinds <list>Restrict to source,test,config,docs,style,markupall
--tokens-per-char <n>Token estimate divisor (0.25 = 4 chars/token)0.25
--no-gitIgnore git metadata (no recency boost)off
--no-contentsMarkdown only: omit file bodiesoff

Configuration

There is exactly one thing to configure, and it is optional.

.repopickignore

Same syntax as .gitignore. Use it for files that live in the repository but should never be sent to a model: fixtures, snapshots, vendored code, generated data.

# .repopickignore
fixtures/
test/
docs/snapshots/
*.min.js

Token estimation

Sizes are estimated as bytes × 0.25 — roughly four characters per token. If your model tokenises differently, change the divisor:

repopick . --task "..." --tokens-per-char 0.3 --budget 8000

Using it with an agent

Produce a JSON selection and hand it to a tool-using agent, or generate a Markdown digest and paste it into any chat model.

repopick . --task "$TASK" --format json --out selection.json
repopick . --task "$TASK" --format md   --out context.md

FAQ

Does it send my code anywhere?

No. repopick never opens a network connection. It reads the files you point it at and writes the output you ask for — nothing else.

Why regex parsing instead of tree-sitter?

Native grammars are a real barrier to install and to contribute to. Regex extraction is good enough for ranking, and it means the tool works on languages nobody has written a grammar for yet.

Is the output reproducible?

Yes, by design. The same repository and the same flags produce byte-identical output. Determinism is enforced by tests and by CI, because a context tool you can't reproduce is a context tool you can't trust.

It selected something useless — can I fix it?

Yes: add the file or directory to .repopickignore, or narrow the run with --kinds. If a whole category is mis-ranked, that is a ranking bug worth an issue.

Does it work on monorepos?

Yes. It resolves relative, aliased and cross-package imports, and falls back to basename matching when an alias can't be resolved.

Which Node versions are supported?

Node.js 18 and later. CI runs the test suite on Node 18, 20 and 22.

Troubleshooting

“It picked every file”

Your repository is small relative to the budget, so everything fit. Lower the budget (--budget 4000) or the cap (--top 10).

“The wrong module came up first”

Make the task more specific — include the domain word that appears in the file names or symbol names. --entry src/your/module.ts forcibly anchors the ranking.

“Numbers look wrong for my model”

Token counts are estimates. Tune with --tokens-per-char.

“Nothing was ignored”

Check that your .repopickignore is at the repository root you passed to repopick, not a parent directory.

Exit codes

CodeMeaning
0Success
1Runtime error (path not found, not a directory, analysis failed)
2Usage error (unknown flag, unknown format, bad value)