@googlarz/agents-sync 1.4.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 (186) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +507 -0
  3. package/dist/cli.d.ts +3 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +267 -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 +93 -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 +134 -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 +125 -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 +6 -0
  64. package/dist/generator/agents-md.d.ts.map +1 -0
  65. package/dist/generator/agents-md.js +135 -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 +26 -0
  100. package/dist/scanner/index.d.ts.map +1 -0
  101. package/dist/scanner/index.js +95 -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 +245 -0
  130. package/dist/server.js.map +1 -0
  131. package/dist/snapshot/drift.d.ts +28 -0
  132. package/dist/snapshot/drift.d.ts.map +1 -0
  133. package/dist/snapshot/drift.js +205 -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 +51 -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/lint.d.ts +24 -0
  156. package/dist/tools/lint.d.ts.map +1 -0
  157. package/dist/tools/lint.js +213 -0
  158. package/dist/tools/lint.js.map +1 -0
  159. package/dist/tools/scan-report.d.ts +14 -0
  160. package/dist/tools/scan-report.d.ts.map +1 -0
  161. package/dist/tools/scan-report.js +136 -0
  162. package/dist/tools/scan-report.js.map +1 -0
  163. package/dist/tools/status.d.ts +18 -0
  164. package/dist/tools/status.d.ts.map +1 -0
  165. package/dist/tools/status.js +38 -0
  166. package/dist/tools/status.js.map +1 -0
  167. package/dist/tools/sync.d.ts +22 -0
  168. package/dist/tools/sync.d.ts.map +1 -0
  169. package/dist/tools/sync.js +123 -0
  170. package/dist/tools/sync.js.map +1 -0
  171. package/dist/tools/validate.d.ts +22 -0
  172. package/dist/tools/validate.d.ts.map +1 -0
  173. package/dist/tools/validate.js +97 -0
  174. package/dist/tools/validate.js.map +1 -0
  175. package/docs/agents-md-spec.md +233 -0
  176. package/docs/examples/.clinerules +29 -0
  177. package/docs/examples/.cursorrules +19 -0
  178. package/docs/examples/.windsurfrules +14 -0
  179. package/docs/examples/AGENTS.md +97 -0
  180. package/docs/examples/CLAUDE.md +88 -0
  181. package/docs/examples/GEMINI.md +61 -0
  182. package/docs/examples/copilot-instructions.md +24 -0
  183. package/docs/github-action.yml +89 -0
  184. package/package.json +63 -0
  185. package/scripts/demo.sh +138 -0
  186. package/skill/SKILL.md +158 -0
@@ -0,0 +1,93 @@
1
+ import path from "node:path";
2
+ import { injectCustomBlocks, loadExistingCustomBlocks, loadUnmanagedFileAsCustomBlock } from "./merger.js";
3
+ import { scanProjectSkills, formatSkillsSection } from "../scanner/skills.js";
4
+ const CLAUDE_CODE_SECTION = `---
5
+
6
+ ## Claude Code Notes
7
+
8
+ > This file is managed by agents-sync. Edit \`AGENTS.md\` and run \`/agents-sync sync\`.
9
+
10
+ ### Tool Files
11
+ - Canonical: \`AGENTS.md\`
12
+ - Cursor: \`.cursorrules\`
13
+ - Copilot: \`.github/copilot-instructions.md\`
14
+
15
+ ### Re-sync
16
+ Run \`/agents-sync sync\` after major refactors, new dependencies, or architecture changes.
17
+ Run \`/agents-sync drift\` to check what's changed since last sync.
18
+ `;
19
+ function recommendSkills(metadata) {
20
+ const recs = [];
21
+ const { project, stack, testing } = metadata;
22
+ const lang = project.language.toLowerCase();
23
+ const fw = (project.framework ?? "").toLowerCase();
24
+ const testFw = (testing.framework ?? stack.testing ?? "").toLowerCase();
25
+ const db = (stack.database ?? "").toLowerCase();
26
+ const auth = (stack.auth ?? "").toLowerCase();
27
+ const deploy = (stack.deploy ?? stack.deploy ?? "").toLowerCase();
28
+ // Universal
29
+ recs.push({ slug: "agent-skills:spec-driven-development", reason: "requirements before code" });
30
+ // Testing
31
+ if (testFw || testing.command) {
32
+ recs.push({ slug: "agent-skills:test-driven-development", reason: `${testFw || "tests"} workflow` });
33
+ }
34
+ // Frontend
35
+ if (/next|react|vue|svelte|solid|nuxt|remix|astro/.test(fw)) {
36
+ recs.push({ slug: "agent-skills:frontend-ui-engineering", reason: `${fw} UI work` });
37
+ }
38
+ // API / backend
39
+ if (/express|fastify|hono|django|fastapi|flask|axum|gin|echo/.test(fw) || /api|server|backend/.test(project.description?.toLowerCase() ?? "")) {
40
+ recs.push({ slug: "agent-skills:api-and-interface-design", reason: "API design" });
41
+ }
42
+ // Security-sensitive
43
+ if (auth || /payment|stripe|billing|oauth|jwt|session/.test([db, stack.other.join(" ")].join(" ").toLowerCase())) {
44
+ recs.push({ slug: "agent-skills:security-and-hardening", reason: "auth/payments in stack" });
45
+ }
46
+ // Observability — deploy target present
47
+ if (deploy) {
48
+ recs.push({ slug: "agent-skills:observability-and-monitoring", reason: `${deploy} deployment` });
49
+ }
50
+ // TypeScript-specific
51
+ if (lang === "typescript") {
52
+ recs.push({ slug: "agent-skills:code-review-and-quality", reason: "TypeScript quality gates" });
53
+ }
54
+ // Deduplicate by slug
55
+ const seen = new Set();
56
+ return recs.filter((r) => {
57
+ if (seen.has(r.slug))
58
+ return false;
59
+ seen.add(r.slug);
60
+ return true;
61
+ });
62
+ }
63
+ /**
64
+ * Derives the full content for CLAUDE.md.
65
+ *
66
+ * Content = canonical AGENTS.md + Claude Code-specific section.
67
+ * If preserveCustom is true (default) any existing custom blocks from the
68
+ * current CLAUDE.md are appended after the generated body.
69
+ *
70
+ * Does NOT write the file — the caller is responsible for writing.
71
+ */
72
+ export async function deriveClaudeMd(options) {
73
+ const { projectPath, agentsMdContent, metadata, preserveCustom = true } = options;
74
+ const skillsSummary = await scanProjectSkills(projectPath);
75
+ const skillsSection = formatSkillsSection(skillsSummary);
76
+ const skillsBlock = skillsSection ? `\n${skillsSection}\n` : "";
77
+ const recs = recommendSkills(metadata);
78
+ const recsBlock = recs.length > 0
79
+ ? `\n## Recommended Skills\n\n${recs.map((r) => `- \`/${r.slug}\` — ${r.reason}`).join("\n")}\n`
80
+ : "";
81
+ const generated = `${agentsMdContent.trimEnd()}${skillsBlock}${recsBlock}\n${CLAUDE_CODE_SECTION}`;
82
+ if (!preserveCustom)
83
+ return generated;
84
+ const claudeMdPath = path.join(projectPath, "CLAUDE.md");
85
+ // Preserve managed custom blocks first; fall back to wrapping the whole
86
+ // file if it exists but was never managed by agents-sync.
87
+ const existingBlocks = await loadExistingCustomBlocks(claudeMdPath);
88
+ const blocks = existingBlocks.length > 0
89
+ ? existingBlocks
90
+ : await loadUnmanagedFileAsCustomBlock(claudeMdPath);
91
+ return injectCustomBlocks(generated, blocks);
92
+ }
93
+ //# sourceMappingURL=claude.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude.js","sourceRoot":"","sources":["../../src/derivers/claude.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import type { ProjectMetadata } from "../extractor/schema.js";
2
+ export interface ClineDerivationOptions {
3
+ projectPath: string;
4
+ agentsMdContent: string;
5
+ metadata: ProjectMetadata;
6
+ /** @default true */
7
+ preserveCustom?: boolean;
8
+ }
9
+ /**
10
+ * Derives `.clinerules` content from AGENTS.md + metadata.
11
+ * Cline reads this file for project-specific AI instructions.
12
+ * Target < 400 words.
13
+ *
14
+ * Does NOT write the file — the caller is responsible for writing.
15
+ */
16
+ export declare function deriveClineRules(options: ClineDerivationOptions): Promise<string>;
17
+ //# sourceMappingURL=cline.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cline.d.ts","sourceRoot":"","sources":["../../src/derivers/cline.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAG9D,MAAM,WAAW,sBAAsB;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,eAAe,CAAC;IAC1B,oBAAoB;IACpB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAyCD;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,MAAM,CAAC,CAiEvF"}
@@ -0,0 +1,92 @@
1
+ import path from "node:path";
2
+ import { injectCustomBlocks, loadExistingCustomBlocks } from "./merger.js";
3
+ function escapeRegExp(s) {
4
+ return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
5
+ }
6
+ function extractSection(content, heading) {
7
+ const re = new RegExp(`^##\\s+${escapeRegExp(heading)}\\s*$([\\s\\S]*?)(?=^##\\s|$)`, "mi");
8
+ const match = re.exec(content);
9
+ return match ? match[1].trim() : "";
10
+ }
11
+ function extractSubSection(content, heading) {
12
+ const re = new RegExp(`^###\\s+${escapeRegExp(heading)}\\s*$([\\s\\S]*?)(?=^###\\s|^##\\s|$)`, "mi");
13
+ const match = re.exec(content);
14
+ return match ? match[1].trim() : "";
15
+ }
16
+ function sectionToLines(text) {
17
+ return text
18
+ .split("\n")
19
+ .map((l) => l.replace(/^[\s\-*>]+/, "").trim())
20
+ .filter((l) => l.length > 0);
21
+ }
22
+ function deduplicateLines(items) {
23
+ const seen = new Set();
24
+ return items.filter((item) => {
25
+ const key = item.toLowerCase().trim();
26
+ if (seen.has(key))
27
+ return false;
28
+ seen.add(key);
29
+ return true;
30
+ });
31
+ }
32
+ /**
33
+ * Derives `.clinerules` content from AGENTS.md + metadata.
34
+ * Cline reads this file for project-specific AI instructions.
35
+ * Target < 400 words.
36
+ *
37
+ * Does NOT write the file — the caller is responsible for writing.
38
+ */
39
+ export async function deriveClineRules(options) {
40
+ const { projectPath, agentsMdContent, metadata, preserveCustom = true } = options;
41
+ const { project, conventions: metaConventions, gotchas: metaGotchas, boundaries, testing } = metadata;
42
+ const conventionsSection = sectionToLines(extractSection(agentsMdContent, "Conventions"));
43
+ const gotchasSection = sectionToLines(extractSection(agentsMdContent, "Gotchas"));
44
+ const neverSection = sectionToLines(extractSubSection(agentsMdContent, "Never"));
45
+ const allConventions = deduplicateLines([...metaConventions, ...conventionsSection]);
46
+ const allGotchas = deduplicateLines([...metaGotchas, ...gotchasSection]);
47
+ const allNever = deduplicateLines([...boundaries.never, ...neverSection]);
48
+ const lines = [];
49
+ const fwPart = project.framework ? ` / ${project.framework}` : "";
50
+ lines.push(`# .clinerules — managed by agents-sync`);
51
+ lines.push(`# Language: ${project.language}${fwPart}`);
52
+ lines.push("");
53
+ if (allConventions.length > 0) {
54
+ lines.push("## Conventions");
55
+ for (const rule of allConventions) {
56
+ lines.push(`- ${rule}`);
57
+ }
58
+ lines.push("");
59
+ }
60
+ if (allGotchas.length > 0) {
61
+ lines.push("## Gotchas");
62
+ for (const gotcha of allGotchas) {
63
+ lines.push(`- ${gotcha}`);
64
+ }
65
+ lines.push("");
66
+ }
67
+ if (allNever.length > 0) {
68
+ lines.push("## Never");
69
+ for (const rule of allNever) {
70
+ lines.push(`- ${rule}`);
71
+ }
72
+ lines.push("");
73
+ }
74
+ if (boundaries.alwaysDo.length > 0) {
75
+ lines.push("## Always");
76
+ for (const rule of boundaries.alwaysDo) {
77
+ lines.push(`- ${rule}`);
78
+ }
79
+ lines.push("");
80
+ }
81
+ if (testing.command) {
82
+ lines.push(`**Tests:** \`${testing.command}\``);
83
+ lines.push("");
84
+ }
85
+ const generated = lines.join("\n").trimEnd() + "\n";
86
+ if (!preserveCustom)
87
+ return generated;
88
+ const clinePath = path.join(projectPath, ".clinerules");
89
+ const existingBlocks = await loadExistingCustomBlocks(clinePath);
90
+ return injectCustomBlocks(generated, existingBlocks);
91
+ }
92
+ //# sourceMappingURL=cline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cline.js","sourceRoot":"","sources":["../../src/derivers/cline.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import type { ProjectMetadata } from "../extractor/schema.js";
2
+ export interface CopilotDerivationOptions {
3
+ projectPath: string;
4
+ agentsMdContent: string;
5
+ metadata: ProjectMetadata;
6
+ /** @default true */
7
+ preserveCustom?: boolean;
8
+ }
9
+ /**
10
+ * Derives `.github/copilot-instructions.md` content from AGENTS.md + metadata.
11
+ * Focuses strictly on inline code-generation context — target < 300 words.
12
+ *
13
+ * Does NOT write the file — the caller is responsible for writing.
14
+ */
15
+ export declare function deriveCopilotInstructions(options: CopilotDerivationOptions): Promise<string>;
16
+ //# sourceMappingURL=copilot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"copilot.d.ts","sourceRoot":"","sources":["../../src/derivers/copilot.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAG9D,MAAM,WAAW,wBAAwB;IACvC,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,eAAe,CAAC;IAC1B,oBAAoB;IACpB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAyGD;;;;;GAKG;AACH,wBAAsB,yBAAyB,CAC7C,OAAO,EAAE,wBAAwB,GAChC,OAAO,CAAC,MAAM,CAAC,CA4EjB"}
@@ -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"}