Install and annotate one function
Install GuardLink, annotate a single function, and finish with a threat model that validates clean in CI.
GuardLink keeps a threat model inside the repository it describes. You write the model as annotations in your source, anchored to real code positions, and guardlink parses them into a live model it can validate, diff, and export.
Under the hood it reads a small annotation language called GAL. You declare assets, threats, controls, and actors, then state how they relate: this asset is exposed to that threat, here; this control mitigates it; this risk is accepted and why. Because the statements sit beside the code they describe, they travel with it when it moves.
The problem that solves is rot. A threat model written as a document is accurate
on the day it is signed off and decays from then on: the code moves, the document
does not, and nobody finds out until an incident. Annotations decay too, but they
decay visibly. When an anchored block no longer sits on the symbol it names,
guardlink ci reports the drift, guardlink reanchor repairs the ones whose
symbol still exists, and what is left needs a human precisely because the
function it described is gone. See
why annotations live in code.
npm install guardlink@2.0.0Take a login handler that reads from the database. One line above it records what is at stake:
// @exposes api.auth to SQL Injection [high] cwe:CWE-89When someone adds input validation, a second line closes it:
// @mitigates api.auth against SQL Injection using Input ValidationNothing here is inferred. A person stated both, git dates and attributes them,
and guardlink ci reports the exposure for as long as the first line stands
without the second. Move the handler to another file and both lines move with it.
npx guardlink gal prints the whole language with an example per verb, which is
the fastest reference while you are writing annotations.
Once the annotations are in place, one model feeds several consumers.
flowchart TB
SRC["annotations in your source<br/>@exposes, @mitigates, @confirmed"] --> P["guardlink parse"]
P --> M["the threat model<br/>.guardlink/model.json"]
M --> CI["guardlink ci<br/>open exposures, drifted anchors"]
M --> EX["sarif, report, dashboard, diff"]
M --> AG["MCP server<br/>an agent reads and extends it"]
class M emphasis
| Output | Command | For |
|---|---|---|
| The model as JSON | guardlink parse |
Anything that wants to read the model directly |
| A CI gate | guardlink ci |
Failing a build on unmitigated exposures and drifted anchors |
| SARIF 2.1.0 | guardlink sarif |
GitHub Advanced Security, VS Code |
| A report with a Mermaid diagram | guardlink report |
A human reading the model |
| An interactive HTML dashboard | guardlink dashboard |
Browsing the model and its diagrams |
| What changed since a git ref | guardlink diff |
Reviewing a pull request |
| What you are doing | Reach for | Why |
|---|---|---|
| Recording what a piece of code puts at risk | @exposes and @mitigates in source |
The statement is dated by git and attributable, and it moves with the code |
| Gating a build on the model | guardlink ci |
Advisory by default, and --strict makes it fail |
| Finding annotations that drifted off their symbol | guardlink reanchor |
Reports @source blocks whose file:line no longer holds the symbol they name |
| Feeding a code-scanning pipeline | guardlink sarif |
Standard SARIF, so existing tooling reads it without adapters |
| Handing the model to a coding agent | guardlink mcp |
An agent reads and extends the model instead of inferring one |
| Testing whether an exposure is real | cxg pentest | guardlink states the hypothesis, cxg tries to confirm it at runtime |
| Reading the model from your own code | The library API | Seven subpath exports, from the published TypeScript declarations |
Three things surprise people. Each one is covered in full elsewhere.
Install and annotate one function
Install GuardLink, annotate a single function, and finish with a threat model that validates clean in CI.
Annotate a real repository
Vocabulary first, then the seams, then a gate that catches drift.
Give an agent the model
Wire the MCP server into a coding agent: 24 tools and 3 resources over stdio.
Understand the trade
What annotations buy over a threat-model document, and what guardlink never checks.
These pages describe GuardLink 2.0.0, the current release on npm. Every command shown was run against that version and its real output pasted in.
Each of the three references is produced from the installed package: its
--help output, its shipped .d.ts files, and its running MCP server. None of
them can claim a behaviour the release does not have.
| Reference | Covers |
|---|---|
| CLI reference | Both executables, guardlink and guardlink-mcp |
| API reference | The seven subpath exports, from the published TypeScript declarations |
| MCP tool reference | Every tool and resource the MCP server registers |
The major version is scoped to the TypeScript type surface and the threat-model JSON schema. No CLI command, flag, or output behaviour was removed, so CLI and MCP users upgrade with no migration.
| Change | Affects |
|---|---|
coverage reshaped to {annotation_count, coverage_percent} |
Anything reading total_symbols, annotated_symbols, or unannotated_critical. See the artifact page |
Model schema 1.1.0 to 1.2.0, report schema 1.0.0 to 1.1.0 |
guardlink merge warns on a mixed-version set and normalises the old shape |
UnannotatedSymbol removed from the type surface |
TypeScript consumers |
New unknown-verb diagnostic |
A misspelled verb now warns instead of vanishing |
Every diagnostic carries a machine-readable code |
Consumers classifying diagnostics. Twelve codes are defined |
| Version reporting corrected | SARIF tool.driver.version reported 1.4.3 regardless of the installed version. It now reports the real one |
guardlink-mcp --help and --version |
Both previously started the server and blocked |
parse --no-pretty |
Compact single-line JSON, which had no flag before |
report --format <bogus> now exits 1 |
Previously wrote nothing and exited 0 |