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,42 @@
1
+ /**
2
+ * GuardLink init — Project detection utilities.
3
+ * Detects language, project name, and existing agent instruction files.
4
+ */
5
+ export type ProjectLanguage = 'typescript' | 'javascript' | 'python' | 'go' | 'rust' | 'java' | 'csharp' | 'ruby' | 'swift' | 'kotlin' | 'terraform' | 'unknown';
6
+ export interface AgentFile {
7
+ /** Relative path from project root */
8
+ path: string;
9
+ /** Agent platform: claude, cursor, codex, copilot, windsurf, cline, gemini, generic */
10
+ platform: string;
11
+ /** Whether the file already exists */
12
+ exists: boolean;
13
+ /** Whether it already contains GuardLink instructions */
14
+ hasGuardLink: boolean;
15
+ /** Whether the agent's directory exists (e.g. .cursor/, .claude/) even if instruction file doesn't */
16
+ dirDetected: boolean;
17
+ /** The directory hint that was detected, if any */
18
+ dirHint?: string;
19
+ }
20
+ export interface ProjectInfo {
21
+ /** Project root directory */
22
+ root: string;
23
+ /** Detected project name */
24
+ name: string;
25
+ /** Primary language */
26
+ language: ProjectLanguage;
27
+ /** Comment prefix for the primary language */
28
+ commentPrefix: string;
29
+ /** File extension for definitions file */
30
+ definitionsExt: string;
31
+ /** Detected agent instruction files */
32
+ agentFiles: AgentFile[];
33
+ /** Whether .guardlink/ already exists */
34
+ alreadyInitialized: boolean;
35
+ }
36
+ export declare function detectProject(root: string): ProjectInfo;
37
+ /**
38
+ * Get unique platforms that have been auto-detected via directory presence or existing files.
39
+ * Used by the picker to separate "detected" from "optional" agents.
40
+ */
41
+ export declare function getDetectedPlatforms(agentFiles: AgentFile[]): Map<string, string>;
42
+ //# sourceMappingURL=detect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detect.d.ts","sourceRoot":"","sources":["../../src/init/detect.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,MAAM,MAAM,eAAe,GACvB,YAAY,GAAG,YAAY,GAAG,QAAQ,GAAG,IAAI,GAAG,MAAM,GACtD,MAAM,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,GAC/C,WAAW,GAAG,SAAS,CAAC;AAE5B,MAAM,WAAW,SAAS;IACxB,sCAAsC;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,uFAAuF;IACvF,QAAQ,EAAE,MAAM,CAAC;IACjB,sCAAsC;IACtC,MAAM,EAAE,OAAO,CAAC;IAChB,yDAAyD;IACzD,YAAY,EAAE,OAAO,CAAC;IACtB,sGAAsG;IACtG,WAAW,EAAE,OAAO,CAAC;IACrB,mDAAmD;IACnD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,WAAW;IAC1B,6BAA6B;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,4BAA4B;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,uBAAuB;IACvB,QAAQ,EAAE,eAAe,CAAC;IAC1B,8CAA8C;IAC9C,aAAa,EAAE,MAAM,CAAC;IACtB,0CAA0C;IAC1C,cAAc,EAAE,MAAM,CAAC;IACvB,uCAAuC;IACvC,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,yCAAyC;IACzC,kBAAkB,EAAE,OAAO,CAAC;CAC7B;AAiDD,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAUvD;AA6GD;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,SAAS,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAWjF"}
@@ -0,0 +1,185 @@
1
+ /**
2
+ * GuardLink init — Project detection utilities.
3
+ * Detects language, project name, and existing agent instruction files.
4
+ */
5
+ import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs';
6
+ import { join, basename } from 'node:path';
7
+ // ─── Agent file locations ────────────────────────────────────────────
8
+ const AGENT_FILE_SPECS = [
9
+ { path: 'CLAUDE.md', platform: 'claude', dirHint: '.claude' },
10
+ { path: '.cursorrules', platform: 'cursor', dirHint: '.cursor' },
11
+ { path: '.cursor/rules/guardlink.mdc', platform: 'cursor', dirHint: '.cursor' },
12
+ { path: 'AGENTS.md', platform: 'codex', dirHint: '.codex' },
13
+ { path: 'codex.md', platform: 'codex', dirHint: '.codex' },
14
+ { path: '.github/copilot-instructions.md', platform: 'copilot', dirHint: '.github' },
15
+ { path: '.windsurfrules', platform: 'windsurf' },
16
+ { path: '.clinerules', platform: 'cline' },
17
+ { path: '.gemini/settings.json', platform: 'gemini', dirHint: '.gemini' },
18
+ ];
19
+ // ─── Language detection ──────────────────────────────────────────────
20
+ const LANG_SIGNALS = [
21
+ { files: ['tsconfig.json', 'tsconfig.build.json'], language: 'typescript' },
22
+ { files: ['package.json'], language: 'javascript' },
23
+ { files: ['pyproject.toml', 'setup.py', 'requirements.txt'], language: 'python' },
24
+ { files: ['go.mod', 'go.sum'], language: 'go' },
25
+ { files: ['Cargo.toml', 'Cargo.lock'], language: 'rust' },
26
+ { files: ['pom.xml', 'build.gradle', 'build.gradle.kts'], language: 'java' },
27
+ { files: ['*.csproj', '*.sln'], language: 'csharp' },
28
+ { files: ['Gemfile', 'Rakefile'], language: 'ruby' },
29
+ { files: ['Package.swift'], language: 'swift' },
30
+ { files: ['build.gradle.kts'], language: 'kotlin' },
31
+ { files: ['main.tf', 'variables.tf'], language: 'terraform' },
32
+ ];
33
+ const LANG_CONFIG = {
34
+ typescript: { commentPrefix: '//', ext: '.ts' },
35
+ javascript: { commentPrefix: '//', ext: '.js' },
36
+ python: { commentPrefix: '#', ext: '.py' },
37
+ go: { commentPrefix: '//', ext: '.go' },
38
+ rust: { commentPrefix: '//', ext: '.rs' },
39
+ java: { commentPrefix: '//', ext: '.java' },
40
+ csharp: { commentPrefix: '//', ext: '.cs' },
41
+ ruby: { commentPrefix: '#', ext: '.rb' },
42
+ swift: { commentPrefix: '//', ext: '.swift' },
43
+ kotlin: { commentPrefix: '//', ext: '.kt' },
44
+ terraform: { commentPrefix: '#', ext: '.tf' },
45
+ unknown: { commentPrefix: '//', ext: '.ts' },
46
+ };
47
+ // ─── Detection functions ─────────────────────────────────────────────
48
+ export function detectProject(root) {
49
+ return {
50
+ root,
51
+ name: detectProjectName(root),
52
+ language: detectLanguage(root),
53
+ commentPrefix: LANG_CONFIG[detectLanguage(root)].commentPrefix,
54
+ definitionsExt: LANG_CONFIG[detectLanguage(root)].ext,
55
+ agentFiles: detectAgentFiles(root),
56
+ alreadyInitialized: existsSync(join(root, '.guardlink')),
57
+ };
58
+ }
59
+ function detectProjectName(root) {
60
+ // Try package.json
61
+ const pkgPath = join(root, 'package.json');
62
+ if (existsSync(pkgPath)) {
63
+ try {
64
+ const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
65
+ if (pkg.name)
66
+ return pkg.name;
67
+ }
68
+ catch { /* ignore */ }
69
+ }
70
+ // Try Cargo.toml
71
+ const cargoPath = join(root, 'Cargo.toml');
72
+ if (existsSync(cargoPath)) {
73
+ try {
74
+ const cargo = readFileSync(cargoPath, 'utf-8');
75
+ const m = cargo.match(/^name\s*=\s*"([^"]+)"/m);
76
+ if (m)
77
+ return m[1];
78
+ }
79
+ catch { /* ignore */ }
80
+ }
81
+ // Try go.mod
82
+ const goModPath = join(root, 'go.mod');
83
+ if (existsSync(goModPath)) {
84
+ try {
85
+ const goMod = readFileSync(goModPath, 'utf-8');
86
+ const m = goMod.match(/^module\s+(\S+)/m);
87
+ if (m)
88
+ return m[1].split('/').pop() || m[1];
89
+ }
90
+ catch { /* ignore */ }
91
+ }
92
+ // Try pyproject.toml
93
+ const pyprojectPath = join(root, 'pyproject.toml');
94
+ if (existsSync(pyprojectPath)) {
95
+ try {
96
+ const pyp = readFileSync(pyprojectPath, 'utf-8');
97
+ const m = pyp.match(/^name\s*=\s*"([^"]+)"/m);
98
+ if (m)
99
+ return m[1];
100
+ }
101
+ catch { /* ignore */ }
102
+ }
103
+ // Fallback: directory name
104
+ return basename(root);
105
+ }
106
+ function detectLanguage(root) {
107
+ let entries;
108
+ try {
109
+ entries = readdirSync(root);
110
+ }
111
+ catch {
112
+ return 'unknown';
113
+ }
114
+ for (const signal of LANG_SIGNALS) {
115
+ for (const pattern of signal.files) {
116
+ if (pattern.includes('*')) {
117
+ const ext = pattern.replace('*', '');
118
+ if (entries.some(e => e.endsWith(ext)))
119
+ return signal.language;
120
+ }
121
+ else {
122
+ if (entries.includes(pattern))
123
+ return signal.language;
124
+ }
125
+ }
126
+ }
127
+ // tsconfig.json takes priority over plain package.json for TS vs JS
128
+ if (entries.includes('tsconfig.json'))
129
+ return 'typescript';
130
+ if (entries.includes('package.json'))
131
+ return 'javascript';
132
+ return 'unknown';
133
+ }
134
+ function detectAgentFiles(root) {
135
+ const results = [];
136
+ for (const spec of AGENT_FILE_SPECS) {
137
+ const fullPath = join(root, spec.path);
138
+ const exists = existsSync(fullPath);
139
+ let hasGuardLink = false;
140
+ if (exists) {
141
+ try {
142
+ const content = readFileSync(fullPath, 'utf-8');
143
+ hasGuardLink = content.includes('GuardLink') || content.includes('guardlink');
144
+ }
145
+ catch { /* ignore */ }
146
+ }
147
+ // Check if agent directory exists even when instruction file doesn't
148
+ let dirDetected = false;
149
+ if (spec.dirHint) {
150
+ const dirPath = join(root, spec.dirHint);
151
+ try {
152
+ dirDetected = existsSync(dirPath) && statSync(dirPath).isDirectory();
153
+ }
154
+ catch { /* ignore */ }
155
+ }
156
+ results.push({
157
+ path: spec.path,
158
+ platform: spec.platform,
159
+ exists,
160
+ hasGuardLink,
161
+ dirDetected,
162
+ dirHint: spec.dirHint,
163
+ });
164
+ }
165
+ return results;
166
+ }
167
+ /**
168
+ * Get unique platforms that have been auto-detected via directory presence or existing files.
169
+ * Used by the picker to separate "detected" from "optional" agents.
170
+ */
171
+ export function getDetectedPlatforms(agentFiles) {
172
+ const detected = new Map(); // platform → reason
173
+ for (const af of agentFiles) {
174
+ if (detected.has(af.platform))
175
+ continue;
176
+ if (af.exists) {
177
+ detected.set(af.platform, `found ${af.path}`);
178
+ }
179
+ else if (af.dirDetected && af.dirHint) {
180
+ detected.set(af.platform, `found ${af.dirHint}/`);
181
+ }
182
+ }
183
+ return detected;
184
+ }
185
+ //# sourceMappingURL=detect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detect.js","sourceRoot":"","sources":["../../src/init/detect.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC1E,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAyC3C,wEAAwE;AAExE,MAAM,gBAAgB,GAAgE;IACpF,EAAE,IAAI,EAAE,WAAW,EAA2B,QAAQ,EAAE,QAAQ,EAAI,OAAO,EAAE,SAAS,EAAE;IACxF,EAAE,IAAI,EAAE,cAAc,EAAyB,QAAQ,EAAE,QAAQ,EAAI,OAAO,EAAE,SAAS,EAAE;IACzF,EAAE,IAAI,EAAE,6BAA6B,EAAS,QAAQ,EAAE,QAAQ,EAAI,OAAO,EAAE,SAAS,EAAE;IACxF,EAAE,IAAI,EAAE,WAAW,EAA4B,QAAQ,EAAE,OAAO,EAAK,OAAO,EAAE,QAAQ,EAAE;IACxF,EAAE,IAAI,EAAE,UAAU,EAA6B,QAAQ,EAAE,OAAO,EAAK,OAAO,EAAE,QAAQ,EAAE;IACxF,EAAE,IAAI,EAAE,iCAAiC,EAAM,QAAQ,EAAE,SAAS,EAAG,OAAO,EAAE,SAAS,EAAE;IACzF,EAAE,IAAI,EAAE,gBAAgB,EAAuB,QAAQ,EAAE,UAAU,EAAE;IACrE,EAAE,IAAI,EAAE,aAAa,EAA0B,QAAQ,EAAE,OAAO,EAAE;IAClE,EAAE,IAAI,EAAE,uBAAuB,EAAgB,QAAQ,EAAE,QAAQ,EAAI,OAAO,EAAE,SAAS,EAAE;CAC1F,CAAC;AAEF,wEAAwE;AAExE,MAAM,YAAY,GAA0D;IAC1E,EAAE,KAAK,EAAE,CAAC,eAAe,EAAE,qBAAqB,CAAC,EAAU,QAAQ,EAAE,YAAY,EAAE;IACnF,EAAE,KAAK,EAAE,CAAC,cAAc,CAAC,EAAmC,QAAQ,EAAE,YAAY,EAAE;IACpF,EAAE,KAAK,EAAE,CAAC,gBAAgB,EAAE,UAAU,EAAE,kBAAkB,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE;IACjF,EAAE,KAAK,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAA+B,QAAQ,EAAE,IAAI,EAAE;IAC5E,EAAE,KAAK,EAAE,CAAC,YAAY,EAAE,YAAY,CAAC,EAAuB,QAAQ,EAAE,MAAM,EAAE;IAC9E,EAAE,KAAK,EAAE,CAAC,SAAS,EAAE,cAAc,EAAE,kBAAkB,CAAC,EAAG,QAAQ,EAAE,MAAM,EAAE;IAC7E,EAAE,KAAK,EAAE,CAAC,UAAU,EAAE,OAAO,CAAC,EAA8B,QAAQ,EAAE,QAAQ,EAAE;IAChF,EAAE,KAAK,EAAE,CAAC,SAAS,EAAE,UAAU,CAAC,EAA4B,QAAQ,EAAE,MAAM,EAAE;IAC9E,EAAE,KAAK,EAAE,CAAC,eAAe,CAAC,EAAkC,QAAQ,EAAE,OAAO,EAAE;IAC/E,EAAE,KAAK,EAAE,CAAC,kBAAkB,CAAC,EAA+B,QAAQ,EAAE,QAAQ,EAAE;IAChF,EAAE,KAAK,EAAE,CAAC,SAAS,EAAE,cAAc,CAAC,EAAwB,QAAQ,EAAE,WAAW,EAAE;CACpF,CAAC;AAEF,MAAM,WAAW,GAAoE;IACnF,UAAU,EAAG,EAAE,aAAa,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE;IAChD,UAAU,EAAG,EAAE,aAAa,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE;IAChD,MAAM,EAAO,EAAE,aAAa,EAAE,GAAG,EAAG,GAAG,EAAE,KAAK,EAAE;IAChD,EAAE,EAAW,EAAE,aAAa,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE;IAChD,IAAI,EAAS,EAAE,aAAa,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE;IAChD,IAAI,EAAS,EAAE,aAAa,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE;IAClD,MAAM,EAAO,EAAE,aAAa,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE;IAChD,IAAI,EAAS,EAAE,aAAa,EAAE,GAAG,EAAG,GAAG,EAAE,KAAK,EAAE;IAChD,KAAK,EAAQ,EAAE,aAAa,EAAE,IAAI,EAAE,GAAG,EAAE,QAAQ,EAAE;IACnD,MAAM,EAAO,EAAE,aAAa,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE;IAChD,SAAS,EAAI,EAAE,aAAa,EAAE,GAAG,EAAG,GAAG,EAAE,KAAK,EAAE;IAChD,OAAO,EAAM,EAAE,aAAa,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE;CACjD,CAAC;AAEF,wEAAwE;AAExE,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,OAAO;QACL,IAAI;QACJ,IAAI,EAAE,iBAAiB,CAAC,IAAI,CAAC;QAC7B,QAAQ,EAAE,cAAc,CAAC,IAAI,CAAC;QAC9B,aAAa,EAAE,WAAW,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,aAAa;QAC9D,cAAc,EAAE,WAAW,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG;QACrD,UAAU,EAAE,gBAAgB,CAAC,IAAI,CAAC;QAClC,kBAAkB,EAAE,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;KACzD,CAAC;AACJ,CAAC;AAED,SAAS,iBAAiB,CAAC,IAAY;IACrC,mBAAmB;IACnB,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;IAC3C,IAAI,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QACxB,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;YACvD,IAAI,GAAG,CAAC,IAAI;gBAAE,OAAO,GAAG,CAAC,IAAI,CAAC;QAChC,CAAC;QAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;IAC1B,CAAC;IAED,iBAAiB;IACjB,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;IAC3C,IAAI,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC1B,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,YAAY,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;YAC/C,MAAM,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC;YAChD,IAAI,CAAC;gBAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;QACrB,CAAC;QAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;IAC1B,CAAC;IAED,aAAa;IACb,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IACvC,IAAI,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC1B,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,YAAY,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;YAC/C,MAAM,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;YAC1C,IAAI,CAAC;gBAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9C,CAAC;QAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;IAC1B,CAAC;IAED,qBAAqB;IACrB,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,EAAE,gBAAgB,CAAC,CAAC;IACnD,IAAI,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;QAC9B,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,YAAY,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;YACjD,MAAM,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC;YAC9C,IAAI,CAAC;gBAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;QACrB,CAAC;QAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;IAC1B,CAAC;IAED,2BAA2B;IAC3B,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC;AACxB,CAAC;AAED,SAAS,cAAc,CAAC,IAAY;IAClC,IAAI,OAAiB,CAAC;IACtB,IAAI,CAAC;QACH,OAAO,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IAC9B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,KAAK,MAAM,MAAM,IAAI,YAAY,EAAE,CAAC;QAClC,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;YACnC,IAAI,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC1B,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;gBACrC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;oBAAE,OAAO,MAAM,CAAC,QAAQ,CAAC;YACjE,CAAC;iBAAM,CAAC;gBACN,IAAI,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC;oBAAE,OAAO,MAAM,CAAC,QAAQ,CAAC;YACxD,CAAC;QACH,CAAC;IACH,CAAC;IAED,oEAAoE;IACpE,IAAI,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAC;QAAE,OAAO,YAAY,CAAC;IAC3D,IAAI,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC;QAAE,OAAO,YAAY,CAAC;IAE1D,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,gBAAgB,CAAC,IAAY;IACpC,MAAM,OAAO,GAAgB,EAAE,CAAC;IAEhC,KAAK,MAAM,IAAI,IAAI,gBAAgB,EAAE,CAAC;QACpC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QACvC,MAAM,MAAM,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;QACpC,IAAI,YAAY,GAAG,KAAK,CAAC;QAEzB,IAAI,MAAM,EAAE,CAAC;YACX,IAAI,CAAC;gBACH,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;gBAChD,YAAY,GAAG,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;YAChF,CAAC;YAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;QAC1B,CAAC;QAED,qEAAqE;QACrE,IAAI,WAAW,GAAG,KAAK,CAAC;QACxB,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;YACzC,IAAI,CAAC;gBACH,WAAW,GAAG,UAAU,CAAC,OAAO,CAAC,IAAI,QAAQ,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC;YACvE,CAAC;YAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;QAC1B,CAAC;QAED,OAAO,CAAC,IAAI,CAAC;YACX,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,MAAM;YACN,YAAY;YACZ,WAAW;YACX,OAAO,EAAE,IAAI,CAAC,OAAO;SACtB,CAAC,CAAC;IACL,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAAC,UAAuB;IAC1D,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAkB,CAAC,CAAC,oBAAoB;IAChE,KAAK,MAAM,EAAE,IAAI,UAAU,EAAE,CAAC;QAC5B,IAAI,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,QAAQ,CAAC;YAAE,SAAS;QACxC,IAAI,EAAE,CAAC,MAAM,EAAE,CAAC;YACd,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,QAAQ,EAAE,SAAS,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;QAChD,CAAC;aAAM,IAAI,EAAE,CAAC,WAAW,IAAI,EAAE,CAAC,OAAO,EAAE,CAAC;YACxC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,QAAQ,EAAE,SAAS,EAAE,CAAC,OAAO,GAAG,CAAC,CAAC;QACpD,CAAC;IACH,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * GuardLink init — Project initialization.
3
+ *
4
+ * Detects project language and existing agent files, creates .guardlink/
5
+ * directory with shared definitions, and injects GuardLink instructions
6
+ * into agent instruction files (CLAUDE.md, .cursorrules, etc.).
7
+ *
8
+ * @exposes #init to #arbitrary-write [high] cwe:CWE-73 -- "Writes config files and agent instructions to user-specified root"
9
+ * @exposes #init to #path-traversal [high] cwe:CWE-22 -- "Creates directories and files based on user-provided root path"
10
+ * @mitigates #init against #arbitrary-write using #path-validation -- "Files written only to .guardlink/ subdirectory and known agent file locations"
11
+ * @mitigates #init against #path-traversal using #path-validation -- "join() used with fixed relative paths within root"
12
+ * @flows #cli -> #init via initProject -- "CLI passes user-specified root directory"
13
+ * @flows #init -> Filesystem via writeFileSync -- "Creates config.json, definitions.ts, agent instruction files"
14
+ */
15
+ import { type ProjectInfo } from './detect.js';
16
+ export { detectProject, type ProjectInfo, type AgentFile } from './detect.js';
17
+ export { promptAgentSelection, resolveAgentFiles, AGENT_CHOICES } from './picker.js';
18
+ export interface InitOptions {
19
+ /** Project root directory */
20
+ root: string;
21
+ /** Override project name */
22
+ project?: string;
23
+ /** Skip agent file updates (only create .guardlink/) */
24
+ skipAgentFiles?: boolean;
25
+ /** Force overwrite even if already initialized */
26
+ force?: boolean;
27
+ /** Dry run — show what would be created without writing */
28
+ dryRun?: boolean;
29
+ /** Explicit agent IDs to create files for (when no existing agent files found) */
30
+ agentIds?: string[];
31
+ }
32
+ export interface InitResult {
33
+ project: ProjectInfo;
34
+ created: string[];
35
+ updated: string[];
36
+ skipped: string[];
37
+ }
38
+ export declare function initProject(options: InitOptions): InitResult;
39
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/init/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH,OAAO,EAAiB,KAAK,WAAW,EAAkB,MAAM,aAAa,CAAC;AAa9E,OAAO,EAAE,aAAa,EAAE,KAAK,WAAW,EAAE,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AAC9E,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAIrF,MAAM,WAAW,WAAW;IAC1B,6BAA6B;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,4BAA4B;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,wDAAwD;IACxD,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,kDAAkD;IAClD,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,2DAA2D;IAC3D,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,kFAAkF;IAClF,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,WAAW,CAAC;IACrB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AASD,wBAAgB,WAAW,CAAC,OAAO,EAAE,WAAW,GAAG,UAAU,CAoF5D"}
@@ -0,0 +1,228 @@
1
+ /**
2
+ * GuardLink init — Project initialization.
3
+ *
4
+ * Detects project language and existing agent files, creates .guardlink/
5
+ * directory with shared definitions, and injects GuardLink instructions
6
+ * into agent instruction files (CLAUDE.md, .cursorrules, etc.).
7
+ *
8
+ * @exposes #init to #arbitrary-write [high] cwe:CWE-73 -- "Writes config files and agent instructions to user-specified root"
9
+ * @exposes #init to #path-traversal [high] cwe:CWE-22 -- "Creates directories and files based on user-provided root path"
10
+ * @mitigates #init against #arbitrary-write using #path-validation -- "Files written only to .guardlink/ subdirectory and known agent file locations"
11
+ * @mitigates #init against #path-traversal using #path-validation -- "join() used with fixed relative paths within root"
12
+ * @flows #cli -> #init via initProject -- "CLI passes user-specified root directory"
13
+ * @flows #init -> Filesystem via writeFileSync -- "Creates config.json, definitions.ts, agent instruction files"
14
+ */
15
+ import { existsSync, readFileSync, mkdirSync, writeFileSync, appendFileSync } from 'node:fs';
16
+ import { join, dirname } from 'node:path';
17
+ import { detectProject } from './detect.js';
18
+ import { agentInstructions, cursorRulesContent, cursorMdcContent, definitionsContent, configContent, mcpConfig, referenceDocContent, GITIGNORE_ENTRY, } from './templates.js';
19
+ import { AGENT_CHOICES } from './picker.js';
20
+ export { detectProject } from './detect.js';
21
+ export { promptAgentSelection, resolveAgentFiles, AGENT_CHOICES } from './picker.js';
22
+ // ─── Marker for detecting our content ────────────────────────────────
23
+ const GUARDLINK_MARKER = '<!-- guardlink:begin -->';
24
+ const GUARDLINK_MARKER_END = '<!-- guardlink:end -->';
25
+ // ─── Main init function ──────────────────────────────────────────────
26
+ export function initProject(options) {
27
+ const { root, force = false, dryRun = false, skipAgentFiles = false } = options;
28
+ const project = detectProject(root);
29
+ if (options.project)
30
+ project.name = options.project;
31
+ const created = [];
32
+ const updated = [];
33
+ const skipped = [];
34
+ // ── 1. Create .guardlink/ directory ──
35
+ const tsDir = join(root, '.guardlink');
36
+ if (!existsSync(tsDir)) {
37
+ if (!dryRun)
38
+ mkdirSync(tsDir, { recursive: true });
39
+ created.push('.guardlink/');
40
+ }
41
+ // ── 2. Create config.json ──
42
+ const configPath = join(tsDir, 'config.json');
43
+ if (!existsSync(configPath) || force) {
44
+ if (!dryRun)
45
+ writeFileSync(configPath, configContent(project));
46
+ created.push('.guardlink/config.json');
47
+ }
48
+ else {
49
+ skipped.push('.guardlink/config.json (exists)');
50
+ }
51
+ // ── 3. Create definitions file ──
52
+ const defsFile = `definitions${project.definitionsExt}`;
53
+ const defsPath = join(tsDir, defsFile);
54
+ if (!existsSync(defsPath) || force) {
55
+ if (!dryRun)
56
+ writeFileSync(defsPath, definitionsContent(project));
57
+ created.push(`.guardlink/${defsFile}`);
58
+ }
59
+ else {
60
+ skipped.push(`.guardlink/${defsFile} (exists)`);
61
+ }
62
+ // ── 4. Create docs/GUARDLINK_REFERENCE.md ──
63
+ const docsDir = join(root, 'docs');
64
+ const refDocPath = join(docsDir, 'GUARDLINK_REFERENCE.md');
65
+ if (!existsSync(refDocPath) || force) {
66
+ if (!dryRun) {
67
+ ensureDir(docsDir);
68
+ writeFileSync(refDocPath, referenceDocContent(project));
69
+ }
70
+ created.push('docs/GUARDLINK_REFERENCE.md');
71
+ }
72
+ else {
73
+ skipped.push('docs/GUARDLINK_REFERENCE.md (exists)');
74
+ }
75
+ // ── 5. Update .gitignore ──
76
+ const gitignorePath = join(root, '.gitignore');
77
+ if (existsSync(gitignorePath)) {
78
+ const content = readFileSync(gitignorePath, 'utf-8');
79
+ if (!content.includes('GuardLink') && !content.includes('.guardlink')) {
80
+ if (!dryRun)
81
+ appendFileSync(gitignorePath, GITIGNORE_ENTRY);
82
+ updated.push('.gitignore');
83
+ }
84
+ }
85
+ // ── 6. Update/create agent instruction files ──
86
+ if (!skipAgentFiles) {
87
+ const agentResults = updateAgentFiles(root, project, force, dryRun, options.agentIds);
88
+ created.push(...agentResults.created);
89
+ updated.push(...agentResults.updated);
90
+ skipped.push(...agentResults.skipped);
91
+ }
92
+ // ── 7. Create .mcp.json for Claude Code MCP integration ──
93
+ const mcpPath = join(root, '.mcp.json');
94
+ if (!existsSync(mcpPath) || force) {
95
+ if (!dryRun)
96
+ writeFileSync(mcpPath, mcpConfig());
97
+ created.push('.mcp.json');
98
+ }
99
+ else {
100
+ skipped.push('.mcp.json (exists)');
101
+ }
102
+ return { project, created, updated, skipped };
103
+ }
104
+ // ─── Agent file update logic ─────────────────────────────────────────
105
+ function updateAgentFiles(root, project, force, dryRun, agentIds) {
106
+ const created = [];
107
+ const updated = [];
108
+ const skipped = [];
109
+ const ids = agentIds ?? ['claude'];
110
+ for (const id of ids) {
111
+ const choice = AGENT_CHOICES.find(c => c.id === id);
112
+ if (!choice)
113
+ continue;
114
+ const filePath = join(root, choice.file);
115
+ const exists = existsSync(filePath);
116
+ if (exists) {
117
+ // File exists — inject/update GuardLink block
118
+ const af = project.agentFiles.find(f => f.path === choice.file);
119
+ if (af?.hasGuardLink && !force) {
120
+ skipped.push(`${choice.file} (already has GuardLink)`);
121
+ continue;
122
+ }
123
+ const result = injectIntoAgentFile(root, choice.file, project, force, dryRun);
124
+ if (result === 'updated')
125
+ updated.push(choice.file);
126
+ else if (result === 'skipped')
127
+ skipped.push(choice.file);
128
+ }
129
+ else {
130
+ // File doesn't exist — create fresh
131
+ if (choice.file.endsWith('.mdc')) {
132
+ if (!dryRun) {
133
+ ensureDir(dirname(filePath));
134
+ writeFileSync(filePath, cursorMdcContent(project));
135
+ }
136
+ created.push(choice.file);
137
+ }
138
+ else if (choice.file === '.cursorrules' || choice.file === '.windsurfrules' || choice.file === '.clinerules') {
139
+ if (!dryRun) {
140
+ writeFileSync(filePath, wrapMarkers(cursorRulesContent(project)));
141
+ }
142
+ created.push(choice.file);
143
+ }
144
+ else {
145
+ // Markdown-based (CLAUDE.md, AGENTS.md, copilot-instructions.md, .gemini/GEMINI.md)
146
+ if (!dryRun) {
147
+ ensureDir(dirname(filePath));
148
+ writeFileSync(filePath, buildClaudeMdFromScratch(project));
149
+ }
150
+ created.push(choice.file);
151
+ }
152
+ }
153
+ }
154
+ return { created, updated, skipped };
155
+ }
156
+ function injectIntoAgentFile(root, relPath, project, force, dryRun) {
157
+ const fullPath = join(root, relPath);
158
+ // Special handling for Cursor .mdc files
159
+ if (relPath.endsWith('.mdc')) {
160
+ if (!dryRun) {
161
+ ensureDir(dirname(fullPath));
162
+ writeFileSync(fullPath, cursorMdcContent(project));
163
+ }
164
+ return 'updated';
165
+ }
166
+ // Special handling for .cursorrules / .windsurfrules / .clinerules (no markdown headers)
167
+ if (relPath === '.cursorrules' || relPath === '.windsurfrules' || relPath === '.clinerules') {
168
+ const existing = readFileSync(fullPath, 'utf-8');
169
+ if (existing.includes('GuardLink') && !force)
170
+ return 'skipped';
171
+ if (!dryRun) {
172
+ const block = wrapMarkers(cursorRulesContent(project));
173
+ const newContent = replaceOrAppend(existing, block);
174
+ writeFileSync(fullPath, newContent);
175
+ }
176
+ return 'updated';
177
+ }
178
+ // Special handling for Gemini settings.json
179
+ if (relPath.endsWith('settings.json')) {
180
+ return 'skipped';
181
+ }
182
+ // All other markdown-based files
183
+ const existing = readFileSync(fullPath, 'utf-8');
184
+ if (existing.includes('GuardLink') && !force)
185
+ return 'skipped';
186
+ if (!dryRun) {
187
+ const block = wrapMarkers(agentInstructions(project));
188
+ const newContent = replaceOrAppend(existing, block);
189
+ writeFileSync(fullPath, newContent);
190
+ }
191
+ return 'updated';
192
+ }
193
+ function buildClaudeMdFromScratch(project) {
194
+ return `# ${toPascalCase(project.name)} — Project Instructions
195
+
196
+ ${wrapMarkers(agentInstructions(project))}`;
197
+ }
198
+ // ─── Helpers ─────────────────────────────────────────────────────────
199
+ function wrapMarkers(content) {
200
+ return `${GUARDLINK_MARKER}\n${content}\n${GUARDLINK_MARKER_END}\n`;
201
+ }
202
+ /**
203
+ * If markers exist, replace the content between them.
204
+ * Otherwise append to end of file.
205
+ */
206
+ function replaceOrAppend(existing, block) {
207
+ const beginIdx = existing.indexOf(GUARDLINK_MARKER);
208
+ const endIdx = existing.indexOf(GUARDLINK_MARKER_END);
209
+ if (beginIdx !== -1 && endIdx !== -1) {
210
+ // Replace existing block
211
+ return existing.slice(0, beginIdx) + block + existing.slice(endIdx + GUARDLINK_MARKER_END.length);
212
+ }
213
+ // Append with separator
214
+ const separator = existing.endsWith('\n') ? '\n' : '\n\n';
215
+ return existing + separator + block;
216
+ }
217
+ function ensureDir(dir) {
218
+ if (!existsSync(dir))
219
+ mkdirSync(dir, { recursive: true });
220
+ }
221
+ function toPascalCase(s) {
222
+ return s
223
+ .replace(/[-_./]/g, ' ')
224
+ .split(/\s+/)
225
+ .map(w => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase())
226
+ .join('');
227
+ }
228
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/init/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * GuardLink init — Interactive agent picker.
3
+ *
4
+ * Shows a detection-aware prompt:
5
+ * - Always-created files (reference doc, AGENTS.md, .mcp.json)
6
+ * - Auto-detected agents (directories found on disk)
7
+ * - Optional agents the user can additionally select
8
+ */
9
+ import type { AgentFile } from './detect.js';
10
+ export interface AgentChoice {
11
+ id: string;
12
+ label: string;
13
+ file: string;
14
+ platform: string;
15
+ }
16
+ export declare const AGENT_CHOICES: AgentChoice[];
17
+ /** Files that are always created regardless of agent selection. */
18
+ export declare const ALWAYS_FILES: string[];
19
+ /**
20
+ * Show detection-aware prompt. Displays:
21
+ * 1. Always-created files
22
+ * 2. Auto-detected agents (from directory presence)
23
+ * 3. Optional agents user can add
24
+ *
25
+ * Returns combined list of agent IDs (detected + user-selected).
26
+ */
27
+ export declare function promptAgentSelection(agentFiles: AgentFile[]): Promise<string[]>;
28
+ /**
29
+ * Resolve agent IDs (from picker or flags) to file paths.
30
+ */
31
+ export declare function resolveAgentFiles(agentIds: string[]): AgentChoice[];
32
+ //# sourceMappingURL=picker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"picker.d.ts","sourceRoot":"","sources":["../../src/init/picker.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAG7C,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,eAAO,MAAM,aAAa,EAAE,WAAW,EAQtC,CAAC;AAEF,mEAAmE;AACnE,eAAO,MAAM,YAAY,UAGxB,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAsB,oBAAoB,CAAC,UAAU,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CA8ErF;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,WAAW,EAAE,CAInE"}