@googlarz/agents-sync 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 (189) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +366 -0
  3. package/dist/cli.d.ts +3 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +237 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/config/loader.d.ts +9 -0
  8. package/dist/config/loader.d.ts.map +1 -0
  9. package/dist/config/loader.js +55 -0
  10. package/dist/config/loader.js.map +1 -0
  11. package/dist/config/schema.d.ts +69 -0
  12. package/dist/config/schema.d.ts.map +1 -0
  13. package/dist/config/schema.js +33 -0
  14. package/dist/config/schema.js.map +1 -0
  15. package/dist/derivers/aider.d.ts +19 -0
  16. package/dist/derivers/aider.d.ts.map +1 -0
  17. package/dist/derivers/aider.js +117 -0
  18. package/dist/derivers/aider.js.map +1 -0
  19. package/dist/derivers/claude.d.ts +19 -0
  20. package/dist/derivers/claude.d.ts.map +1 -0
  21. package/dist/derivers/claude.js +41 -0
  22. package/dist/derivers/claude.js.map +1 -0
  23. package/dist/derivers/cline.d.ts +17 -0
  24. package/dist/derivers/cline.d.ts.map +1 -0
  25. package/dist/derivers/cline.js +92 -0
  26. package/dist/derivers/cline.js.map +1 -0
  27. package/dist/derivers/copilot.d.ts +16 -0
  28. package/dist/derivers/copilot.d.ts.map +1 -0
  29. package/dist/derivers/copilot.js +162 -0
  30. package/dist/derivers/copilot.js.map +1 -0
  31. package/dist/derivers/cursor.d.ts +16 -0
  32. package/dist/derivers/cursor.d.ts.map +1 -0
  33. package/dist/derivers/cursor.js +121 -0
  34. package/dist/derivers/cursor.js.map +1 -0
  35. package/dist/derivers/gemini.d.ts +19 -0
  36. package/dist/derivers/gemini.d.ts.map +1 -0
  37. package/dist/derivers/gemini.js +33 -0
  38. package/dist/derivers/gemini.js.map +1 -0
  39. package/dist/derivers/index.d.ts +33 -0
  40. package/dist/derivers/index.d.ts.map +1 -0
  41. package/dist/derivers/index.js +124 -0
  42. package/dist/derivers/index.js.map +1 -0
  43. package/dist/derivers/merger.d.ts +36 -0
  44. package/dist/derivers/merger.d.ts.map +1 -0
  45. package/dist/derivers/merger.js +83 -0
  46. package/dist/derivers/merger.js.map +1 -0
  47. package/dist/derivers/roo.d.ts +18 -0
  48. package/dist/derivers/roo.d.ts.map +1 -0
  49. package/dist/derivers/roo.js +92 -0
  50. package/dist/derivers/roo.js.map +1 -0
  51. package/dist/derivers/windsurf.d.ts +16 -0
  52. package/dist/derivers/windsurf.d.ts.map +1 -0
  53. package/dist/derivers/windsurf.js +91 -0
  54. package/dist/derivers/windsurf.js.map +1 -0
  55. package/dist/extractor/extractor.d.ts +4 -0
  56. package/dist/extractor/extractor.d.ts.map +1 -0
  57. package/dist/extractor/extractor.js +117 -0
  58. package/dist/extractor/extractor.js.map +1 -0
  59. package/dist/extractor/schema.d.ts +187 -0
  60. package/dist/extractor/schema.d.ts.map +1 -0
  61. package/dist/extractor/schema.js +44 -0
  62. package/dist/extractor/schema.js.map +1 -0
  63. package/dist/generator/agents-md.d.ts +3 -0
  64. package/dist/generator/agents-md.d.ts.map +1 -0
  65. package/dist/generator/agents-md.js +127 -0
  66. package/dist/generator/agents-md.js.map +1 -0
  67. package/dist/generator/validator.d.ts +7 -0
  68. package/dist/generator/validator.d.ts.map +1 -0
  69. package/dist/generator/validator.js +67 -0
  70. package/dist/generator/validator.js.map +1 -0
  71. package/dist/lib/claude-client.d.ts +11 -0
  72. package/dist/lib/claude-client.d.ts.map +1 -0
  73. package/dist/lib/claude-client.js +74 -0
  74. package/dist/lib/claude-client.js.map +1 -0
  75. package/dist/lib/errors.d.ts +10 -0
  76. package/dist/lib/errors.d.ts.map +1 -0
  77. package/dist/lib/errors.js +27 -0
  78. package/dist/lib/errors.js.map +1 -0
  79. package/dist/lib/file-utils.d.ts +7 -0
  80. package/dist/lib/file-utils.d.ts.map +1 -0
  81. package/dist/lib/file-utils.js +56 -0
  82. package/dist/lib/file-utils.js.map +1 -0
  83. package/dist/lib/token-estimate.d.ts +7 -0
  84. package/dist/lib/token-estimate.d.ts.map +1 -0
  85. package/dist/lib/token-estimate.js +15 -0
  86. package/dist/lib/token-estimate.js.map +1 -0
  87. package/dist/scanner/codegraph.d.ts +13 -0
  88. package/dist/scanner/codegraph.d.ts.map +1 -0
  89. package/dist/scanner/codegraph.js +65 -0
  90. package/dist/scanner/codegraph.js.map +1 -0
  91. package/dist/scanner/docs.d.ts +13 -0
  92. package/dist/scanner/docs.d.ts.map +1 -0
  93. package/dist/scanner/docs.js +63 -0
  94. package/dist/scanner/docs.js.map +1 -0
  95. package/dist/scanner/gotchas.d.ts +8 -0
  96. package/dist/scanner/gotchas.d.ts.map +1 -0
  97. package/dist/scanner/gotchas.js +107 -0
  98. package/dist/scanner/gotchas.js.map +1 -0
  99. package/dist/scanner/index.d.ts +21 -0
  100. package/dist/scanner/index.d.ts.map +1 -0
  101. package/dist/scanner/index.js +87 -0
  102. package/dist/scanner/index.js.map +1 -0
  103. package/dist/scanner/manifest.d.ts +13 -0
  104. package/dist/scanner/manifest.d.ts.map +1 -0
  105. package/dist/scanner/manifest.js +285 -0
  106. package/dist/scanner/manifest.js.map +1 -0
  107. package/dist/scanner/mcp.d.ts +12 -0
  108. package/dist/scanner/mcp.d.ts.map +1 -0
  109. package/dist/scanner/mcp.js +96 -0
  110. package/dist/scanner/mcp.js.map +1 -0
  111. package/dist/scanner/repomix.d.ts +11 -0
  112. package/dist/scanner/repomix.d.ts.map +1 -0
  113. package/dist/scanner/repomix.js +87 -0
  114. package/dist/scanner/repomix.js.map +1 -0
  115. package/dist/scanner/skills.d.ts +18 -0
  116. package/dist/scanner/skills.d.ts.map +1 -0
  117. package/dist/scanner/skills.js +100 -0
  118. package/dist/scanner/skills.js.map +1 -0
  119. package/dist/scanner/source.d.ts +13 -0
  120. package/dist/scanner/source.d.ts.map +1 -0
  121. package/dist/scanner/source.js +157 -0
  122. package/dist/scanner/source.js.map +1 -0
  123. package/dist/scanner/structure.d.ts +10 -0
  124. package/dist/scanner/structure.d.ts.map +1 -0
  125. package/dist/scanner/structure.js +168 -0
  126. package/dist/scanner/structure.js.map +1 -0
  127. package/dist/server.d.ts +2 -0
  128. package/dist/server.d.ts.map +1 -0
  129. package/dist/server.js +212 -0
  130. package/dist/server.js.map +1 -0
  131. package/dist/snapshot/drift.d.ts +22 -0
  132. package/dist/snapshot/drift.d.ts.map +1 -0
  133. package/dist/snapshot/drift.js +105 -0
  134. package/dist/snapshot/drift.js.map +1 -0
  135. package/dist/snapshot/schema.d.ts +94 -0
  136. package/dist/snapshot/schema.d.ts.map +1 -0
  137. package/dist/snapshot/schema.js +24 -0
  138. package/dist/snapshot/schema.js.map +1 -0
  139. package/dist/snapshot/writer.d.ts +17 -0
  140. package/dist/snapshot/writer.d.ts.map +1 -0
  141. package/dist/snapshot/writer.js +44 -0
  142. package/dist/snapshot/writer.js.map +1 -0
  143. package/dist/tools/drift.d.ts +15 -0
  144. package/dist/tools/drift.d.ts.map +1 -0
  145. package/dist/tools/drift.js +31 -0
  146. package/dist/tools/drift.js.map +1 -0
  147. package/dist/tools/export.d.ts +14 -0
  148. package/dist/tools/export.d.ts.map +1 -0
  149. package/dist/tools/export.js +53 -0
  150. package/dist/tools/export.js.map +1 -0
  151. package/dist/tools/init.d.ts +28 -0
  152. package/dist/tools/init.d.ts.map +1 -0
  153. package/dist/tools/init.js +103 -0
  154. package/dist/tools/init.js.map +1 -0
  155. package/dist/tools/install-hook.d.ts +15 -0
  156. package/dist/tools/install-hook.d.ts.map +1 -0
  157. package/dist/tools/install-hook.js +169 -0
  158. package/dist/tools/install-hook.js.map +1 -0
  159. package/dist/tools/lint.d.ts +24 -0
  160. package/dist/tools/lint.d.ts.map +1 -0
  161. package/dist/tools/lint.js +213 -0
  162. package/dist/tools/lint.js.map +1 -0
  163. package/dist/tools/scan-report.d.ts +14 -0
  164. package/dist/tools/scan-report.d.ts.map +1 -0
  165. package/dist/tools/scan-report.js +136 -0
  166. package/dist/tools/scan-report.js.map +1 -0
  167. package/dist/tools/status.d.ts +18 -0
  168. package/dist/tools/status.d.ts.map +1 -0
  169. package/dist/tools/status.js +38 -0
  170. package/dist/tools/status.js.map +1 -0
  171. package/dist/tools/sync.d.ts +22 -0
  172. package/dist/tools/sync.d.ts.map +1 -0
  173. package/dist/tools/sync.js +123 -0
  174. package/dist/tools/sync.js.map +1 -0
  175. package/dist/tools/validate.d.ts +22 -0
  176. package/dist/tools/validate.d.ts.map +1 -0
  177. package/dist/tools/validate.js +97 -0
  178. package/dist/tools/validate.js.map +1 -0
  179. package/docs/examples/.clinerules +29 -0
  180. package/docs/examples/.cursorrules +19 -0
  181. package/docs/examples/.windsurfrules +14 -0
  182. package/docs/examples/AGENTS.md +97 -0
  183. package/docs/examples/CLAUDE.md +88 -0
  184. package/docs/examples/GEMINI.md +61 -0
  185. package/docs/examples/copilot-instructions.md +24 -0
  186. package/docs/github-action.yml +89 -0
  187. package/package.json +63 -0
  188. package/scripts/demo.sh +138 -0
  189. package/skill/SKILL.md +158 -0
@@ -0,0 +1,162 @@
1
+ import path from "node:path";
2
+ import { injectCustomBlocks, loadExistingCustomBlocks } from "./merger.js";
3
+ // ---------------------------------------------------------------------------
4
+ // Framework-specific hints
5
+ // ---------------------------------------------------------------------------
6
+ /**
7
+ * Maps known framework names to inline code-generation hints.
8
+ * Keeps it short — only things that meaningfully affect completion quality.
9
+ */
10
+ const FRAMEWORK_HINTS = {
11
+ nextjs: "prefer Server Components; use `'use client'` only when necessary",
12
+ "next.js": "prefer Server Components; use `'use client'` only when necessary",
13
+ react: "functional components only; hooks over class components",
14
+ django: "use async views where possible; prefer class-based views for CRUD",
15
+ fastapi: "async endpoints; pydantic models for all request/response shapes",
16
+ express: "async route handlers; centralise error handling via middleware",
17
+ axum: "use `#[axum::debug_handler]` during development; prefer extractors",
18
+ flask: "use blueprints; prefer `current_app` over global state",
19
+ nuxt: "use `<script setup lang='ts'>`; prefer composables over options API",
20
+ vue: "use Composition API with `<script setup>`; TypeScript by default",
21
+ angular: "standalone components preferred; inject via `inject()` function",
22
+ svelte: "prefer `$state` runes (Svelte 5); avoid legacy reactive statements",
23
+ remix: "loaders and actions for all data; avoid client-side fetching",
24
+ nestjs: "dependency injection everywhere; DTOs with class-validator decorators",
25
+ };
26
+ function frameworkHint(framework) {
27
+ if (!framework)
28
+ return null;
29
+ const key = framework.toLowerCase();
30
+ return FRAMEWORK_HINTS[key] ?? null;
31
+ }
32
+ // ---------------------------------------------------------------------------
33
+ // Parsing helpers (minimal — only what copilot needs)
34
+ // ---------------------------------------------------------------------------
35
+ function escapeRegExp(s) {
36
+ return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
37
+ }
38
+ function extractSubSection(content, heading) {
39
+ const re = new RegExp(`^###\\s+${escapeRegExp(heading)}\\s*$([\\s\\S]*?)(?=^###\\s|^##\\s|$)`, "mi");
40
+ const match = re.exec(content);
41
+ return match ? match[1].trim() : "";
42
+ }
43
+ function sectionToLines(text) {
44
+ return text
45
+ .split("\n")
46
+ .map((l) => l.replace(/^[\s\-*>]+/, "").trim())
47
+ .filter((l) => l.length > 0);
48
+ }
49
+ // ---------------------------------------------------------------------------
50
+ // Convention filters — keep only lines relevant to code-level suggestions
51
+ // ---------------------------------------------------------------------------
52
+ const CODE_LEVEL_KEYWORDS = [
53
+ "import",
54
+ "export",
55
+ "naming",
56
+ "filename",
57
+ "file name",
58
+ "type",
59
+ "interface",
60
+ "async",
61
+ "await",
62
+ "module",
63
+ "esm",
64
+ "cjs",
65
+ "require",
66
+ "class",
67
+ "function",
68
+ "const ",
69
+ "let ",
70
+ "var ",
71
+ "enum",
72
+ "generic",
73
+ "zod",
74
+ "schema",
75
+ "validation",
76
+ "null",
77
+ "undefined",
78
+ "error",
79
+ "throw",
80
+ "return",
81
+ "comment",
82
+ "doc",
83
+ "format",
84
+ "lint",
85
+ ];
86
+ function isCodeLevel(rule) {
87
+ const lower = rule.toLowerCase();
88
+ return CODE_LEVEL_KEYWORDS.some((kw) => lower.includes(kw));
89
+ }
90
+ // ---------------------------------------------------------------------------
91
+ // Deriver
92
+ // ---------------------------------------------------------------------------
93
+ /**
94
+ * Derives `.github/copilot-instructions.md` content from AGENTS.md + metadata.
95
+ * Focuses strictly on inline code-generation context — target < 300 words.
96
+ *
97
+ * Does NOT write the file — the caller is responsible for writing.
98
+ */
99
+ export async function deriveCopilotInstructions(options) {
100
+ const { projectPath, agentsMdContent, metadata, preserveCustom = true } = options;
101
+ const { project, stack, conventions: metaConventions, boundaries, testing } = metadata;
102
+ // Code-level conventions only
103
+ const codeLevelConventions = metaConventions.filter(isCodeLevel);
104
+ // "Never" rules that directly affect code generation (short enough to fit)
105
+ const neverLines = sectionToLines(extractSubSection(agentsMdContent, "Never"));
106
+ const codeNever = [...boundaries.never, ...neverLines]
107
+ .filter(isCodeLevel)
108
+ .slice(0, 6); // hard cap to stay under word budget
109
+ const lines = [];
110
+ // Header
111
+ lines.push("# GitHub Copilot Instructions — managed by agents-sync");
112
+ lines.push("");
113
+ // Language + framework
114
+ const fwPart = project.framework ? ` / ${project.framework}` : "";
115
+ lines.push(`**Stack:** ${project.language}${fwPart}${stack.runtime ? ` (${stack.runtime})` : ""}`);
116
+ lines.push("");
117
+ // Framework-specific hint
118
+ const hint = frameworkHint(project.framework);
119
+ if (hint) {
120
+ lines.push(`**Framework:** ${hint}`);
121
+ lines.push("");
122
+ }
123
+ // Import style — derive from conventions or fall back to language default
124
+ const importConvention = metaConventions.find((c) => c.toLowerCase().includes("import") || c.toLowerCase().includes("esm") || c.toLowerCase().includes("require"));
125
+ if (importConvention) {
126
+ lines.push(`**Imports:** ${importConvention}`);
127
+ lines.push("");
128
+ }
129
+ // Test location / naming
130
+ if (testing.location || testing.command) {
131
+ const testParts = [];
132
+ if (testing.location)
133
+ testParts.push(`location: ${testing.location}`);
134
+ if (testing.command)
135
+ testParts.push(`run: \`${testing.command}\``);
136
+ lines.push(`**Tests:** ${testParts.join(" · ")}`);
137
+ lines.push("");
138
+ }
139
+ // Code-level conventions
140
+ if (codeLevelConventions.length > 0) {
141
+ lines.push("## Conventions");
142
+ for (const rule of codeLevelConventions) {
143
+ lines.push(`- ${rule}`);
144
+ }
145
+ lines.push("");
146
+ }
147
+ // Hard never rules (code-affecting)
148
+ if (codeNever.length > 0) {
149
+ lines.push("## Never");
150
+ for (const rule of codeNever) {
151
+ lines.push(`- ${rule}`);
152
+ }
153
+ lines.push("");
154
+ }
155
+ const generated = lines.join("\n").trimEnd() + "\n";
156
+ if (!preserveCustom)
157
+ return generated;
158
+ const copilotPath = path.join(projectPath, ".github", "copilot-instructions.md");
159
+ const existingBlocks = await loadExistingCustomBlocks(copilotPath);
160
+ return injectCustomBlocks(generated, existingBlocks);
161
+ }
162
+ //# sourceMappingURL=copilot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"copilot.js","sourceRoot":"","sources":["../../src/derivers/copilot.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import type { ProjectMetadata } from "../extractor/schema.js";
2
+ export interface CursorDerivationOptions {
3
+ projectPath: string;
4
+ agentsMdContent: string;
5
+ metadata: ProjectMetadata;
6
+ /** @default true */
7
+ preserveCustom?: boolean;
8
+ }
9
+ /**
10
+ * Derives directive-style `.cursorrules` content from AGENTS.md + metadata.
11
+ * Keeps output terse and scannable — target < 400 words.
12
+ *
13
+ * Does NOT write the file — the caller is responsible for writing.
14
+ */
15
+ export declare function deriveCursorRules(options: CursorDerivationOptions): Promise<string>;
16
+ //# sourceMappingURL=cursor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cursor.d.ts","sourceRoot":"","sources":["../../src/derivers/cursor.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAG9D,MAAM,WAAW,uBAAuB;IACtC,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,eAAe,CAAC;IAC1B,oBAAoB;IACpB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAkDD;;;;;GAKG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,uBAAuB,GAAG,OAAO,CAAC,MAAM,CAAC,CA6EzF"}
@@ -0,0 +1,121 @@
1
+ import path from "node:path";
2
+ import { injectCustomBlocks, loadExistingCustomBlocks } from "./merger.js";
3
+ // ---------------------------------------------------------------------------
4
+ // Parsing helpers
5
+ // ---------------------------------------------------------------------------
6
+ /**
7
+ * Extracts the text body of the first `## Heading` section that matches the
8
+ * given heading name (case-insensitive). Returns an empty string when not found.
9
+ */
10
+ function extractSection(content, heading) {
11
+ const re = new RegExp(`^##\\s+${escapeRegExp(heading)}\\s*$([\\s\\S]*?)(?=^##\\s|$)`, "mi");
12
+ const match = re.exec(content);
13
+ return match ? match[1].trim() : "";
14
+ }
15
+ /**
16
+ * Extracts the text body of the first `### Heading` subsection that matches.
17
+ */
18
+ function extractSubSection(content, heading) {
19
+ const re = new RegExp(`^###\\s+${escapeRegExp(heading)}\\s*$([\\s\\S]*?)(?=^###\\s|^##\\s|$)`, "mi");
20
+ const match = re.exec(content);
21
+ return match ? match[1].trim() : "";
22
+ }
23
+ function escapeRegExp(s) {
24
+ return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
25
+ }
26
+ /**
27
+ * Parses a markdown section into a list of individual rule strings, stripping
28
+ * leading list markers and blank lines.
29
+ */
30
+ function sectionToLines(text) {
31
+ return text
32
+ .split("\n")
33
+ .map((l) => l.replace(/^[\s\-*>]+/, "").trim())
34
+ .filter((l) => l.length > 0);
35
+ }
36
+ // ---------------------------------------------------------------------------
37
+ // Deriver
38
+ // ---------------------------------------------------------------------------
39
+ /**
40
+ * Derives directive-style `.cursorrules` content from AGENTS.md + metadata.
41
+ * Keeps output terse and scannable — target < 400 words.
42
+ *
43
+ * Does NOT write the file — the caller is responsible for writing.
44
+ */
45
+ export async function deriveCursorRules(options) {
46
+ const { projectPath, agentsMdContent, metadata, preserveCustom = true } = options;
47
+ const { project, conventions: metaConventions, gotchas: metaGotchas, boundaries, testing } = metadata;
48
+ // Pull extra rules from AGENTS.md prose
49
+ const conventionsSection = sectionToLines(extractSection(agentsMdContent, "Conventions"));
50
+ const gotchasSection = sectionToLines(extractSection(agentsMdContent, "Gotchas"));
51
+ const neverSection = sectionToLines(extractSubSection(agentsMdContent, "Never"));
52
+ // Merge with metadata, preferring metadata as it's structured
53
+ const allConventions = deduplicateLines([...metaConventions, ...conventionsSection]);
54
+ const allGotchas = deduplicateLines([...metaGotchas, ...gotchasSection]);
55
+ const allNever = deduplicateLines([...boundaries.never, ...neverSection]);
56
+ const lines = [];
57
+ // Header
58
+ lines.push("# .cursorrules — managed by agents-sync");
59
+ lines.push("");
60
+ // Project identity
61
+ const frameworkPart = project.framework ? ` · ${project.framework}` : "";
62
+ lines.push(`${project.name} — ${project.language}${frameworkPart}`);
63
+ lines.push("");
64
+ // Test command
65
+ if (testing.command) {
66
+ lines.push(`**Test command:** \`${testing.command}\``);
67
+ lines.push("");
68
+ }
69
+ // Conventions
70
+ if (allConventions.length > 0) {
71
+ lines.push("## Conventions");
72
+ for (const rule of allConventions) {
73
+ lines.push(`- Always: ${rule}`);
74
+ }
75
+ lines.push("");
76
+ }
77
+ // Gotchas
78
+ if (allGotchas.length > 0) {
79
+ lines.push("## Gotchas");
80
+ for (const gotcha of allGotchas) {
81
+ // Gotchas already include consequence phrasing; surface as "Never" hints
82
+ lines.push(`- Never: ${gotcha}`);
83
+ }
84
+ lines.push("");
85
+ }
86
+ // Hard never rules (boundaries)
87
+ if (allNever.length > 0) {
88
+ lines.push("## Hard boundaries");
89
+ for (const rule of allNever) {
90
+ lines.push(`- Never: ${rule}`);
91
+ }
92
+ lines.push("");
93
+ }
94
+ // Always-do boundaries
95
+ if (boundaries.alwaysDo.length > 0) {
96
+ lines.push("## Always do");
97
+ for (const rule of boundaries.alwaysDo) {
98
+ lines.push(`- ${rule}`);
99
+ }
100
+ lines.push("");
101
+ }
102
+ const generated = lines.join("\n").trimEnd() + "\n";
103
+ if (!preserveCustom)
104
+ return generated;
105
+ const cursorPath = path.join(projectPath, ".cursorrules");
106
+ const existingBlocks = await loadExistingCustomBlocks(cursorPath);
107
+ return injectCustomBlocks(generated, existingBlocks);
108
+ }
109
+ function deduplicateLines(items) {
110
+ const seen = new Set();
111
+ const result = [];
112
+ for (const item of items) {
113
+ const key = item.toLowerCase().trim();
114
+ if (!seen.has(key)) {
115
+ seen.add(key);
116
+ result.push(item);
117
+ }
118
+ }
119
+ return result;
120
+ }
121
+ //# sourceMappingURL=cursor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cursor.js","sourceRoot":"","sources":["../../src/derivers/cursor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import type { ProjectMetadata } from "../extractor/schema.js";
2
+ export interface GeminiDerivationOptions {
3
+ projectPath: string;
4
+ agentsMdContent: string;
5
+ metadata: ProjectMetadata;
6
+ /** @default true */
7
+ preserveCustom?: boolean;
8
+ }
9
+ /**
10
+ * Derives the full content for GEMINI.md.
11
+ *
12
+ * Content = canonical AGENTS.md + Gemini CLI-specific section.
13
+ * If preserveCustom is true (default) any existing custom blocks from the
14
+ * current GEMINI.md are appended after the generated body.
15
+ *
16
+ * Does NOT write the file — the caller is responsible for writing.
17
+ */
18
+ export declare function deriveGeminiMd(options: GeminiDerivationOptions): Promise<string>;
19
+ //# sourceMappingURL=gemini.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gemini.d.ts","sourceRoot":"","sources":["../../src/derivers/gemini.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAG9D,MAAM,WAAW,uBAAuB;IACtC,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,eAAe,CAAC;IAC1B,oBAAoB;IACpB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAYD;;;;;;;;GAQG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,uBAAuB,GAAG,OAAO,CAAC,MAAM,CAAC,CActF"}
@@ -0,0 +1,33 @@
1
+ import path from "node:path";
2
+ import { injectCustomBlocks, loadExistingCustomBlocks, loadUnmanagedFileAsCustomBlock } from "./merger.js";
3
+ const GEMINI_SECTION = `---
4
+
5
+ ## Gemini CLI Notes
6
+
7
+ > This file is managed by agents-sync. Edit \`AGENTS.md\` and run \`/agents-sync sync\`.
8
+
9
+ ### Re-sync
10
+ Run \`agents-sync sync\` after major refactors, new dependencies, or architecture changes.
11
+ `;
12
+ /**
13
+ * Derives the full content for GEMINI.md.
14
+ *
15
+ * Content = canonical AGENTS.md + Gemini CLI-specific section.
16
+ * If preserveCustom is true (default) any existing custom blocks from the
17
+ * current GEMINI.md are appended after the generated body.
18
+ *
19
+ * Does NOT write the file — the caller is responsible for writing.
20
+ */
21
+ export async function deriveGeminiMd(options) {
22
+ const { projectPath, agentsMdContent, preserveCustom = true } = options;
23
+ const generated = `${agentsMdContent.trimEnd()}\n\n${GEMINI_SECTION}`;
24
+ if (!preserveCustom)
25
+ return generated;
26
+ const geminiPath = path.join(projectPath, "GEMINI.md");
27
+ const existingBlocks = await loadExistingCustomBlocks(geminiPath);
28
+ const blocks = existingBlocks.length > 0
29
+ ? existingBlocks
30
+ : await loadUnmanagedFileAsCustomBlock(geminiPath);
31
+ return injectCustomBlocks(generated, blocks);
32
+ }
33
+ //# sourceMappingURL=gemini.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gemini.js","sourceRoot":"","sources":["../../src/derivers/gemini.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,kBAAkB,EAAE,wBAAwB,EAAE,8BAA8B,EAAE,MAAM,aAAa,CAAC;AAU3G,MAAM,cAAc,GAAG;;;;;;;;CAQtB,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,OAAgC;IACnE,MAAM,EAAE,WAAW,EAAE,eAAe,EAAE,cAAc,GAAG,IAAI,EAAE,GAAG,OAAO,CAAC;IAExE,MAAM,SAAS,GAAG,GAAG,eAAe,CAAC,OAAO,EAAE,OAAO,cAAc,EAAE,CAAC;IAEtE,IAAI,CAAC,cAAc;QAAE,OAAO,SAAS,CAAC;IAEtC,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;IACvD,MAAM,cAAc,GAAG,MAAM,wBAAwB,CAAC,UAAU,CAAC,CAAC;IAClE,MAAM,MAAM,GAAG,cAAc,CAAC,MAAM,GAAG,CAAC;QACtC,CAAC,CAAC,cAAc;QAChB,CAAC,CAAC,MAAM,8BAA8B,CAAC,UAAU,CAAC,CAAC;IAErD,OAAO,kBAAkB,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;AAC/C,CAAC"}
@@ -0,0 +1,33 @@
1
+ import type { ProjectMetadata } from "../extractor/schema.js";
2
+ export type ToolName = "claude" | "cursor" | "copilot" | "gemini" | "windsurf" | "cline";
3
+ export interface DerivationResult {
4
+ tool: ToolName | "agents-md";
5
+ /** Absolute path to the file. */
6
+ path: string;
7
+ written: boolean;
8
+ customBlocksPreserved: number;
9
+ /** true when dryRun is enabled — file was not written. */
10
+ skipped?: boolean;
11
+ error?: string;
12
+ }
13
+ export interface DeriveAllOptions {
14
+ projectPath: string;
15
+ agentsMdContent: string;
16
+ metadata: ProjectMetadata;
17
+ /** Tools to derive. Defaults to all six. */
18
+ tools?: ToolName[];
19
+ dryRun?: boolean;
20
+ /** @default true */
21
+ preserveCustom?: boolean;
22
+ }
23
+ export declare const ALL_TOOLS: ToolName[];
24
+ export declare function toolPath(projectPath: string, tool: ToolName): string;
25
+ /**
26
+ * Runs all (or selected) derivers and writes the results.
27
+ *
28
+ * AGENTS.md is always written first as the canonical source file.
29
+ * Per-tool errors are caught and returned as `{ error }` entries — one
30
+ * failing tool does not abort the others.
31
+ */
32
+ export declare function deriveAll(options: DeriveAllOptions): Promise<DerivationResult[]>;
33
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/derivers/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAW9D,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,GAAG,UAAU,GAAG,OAAO,CAAC;AAEzF,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,QAAQ,GAAG,WAAW,CAAC;IAC7B,iCAAiC;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,0DAA0D;IAC1D,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,eAAe,CAAC;IAC1B,4CAA4C;IAC5C,KAAK,CAAC,EAAE,QAAQ,EAAE,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,oBAAoB;IACpB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,eAAO,MAAM,SAAS,EAAE,QAAQ,EAAmE,CAAC;AAMpG,wBAAgB,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG,MAAM,CAepE;AAiCD;;;;;;GAMG;AACH,wBAAsB,SAAS,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAwEtF"}
@@ -0,0 +1,124 @@
1
+ import path from "node:path";
2
+ import { writeFileAtomic } from "../lib/file-utils.js";
3
+ import { toMcpError } from "../lib/errors.js";
4
+ import { extractCustomBlocks } from "./merger.js";
5
+ import { deriveClaudeMd } from "./claude.js";
6
+ import { deriveCursorRules } from "./cursor.js";
7
+ import { deriveCopilotInstructions } from "./copilot.js";
8
+ import { deriveGeminiMd } from "./gemini.js";
9
+ import { deriveWindsurfRules } from "./windsurf.js";
10
+ import { deriveClineRules } from "./cline.js";
11
+ export const ALL_TOOLS = ["claude", "cursor", "copilot", "gemini", "windsurf", "cline"];
12
+ // ---------------------------------------------------------------------------
13
+ // Tool → file-path mapping
14
+ // ---------------------------------------------------------------------------
15
+ export function toolPath(projectPath, tool) {
16
+ switch (tool) {
17
+ case "claude":
18
+ return path.join(projectPath, "CLAUDE.md");
19
+ case "cursor":
20
+ return path.join(projectPath, ".cursorrules");
21
+ case "copilot":
22
+ return path.join(projectPath, ".github", "copilot-instructions.md");
23
+ case "gemini":
24
+ return path.join(projectPath, "GEMINI.md");
25
+ case "windsurf":
26
+ return path.join(projectPath, ".windsurfrules");
27
+ case "cline":
28
+ return path.join(projectPath, ".clinerules");
29
+ }
30
+ }
31
+ // ---------------------------------------------------------------------------
32
+ // Per-tool content generation
33
+ // ---------------------------------------------------------------------------
34
+ async function deriveContent(tool, options) {
35
+ const { projectPath, agentsMdContent, metadata, preserveCustom = true } = options;
36
+ const shared = { projectPath, agentsMdContent, metadata, preserveCustom };
37
+ switch (tool) {
38
+ case "claude":
39
+ return deriveClaudeMd(shared);
40
+ case "cursor":
41
+ return deriveCursorRules(shared);
42
+ case "copilot":
43
+ return deriveCopilotInstructions(shared);
44
+ case "gemini":
45
+ return deriveGeminiMd(shared);
46
+ case "windsurf":
47
+ return deriveWindsurfRules(shared);
48
+ case "cline":
49
+ return deriveClineRules(shared);
50
+ }
51
+ }
52
+ // ---------------------------------------------------------------------------
53
+ // Main entry point
54
+ // ---------------------------------------------------------------------------
55
+ /**
56
+ * Runs all (or selected) derivers and writes the results.
57
+ *
58
+ * AGENTS.md is always written first as the canonical source file.
59
+ * Per-tool errors are caught and returned as `{ error }` entries — one
60
+ * failing tool does not abort the others.
61
+ */
62
+ export async function deriveAll(options) {
63
+ const { projectPath, agentsMdContent, tools = ALL_TOOLS, dryRun = false, } = options;
64
+ const results = [];
65
+ // --- Always write AGENTS.md (canonical) --------------------------------
66
+ const agentsMdPath = path.join(projectPath, "AGENTS.md");
67
+ try {
68
+ if (!dryRun) {
69
+ await writeFileAtomic(agentsMdPath, agentsMdContent);
70
+ }
71
+ results.push({
72
+ tool: "agents-md",
73
+ path: agentsMdPath,
74
+ written: !dryRun,
75
+ customBlocksPreserved: 0,
76
+ skipped: dryRun || undefined,
77
+ });
78
+ }
79
+ catch (e) {
80
+ results.push({
81
+ tool: "agents-md",
82
+ path: agentsMdPath,
83
+ written: false,
84
+ customBlocksPreserved: 0,
85
+ error: toMcpError(e),
86
+ });
87
+ }
88
+ // --- Derive and write each tool file ------------------------------------
89
+ for (const tool of tools) {
90
+ const filePath = toolPath(projectPath, tool);
91
+ try {
92
+ const content = await deriveContent(tool, options);
93
+ const customBlocksPreserved = extractCustomBlocks(content).length;
94
+ if (dryRun) {
95
+ results.push({
96
+ tool,
97
+ path: filePath,
98
+ written: false,
99
+ customBlocksPreserved,
100
+ skipped: true,
101
+ });
102
+ continue;
103
+ }
104
+ await writeFileAtomic(filePath, content);
105
+ results.push({
106
+ tool,
107
+ path: filePath,
108
+ written: true,
109
+ customBlocksPreserved,
110
+ });
111
+ }
112
+ catch (e) {
113
+ results.push({
114
+ tool,
115
+ path: filePath,
116
+ written: false,
117
+ customBlocksPreserved: 0,
118
+ error: toMcpError(e),
119
+ });
120
+ }
121
+ }
122
+ return results;
123
+ }
124
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/derivers/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Returns all text between CUSTOM_START and CUSTOM_END markers.
3
+ * Multiple blocks are supported; each returned string is the inner content
4
+ * (exclusive of the marker lines themselves).
5
+ */
6
+ export declare function extractCustomBlocks(content: string): string[];
7
+ /**
8
+ * Appends custom blocks at the end of the generated content, each wrapped in
9
+ * markers and preceded by a divider on the first block.
10
+ */
11
+ export declare function injectCustomBlocks(generated: string, blocks: string[]): string;
12
+ /**
13
+ * Reads the file at filePath (if it exists) and extracts its custom blocks.
14
+ * Returns [] when the file is missing or contains no custom blocks.
15
+ */
16
+ export declare function loadExistingCustomBlocks(filePath: string): Promise<string[]>;
17
+ /**
18
+ * Wraps user-provided content in the CUSTOM markers so it can be embedded in a
19
+ * managed file.
20
+ */
21
+ export declare function buildCustomSection(userContent: string): string;
22
+ /**
23
+ * Returns true when the file content was written by agents-sync (has the
24
+ * generated-by comment at the top).
25
+ */
26
+ export declare function isManagedByAgentsSync(content: string): boolean;
27
+ /**
28
+ * If the file at filePath exists and was NOT previously managed by agents-sync,
29
+ * returns the entire file content wrapped as a single custom block so it
30
+ * survives the next write. Returns [] when:
31
+ * - the file does not exist
32
+ * - the file is already managed (has the generated-by marker)
33
+ * - the file is empty
34
+ */
35
+ export declare function loadUnmanagedFileAsCustomBlock(filePath: string): Promise<string[]>;
36
+ //# sourceMappingURL=merger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merger.d.ts","sourceRoot":"","sources":["../../src/derivers/merger.ts"],"names":[],"mappings":"AAQA;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAqB7D;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,CAQ9E;AAED;;;GAGG;AACH,wBAAsB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAIlF;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAE9D;AAID;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAE9D;AAED;;;;;;;GAOG;AACH,wBAAsB,8BAA8B,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAMxF"}