guardlink 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (172) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/LICENSE +21 -0
  3. package/README.md +344 -0
  4. package/dist/agents/config.d.ts +46 -0
  5. package/dist/agents/config.d.ts.map +1 -0
  6. package/dist/agents/config.js +189 -0
  7. package/dist/agents/config.js.map +1 -0
  8. package/dist/agents/index.d.ts +24 -0
  9. package/dist/agents/index.d.ts.map +1 -0
  10. package/dist/agents/index.js +42 -0
  11. package/dist/agents/index.js.map +1 -0
  12. package/dist/agents/launcher.d.ts +54 -0
  13. package/dist/agents/launcher.d.ts.map +1 -0
  14. package/dist/agents/launcher.js +152 -0
  15. package/dist/agents/launcher.js.map +1 -0
  16. package/dist/agents/prompts.d.ts +14 -0
  17. package/dist/agents/prompts.d.ts.map +1 -0
  18. package/dist/agents/prompts.js +120 -0
  19. package/dist/agents/prompts.js.map +1 -0
  20. package/dist/analyze/index.d.ts +80 -0
  21. package/dist/analyze/index.d.ts.map +1 -0
  22. package/dist/analyze/index.js +306 -0
  23. package/dist/analyze/index.js.map +1 -0
  24. package/dist/analyze/llm.d.ts +52 -0
  25. package/dist/analyze/llm.d.ts.map +1 -0
  26. package/dist/analyze/llm.js +295 -0
  27. package/dist/analyze/llm.js.map +1 -0
  28. package/dist/analyze/prompts.d.ts +14 -0
  29. package/dist/analyze/prompts.d.ts.map +1 -0
  30. package/dist/analyze/prompts.js +205 -0
  31. package/dist/analyze/prompts.js.map +1 -0
  32. package/dist/analyzer/index.d.ts +5 -0
  33. package/dist/analyzer/index.d.ts.map +1 -0
  34. package/dist/analyzer/index.js +5 -0
  35. package/dist/analyzer/index.js.map +1 -0
  36. package/dist/analyzer/sarif.d.ts +84 -0
  37. package/dist/analyzer/sarif.d.ts.map +1 -0
  38. package/dist/analyzer/sarif.js +149 -0
  39. package/dist/analyzer/sarif.js.map +1 -0
  40. package/dist/cli/index.d.ts +25 -0
  41. package/dist/cli/index.d.ts.map +1 -0
  42. package/dist/cli/index.js +821 -0
  43. package/dist/cli/index.js.map +1 -0
  44. package/dist/dashboard/data.d.ts +52 -0
  45. package/dist/dashboard/data.d.ts.map +1 -0
  46. package/dist/dashboard/data.js +93 -0
  47. package/dist/dashboard/data.js.map +1 -0
  48. package/dist/dashboard/diagrams.d.ts +25 -0
  49. package/dist/dashboard/diagrams.d.ts.map +1 -0
  50. package/dist/dashboard/diagrams.js +243 -0
  51. package/dist/dashboard/diagrams.js.map +1 -0
  52. package/dist/dashboard/generate.d.ts +17 -0
  53. package/dist/dashboard/generate.d.ts.map +1 -0
  54. package/dist/dashboard/generate.js +1258 -0
  55. package/dist/dashboard/generate.js.map +1 -0
  56. package/dist/dashboard/index.d.ts +7 -0
  57. package/dist/dashboard/index.d.ts.map +1 -0
  58. package/dist/dashboard/index.js +7 -0
  59. package/dist/dashboard/index.js.map +1 -0
  60. package/dist/diff/engine.d.ts +51 -0
  61. package/dist/diff/engine.d.ts.map +1 -0
  62. package/dist/diff/engine.js +153 -0
  63. package/dist/diff/engine.js.map +1 -0
  64. package/dist/diff/format.d.ts +10 -0
  65. package/dist/diff/format.d.ts.map +1 -0
  66. package/dist/diff/format.js +111 -0
  67. package/dist/diff/format.js.map +1 -0
  68. package/dist/diff/git.d.ts +24 -0
  69. package/dist/diff/git.d.ts.map +1 -0
  70. package/dist/diff/git.js +85 -0
  71. package/dist/diff/git.js.map +1 -0
  72. package/dist/diff/index.d.ts +7 -0
  73. package/dist/diff/index.d.ts.map +1 -0
  74. package/dist/diff/index.js +7 -0
  75. package/dist/diff/index.js.map +1 -0
  76. package/dist/index.d.ts +20 -0
  77. package/dist/index.d.ts.map +1 -0
  78. package/dist/index.js +17 -0
  79. package/dist/index.js.map +1 -0
  80. package/dist/init/detect.d.ts +42 -0
  81. package/dist/init/detect.d.ts.map +1 -0
  82. package/dist/init/detect.js +185 -0
  83. package/dist/init/detect.js.map +1 -0
  84. package/dist/init/index.d.ts +39 -0
  85. package/dist/init/index.d.ts.map +1 -0
  86. package/dist/init/index.js +228 -0
  87. package/dist/init/index.js.map +1 -0
  88. package/dist/init/picker.d.ts +32 -0
  89. package/dist/init/picker.d.ts.map +1 -0
  90. package/dist/init/picker.js +105 -0
  91. package/dist/init/picker.js.map +1 -0
  92. package/dist/init/templates.d.ts +25 -0
  93. package/dist/init/templates.d.ts.map +1 -0
  94. package/dist/init/templates.js +263 -0
  95. package/dist/init/templates.js.map +1 -0
  96. package/dist/mcp/index.d.ts +12 -0
  97. package/dist/mcp/index.d.ts.map +1 -0
  98. package/dist/mcp/index.js +18 -0
  99. package/dist/mcp/index.js.map +1 -0
  100. package/dist/mcp/lookup.d.ts +27 -0
  101. package/dist/mcp/lookup.d.ts.map +1 -0
  102. package/dist/mcp/lookup.js +282 -0
  103. package/dist/mcp/lookup.js.map +1 -0
  104. package/dist/mcp/server.d.ts +41 -0
  105. package/dist/mcp/server.d.ts.map +1 -0
  106. package/dist/mcp/server.js +388 -0
  107. package/dist/mcp/server.js.map +1 -0
  108. package/dist/mcp/suggest.d.ts +35 -0
  109. package/dist/mcp/suggest.d.ts.map +1 -0
  110. package/dist/mcp/suggest.js +268 -0
  111. package/dist/mcp/suggest.js.map +1 -0
  112. package/dist/parser/comment-strip.d.ts +15 -0
  113. package/dist/parser/comment-strip.d.ts.map +1 -0
  114. package/dist/parser/comment-strip.js +76 -0
  115. package/dist/parser/comment-strip.js.map +1 -0
  116. package/dist/parser/index.d.ts +10 -0
  117. package/dist/parser/index.d.ts.map +1 -0
  118. package/dist/parser/index.js +9 -0
  119. package/dist/parser/index.js.map +1 -0
  120. package/dist/parser/normalize.d.ts +22 -0
  121. package/dist/parser/normalize.d.ts.map +1 -0
  122. package/dist/parser/normalize.js +42 -0
  123. package/dist/parser/normalize.js.map +1 -0
  124. package/dist/parser/parse-file.d.ts +18 -0
  125. package/dist/parser/parse-file.d.ts.map +1 -0
  126. package/dist/parser/parse-file.js +68 -0
  127. package/dist/parser/parse-file.js.map +1 -0
  128. package/dist/parser/parse-line.d.ts +21 -0
  129. package/dist/parser/parse-line.d.ts.map +1 -0
  130. package/dist/parser/parse-line.js +230 -0
  131. package/dist/parser/parse-line.js.map +1 -0
  132. package/dist/parser/parse-project.d.ts +31 -0
  133. package/dist/parser/parse-project.d.ts.map +1 -0
  134. package/dist/parser/parse-project.js +281 -0
  135. package/dist/parser/parse-project.js.map +1 -0
  136. package/dist/report/index.d.ts +6 -0
  137. package/dist/report/index.d.ts.map +1 -0
  138. package/dist/report/index.js +6 -0
  139. package/dist/report/index.js.map +1 -0
  140. package/dist/report/mermaid.d.ts +15 -0
  141. package/dist/report/mermaid.d.ts.map +1 -0
  142. package/dist/report/mermaid.js +260 -0
  143. package/dist/report/mermaid.js.map +1 -0
  144. package/dist/report/report.d.ts +16 -0
  145. package/dist/report/report.d.ts.map +1 -0
  146. package/dist/report/report.js +211 -0
  147. package/dist/report/report.js.map +1 -0
  148. package/dist/tui/commands.d.ts +42 -0
  149. package/dist/tui/commands.d.ts.map +1 -0
  150. package/dist/tui/commands.js +1216 -0
  151. package/dist/tui/commands.js.map +1 -0
  152. package/dist/tui/config.d.ts +27 -0
  153. package/dist/tui/config.d.ts.map +1 -0
  154. package/dist/tui/config.js +27 -0
  155. package/dist/tui/config.js.map +1 -0
  156. package/dist/tui/format.d.ts +63 -0
  157. package/dist/tui/format.d.ts.map +1 -0
  158. package/dist/tui/format.js +253 -0
  159. package/dist/tui/format.js.map +1 -0
  160. package/dist/tui/index.d.ts +18 -0
  161. package/dist/tui/index.d.ts.map +1 -0
  162. package/dist/tui/index.js +470 -0
  163. package/dist/tui/index.js.map +1 -0
  164. package/dist/tui/input.d.ts +63 -0
  165. package/dist/tui/input.d.ts.map +1 -0
  166. package/dist/tui/input.js +454 -0
  167. package/dist/tui/input.js.map +1 -0
  168. package/dist/types/index.d.ts +254 -0
  169. package/dist/types/index.d.ts.map +1 -0
  170. package/dist/types/index.js +6 -0
  171. package/dist/types/index.js.map +1 -0
  172. package/package.json +97 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,30 @@
1
+ # Changelog
2
+
3
+ All notable changes to GuardLink CLI will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [1.0.0] — 2026-02-21
9
+
10
+ Initial public release of GuardLink.
11
+
12
+ ### Added
13
+
14
+ - **Parser**: 16 annotation types, 25+ comment styles, v1 backward compatibility
15
+ - **Parser**: External reference support (cwe, capec, owasp), severity levels
16
+ - **Analyzer**: Coverage statistics, dangling ref detection, duplicate ID detection
17
+ - **Analyzer**: SARIF 2.1.0 export for GitHub/GitLab Security tab
18
+ - **Analyzer**: Suggestion engine with 14 patterns for common security scenarios
19
+ - **Diff**: Threat model comparison between git refs, change classification
20
+ - **Report**: Markdown report with executive summary and Mermaid DFD diagram
21
+ - **Report**: Compact diagram mode for high-exposure codebases
22
+ - **Init**: Project initialization with multi-agent support (Claude Code, Cursor, Windsurf, Cline, Codex, GitHub Copilot)
23
+ - **Init**: Behavioral directive injection for automatic annotation by AI agents
24
+ - **MCP**: 12 tools (parse, validate, status, suggest, lookup, threat_report, threat_reports, annotate, report, dashboard, sarif, diff) and 3 resources
25
+ - **CLI**: 12 commands (init, parse, status, validate, report, diff, sarif, mcp, threat-report, annotate, dashboard, scan)
26
+ - **TUI**: Interactive terminal interface with command palette, autocomplete, and inline help
27
+ - **Dashboard**: HTML threat model dashboard with exposure explorer, file tree, and threat report viewer
28
+ - **Agents**: Unified agent launcher (Claude Code, Cursor, Windsurf, Cline, Codex, Gemini CLI) with config resolution chain
29
+ - **Threat Reports**: AI-powered threat analysis using STRIDE, DREAD, PASTA, and other frameworks
30
+ - **CI**: --strict flag on validate, --fail-on-new on diff for CI gates
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025-2026 BugB Technologies
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,344 @@
1
+ # GuardLink
2
+
3
+ [![npm version](https://img.shields.io/npm/v/guardlink.svg)](https://www.npmjs.com/package/guardlink)
4
+ [![CI](https://github.com/Bugb-Technologies/guardlink/actions/workflows/ci.yml/badge.svg)](https://github.com/Bugb-Technologies/guardlink/actions)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
6
+ [![Node.js 18+](https://img.shields.io/badge/node-18%2B-green.svg)](https://nodejs.org)
7
+ [![Spec: CC-BY-4.0](https://img.shields.io/badge/spec-CC--BY--4.0-orange.svg)](docs/SPEC.md)
8
+
9
+ **Security annotations that live in your code. Your threat model updates when your code changes.**
10
+
11
+ > **This repository is secured by GuardLink.** Run `guardlink status .` to see 152 annotations across 12 assets, 13 threats, and 10 controls — maintained by AI agents, validated in CI.
12
+
13
+ ```javascript
14
+ // @asset PaymentService (#payments) -- "Handles card transactions"
15
+ // @threat SQL_Injection (#sqli) [critical] cwe:CWE-89
16
+
17
+ // @mitigates #payments against #sqli using #prepared-stmts
18
+ app.post('/charge', async (req, res) => {
19
+ const result = await db.query('SELECT * FROM cards WHERE id = $1', [req.body.id]);
20
+ });
21
+
22
+ // @exposes #payments to #idor [P1] cwe:CWE-639 -- "No ownership check"
23
+ app.get('/receipts/:id', async (req, res) => {
24
+ const receipt = await db.query('SELECT * FROM receipts WHERE id = $1', [req.params.id]);
25
+ });
26
+ ```
27
+
28
+ ---
29
+
30
+ ## Install
31
+
32
+ ```bash
33
+ npm install -g guardlink
34
+ ```
35
+
36
+ Requires Node.js 18+.
37
+
38
+ ## Quick Start
39
+
40
+ ```bash
41
+ # Initialize in your project (detects your AI agent automatically)
42
+ guardlink init
43
+
44
+ # Let your AI coding agent annotate, or write annotations manually
45
+ # Then validate
46
+ guardlink validate .
47
+
48
+ # See your security posture
49
+ guardlink status .
50
+ ```
51
+
52
+ ```
53
+ Assets: 3 Mitigations: 4
54
+ Threats: 8 Exposures: 6 (3 unmitigated)
55
+ Controls: 5 Coverage: 62%
56
+ ```
57
+
58
+ ```bash
59
+ # Generate a full threat model report
60
+ guardlink report .
61
+
62
+ # Interactive HTML dashboard
63
+ guardlink dashboard .
64
+
65
+ # AI threat analysis (STRIDE, DREAD, PASTA, etc.)
66
+ guardlink threat-report stride --claude-code
67
+
68
+ # Interactive TUI with slash commands
69
+ guardlink
70
+ ```
71
+
72
+ ---
73
+
74
+ ## Why GuardLink
75
+
76
+ Threat models rot. Teams do a session at the start of a project, someone creates a Confluence page, and it's stale by the next sprint. SAST scanners find 200 things with no context about what matters. Pen test reports sit in shared drives. The root cause is always the same: **security knowledge lives outside the code**.
77
+
78
+ GuardLink fixes this at three levels:
79
+
80
+ **1. Annotations in code.** Security decisions are structured comments next to the code they describe. When a developer writes a parameterized query, `@mitigates #api against #sqli using #prepared-stmts` lives right above it. When the code changes, the annotation is right there to update. The threat model *is* the code.
81
+
82
+ **2. AI agents maintain it.** GuardLink integrates with AI coding agents through MCP and behavioral directives. When your agent writes a route handler, it adds `@exposes` and `@mitigates` annotations automatically. The threat model maintains itself because the thing writing the code also writes the security context.
83
+
84
+ **3. CI enforces it.** `guardlink validate` fails on syntax errors. `guardlink diff --fail-on-new` blocks PRs that introduce unmitigated exposures. `guardlink sarif` exports to GitHub's Security tab. The threat model becomes a quality gate, not a checkbox.
85
+
86
+ ```
87
+ Developer writes code
88
+
89
+ AI agent adds security annotations
90
+
91
+ CI validates on every PR
92
+
93
+ Team reviews security posture in the diff
94
+
95
+ Threat model is always current, always enforced
96
+ ```
97
+
98
+ ---
99
+
100
+ ## AI Agent Integration
101
+
102
+ GuardLink ships an MCP server and behavioral directives for AI coding agents. After `guardlink init`, your agent treats security annotations like type safety — adding them by default when writing security-relevant code.
103
+
104
+ `guardlink init` detects your agent and configures two things:
105
+
106
+ **MCP server** — tools to read the threat model, validate annotations, suggest annotations, and query threats by keyword. The agent can ask "what threats affect #api?" before writing code that touches the API.
107
+
108
+ **Behavioral directive** — a rule injected into your agent's instruction file (CLAUDE.md, .cursorrules, etc.) that says: *when writing code that handles routes, auth, database access, file I/O, or external services, add GuardLink annotations.*
109
+
110
+ ### Supported Agents
111
+
112
+ | Agent | Config File | MCP Support |
113
+ |-------|------------|-------------|
114
+ | Claude Code | `CLAUDE.md` + `.mcp.json` | ✅ Full |
115
+ | Cursor | `.cursorrules` + `.cursor/mcp.json` | ✅ Full |
116
+ | Windsurf | `.windsurfrules` + `.windsurf/mcp.json` | ✅ Full |
117
+ | Cline | `.clinerules` + `.cline/mcp.json` | ✅ Full |
118
+ | Codex | `AGENTS.md` | Directive only |
119
+ | GitHub Copilot | `.github/copilot-instructions.md` | Directive only |
120
+
121
+ ### MCP Tools
122
+
123
+ | Tool | Description |
124
+ |------|-------------|
125
+ | `guardlink_parse` | Full threat model as JSON |
126
+ | `guardlink_validate` | Check for errors and dangling references |
127
+ | `guardlink_status` | Coverage summary |
128
+ | `guardlink_suggest` | Suggest annotations for a code snippet |
129
+ | `guardlink_lookup` | Query threats, controls, flows by keyword |
130
+ | `guardlink_threat_report` | AI threat report (STRIDE, DREAD, etc.) |
131
+ | `guardlink_annotate` | Build annotation prompt for the agent |
132
+ | `guardlink_report` | Generate markdown report |
133
+ | `guardlink_dashboard` | Generate HTML dashboard |
134
+ | `guardlink_sarif` | Export SARIF 2.1.0 |
135
+ | `guardlink_diff` | Compare threat model against a git ref |
136
+
137
+ **Resources:** `guardlink://model`, `guardlink://definitions`, `guardlink://config`
138
+
139
+ ---
140
+
141
+ ## Commands
142
+
143
+ | Command | Description |
144
+ |---------|-------------|
145
+ | `guardlink init [dir]` | Initialize project with definitions, config, and agent integration |
146
+ | `guardlink parse [dir]` | Parse all annotations, output ThreatModel JSON |
147
+ | `guardlink status [dir]` | Coverage summary: assets, threats, mitigations, exposures |
148
+ | `guardlink validate [dir]` | Check for syntax errors, dangling refs, duplicate IDs |
149
+ | `guardlink validate --strict` | Also fail on unmitigated exposures |
150
+ | `guardlink scan [dir]` | Find unannotated security-relevant functions |
151
+ | `guardlink report [dir]` | Markdown threat model with Mermaid architecture diagram |
152
+ | `guardlink dashboard [dir]` | Interactive HTML threat model dashboard |
153
+ | `guardlink diff --from <ref>` | Compare threat models between git refs |
154
+ | `guardlink diff --fail-on-new` | Exit 1 if new unmitigated exposures found |
155
+ | `guardlink sarif [dir]` | Export unmitigated exposures as SARIF 2.1.0 |
156
+ | `guardlink threat-report [fw]` | AI threat report (stride/dread/pasta/attacker/rapid/general) |
157
+ | `guardlink threat-reports` | List saved AI threat reports |
158
+ | `guardlink annotate [prompt]` | Launch a coding agent to add annotations |
159
+ | `guardlink config` | Set AI provider and API key |
160
+ | `guardlink mcp` | Start MCP server for AI agent integration |
161
+
162
+ ---
163
+
164
+ ## Annotation Reference
165
+
166
+ GuardLink annotations go in comments in any language. The parser supports `//`, `#`, `--`, `/* */`, `""" """`, and 25+ comment styles.
167
+
168
+ ### Definitions (shared, in `.guardlink/definitions.js`)
169
+
170
+ ```javascript
171
+ // @asset App.API (#api) -- "Express REST API serving mobile and web clients"
172
+ // @threat SQL_Injection (#sqli) [critical] cwe:CWE-89 -- "Unsanitized input reaches SQL query"
173
+ // @control Parameterized_Queries (#prepared-stmts) -- "All queries use bound parameters"
174
+ ```
175
+
176
+ ### Relationships (in source files, next to the code)
177
+
178
+ ```python
179
+ # @mitigates #api against #sqli using #prepared-stmts -- "All queries parameterized"
180
+ # @exposes #api to #xss [P1] cwe:CWE-79 -- "User bio rendered without escaping"
181
+ # @accepts #info-disclosure on #api -- "Health endpoint is intentionally public"
182
+ # @transfers #sqli from #api to #database -- "DB handles untrusted input"
183
+ ```
184
+
185
+ ### Data Flow & Architecture
186
+
187
+ ```go
188
+ // @flow #api -> #database via "PostgreSQL wire protocol"
189
+ // @boundary #api <-> #cdn -- "TLS termination point"
190
+ // @handles pii on #api -- "Processes user email and address"
191
+ // @handles secrets on #auth -- "Manages JWT signing keys"
192
+ ```
193
+
194
+ ### Operational
195
+
196
+ ```rust
197
+ // @audit #api by "PenTest Corp" on 2025-03-15 -- "Annual penetration test"
198
+ // @validates #input-validation on #api using "Jest integration tests"
199
+ // @assumes #api -- "Rate limiting handled by API gateway"
200
+ // @owns #api by "backend-team"
201
+ ```
202
+
203
+ ### All Annotation Types
204
+
205
+ | Verb | Purpose | Example |
206
+ |------|---------|---------|
207
+ | `@asset` | Define a component | `@asset UserService (#users)` |
208
+ | `@threat` | Define a threat | `@threat XSS (#xss) [high] cwe:CWE-79` |
209
+ | `@control` | Define a security control | `@control WAF (#waf)` |
210
+ | `@mitigates` | Control protects asset against threat | `@mitigates #api against #sqli using #prepared-stmts` |
211
+ | `@exposes` | Asset vulnerable to threat | `@exposes #api to #xss [P1]` |
212
+ | `@accepts` | Risk acknowledged | `@accepts #dos on #api -- "By design"` |
213
+ | `@transfers` | Risk moved between assets | `@transfers #sqli from #api to #db` |
214
+ | `@flow` | Data flow between assets | `@flow #api -> #db via "SQL"` |
215
+ | `@boundary` | Trust boundary | `@boundary #api <-> #external` |
216
+ | `@handles` | Data classification | `@handles pii on #users` |
217
+ | `@audit` | Security audit record | `@audit #api by "Firm" on 2025-01-01` |
218
+ | `@validates` | Control verification | `@validates #auth on #api using "tests"` |
219
+ | `@assumes` | Security assumption | `@assumes #api -- "Behind VPN"` |
220
+ | `@owns` | Component ownership | `@owns #api by "team-backend"` |
221
+ | `@shield` | AI exclusion zone | `@shield #api requires #auth-check` |
222
+
223
+ Severity: `[critical]`/`[P0]`, `[high]`/`[P1]`, `[medium]`/`[P2]`, `[low]`/`[P3]`. External refs: `cwe:CWE-89`, `capec:CAPEC-66`, `owasp:A03`.
224
+
225
+ ---
226
+
227
+ ## CI Integration
228
+
229
+ ### GitHub Actions
230
+
231
+ ```yaml
232
+ name: GuardLink
233
+ on: [pull_request]
234
+
235
+ jobs:
236
+ guardlink:
237
+ runs-on: ubuntu-latest
238
+ steps:
239
+ - uses: actions/checkout@v4
240
+ with: { fetch-depth: 0 }
241
+
242
+ - uses: actions/setup-node@v4
243
+ with: { node-version: '20' }
244
+
245
+ - run: npm install -g guardlink
246
+
247
+ - name: Validate annotations
248
+ run: guardlink validate .
249
+
250
+ - name: Threat model diff
251
+ run: guardlink diff --from origin/main --to HEAD
252
+
253
+ - name: Export SARIF
254
+ run: guardlink sarif . -o guardlink.sarif
255
+
256
+ - uses: github/codeql-action/upload-sarif@v3
257
+ with: { sarif_file: guardlink.sarif }
258
+ ```
259
+
260
+ See [`examples/github-action.yml`](examples/github-action.yml) for a full example with PR comments and SARIF upload.
261
+
262
+ ### What CI Catches
263
+
264
+ - **New route, no annotations:** `guardlink diff` shows "+1 endpoint, 0 mitigations" — the team sees the gap.
265
+ - **Agent annotated properly:** diff shows "+1 asset, +2 mitigations, +1 exposure (IDOR)" — team reviews.
266
+ - **Control removed:** diff shows "-1 mitigation, +1 unmitigated exposure" — `--fail-on-new` blocks the PR.
267
+
268
+ ### SARIF
269
+
270
+ `guardlink sarif` exports unmitigated exposures as SARIF 2.1.0. Upload to GitHub Advanced Security and every `@exposes` appears as a code scanning alert with file, line, severity, and CWE.
271
+
272
+ ---
273
+
274
+ ## Real-World Results
275
+
276
+ We tested GuardLink + Claude Code on [vuln-node.js-express.js-app](https://github.com/SirAppSec/vuln-node.js-express.js-app), a deliberately vulnerable Express.js application with 37 documented vulnerability types.
277
+
278
+ **In 6 minutes, with no human intervention:**
279
+
280
+ - 143 annotations across 6 route files
281
+ - 29 distinct threats identified with CWE mappings
282
+ - 66 unmitigated exposures documented with file:line precision
283
+ - 27 of 37 known vulnerabilities detected (73% recall, 81% with partial matches)
284
+ - Architecture: 8 assets, 3 data flows, Mermaid diagram with risk heat map
285
+ - Cost: ~$0.50 in Haiku tokens
286
+
287
+ A scanner gives you a list of findings. GuardLink gives you a threat model — assets, threats, controls, data flows, trust boundaries, and the relationships between them. Every exposure traceable to a line of code. Every mitigation documented next to the control it implements. And because it's all in code comments, it updates when the code changes.
288
+
289
+ ---
290
+
291
+ ## Library API
292
+
293
+ ```typescript
294
+ import { parseProject } from 'guardlink/parser';
295
+ import { generateReport } from 'guardlink/report';
296
+ import { diffModels } from 'guardlink/diff';
297
+ import { generateSarif } from 'guardlink/analyzer';
298
+ import type { ThreatModel } from 'guardlink';
299
+
300
+ const { model } = await parseProject({ root: '.', project: 'my-app' });
301
+
302
+ const markdown = generateReport(model);
303
+ const diff = diffModels(oldModel, newModel);
304
+ const sarif = generateSarif(model, '.');
305
+ ```
306
+
307
+ ---
308
+
309
+ ## Specification
310
+
311
+ GuardLink is an open specification. The annotation grammar, threat model schema, and conformance levels are defined in the [GuardLink Specification](docs/SPEC.md).
312
+
313
+ Anyone can build conformant parsers, analyzers, or integrations. This CLI is the reference implementation.
314
+
315
+ | Level | Name | Capabilities |
316
+ |-------|------|-------------|
317
+ | L1 | Parser | Parse all 16 annotation types, produce ThreatModel JSON |
318
+ | L2 | Analyzer | Coverage stats, unmitigated detection, dangling ref detection |
319
+ | L3 | CI/CD | Threat model diffs, change classification, SARIF export |
320
+ | L4 | AI-Integrated | MCP server, suggestion engine, agent behavioral directives |
321
+
322
+ This implementation is **Level 4** conformant.
323
+
324
+ ---
325
+
326
+ ## Heritage
327
+
328
+ GuardLink builds on the annotation grammar created by [ThreatSpec](https://github.com/threatspec/threatspec) (2015–2020) by Fraser Scott — the first tool to propose continuous threat modeling through code annotations. The core verbs (`@mitigates`, `@exposes`, `@transfers`, `@accepts`) originate from that work.
329
+
330
+ We extend the specification with severity levels, external references (CWE/CAPEC/OWASP), data flow and trust boundary annotations, data classification, a structured JSON schema, SARIF export, MCP integration for AI agents, and CI/CD enforcement tooling. ThreatSpec had the right idea. Our contribution is making it work in a world where AI writes most of the code.
331
+
332
+ ---
333
+
334
+ ## Contributing
335
+
336
+ See [CONTRIBUTING.md](CONTRIBUTING.md).
337
+
338
+ ## License
339
+
340
+ MIT — see [LICENSE](LICENSE). The GuardLink specification is published under CC-BY-4.0.
341
+
342
+ ---
343
+
344
+ Built by [BugB Technologies](https://bugb.io).
@@ -0,0 +1,46 @@
1
+ /**
2
+ * GuardLink Agents — Unified LLM configuration resolution.
3
+ *
4
+ * Resolution order (highest to lowest priority):
5
+ * 1. Explicit flags (--api-key, --provider, --model) — CLI only, never persisted
6
+ * 2. GUARDLINK_LLM_KEY + GUARDLINK_LLM_PROVIDER env vars
7
+ * 3. Provider-specific env vars (ANTHROPIC_API_KEY, OPENAI_API_KEY, etc.)
8
+ * 4. Project config: .guardlink/config.json
9
+ * 5. Global config: ~/.config/guardlink/config.json
10
+ *
11
+ * Replaces the fragmented tui-config.json / CLI flag / env var resolution.
12
+ */
13
+ import type { LLMConfig, LLMProvider } from '../analyze/llm.js';
14
+ interface SavedConfig {
15
+ provider?: LLMProvider;
16
+ model?: string;
17
+ apiKey?: string;
18
+ }
19
+ /**
20
+ * Resolve LLM configuration using the unified priority chain.
21
+ *
22
+ * @param root - Project root directory (for project-level config)
23
+ * @param flags - Explicit CLI flags (highest priority, never persisted)
24
+ */
25
+ export declare function resolveConfig(root: string, flags?: {
26
+ provider?: string;
27
+ model?: string;
28
+ apiKey?: string;
29
+ }): LLMConfig | null;
30
+ /** Save config to project-level .guardlink/config.json */
31
+ export declare function saveProjectConfig(root: string, cfg: SavedConfig): void;
32
+ /** Save config to global ~/.config/guardlink/config.json */
33
+ export declare function saveGlobalConfig(cfg: SavedConfig): void;
34
+ /** Load project config (new or legacy path) */
35
+ export declare function loadProjectConfig(root: string): SavedConfig | null;
36
+ /** Load global config */
37
+ export declare function loadGlobalConfig(): SavedConfig | null;
38
+ /** Mask an API key for display: sk-ant-***...***xyz */
39
+ export declare function maskKey(key: string): string;
40
+ /** Describe the source of the resolved config */
41
+ export declare function describeConfigSource(root: string, flags?: {
42
+ provider?: string;
43
+ apiKey?: string;
44
+ }): string;
45
+ export {};
46
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/agents/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAKH,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAIhE,UAAU,WAAW;IACnB,QAAQ,CAAC,EAAE,WAAW,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAgDD;;;;;GAKG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,EACZ,KAAK,CAAC,EAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAC7D,SAAS,GAAG,IAAI,CAmDlB;AAiCD,0DAA0D;AAC1D,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,WAAW,GAAG,IAAI,CAEtE;AAED,4DAA4D;AAC5D,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,WAAW,GAAG,IAAI,CAEvD;AAED,+CAA+C;AAC/C,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAGlE;AAED,yBAAyB;AACzB,wBAAgB,gBAAgB,IAAI,WAAW,GAAG,IAAI,CAErD;AAID,uDAAuD;AACvD,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAG3C;AAED,iDAAiD;AACjD,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,EACZ,KAAK,CAAC,EAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAC7C,MAAM,CAcR"}
@@ -0,0 +1,189 @@
1
+ /**
2
+ * GuardLink Agents — Unified LLM configuration resolution.
3
+ *
4
+ * Resolution order (highest to lowest priority):
5
+ * 1. Explicit flags (--api-key, --provider, --model) — CLI only, never persisted
6
+ * 2. GUARDLINK_LLM_KEY + GUARDLINK_LLM_PROVIDER env vars
7
+ * 3. Provider-specific env vars (ANTHROPIC_API_KEY, OPENAI_API_KEY, etc.)
8
+ * 4. Project config: .guardlink/config.json
9
+ * 5. Global config: ~/.config/guardlink/config.json
10
+ *
11
+ * Replaces the fragmented tui-config.json / CLI flag / env var resolution.
12
+ */
13
+ import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
14
+ import { join } from 'node:path';
15
+ import { homedir } from 'node:os';
16
+ const DEFAULT_MODELS = {
17
+ anthropic: 'claude-sonnet-4-5-20250929',
18
+ openai: 'gpt-4o',
19
+ openrouter: 'anthropic/claude-sonnet-4-5-20250929',
20
+ deepseek: 'deepseek-chat',
21
+ };
22
+ const CONFIG_FILE = 'config.json';
23
+ const LEGACY_CONFIG_FILE = 'tui-config.json';
24
+ // ─── Config file paths ───────────────────────────────────────────────
25
+ /** Project-level config: <root>/.guardlink/config.json */
26
+ function projectConfigPath(root) {
27
+ return join(root, '.guardlink', CONFIG_FILE);
28
+ }
29
+ /** Legacy project config: <root>/.guardlink/tui-config.json */
30
+ function legacyConfigPath(root) {
31
+ return join(root, '.guardlink', LEGACY_CONFIG_FILE);
32
+ }
33
+ /** Global config: ~/.config/guardlink/config.json */
34
+ function globalConfigPath() {
35
+ return join(homedir(), '.config', 'guardlink', CONFIG_FILE);
36
+ }
37
+ // ─── Read/write helpers ──────────────────────────────────────────────
38
+ function readJsonFile(path) {
39
+ if (!existsSync(path))
40
+ return null;
41
+ try {
42
+ return JSON.parse(readFileSync(path, 'utf-8'));
43
+ }
44
+ catch {
45
+ return null;
46
+ }
47
+ }
48
+ function writeJsonFile(path, data) {
49
+ const dir = join(path, '..');
50
+ if (!existsSync(dir))
51
+ mkdirSync(dir, { recursive: true });
52
+ writeFileSync(path, JSON.stringify(data, null, 2) + '\n');
53
+ }
54
+ // ─── Unified resolution ──────────────────────────────────────────────
55
+ /**
56
+ * Resolve LLM configuration using the unified priority chain.
57
+ *
58
+ * @param root - Project root directory (for project-level config)
59
+ * @param flags - Explicit CLI flags (highest priority, never persisted)
60
+ */
61
+ export function resolveConfig(root, flags) {
62
+ // 1. Explicit flags
63
+ if (flags?.apiKey && flags?.provider) {
64
+ const provider = flags.provider;
65
+ return {
66
+ provider,
67
+ model: flags.model || DEFAULT_MODELS[provider] || 'gpt-4o',
68
+ apiKey: flags.apiKey,
69
+ };
70
+ }
71
+ // 2. GUARDLINK_LLM_KEY + GUARDLINK_LLM_PROVIDER
72
+ const guardlinkKey = process.env.GUARDLINK_LLM_KEY;
73
+ const guardlinkProvider = process.env.GUARDLINK_LLM_PROVIDER;
74
+ if (guardlinkKey) {
75
+ const provider = guardlinkProvider || detectProviderFromKey(guardlinkKey);
76
+ if (provider) {
77
+ return {
78
+ provider,
79
+ model: flags?.model || DEFAULT_MODELS[provider],
80
+ apiKey: guardlinkKey,
81
+ };
82
+ }
83
+ }
84
+ // 3. Provider-specific env vars
85
+ const envConfig = resolveFromEnv(flags?.model);
86
+ if (envConfig)
87
+ return envConfig;
88
+ // 4. Project config: .guardlink/config.json (+ legacy tui-config.json)
89
+ const projectCfg = readJsonFile(projectConfigPath(root))
90
+ || readJsonFile(legacyConfigPath(root));
91
+ if (projectCfg?.provider && projectCfg?.apiKey) {
92
+ return {
93
+ provider: projectCfg.provider,
94
+ model: flags?.model || projectCfg.model || DEFAULT_MODELS[projectCfg.provider],
95
+ apiKey: projectCfg.apiKey,
96
+ };
97
+ }
98
+ // 5. Global config: ~/.config/guardlink/config.json
99
+ const globalCfg = readJsonFile(globalConfigPath());
100
+ if (globalCfg?.provider && globalCfg?.apiKey) {
101
+ return {
102
+ provider: globalCfg.provider,
103
+ model: flags?.model || globalCfg.model || DEFAULT_MODELS[globalCfg.provider],
104
+ apiKey: globalCfg.apiKey,
105
+ };
106
+ }
107
+ return null;
108
+ }
109
+ /** Resolve from provider-specific env vars (ANTHROPIC_API_KEY, etc.) */
110
+ function resolveFromEnv(modelOverride) {
111
+ const checks = [
112
+ ['ANTHROPIC_API_KEY', 'anthropic'],
113
+ ['OPENAI_API_KEY', 'openai'],
114
+ ['OPENROUTER_API_KEY', 'openrouter'],
115
+ ['DEEPSEEK_API_KEY', 'deepseek'],
116
+ ];
117
+ for (const [envVar, provider] of checks) {
118
+ const key = process.env[envVar];
119
+ if (key) {
120
+ return {
121
+ provider,
122
+ model: modelOverride || DEFAULT_MODELS[provider],
123
+ apiKey: key,
124
+ };
125
+ }
126
+ }
127
+ return null;
128
+ }
129
+ /** Heuristic: detect provider from API key prefix */
130
+ function detectProviderFromKey(key) {
131
+ if (key.startsWith('sk-ant-'))
132
+ return 'anthropic';
133
+ if (key.startsWith('sk-or-'))
134
+ return 'openrouter';
135
+ if (key.startsWith('sk-'))
136
+ return 'openai'; // OpenAI uses sk- prefix
137
+ return null; // Can't detect — need GUARDLINK_LLM_PROVIDER
138
+ }
139
+ // ─── Save/load for `guardlink config` and `/model` ──────────────────
140
+ /** Save config to project-level .guardlink/config.json */
141
+ export function saveProjectConfig(root, cfg) {
142
+ writeJsonFile(projectConfigPath(root), cfg);
143
+ }
144
+ /** Save config to global ~/.config/guardlink/config.json */
145
+ export function saveGlobalConfig(cfg) {
146
+ writeJsonFile(globalConfigPath(), cfg);
147
+ }
148
+ /** Load project config (new or legacy path) */
149
+ export function loadProjectConfig(root) {
150
+ return readJsonFile(projectConfigPath(root))
151
+ || readJsonFile(legacyConfigPath(root));
152
+ }
153
+ /** Load global config */
154
+ export function loadGlobalConfig() {
155
+ return readJsonFile(globalConfigPath());
156
+ }
157
+ // ─── Display helpers ─────────────────────────────────────────────────
158
+ /** Mask an API key for display: sk-ant-***...***xyz */
159
+ export function maskKey(key) {
160
+ if (key.length <= 12)
161
+ return '***';
162
+ return key.slice(0, 7) + '•'.repeat(8) + key.slice(-3);
163
+ }
164
+ /** Describe the source of the resolved config */
165
+ export function describeConfigSource(root, flags) {
166
+ if (flags?.apiKey && flags?.provider)
167
+ return 'CLI flags';
168
+ if (process.env.GUARDLINK_LLM_KEY)
169
+ return 'GUARDLINK_LLM_KEY env var';
170
+ if (process.env.ANTHROPIC_API_KEY)
171
+ return 'ANTHROPIC_API_KEY env var';
172
+ if (process.env.OPENAI_API_KEY)
173
+ return 'OPENAI_API_KEY env var';
174
+ if (process.env.OPENROUTER_API_KEY)
175
+ return 'OPENROUTER_API_KEY env var';
176
+ if (process.env.DEEPSEEK_API_KEY)
177
+ return 'DEEPSEEK_API_KEY env var';
178
+ const pc = readJsonFile(projectConfigPath(root));
179
+ if (pc && Object.keys(pc).length > 0 && pc.provider)
180
+ return `.guardlink/${CONFIG_FILE}`;
181
+ const lc = readJsonFile(legacyConfigPath(root));
182
+ if (lc && Object.keys(lc).length > 0 && lc.provider)
183
+ return `.guardlink/${LEGACY_CONFIG_FILE} (legacy)`;
184
+ const gc = readJsonFile(globalConfigPath());
185
+ if (gc && Object.keys(gc).length > 0 && gc.provider)
186
+ return `~/.config/guardlink/${CONFIG_FILE}`;
187
+ return 'none';
188
+ }
189
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/agents/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAWlC,MAAM,cAAc,GAAgC;IAClD,SAAS,EAAE,4BAA4B;IACvC,MAAM,EAAE,QAAQ;IAChB,UAAU,EAAE,sCAAsC;IAClD,QAAQ,EAAE,eAAe;CAC1B,CAAC;AAEF,MAAM,WAAW,GAAG,aAAa,CAAC;AAClC,MAAM,kBAAkB,GAAG,iBAAiB,CAAC;AAE7C,wEAAwE;AAExE,0DAA0D;AAC1D,SAAS,iBAAiB,CAAC,IAAY;IACrC,OAAO,IAAI,CAAC,IAAI,EAAE,YAAY,EAAE,WAAW,CAAC,CAAC;AAC/C,CAAC;AAED,+DAA+D;AAC/D,SAAS,gBAAgB,CAAC,IAAY;IACpC,OAAO,IAAI,CAAC,IAAI,EAAE,YAAY,EAAE,kBAAkB,CAAC,CAAC;AACtD,CAAC;AAED,qDAAqD;AACrD,SAAS,gBAAgB;IACvB,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,WAAW,EAAE,WAAW,CAAC,CAAC;AAC9D,CAAC;AAED,wEAAwE;AAExE,SAAS,YAAY,CAAC,IAAY;IAChC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACnC,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;IACjD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,aAAa,CAAC,IAAY,EAAE,IAAiB;IACpD,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC7B,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1D,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;AAC5D,CAAC;AAED,wEAAwE;AAExE;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAC3B,IAAY,EACZ,KAA8D;IAE9D,oBAAoB;IACpB,IAAI,KAAK,EAAE,MAAM,IAAI,KAAK,EAAE,QAAQ,EAAE,CAAC;QACrC,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAuB,CAAC;QAC/C,OAAO;YACL,QAAQ;YACR,KAAK,EAAE,KAAK,CAAC,KAAK,IAAI,cAAc,CAAC,QAAQ,CAAC,IAAI,QAAQ;YAC1D,MAAM,EAAE,KAAK,CAAC,MAAM;SACrB,CAAC;IACJ,CAAC;IAED,gDAAgD;IAChD,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;IACnD,MAAM,iBAAiB,GAAG,OAAO,CAAC,GAAG,CAAC,sBAAiD,CAAC;IACxF,IAAI,YAAY,EAAE,CAAC;QACjB,MAAM,QAAQ,GAAG,iBAAiB,IAAI,qBAAqB,CAAC,YAAY,CAAC,CAAC;QAC1E,IAAI,QAAQ,EAAE,CAAC;YACb,OAAO;gBACL,QAAQ;gBACR,KAAK,EAAE,KAAK,EAAE,KAAK,IAAI,cAAc,CAAC,QAAQ,CAAC;gBAC/C,MAAM,EAAE,YAAY;aACrB,CAAC;QACJ,CAAC;IACH,CAAC;IAED,gCAAgC;IAChC,MAAM,SAAS,GAAG,cAAc,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IAC/C,IAAI,SAAS;QAAE,OAAO,SAAS,CAAC;IAEhC,uEAAuE;IACvE,MAAM,UAAU,GAAG,YAAY,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;WACnD,YAAY,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC;IAC1C,IAAI,UAAU,EAAE,QAAQ,IAAI,UAAU,EAAE,MAAM,EAAE,CAAC;QAC/C,OAAO;YACL,QAAQ,EAAE,UAAU,CAAC,QAAQ;YAC7B,KAAK,EAAE,KAAK,EAAE,KAAK,IAAI,UAAU,CAAC,KAAK,IAAI,cAAc,CAAC,UAAU,CAAC,QAAQ,CAAC;YAC9E,MAAM,EAAE,UAAU,CAAC,MAAM;SAC1B,CAAC;IACJ,CAAC;IAED,oDAAoD;IACpD,MAAM,SAAS,GAAG,YAAY,CAAC,gBAAgB,EAAE,CAAC,CAAC;IACnD,IAAI,SAAS,EAAE,QAAQ,IAAI,SAAS,EAAE,MAAM,EAAE,CAAC;QAC7C,OAAO;YACL,QAAQ,EAAE,SAAS,CAAC,QAAQ;YAC5B,KAAK,EAAE,KAAK,EAAE,KAAK,IAAI,SAAS,CAAC,KAAK,IAAI,cAAc,CAAC,SAAS,CAAC,QAAQ,CAAC;YAC5E,MAAM,EAAE,SAAS,CAAC,MAAM;SACzB,CAAC;IACJ,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,wEAAwE;AACxE,SAAS,cAAc,CAAC,aAAsB;IAC5C,MAAM,MAAM,GAA4B;QACtC,CAAC,mBAAmB,EAAE,WAAW,CAAC;QAClC,CAAC,gBAAgB,EAAE,QAAQ,CAAC;QAC5B,CAAC,oBAAoB,EAAE,YAAY,CAAC;QACpC,CAAC,kBAAkB,EAAE,UAAU,CAAC;KACjC,CAAC;IACF,KAAK,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,IAAI,MAAM,EAAE,CAAC;QACxC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAChC,IAAI,GAAG,EAAE,CAAC;YACR,OAAO;gBACL,QAAQ;gBACR,KAAK,EAAE,aAAa,IAAI,cAAc,CAAC,QAAQ,CAAC;gBAChD,MAAM,EAAE,GAAG;aACZ,CAAC;QACJ,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,qDAAqD;AACrD,SAAS,qBAAqB,CAAC,GAAW;IACxC,IAAI,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO,WAAW,CAAC;IAClD,IAAI,GAAG,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAO,YAAY,CAAC;IAClD,IAAI,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC;QAAE,OAAO,QAAQ,CAAC,CAAE,yBAAyB;IACtE,OAAO,IAAI,CAAC,CAAE,6CAA6C;AAC7D,CAAC;AAED,uEAAuE;AAEvE,0DAA0D;AAC1D,MAAM,UAAU,iBAAiB,CAAC,IAAY,EAAE,GAAgB;IAC9D,aAAa,CAAC,iBAAiB,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC;AAC9C,CAAC;AAED,4DAA4D;AAC5D,MAAM,UAAU,gBAAgB,CAAC,GAAgB;IAC/C,aAAa,CAAC,gBAAgB,EAAE,EAAE,GAAG,CAAC,CAAC;AACzC,CAAC;AAED,+CAA+C;AAC/C,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,OAAO,YAAY,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;WACvC,YAAY,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC;AAC5C,CAAC;AAED,yBAAyB;AACzB,MAAM,UAAU,gBAAgB;IAC9B,OAAO,YAAY,CAAC,gBAAgB,EAAE,CAAC,CAAC;AAC1C,CAAC;AAED,wEAAwE;AAExE,uDAAuD;AACvD,MAAM,UAAU,OAAO,CAAC,GAAW;IACjC,IAAI,GAAG,CAAC,MAAM,IAAI,EAAE;QAAE,OAAO,KAAK,CAAC;IACnC,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AACzD,CAAC;AAED,iDAAiD;AACjD,MAAM,UAAU,oBAAoB,CAClC,IAAY,EACZ,KAA8C;IAE9C,IAAI,KAAK,EAAE,MAAM,IAAI,KAAK,EAAE,QAAQ;QAAE,OAAO,WAAW,CAAC;IACzD,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB;QAAE,OAAO,2BAA2B,CAAC;IACtE,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB;QAAE,OAAO,2BAA2B,CAAC;IACtE,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc;QAAE,OAAO,wBAAwB,CAAC;IAChE,IAAI,OAAO,CAAC,GAAG,CAAC,kBAAkB;QAAE,OAAO,4BAA4B,CAAC;IACxE,IAAI,OAAO,CAAC,GAAG,CAAC,gBAAgB;QAAE,OAAO,0BAA0B,CAAC;IACpE,MAAM,EAAE,GAAG,YAAY,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC;IACjD,IAAI,EAAE,IAAI,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,QAAQ;QAAE,OAAO,cAAc,WAAW,EAAE,CAAC;IACxF,MAAM,EAAE,GAAG,YAAY,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC;IAChD,IAAI,EAAE,IAAI,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,QAAQ;QAAE,OAAO,cAAc,kBAAkB,WAAW,CAAC;IACxG,MAAM,EAAE,GAAG,YAAY,CAAC,gBAAgB,EAAE,CAAC,CAAC;IAC5C,IAAI,EAAE,IAAI,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,QAAQ;QAAE,OAAO,uBAAuB,WAAW,EAAE,CAAC;IACjG,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * GuardLink Agents — Shared agent registry.
3
+ *
4
+ * Used by CLI, TUI, and MCP to identify and resolve coding agents
5
+ * (Claude Code, Codex, Cursor, Windsurf, Gemini, clipboard).
6
+ */
7
+ export interface AgentEntry {
8
+ id: string;
9
+ name: string;
10
+ cmd: string | null;
11
+ app: string | null;
12
+ flag: string;
13
+ }
14
+ export declare const AGENTS: readonly AgentEntry[];
15
+ /** Parse --agent flags from a raw args string (TUI slash commands). */
16
+ export declare function parseAgentFlag(args: string): {
17
+ agent: AgentEntry | null;
18
+ cleanArgs: string;
19
+ };
20
+ /** Resolve agent from Commander option booleans (CLI commands). */
21
+ export declare function agentFromOpts(opts: Record<string, any>): AgentEntry | null;
22
+ export { launchAgentForeground, launchAgentIDE, launchAgent, copyToClipboard } from './launcher.js';
23
+ export { buildAnnotatePrompt } from './prompts.js';
24
+ //# sourceMappingURL=index.d.ts.map