/ljɛ̃/, French for "link"
A local code-health CLI: what's risky to change, and what your change just made worse. 100% local, 100% private.
Lien parses your working tree with Tree-sitter and answers four questions about a change — what is risky to touch, what crossed a complexity threshold, what deterministic signals fire on the diff, and where the hotspots are. There is no server, no database, and nothing to index: every command reads the files on disk when you run it. Point it at a repo and it works.
Full Documentation | Getting Started | How It Works
-
Risk ranking -
lien healthranks functions by complexity × fan-in ÷ test coverage -
Pre-commit gate -
lien deltafails only on NEW complexity threshold crossings, never pre-existing ones -
Deterministic diff signals -
lien reviewflags stale duplicated literals, removed exports, doc drift and more - Complexity analysis - Human-friendly metrics: test paths, mental load, time to understand
- Nothing to set up - No index, no server, no config, no daemon. Install and run
- 100% Local & Private - All analysis happens on your machine; no network calls
-
Fast - Whole-repo parse in seconds;
lien deltain ~50 ms - Free Forever - No API costs, no subscriptions, no network calls at all
- Ecosystem-Aware & Monorepo - Auto-detects 12 ecosystem presets; supports 15+ languages
# 1. Install
npm install -g @liendev/lien
# 2. Run it in any repo
lien healthThat's the whole setup. No editor configuration, no indexing step, no wizard.
lien health # what's risky to change here?
lien delta # did my working tree cross a complexity threshold?
lien review --base main # deterministic signals over my diff
lien complexity # where are the hotspots?| Command | Answers |
|---|---|
lien health |
Which functions are risky to change? (complexity × fan-in ÷ test coverage) |
lien delta |
Did this change push a function over a threshold it was under before? |
lien review |
What deterministic signals fire on this diff? |
lien complexity |
Where is the tech debt? |
lien delta is the one built to sit in a pre-commit hook or CI: it exits non-zero
only for a function that crossed a threshold it was under at the base commit.
Touching or improving a pre-existing violation never fails it.
Previous versions shipped an MCP server, a persisted SQLite index and FTS5 lexical search. All three have been removed, along with
lien serve,lien index, and thesearch_code/get_files_context/get_dependents/list_functions/find_similar/get_complexitytools. An editor configured againstlien servewill fail to start it. The structural questions Lien still answers, it answers by parsing on demand.
Lien tracks code complexity with human-friendly outputs:
- Test paths - Cyclomatic complexity as "needs ~X tests for full coverage"
- Mental load - Cognitive complexity with nesting penalty
- Time to understand - Halstead effort as readable duration (~2h 30m)
- Estimated bugs - Halstead prediction (Effort^(2/3) / 3000)
- Installation - npm, npx, or local setup
- Getting Started - Your first run
- Configuration - Complexity thresholds
- CLI Commands - Full command reference
- How It Works - Architecture overview
TypeScript • JavaScript • Vue • Python • PHP • Liquid • Go • Rust • Java • C/C++ • Ruby • Swift • Kotlin • C# • Scala • Markdown • YAML
Ecosystem Presets: 12 ecosystem presets including Node.js, Python, PHP, Laravel, Ruby, Rails, Rust, JVM, Swift, .NET, Django, and Astro (auto-detected)
Contributions welcome! See CONTRIBUTING.md for guidelines.
- Issues - Report bugs or request features
- Discussions - Ask questions and share ideas
AGPL-3.0 © Alf Henderson
Lien is free forever for local use. The AGPL-3.0 license requires that anyone who distributes a modified version release its source under the same terms. For licensing questions, contact alf@lien.dev.