cruxlines
cruxlines analyzes a codebase and ranks symbol definitions by how often they are referenced, with a bias toward references coming from "hot" files. It outputs quickfix-friendly lines for jumping to definitions.
What it does
- Parses source files with tree-sitter.
- Finds definitions and references across files.
- Builds a file-level reference graph and computes a file rank.
- Weights references by file rank and git frecency.
- Outputs one line per definition.
How it works
cruxlines works in two layers:
-
File graph
- A file-level graph is built from usage file -> definition file edges.
- PageRank is computed on this small graph to get a per-file rank.
-
Definition scoring
- Each definition gets a local score based on how many references it has.
- References are weighted by the rank of the file they come from.
- If a name is defined multiple times, the score is divided by the number of definitions to reduce name-collision noise.
- Final score = local_score * file_rank(definition_file).
The output includes all components so you can interpret the score.
Heuristics (and why)
The goal is to keep logic simple and avoid heavy per-language semantics:
- Python: only top-level definitions/assignments (importable symbols).
- JavaScript/TypeScript: only exported declarations (importable symbols).
- Rust: only top-level items (importable symbols).
- References are name-based, which is fast and language-agnostic.
- Name collisions are smoothed by splitting score across same-name definitions.
These heuristics are not semantically perfect, but they keep complexity low while producing useful rankings.
CLI usage
Analyze the current repo (run from the repo root):
cruxlines
Filter by ecosystem (defaults to all):
cruxlines --ecosystem python
Shorthand aliases are supported (py, js, ts, tsx, rs):
cruxlines -e py
Java/Kotlin use the java ecosystem (alias jvm):
cruxlines -e java
Include score metadata in the output:
cruxlines --metadata
Library usage
Use the library API by passing a repo root and selected ecosystems:
use HashSet;
use PathBuf;
use ;
let repo_root = from;
let ecosystems = from;
let rows = cruxlines?;
Output format
Each line matches the Vim quickfix format and includes the definition line:
path:line:col: <line>
With --metadata, the message includes the scoring fields:
path:line:col: rank=... local=... file=... name=... | <line>
Reference detection is heuristic and may include false positives.
Supported languages
- Java (
.java) - Python (
.py) - JavaScript (
.js,.jsx) - TypeScript (
.ts,.tsx) - Kotlin (
.kt,.kts) - Rust (
.rs)
Git ignore behavior
- Directory scans respect gitignore and common ignore files.
Repo root
cruxlines expects to run from the repository root (a directory with .git) and
always scans the whole repo.
Notes
cruxlines uses git history to compute frecency for files via the frecenfile
crate. If no git repository is found, frecency defaults to neutral weighting.