# 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:
1) 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.
2) 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:
```rust
use std::collections::HashSet;
use std::path::PathBuf;
use cruxlines::{cruxlines, Ecosystem};
let repo_root = PathBuf::from(".");
let ecosystems = HashSet::from([Ecosystem::Python, Ecosystem::JavaScript]);
let rows = cruxlines(&repo_root, &ecosystems)?;
```
## 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:
```
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.