Claude Code Plugin
Installing Lien as a Claude Code plugin gets you more than an MCP config. Two PostToolUse hooks push structural context and complexity accounting into the agent's next turn automatically — after a read, before a commit — without the agent having to ask, and without depending on it remembering to. This page covers what ships and what each hook actually does.
Install
/plugin marketplace add getlien/lien
/plugin install lienThat's it — no npm install, no lien init, no per-project .mcp.json. The plugin's MCP server launches on demand via npx -y @liendev/lien@latest serve, which always resolves against the npm registry, so it runs the latest published release even if you have a local npm link or workspace copy of @liendev/lien on the machine. First use in a new git repo triggers a one-time index automatically.
Working on Lien itself?
Don't install this plugin in Lien's own dev environment — it points the MCP server at the published npm binary, bypassing your local build. See CONTRIBUTING.md for the dogfooding setup that points at your local build instead.
This is Claude Code-specific. For other MCP-compatible editors (Cursor, Windsurf, OpenCode, Kilo Code, Antigravity), see the installation guide.
What you get
MCP tools
search_code, get_files_context, get_dependents, list_functions, get_complexity, and find_similar all become available with no server to configure. See the MCP Tools reference for parameters and response shapes.
The read hook — structural context before you edit
annotate-read.sh fires on PostToolUse:Read. When the file you just read has non-trivial blast radius, it injects a short impact summary as additionalContext — the one hook output channel verified to actually reach the model on its next turn (a bare systemMessage does not). A real example, captured live in this session:
Lien impact for packages/cli/src/cli/annotate-cmd.ts:
• 2 files import this — packages/cli/src/cli/index.ts, packages/cli/src/cli/annotate-cmd.test.ts; risk: medium (2 callers, 1 untested).
• Test coverage: packages/cli/src/cli/annotate-cmd.test.ts.It reports dependent count and blast-radius risk (with reasoning), test coverage, and — when present — a complexity warning (max cyclomatic complexity and how many functions in the file are over the warn threshold). It stays silent when impact is trivial (0-1 dependents, no complexity warnings, existing test coverage), and it won't repeat for the same file within a session for a TTL (default 5 minutes, LIEN_ANNOTATE_TTL_MIN). The effect is that you see who depends on a file and how well it's tested before you touch it, without having to call get_files_context yourself.
The write gate — lien delta on every edit
delta-write.sh fires on PostToolUse:Edit|Write|MultiEdit. It runs lien delta --file <path> --format json and warns only when that specific edit pushed a function to a new complexity-threshold crossing — a function that was under a cyclomatic/cognitive/Halstead threshold before and is now over it, or a brand-new function that starts out over. It's silent for everything else: improvements, pre-existing violations, or worsened-but-still- under movement. The underlying delta computation is a ~50ms deterministic check (no LLM call); the hook's own end-to-end latency, including CLI process startup, measures ~215ms warm / ~410ms cold — well under its 5s timeout.
⚠ lien delta: extractSymbols cognitive 12→29 (threshold 15) — consider simplifying before you commit.This drives the exact same primitive that backs the lien delta CLI gate, so the hook's verdict and the command's verdict can never disagree. Because the warning lands via additionalContext, it reaches the agent on its very next turn — while the change is still in hand, not after a PR review catches it later. Disable with LIEN_DELTA_HOOK=off.
Explore-agent nudge
A third hook (PreToolUse:Agent|Task) appends a short Lien-tool mandate to the prompt whenever Claude Code launches its built-in Explore subagent — subagents start with a fresh prompt and don't inherit the parent session's instructions, so this is the only channel available to reach them. It's a no-op if the repo has no index yet, or if the prompt already names a Lien MCP tool. The plugin doesn't ship its own Explore agent definition — this targets Claude Code's built-in Explore subagent (or one installed the legacy way via lien init --legacy).
Why hooks, not CLAUDE.md rules
A rule written into CLAUDE.md only helps if the agent remembers to follow it, and that gets less reliable as a session's context fills up. A PostToolUse hook fires deterministically on every matching tool call, regardless of what's still in context. Lien's own CLAUDE.md notes that this hook pair automates two of its own MANDATORY policies — checking file context before an edit, and running lien delta before a commit — which is also why the plugin runs on Lien's own development, not just its users' repos.
Configuration
Every hook is best-effort: a missing lien/jq, an unindexed repo, or any internal error exits silently rather than blocking your tool call.
| Env var | Effect |
|---|---|
LIEN_ANNOTATE_TTL_MIN | Read-hook suppression window in minutes (default 5) |
LIEN_DELTA_HOOK=off | Disables the write-time complexity gate |
LIEN_EXPLORE_INJECT=off | Disables the Explore-agent prompt nudge |
Updating
Installed plugins are commit-pinned snapshots (~/.claude/plugins/cache/lien/lien/<commit>/) — merging a change into this repo does not update a session that already installed the plugin. Run /plugin update lien, or if that errors, /plugin uninstall lien@lien then /plugin install lien@lien to force a fresh snapshot.