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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/agents/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,eAAO,MAAM,MAAM,EAAE,SAAS,UAAU,EAO9B,CAAC;AAEX,uEAAuE;AACvE,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,UAAU,GAAG,IAAI,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAO5F;AAED,mEAAmE;AACnE,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,UAAU,GAAG,IAAI,CAQ1E;AAED,OAAO,EAAE,qBAAqB,EAAE,cAAc,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AACpG,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,42 @@
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 const AGENTS = [
8
+ { id: 'claude-code', name: 'Claude Code', cmd: 'claude', app: null, flag: '--claude-code' },
9
+ { id: 'cursor', name: 'Cursor', cmd: null, app: 'Cursor', flag: '--cursor' },
10
+ { id: 'windsurf', name: 'Windsurf', cmd: null, app: 'Windsurf', flag: '--windsurf' },
11
+ { id: 'codex', name: 'Codex CLI', cmd: 'codex', app: null, flag: '--codex' },
12
+ { id: 'gemini', name: 'Gemini CLI', cmd: 'gemini', app: null, flag: '--gemini' },
13
+ { id: 'clipboard', name: 'Clipboard', cmd: null, app: null, flag: '--clipboard' },
14
+ ];
15
+ /** Parse --agent flags from a raw args string (TUI slash commands). */
16
+ export function parseAgentFlag(args) {
17
+ for (const a of AGENTS) {
18
+ if (args.includes(a.flag)) {
19
+ return { agent: a, cleanArgs: args.replace(a.flag, '').trim() };
20
+ }
21
+ }
22
+ return { agent: null, cleanArgs: args };
23
+ }
24
+ /** Resolve agent from Commander option booleans (CLI commands). */
25
+ export function agentFromOpts(opts) {
26
+ if (opts.claudeCode)
27
+ return AGENTS.find(a => a.id === 'claude-code');
28
+ if (opts.cursor)
29
+ return AGENTS.find(a => a.id === 'cursor');
30
+ if (opts.windsurf)
31
+ return AGENTS.find(a => a.id === 'windsurf');
32
+ if (opts.codex)
33
+ return AGENTS.find(a => a.id === 'codex');
34
+ if (opts.gemini)
35
+ return AGENTS.find(a => a.id === 'gemini');
36
+ if (opts.clipboard)
37
+ return AGENTS.find(a => a.id === 'clipboard');
38
+ return null;
39
+ }
40
+ export { launchAgentForeground, launchAgentIDE, launchAgent, copyToClipboard } from './launcher.js';
41
+ export { buildAnnotatePrompt } from './prompts.js';
42
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/agents/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAYH,MAAM,CAAC,MAAM,MAAM,GAA0B;IAC3C,EAAE,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,aAAa,EAAE,GAAG,EAAE,QAAQ,EAAG,GAAG,EAAE,IAAI,EAAQ,IAAI,EAAE,eAAe,EAAE;IAClG,EAAE,EAAE,EAAE,QAAQ,EAAO,IAAI,EAAE,QAAQ,EAAO,GAAG,EAAE,IAAI,EAAO,GAAG,EAAE,QAAQ,EAAI,IAAI,EAAE,UAAU,EAAE;IAC7F,EAAE,EAAE,EAAE,UAAU,EAAK,IAAI,EAAE,UAAU,EAAK,GAAG,EAAE,IAAI,EAAO,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE,YAAY,EAAE;IAC/F,EAAE,EAAE,EAAE,OAAO,EAAQ,IAAI,EAAE,WAAW,EAAI,GAAG,EAAE,OAAO,EAAI,GAAG,EAAE,IAAI,EAAQ,IAAI,EAAE,SAAS,EAAE;IAC5F,EAAE,EAAE,EAAE,QAAQ,EAAO,IAAI,EAAE,YAAY,EAAG,GAAG,EAAE,QAAQ,EAAG,GAAG,EAAE,IAAI,EAAQ,IAAI,EAAE,UAAU,EAAE;IAC7F,EAAE,EAAE,EAAE,WAAW,EAAI,IAAI,EAAE,WAAW,EAAI,GAAG,EAAE,IAAI,EAAO,GAAG,EAAE,IAAI,EAAQ,IAAI,EAAE,aAAa,EAAE;CACxF,CAAC;AAEX,uEAAuE;AACvE,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACvB,IAAI,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;YAC1B,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;QAClE,CAAC;IACH,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;AAC1C,CAAC;AAED,mEAAmE;AACnE,MAAM,UAAU,aAAa,CAAC,IAAyB;IACrD,IAAI,IAAI,CAAC,UAAU;QAAE,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,aAAa,CAAE,CAAC;IACtE,IAAI,IAAI,CAAC,MAAM;QAAM,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAE,CAAC;IACjE,IAAI,IAAI,CAAC,QAAQ;QAAI,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,UAAU,CAAE,CAAC;IACnE,IAAI,IAAI,CAAC,KAAK;QAAO,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,OAAO,CAAE,CAAC;IAChE,IAAI,IAAI,CAAC,MAAM;QAAM,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAE,CAAC;IACjE,IAAI,IAAI,CAAC,SAAS;QAAG,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,WAAW,CAAE,CAAC;IACpE,OAAO,IAAI,CAAC;AACd,CAAC;AAED,OAAO,EAAE,qBAAqB,EAAE,cAAc,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AACpG,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * GuardLink Agents — Launch helpers.
3
+ *
4
+ * Two launch patterns:
5
+ * 1. Foreground spawn (CLI + TUI): takes over terminal, returns on exit
6
+ * 2. IDE launch: opens GUI app with project directory
7
+ *
8
+ * Clipboard copy is always performed first regardless of agent type.
9
+ *
10
+ * @exposes #agent-launcher to #child-proc-injection [high] cwe:CWE-78 -- "Spawns child processes for AI coding agents"
11
+ * @exposes #agent-launcher to #cmd-injection [critical] cwe:CWE-78 -- "Windows launch uses shell:true in spawnSync"
12
+ * @mitigates #agent-launcher against #child-proc-injection using #process-sandbox -- "Agent commands are fixed binaries (claude, codex), not user-controlled"
13
+ * @mitigates #agent-launcher against #cmd-injection using #param-commands -- "spawnSync with args array on macOS/Linux, only Windows uses shell"
14
+ * @flows #cli -> #agent-launcher via launchAgent -- "CLI invokes agent with prompt and cwd"
15
+ * @flows #agent-launcher -> External_Process via spawnSync -- "Spawns claude, codex, cursor, etc."
16
+ * @boundary between #agent-launcher and External_AI_Agents (#agent-boundary) -- "Process spawn crosses trust boundary to external AI tools"
17
+ * @comment -- "copyToClipboard uses platform-specific clipboard commands (pbcopy, xclip, clip)"
18
+ */
19
+ import type { AgentEntry } from './index.js';
20
+ /** Copy text to system clipboard. Returns true on success. */
21
+ export declare function copyToClipboard(text: string): boolean;
22
+ /**
23
+ * Launch a CLI agent in the foreground — takes over the current terminal.
24
+ * The agent gets full stdin/stdout/stderr (stdio: 'inherit').
25
+ * Returns when the agent exits. Works cross-platform.
26
+ *
27
+ * This is the `git commit` / `$EDITOR` pattern.
28
+ */
29
+ export declare function launchAgentForeground(agent: AgentEntry, cwd: string): {
30
+ exitCode: number | null;
31
+ error?: string;
32
+ };
33
+ /**
34
+ * Open an IDE/GUI agent with the project directory.
35
+ * Uses `open -a` (macOS), `xdg-open` (Linux), or `start` (Windows).
36
+ */
37
+ export declare function launchAgentIDE(agent: AgentEntry, cwd: string): {
38
+ success: boolean;
39
+ error?: string;
40
+ };
41
+ export interface LaunchResult {
42
+ launched: boolean;
43
+ clipboardCopied: boolean;
44
+ error?: string;
45
+ }
46
+ /**
47
+ * Launch an agent with a prompt. Always copies to clipboard first.
48
+ *
49
+ * For terminal agents (claude, codex, gemini): foreground spawn.
50
+ * For IDE agents (cursor, windsurf): open app.
51
+ * For clipboard: copy only.
52
+ */
53
+ export declare function launchAgent(agent: AgentEntry, prompt: string, cwd: string): LaunchResult;
54
+ //# sourceMappingURL=launcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"launcher.d.ts","sourceRoot":"","sources":["../../src/agents/launcher.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAIH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAI7C,8DAA8D;AAC9D,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAmBrD;AAID;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,GAAG;IACrE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAyBA;AAID;;;GAGG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,GAAG;IAC9D,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAwCA;AAID,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,OAAO,CAAC;IAClB,eAAe,EAAE,OAAO,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,YAAY,CAyBxF"}
@@ -0,0 +1,152 @@
1
+ /**
2
+ * GuardLink Agents — Launch helpers.
3
+ *
4
+ * Two launch patterns:
5
+ * 1. Foreground spawn (CLI + TUI): takes over terminal, returns on exit
6
+ * 2. IDE launch: opens GUI app with project directory
7
+ *
8
+ * Clipboard copy is always performed first regardless of agent type.
9
+ *
10
+ * @exposes #agent-launcher to #child-proc-injection [high] cwe:CWE-78 -- "Spawns child processes for AI coding agents"
11
+ * @exposes #agent-launcher to #cmd-injection [critical] cwe:CWE-78 -- "Windows launch uses shell:true in spawnSync"
12
+ * @mitigates #agent-launcher against #child-proc-injection using #process-sandbox -- "Agent commands are fixed binaries (claude, codex), not user-controlled"
13
+ * @mitigates #agent-launcher against #cmd-injection using #param-commands -- "spawnSync with args array on macOS/Linux, only Windows uses shell"
14
+ * @flows #cli -> #agent-launcher via launchAgent -- "CLI invokes agent with prompt and cwd"
15
+ * @flows #agent-launcher -> External_Process via spawnSync -- "Spawns claude, codex, cursor, etc."
16
+ * @boundary between #agent-launcher and External_AI_Agents (#agent-boundary) -- "Process spawn crosses trust boundary to external AI tools"
17
+ * @comment -- "copyToClipboard uses platform-specific clipboard commands (pbcopy, xclip, clip)"
18
+ */
19
+ import { spawnSync } from 'node:child_process';
20
+ import { platform } from 'node:os';
21
+ // ─── Clipboard ───────────────────────────────────────────────────────
22
+ /** Copy text to system clipboard. Returns true on success. */
23
+ export function copyToClipboard(text) {
24
+ const cmds = platform() === 'darwin'
25
+ ? ['pbcopy']
26
+ : platform() === 'win32'
27
+ ? ['clip']
28
+ : ['xclip -selection clipboard', 'xsel --clipboard --input'];
29
+ for (const cmd of cmds) {
30
+ const [bin, ...args] = cmd.split(' ');
31
+ try {
32
+ const result = spawnSync(bin, args, {
33
+ input: text,
34
+ stdio: ['pipe', 'pipe', 'pipe'],
35
+ timeout: 5000,
36
+ });
37
+ if (result.status === 0)
38
+ return true;
39
+ }
40
+ catch {
41
+ continue;
42
+ }
43
+ }
44
+ return false;
45
+ }
46
+ // ─── Foreground spawn (CLI terminal agents) ──────────────────────────
47
+ /**
48
+ * Launch a CLI agent in the foreground — takes over the current terminal.
49
+ * The agent gets full stdin/stdout/stderr (stdio: 'inherit').
50
+ * Returns when the agent exits. Works cross-platform.
51
+ *
52
+ * This is the `git commit` / `$EDITOR` pattern.
53
+ */
54
+ export function launchAgentForeground(agent, cwd) {
55
+ if (!agent.cmd) {
56
+ return { exitCode: null, error: `${agent.name} is not a terminal agent` };
57
+ }
58
+ try {
59
+ const result = spawnSync(agent.cmd, [], {
60
+ cwd,
61
+ stdio: 'inherit',
62
+ env: { ...process.env },
63
+ // No timeout — user controls session duration
64
+ });
65
+ if (result.error) {
66
+ // Binary not found or spawn failed
67
+ const msg = result.error.code === 'ENOENT'
68
+ ? `${agent.name} (${agent.cmd}) not found. Install it first.`
69
+ : `Failed to launch ${agent.name}: ${result.error.message}`;
70
+ return { exitCode: null, error: msg };
71
+ }
72
+ return { exitCode: result.status };
73
+ }
74
+ catch (err) {
75
+ return { exitCode: null, error: `Failed to launch ${agent.name}: ${err.message}` };
76
+ }
77
+ }
78
+ // ─── IDE app launch ──────────────────────────────────────────────────
79
+ /**
80
+ * Open an IDE/GUI agent with the project directory.
81
+ * Uses `open -a` (macOS), `xdg-open` (Linux), or `start` (Windows).
82
+ */
83
+ export function launchAgentIDE(agent, cwd) {
84
+ if (!agent.app) {
85
+ return { success: false, error: `${agent.name} is not an IDE agent` };
86
+ }
87
+ try {
88
+ const os = platform();
89
+ let result;
90
+ if (os === 'darwin') {
91
+ result = spawnSync('open', ['-a', agent.app, cwd], {
92
+ stdio: ['pipe', 'pipe', 'pipe'],
93
+ timeout: 10000,
94
+ });
95
+ }
96
+ else if (os === 'win32') {
97
+ result = spawnSync('start', ['', agent.app], {
98
+ cwd,
99
+ shell: true,
100
+ stdio: ['pipe', 'pipe', 'pipe'],
101
+ timeout: 10000,
102
+ });
103
+ }
104
+ else {
105
+ // Linux — try xdg-open or direct binary
106
+ result = spawnSync('xdg-open', [cwd], {
107
+ stdio: ['pipe', 'pipe', 'pipe'],
108
+ timeout: 10000,
109
+ });
110
+ }
111
+ if (result.error || (result.status !== null && result.status !== 0)) {
112
+ return {
113
+ success: false,
114
+ error: `Could not open ${agent.name} automatically. Open it manually and navigate to: ${cwd}`,
115
+ };
116
+ }
117
+ return { success: true };
118
+ }
119
+ catch (err) {
120
+ return { success: false, error: err.message };
121
+ }
122
+ }
123
+ /**
124
+ * Launch an agent with a prompt. Always copies to clipboard first.
125
+ *
126
+ * For terminal agents (claude, codex, gemini): foreground spawn.
127
+ * For IDE agents (cursor, windsurf): open app.
128
+ * For clipboard: copy only.
129
+ */
130
+ export function launchAgent(agent, prompt, cwd) {
131
+ // Step 1: Always copy to clipboard
132
+ const clipboardCopied = copyToClipboard(prompt);
133
+ // Step 2: clipboard-only mode
134
+ if (agent.id === 'clipboard') {
135
+ return { launched: true, clipboardCopied };
136
+ }
137
+ // Step 3: Terminal agent — foreground spawn
138
+ if (agent.cmd) {
139
+ const { exitCode, error } = launchAgentForeground(agent, cwd);
140
+ if (error) {
141
+ return { launched: false, clipboardCopied, error };
142
+ }
143
+ return { launched: true, clipboardCopied };
144
+ }
145
+ // Step 4: IDE agent — open app
146
+ if (agent.app) {
147
+ const { success, error } = launchAgentIDE(agent, cwd);
148
+ return { launched: success, clipboardCopied, error };
149
+ }
150
+ return { launched: false, clipboardCopied, error: `Unknown agent type: ${agent.id}` };
151
+ }
152
+ //# sourceMappingURL=launcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"launcher.js","sourceRoot":"","sources":["../../src/agents/launcher.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * GuardLink Agents — Prompt builders for annotation and analysis.
3
+ *
4
+ * Extracted from tui/commands.ts for shared use across CLI, TUI, MCP.
5
+ */
6
+ import type { ThreatModel } from '../types/index.js';
7
+ /**
8
+ * Build a prompt for annotation agents.
9
+ *
10
+ * Includes the GuardLink reference doc (truncated), current model summary,
11
+ * user instructions, and precise GAL syntax rules with common pitfalls.
12
+ */
13
+ export declare function buildAnnotatePrompt(userPrompt: string, root: string, model: ThreatModel | null): string;
14
+ //# sourceMappingURL=prompts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../src/agents/prompts.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,WAAW,GAAG,IAAI,GACxB,MAAM,CAyGR"}
@@ -0,0 +1,120 @@
1
+ /**
2
+ * GuardLink Agents — Prompt builders for annotation and analysis.
3
+ *
4
+ * Extracted from tui/commands.ts for shared use across CLI, TUI, MCP.
5
+ */
6
+ import { existsSync, readFileSync } from 'node:fs';
7
+ import { resolve } from 'node:path';
8
+ /**
9
+ * Build a prompt for annotation agents.
10
+ *
11
+ * Includes the GuardLink reference doc (truncated), current model summary,
12
+ * user instructions, and precise GAL syntax rules with common pitfalls.
13
+ */
14
+ export function buildAnnotatePrompt(userPrompt, root, model) {
15
+ // Read the reference doc if available
16
+ let refDoc = '';
17
+ const refPath = resolve(root, '.guardlink', 'GUARDLINK_REFERENCE.md');
18
+ if (existsSync(refPath)) {
19
+ refDoc = readFileSync(refPath, 'utf-8');
20
+ }
21
+ let modelSummary = 'No threat model parsed yet. Run `guardlink parse` after annotating.';
22
+ let existingIds = '';
23
+ if (model) {
24
+ const parts = [
25
+ `${model.annotations_parsed} annotations`,
26
+ `${model.exposures.length} exposures`,
27
+ `${model.assets.length} assets`,
28
+ `${model.threats.length} threats`,
29
+ `${model.controls.length} controls`,
30
+ `${model.mitigations.length} mitigations`,
31
+ ];
32
+ modelSummary = `Current model: ${parts.join(', ')}.`;
33
+ // Include existing IDs so the agent doesn't create duplicates or dangling refs
34
+ const threatIds = model.threats.filter(t => t.id).map(t => `#${t.id}`);
35
+ const assetIds = model.assets.filter(a => a.id).map(a => `#${a.id}`);
36
+ const controlIds = model.controls.filter(c => c.id).map(c => `#${c.id}`);
37
+ if (threatIds.length + assetIds.length + controlIds.length > 0) {
38
+ const sections = [];
39
+ if (threatIds.length)
40
+ sections.push(`Threats: ${threatIds.join(', ')}`);
41
+ if (assetIds.length)
42
+ sections.push(`Assets: ${assetIds.join(', ')}`);
43
+ if (controlIds.length)
44
+ sections.push(`Controls: ${controlIds.join(', ')}`);
45
+ existingIds = `\n\nExisting defined IDs (use these in @exposes, @mitigates, etc.):\n${sections.join('\n')}`;
46
+ }
47
+ }
48
+ return `You are annotating a codebase with GuardLink security annotations.
49
+
50
+ ${refDoc ? '## GuardLink Reference\n\n' + refDoc.slice(0, 4000) + '\n\n' : ''}## Current State
51
+ ${modelSummary}${existingIds}
52
+
53
+ ## Task
54
+ ${userPrompt}
55
+
56
+ ## PRECISE Annotation Syntax (follow EXACTLY)
57
+
58
+ Definitions go in .guardlink/definitions.js (or .py/.rs). Source files use only relationship verbs.
59
+
60
+ ### Definitions
61
+ \`\`\`
62
+ // @shield:begin -- "Example annotations for agent prompt, excluded from parsing"
63
+ // @asset Server.Auth (#auth) -- "Authentication service"
64
+ // @threat SQL_Injection (#sqli) [P0] cwe:CWE-89 -- "Unsanitized input in SQL"
65
+ // @control Prepared_Statements (#prepared-stmts) -- "Parameterized queries"
66
+ // @shield:end
67
+ \`\`\`
68
+
69
+ ### Relationships (use in source files)
70
+ \`\`\`
71
+ // @shield:begin -- "Example annotations for agent prompt, excluded from parsing"
72
+ // @exposes #auth to #sqli [P0] cwe:CWE-89 owasp:A03:2021 -- "User input concatenated into query"
73
+ // @mitigates #auth against #sqli using #prepared-stmts -- "Uses parameterized queries"
74
+ // @flows req.body.username -> db.query via string-concat -- "User input flows to SQL"
75
+ // @boundary between #frontend and #api (#trust-boundary) -- "Public/private boundary"
76
+ // @handles pii on #auth -- "Processes user credentials"
77
+ // @comment -- "TODO: add rate limiting to prevent brute force"
78
+ // @shield:end
79
+ \`\`\`
80
+
81
+ ## CRITICAL SYNTAX RULES (violations cause parse errors)
82
+
83
+ 1. **@boundary requires TWO assets**: \`@boundary between #A and #B\` or \`@boundary #A | #B\`.
84
+ WRONG: \`@boundary api -- "desc"\` (only one argument — will NOT parse)
85
+ RIGHT: \`@boundary between #api and #client (#api-boundary) -- "Trust boundary"\`
86
+
87
+ 2. **@flows is ONE source → ONE target per line**: \`@flows <source> -> <target> via <mechanism>\`.
88
+ WRONG: \`@flows A -> B, C -> D -- "desc"\` (commas not supported)
89
+ RIGHT: \`@flows A -> B via mechanism -- "desc"\` (one per line, repeat for multiple)
90
+
91
+ 3. **@exposes / @mitigates require DEFINED #id refs**: Every \`#id\` you reference must exist as a definition.
92
+ Before using \`@exposes #app to #sqli\`, ensure \`@threat SQL_Injection (#sqli)\` exists in definitions.
93
+ Add new definitions to .guardlink/definitions.js FIRST, then reference them in source files.
94
+
95
+ 4. **Severity in square brackets**: \`[P0]\` \`[P1]\` \`[P2]\` \`[P3]\` or \`[critical]\` \`[high]\` \`[medium]\` \`[low]\`.
96
+ Goes AFTER the threat ref in @exposes: \`@exposes #app to #sqli [P0] cwe:CWE-89\`
97
+
98
+ 5. **Descriptions in double quotes after --**: \`-- "description text here"\`
99
+ WRONG: \`@comment "just a note"\` or \`@comment -- note without quotes\`
100
+ RIGHT: \`@comment -- "security-relevant developer note"\`
101
+
102
+ 6. **IDs use parentheses in definitions, hash in references**:
103
+ Definition: \`@threat SQL_Injection (#sqli)\`
104
+ Reference: \`@exposes #app to #sqli\`
105
+
106
+ 7. **Asset references**: Use \`#id\` or \`Dotted.Path\` (e.g., \`Server.Auth\`, \`req.body.input\`).
107
+ Names with spaces or special chars will NOT parse.
108
+
109
+ 8. **External refs are space-separated after severity**: \`cwe:CWE-89 owasp:A03:2021 capec:CAPEC-66\`
110
+
111
+ ## Workflow
112
+ 1. Read existing definitions in .guardlink/definitions.js — reuse existing IDs
113
+ 2. Add any NEW threat/control definitions FIRST
114
+ 3. Then add relationship annotations (@exposes, @mitigates, @flows, etc.) in source files
115
+ 4. Use the project's comment style (// for JS/TS, # for Python, etc.)
116
+ 5. Run guardlink_validate (MCP) or \`guardlink validate\` to check for errors
117
+ 6. Fix any validation errors before finishing
118
+ `;
119
+ }
120
+ //# sourceMappingURL=prompts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../src/agents/prompts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,80 @@
1
+ /**
2
+ * GuardLink Threat Reports — AI-powered threat model analysis.
3
+ *
4
+ * Serializes the threat model, sends it to an LLM with a framework-
5
+ * specific prompt, streams the response, and saves timestamped results
6
+ * to .guardlink/threat-reports/.
7
+ *
8
+ * @exposes #llm-client to #arbitrary-write [high] cwe:CWE-73 -- "Writes threat reports to .guardlink/threat-reports/"
9
+ * @exposes #llm-client to #prompt-injection [medium] cwe:CWE-77 -- "Serialized threat model embedded in LLM prompt"
10
+ * @accepts #prompt-injection on #llm-client -- "Core feature: threat model serialized as LLM prompt for analysis"
11
+ * @mitigates #llm-client against #arbitrary-write using #path-validation -- "Reports written to fixed .guardlink/threat-reports/ subdirectory"
12
+ * @flows #parser -> #llm-client via ThreatModel -- "Parsed model data serialized for LLM analysis"
13
+ * @flows #llm-client -> Filesystem via writeFileSync -- "Analysis results saved as markdown files"
14
+ * @handles internal on #llm-client -- "Processes security-sensitive threat model for AI analysis"
15
+ */
16
+ import type { ThreatModel } from '../types/index.js';
17
+ import { type AnalysisFramework } from './prompts.js';
18
+ import { type LLMConfig } from './llm.js';
19
+ export { type AnalysisFramework, FRAMEWORK_LABELS, FRAMEWORK_PROMPTS, buildUserMessage } from './prompts.js';
20
+ export { type LLMConfig, type LLMProvider, buildConfig, autoDetectConfig } from './llm.js';
21
+ export interface ThreatReportOptions {
22
+ root: string;
23
+ model: ThreatModel;
24
+ framework: AnalysisFramework;
25
+ llmConfig: LLMConfig;
26
+ customPrompt?: string;
27
+ stream?: boolean;
28
+ onChunk?: (text: string) => void;
29
+ }
30
+ export interface ThreatReportResult {
31
+ framework: AnalysisFramework;
32
+ label: string;
33
+ content: string;
34
+ model: string;
35
+ timestamp: string;
36
+ savedTo?: string;
37
+ inputTokens?: number;
38
+ outputTokens?: number;
39
+ }
40
+ /**
41
+ * Serialize the threat model to a compact representation for LLM context.
42
+ * Strips empty arrays and location details to save tokens.
43
+ */
44
+ export declare function serializeModel(model: ThreatModel): string;
45
+ /**
46
+ * Compact serialization for MCP agent mode.
47
+ *
48
+ * Designed to minimize token usage (~2-3k tokens vs ~10k for full)
49
+ * while giving the agent everything it needs:
50
+ * - Stats summary (one line)
51
+ * - Asset list (compact)
52
+ * - ALL unmitigated exposures (the actionable stuff)
53
+ * - Threat severity index (deduped)
54
+ * - Flows & boundaries (structural context)
55
+ * - Data handling classifications
56
+ *
57
+ * Omits: resolved mitigations, acceptances, working controls,
58
+ * full descriptions (capped at 80 chars), per-exposure file paths,
59
+ * comments, validations, assumptions (low signal for analysis).
60
+ *
61
+ * The agent can call guardlink_parse or read guardlink://model
62
+ * for full detail if needed.
63
+ */
64
+ export declare function serializeModelCompact(model: ThreatModel): string;
65
+ export declare function generateThreatReport(opts: ThreatReportOptions): Promise<ThreatReportResult>;
66
+ export interface SavedThreatReport {
67
+ filename: string;
68
+ framework: string;
69
+ timestamp: string;
70
+ label: string;
71
+ model?: string;
72
+ /** Which directory this report was found in */
73
+ dirName?: string;
74
+ }
75
+ export declare function listThreatReports(root: string): SavedThreatReport[];
76
+ export interface ThreatReportWithContent extends SavedThreatReport {
77
+ content: string;
78
+ }
79
+ export declare function loadThreatReportsForDashboard(root: string): ThreatReportWithContent[];
80
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/analyze/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,KAAK,iBAAiB,EAAyD,MAAM,cAAc,CAAC;AAC7G,OAAO,EAAE,KAAK,SAAS,EAA+B,MAAM,UAAU,CAAC;AAEvE,OAAO,EAAE,KAAK,iBAAiB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAC7G,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,WAAW,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAI3F,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,WAAW,CAAC;IACnB,SAAS,EAAE,iBAAiB,CAAC;IAC7B,SAAS,EAAE,SAAS,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAClC;AAED,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,iBAAiB,CAAC;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAID;;;GAGG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAwEzD;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAwEhE;AASD,wBAAsB,oBAAoB,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAwDjG;AAID,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+CAA+C;IAC/C,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AA8BD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAenE;AAID,MAAM,WAAW,uBAAwB,SAAQ,iBAAiB;IAChE,OAAO,EAAE,MAAM,CAAC;CACjB;AAID,wBAAgB,6BAA6B,CAAC,IAAI,EAAE,MAAM,GAAG,uBAAuB,EAAE,CAcrF"}