agentpacks 0.3.0 → 0.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 (166) hide show
  1. package/README.md +168 -8
  2. package/dist/api.d.ts +2 -0
  3. package/dist/api.js +929 -409
  4. package/dist/cli/export-cmd.js +281 -149
  5. package/dist/cli/generate.js +740 -247
  6. package/dist/cli/import-cmd.js +57 -85
  7. package/dist/cli/info.d.ts +4 -0
  8. package/dist/cli/info.js +232 -0
  9. package/dist/cli/init.js +8 -36
  10. package/dist/cli/install.js +414 -129
  11. package/dist/cli/login.d.ts +9 -0
  12. package/dist/cli/login.js +202 -0
  13. package/dist/cli/models-explain.d.ts +16 -0
  14. package/dist/cli/models-explain.js +1205 -0
  15. package/dist/cli/pack/create.js +4 -32
  16. package/dist/cli/pack/enable.js +1 -29
  17. package/dist/cli/pack/list.js +266 -134
  18. package/dist/cli/pack/validate.js +274 -127
  19. package/dist/cli/publish.d.ts +8 -0
  20. package/dist/cli/publish.js +672 -0
  21. package/dist/cli/search.d.ts +12 -0
  22. package/dist/cli/search.js +210 -0
  23. package/dist/core/config.d.ts +2 -1
  24. package/dist/core/config.js +74 -117
  25. package/dist/core/dependency-resolver.js +4 -28
  26. package/dist/core/feature-merger.d.ts +7 -0
  27. package/dist/core/feature-merger.js +289 -29
  28. package/dist/core/index.js +283 -140
  29. package/dist/core/lockfile.js +0 -28
  30. package/dist/core/metarepo.js +74 -116
  31. package/dist/core/pack-loader.d.ts +2 -0
  32. package/dist/core/pack-loader.js +266 -133
  33. package/dist/core/profile-resolver.d.ts +75 -0
  34. package/dist/core/profile-resolver.js +111 -0
  35. package/dist/exporters/cursor-plugin.js +4 -32
  36. package/dist/exporters/index.js +4 -32
  37. package/dist/features/agents.d.ts +5 -0
  38. package/dist/features/agents.js +2 -30
  39. package/dist/features/commands.js +2 -30
  40. package/dist/features/hooks.js +2 -30
  41. package/dist/features/ignore.js +0 -28
  42. package/dist/features/index.d.ts +1 -0
  43. package/dist/features/index.js +176 -31
  44. package/dist/features/mcp.js +2 -30
  45. package/dist/features/models.d.ts +167 -0
  46. package/dist/features/models.js +293 -0
  47. package/dist/features/plugins.js +2 -30
  48. package/dist/features/rules.js +2 -30
  49. package/dist/features/skills.js +2 -30
  50. package/dist/importers/claude-code.js +10 -38
  51. package/dist/importers/cursor.js +15 -43
  52. package/dist/importers/opencode.js +16 -44
  53. package/dist/importers/rulesync.js +22 -50
  54. package/dist/index.js +1710 -538
  55. package/dist/node/api.js +929 -409
  56. package/dist/node/cli/export-cmd.js +281 -149
  57. package/dist/node/cli/generate.js +740 -247
  58. package/dist/node/cli/import-cmd.js +57 -85
  59. package/dist/node/cli/info.js +232 -0
  60. package/dist/node/cli/init.js +8 -36
  61. package/dist/node/cli/install.js +414 -129
  62. package/dist/node/cli/login.js +202 -0
  63. package/dist/node/cli/models-explain.js +1205 -0
  64. package/dist/node/cli/pack/create.js +4 -32
  65. package/dist/node/cli/pack/enable.js +1 -29
  66. package/dist/node/cli/pack/list.js +266 -134
  67. package/dist/node/cli/pack/validate.js +274 -127
  68. package/dist/node/cli/publish.js +672 -0
  69. package/dist/node/cli/search.js +210 -0
  70. package/dist/node/core/config.js +74 -117
  71. package/dist/node/core/dependency-resolver.js +4 -28
  72. package/dist/node/core/feature-merger.js +289 -29
  73. package/dist/node/core/index.js +283 -140
  74. package/dist/node/core/lockfile.js +0 -28
  75. package/dist/node/core/metarepo.js +74 -116
  76. package/dist/node/core/pack-loader.js +266 -133
  77. package/dist/node/core/profile-resolver.js +111 -0
  78. package/dist/node/exporters/cursor-plugin.js +4 -32
  79. package/dist/node/exporters/index.js +4 -32
  80. package/dist/node/features/agents.js +2 -30
  81. package/dist/node/features/commands.js +2 -30
  82. package/dist/node/features/hooks.js +2 -30
  83. package/dist/node/features/ignore.js +0 -28
  84. package/dist/node/features/index.js +176 -31
  85. package/dist/node/features/mcp.js +2 -30
  86. package/dist/node/features/models.js +293 -0
  87. package/dist/node/features/plugins.js +2 -30
  88. package/dist/node/features/rules.js +2 -30
  89. package/dist/node/features/skills.js +2 -30
  90. package/dist/node/importers/claude-code.js +10 -38
  91. package/dist/node/importers/cursor.js +15 -43
  92. package/dist/node/importers/opencode.js +16 -44
  93. package/dist/node/importers/rulesync.js +22 -50
  94. package/dist/node/index.js +1710 -538
  95. package/dist/node/sources/git-ref.js +7 -30
  96. package/dist/node/sources/git.js +7 -30
  97. package/dist/node/sources/index.js +337 -39
  98. package/dist/node/sources/local.js +0 -28
  99. package/dist/node/sources/npm-ref.js +0 -28
  100. package/dist/node/sources/npm.js +10 -37
  101. package/dist/node/sources/registry-ref.js +37 -0
  102. package/dist/node/sources/registry.js +355 -0
  103. package/dist/node/targets/additional-targets.js +196 -37
  104. package/dist/node/targets/agents-md.js +5 -33
  105. package/dist/node/targets/base-target.js +0 -28
  106. package/dist/node/targets/claude-code.js +211 -41
  107. package/dist/node/targets/codex-cli.js +7 -35
  108. package/dist/node/targets/copilot.js +202 -41
  109. package/dist/node/targets/cursor.js +188 -40
  110. package/dist/node/targets/gemini-cli.js +10 -38
  111. package/dist/node/targets/generic-md-target.js +196 -37
  112. package/dist/node/targets/index.js +414 -106
  113. package/dist/node/targets/opencode.js +171 -51
  114. package/dist/node/targets/registry.js +414 -106
  115. package/dist/node/utils/credentials.js +38 -0
  116. package/dist/node/utils/diff.js +22 -34
  117. package/dist/node/utils/filesystem.js +2 -30
  118. package/dist/node/utils/frontmatter.js +0 -28
  119. package/dist/node/utils/global.js +3 -31
  120. package/dist/node/utils/markdown.js +0 -28
  121. package/dist/node/utils/model-allowlist.js +110 -0
  122. package/dist/node/utils/model-guidance.js +78 -0
  123. package/dist/node/utils/registry-client.js +142 -0
  124. package/dist/node/utils/tarball.js +49 -0
  125. package/dist/sources/git-ref.js +7 -30
  126. package/dist/sources/git.d.ts +2 -2
  127. package/dist/sources/git.js +7 -30
  128. package/dist/sources/index.d.ts +2 -0
  129. package/dist/sources/index.js +337 -39
  130. package/dist/sources/local.js +0 -28
  131. package/dist/sources/npm-ref.js +0 -28
  132. package/dist/sources/npm.js +10 -37
  133. package/dist/sources/registry-ref.d.ts +30 -0
  134. package/dist/sources/registry-ref.js +37 -0
  135. package/dist/sources/registry.d.ts +18 -0
  136. package/dist/sources/registry.js +355 -0
  137. package/dist/targets/additional-targets.js +196 -37
  138. package/dist/targets/agents-md.js +5 -33
  139. package/dist/targets/base-target.d.ts +2 -0
  140. package/dist/targets/base-target.js +0 -28
  141. package/dist/targets/claude-code.js +211 -41
  142. package/dist/targets/codex-cli.js +7 -35
  143. package/dist/targets/copilot.js +202 -41
  144. package/dist/targets/cursor.js +188 -40
  145. package/dist/targets/gemini-cli.js +10 -38
  146. package/dist/targets/generic-md-target.js +196 -37
  147. package/dist/targets/index.js +414 -106
  148. package/dist/targets/opencode.js +171 -51
  149. package/dist/targets/registry.js +414 -106
  150. package/dist/utils/credentials.d.ts +19 -0
  151. package/dist/utils/credentials.js +38 -0
  152. package/dist/utils/diff.js +22 -34
  153. package/dist/utils/filesystem.js +2 -30
  154. package/dist/utils/frontmatter.js +0 -28
  155. package/dist/utils/global.js +3 -31
  156. package/dist/utils/markdown.js +0 -28
  157. package/dist/utils/model-allowlist.d.ts +39 -0
  158. package/dist/utils/model-allowlist.js +110 -0
  159. package/dist/utils/model-guidance.d.ts +6 -0
  160. package/dist/utils/model-guidance.js +78 -0
  161. package/dist/utils/registry-client.d.ts +141 -0
  162. package/dist/utils/registry-client.js +142 -0
  163. package/dist/utils/tarball.d.ts +13 -0
  164. package/dist/utils/tarball.js +49 -0
  165. package/package.json +171 -5
  166. package/templates/pack/models.json +38 -0
@@ -1,51 +1,85 @@
1
1
  import { createRequire } from "node:module";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropNames = Object.getOwnPropertyNames;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __moduleCache = /* @__PURE__ */ new WeakMap;
7
- var __toCommonJS = (from) => {
8
- var entry = __moduleCache.get(from), desc;
9
- if (entry)
10
- return entry;
11
- entry = __defProp({}, "__esModule", { value: true });
12
- if (from && typeof from === "object" || typeof from === "function")
13
- __getOwnPropNames(from).map((key) => !__hasOwnProp.call(entry, key) && __defProp(entry, key, {
14
- get: () => from[key],
15
- enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
16
- }));
17
- __moduleCache.set(from, entry);
18
- return entry;
19
- };
20
- var __export = (target, all) => {
21
- for (var name in all)
22
- __defProp(target, name, {
23
- get: all[name],
24
- enumerable: true,
25
- configurable: true,
26
- set: (newValue) => all[name] = () => newValue
27
- });
28
- };
29
- var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
30
2
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
31
3
 
32
4
  // src/core/config.ts
33
- var exports_config = {};
34
- __export(exports_config, {
35
- resolveTargets: () => resolveTargets,
36
- resolveFeatures: () => resolveFeatures,
37
- loadWorkspaceConfig: () => loadWorkspaceConfig,
38
- loadPackManifest: () => loadPackManifest,
39
- WorkspaceConfigSchema: () => WorkspaceConfigSchema,
40
- TARGET_IDS: () => TARGET_IDS,
41
- REPO_MODES: () => REPO_MODES,
42
- PackManifestSchema: () => PackManifestSchema,
43
- FEATURE_IDS: () => FEATURE_IDS
44
- });
45
5
  import { z } from "zod";
46
6
  import { readFileSync, existsSync } from "fs";
47
7
  import { resolve } from "path";
48
8
  import { parse as parseJsonc } from "jsonc-parser";
9
+ var TARGET_IDS = [
10
+ "opencode",
11
+ "cursor",
12
+ "claudecode",
13
+ "codexcli",
14
+ "geminicli",
15
+ "copilot",
16
+ "agentsmd",
17
+ "cline",
18
+ "kilo",
19
+ "roo",
20
+ "qwencode",
21
+ "kiro",
22
+ "factorydroid",
23
+ "antigravity",
24
+ "junie",
25
+ "augmentcode",
26
+ "windsurf",
27
+ "warp",
28
+ "replit",
29
+ "zed"
30
+ ];
31
+ var FEATURE_IDS = [
32
+ "rules",
33
+ "commands",
34
+ "agents",
35
+ "skills",
36
+ "hooks",
37
+ "plugins",
38
+ "mcp",
39
+ "ignore",
40
+ "models"
41
+ ];
42
+ var REPO_MODES = ["repo", "monorepo", "metarepo"];
43
+ var PackManifestSchema = z.object({
44
+ name: z.string().min(1),
45
+ version: z.string().default("1.0.0"),
46
+ description: z.string().default(""),
47
+ author: z.union([
48
+ z.string(),
49
+ z.object({ name: z.string(), email: z.string().optional() })
50
+ ]).optional(),
51
+ tags: z.array(z.string()).default([]),
52
+ dependencies: z.array(z.string()).default([]),
53
+ conflicts: z.array(z.string()).default([]),
54
+ targets: z.union([z.literal("*"), z.array(z.string())]).default("*"),
55
+ features: z.union([z.literal("*"), z.array(z.string())]).default("*")
56
+ });
57
+ var FeaturesSchema = z.union([
58
+ z.literal("*"),
59
+ z.array(z.string()),
60
+ z.record(z.string(), z.union([z.literal("*"), z.array(z.string())]))
61
+ ]);
62
+ var WorkspaceConfigSchema = z.object({
63
+ $schema: z.string().optional(),
64
+ packs: z.array(z.string()).default(["./packs/default"]),
65
+ disabled: z.array(z.string()).default([]),
66
+ targets: z.union([z.literal("*"), z.array(z.string())]).default("*"),
67
+ features: FeaturesSchema.default("*"),
68
+ mode: z.enum(REPO_MODES).default("repo"),
69
+ baseDirs: z.array(z.string()).default(["."]),
70
+ global: z.boolean().default(false),
71
+ delete: z.boolean().default(true),
72
+ verbose: z.boolean().default(false),
73
+ silent: z.boolean().default(false),
74
+ overrides: z.record(z.string(), z.record(z.string(), z.string())).default({}),
75
+ sources: z.array(z.object({
76
+ source: z.string(),
77
+ packs: z.array(z.string()).optional(),
78
+ skills: z.array(z.string()).optional()
79
+ })).default([]),
80
+ modelProfile: z.string().optional()
81
+ });
82
+ var CONFIG_FILES = ["agentpacks.local.jsonc", "agentpacks.jsonc"];
49
83
  function loadWorkspaceConfig(projectRoot) {
50
84
  for (const filename of CONFIG_FILES) {
51
85
  const filepath = resolve(projectRoot, filename);
@@ -91,81 +125,6 @@ function resolveTargets(config) {
91
125
  return [...TARGET_IDS];
92
126
  return config.targets;
93
127
  }
94
- var TARGET_IDS, FEATURE_IDS, REPO_MODES, PackManifestSchema, FeaturesSchema, WorkspaceConfigSchema, CONFIG_FILES;
95
- var init_config = __esm(() => {
96
- TARGET_IDS = [
97
- "opencode",
98
- "cursor",
99
- "claudecode",
100
- "codexcli",
101
- "geminicli",
102
- "copilot",
103
- "agentsmd",
104
- "cline",
105
- "kilo",
106
- "roo",
107
- "qwencode",
108
- "kiro",
109
- "factorydroid",
110
- "antigravity",
111
- "junie",
112
- "augmentcode",
113
- "windsurf",
114
- "warp",
115
- "replit",
116
- "zed"
117
- ];
118
- FEATURE_IDS = [
119
- "rules",
120
- "commands",
121
- "agents",
122
- "skills",
123
- "hooks",
124
- "plugins",
125
- "mcp",
126
- "ignore"
127
- ];
128
- REPO_MODES = ["repo", "monorepo", "metarepo"];
129
- PackManifestSchema = z.object({
130
- name: z.string().min(1),
131
- version: z.string().default("1.0.0"),
132
- description: z.string().default(""),
133
- author: z.union([
134
- z.string(),
135
- z.object({ name: z.string(), email: z.string().optional() })
136
- ]).optional(),
137
- tags: z.array(z.string()).default([]),
138
- dependencies: z.array(z.string()).default([]),
139
- conflicts: z.array(z.string()).default([]),
140
- targets: z.union([z.literal("*"), z.array(z.string())]).default("*"),
141
- features: z.union([z.literal("*"), z.array(z.string())]).default("*")
142
- });
143
- FeaturesSchema = z.union([
144
- z.literal("*"),
145
- z.array(z.string()),
146
- z.record(z.string(), z.union([z.literal("*"), z.array(z.string())]))
147
- ]);
148
- WorkspaceConfigSchema = z.object({
149
- $schema: z.string().optional(),
150
- packs: z.array(z.string()).default(["./packs/default"]),
151
- disabled: z.array(z.string()).default([]),
152
- targets: z.union([z.literal("*"), z.array(z.string())]).default("*"),
153
- features: FeaturesSchema.default("*"),
154
- mode: z.enum(REPO_MODES).default("repo"),
155
- baseDirs: z.array(z.string()).default(["."]),
156
- global: z.boolean().default(false),
157
- delete: z.boolean().default(true),
158
- verbose: z.boolean().default(false),
159
- silent: z.boolean().default(false),
160
- overrides: z.record(z.string(), z.record(z.string(), z.string())).default({}),
161
- sources: z.array(z.object({
162
- source: z.string(),
163
- packs: z.array(z.string()).optional(),
164
- skills: z.array(z.string()).optional()
165
- })).default([])
166
- });
167
- CONFIG_FILES = ["agentpacks.local.jsonc", "agentpacks.jsonc"];
168
- });
169
128
 
170
129
  // src/utils/filesystem.ts
171
130
  import {
@@ -174,10 +133,10 @@ import {
174
133
  readFileSync as readFileSync2,
175
134
  writeFileSync,
176
135
  readdirSync,
136
+ rmSync,
177
137
  statSync
178
138
  } from "fs";
179
139
  import { dirname, relative, join } from "path";
180
- import { removeSync } from "fs-extra";
181
140
  var GENERATED_HEADER_MD = "<!-- Generated by agentpacks. DO NOT EDIT. -->";
182
141
  var GENERATED_HEADER_JSON = "// Generated by agentpacks. DO NOT EDIT.";
183
142
  var GENERATED_HEADER_JS = "// Generated by agentpacks. DO NOT EDIT.";
@@ -218,7 +177,7 @@ function ensureDir(dirPath) {
218
177
  }
219
178
  function removeIfExists(targetPath) {
220
179
  if (existsSync2(targetPath)) {
221
- removeSync(targetPath);
180
+ rmSync(targetPath, { recursive: true, force: true });
222
181
  }
223
182
  }
224
183
  function listFiles(dirPath, options = {}) {
@@ -544,10 +503,178 @@ function mergeIgnorePatterns(configs) {
544
503
  return result;
545
504
  }
546
505
 
506
+ // src/features/models.ts
507
+ import { join as join7 } from "path";
508
+ import { z as z2 } from "zod";
509
+ var SECRET_PATTERNS = [
510
+ /["']api[_-]?key["']\s*:/i,
511
+ /["']apiKey["']\s*:/i,
512
+ /["']secret["']\s*:/i,
513
+ /["']password["']\s*:/i,
514
+ /["'](?:auth_token|access_token|bearer_token)["']\s*:/i,
515
+ /["']private[_-]?key["']\s*:/i,
516
+ /-----BEGIN\s+(RSA|EC|DSA|OPENSSH|PGP)\s+PRIVATE\s+KEY-----/,
517
+ /sk-[a-zA-Z0-9]{20,}/,
518
+ /Bearer\s+[a-zA-Z0-9._-]{20,}/
519
+ ];
520
+ var AgentModelSchema = z2.object({
521
+ model: z2.string(),
522
+ temperature: z2.number().min(0).max(2).optional(),
523
+ top_p: z2.number().min(0).max(1).optional()
524
+ });
525
+ var ModelProfileSchema = z2.object({
526
+ extends: z2.string().optional(),
527
+ description: z2.string().optional(),
528
+ default: z2.string().optional(),
529
+ small: z2.string().optional(),
530
+ agents: z2.record(z2.string(), AgentModelSchema).optional()
531
+ });
532
+ var RoutingConditionSchema = z2.object({
533
+ complexity: z2.enum(["low", "medium", "high", "critical"]).optional().describe("Task complexity level"),
534
+ urgency: z2.enum(["low", "normal", "high"]).optional().describe("Time sensitivity"),
535
+ budget: z2.enum(["minimal", "standard", "premium"]).optional().describe("Cost/token budget tier"),
536
+ contextWindowNeed: z2.enum(["small", "medium", "large", "max"]).optional().describe("Required context window size"),
537
+ toolUseIntensity: z2.enum(["none", "light", "heavy"]).optional().describe("Expected tool/function calling intensity")
538
+ });
539
+ var RoutingRuleSchema = z2.object({
540
+ when: z2.record(z2.string(), z2.string()),
541
+ use: z2.string(),
542
+ description: z2.string().optional(),
543
+ priority: z2.number().optional()
544
+ });
545
+ var ProviderModelSchema = z2.object({
546
+ options: z2.record(z2.string(), z2.unknown()).optional(),
547
+ variants: z2.record(z2.string(), z2.record(z2.string(), z2.unknown())).optional()
548
+ });
549
+ var ProviderConfigSchema = z2.object({
550
+ options: z2.record(z2.string(), z2.unknown()).optional(),
551
+ models: z2.record(z2.string(), ProviderModelSchema).optional()
552
+ });
553
+ var ModelsSchema = z2.object({
554
+ default: z2.string().optional(),
555
+ small: z2.string().optional(),
556
+ agents: z2.record(z2.string(), AgentModelSchema).optional(),
557
+ profiles: z2.record(z2.string(), ModelProfileSchema).optional(),
558
+ providers: z2.record(z2.string(), ProviderConfigSchema).optional(),
559
+ routing: z2.array(RoutingRuleSchema).optional(),
560
+ overrides: z2.record(z2.string(), z2.object({
561
+ default: z2.string().optional(),
562
+ small: z2.string().optional(),
563
+ agents: z2.record(z2.string(), AgentModelSchema).optional()
564
+ })).optional()
565
+ });
566
+ function parseModels(packDir, packName) {
567
+ const modelsPath = join7(packDir, "models.json");
568
+ const raw = readJsonOrNull(modelsPath);
569
+ if (!raw)
570
+ return null;
571
+ const parsed = ModelsSchema.parse(raw);
572
+ return {
573
+ packName,
574
+ sourcePath: modelsPath,
575
+ config: parsed
576
+ };
577
+ }
578
+ function mergeModelsConfigs(configs) {
579
+ const warnings = [];
580
+ const result = {};
581
+ for (const entry of configs) {
582
+ const { config, packName } = entry;
583
+ if (config.default !== undefined && result.default === undefined) {
584
+ result.default = config.default;
585
+ } else if (config.default !== undefined && result.default !== undefined) {
586
+ warnings.push(`Models "default" from pack "${packName}" skipped (already defined).`);
587
+ }
588
+ if (config.small !== undefined && result.small === undefined) {
589
+ result.small = config.small;
590
+ } else if (config.small !== undefined && result.small !== undefined) {
591
+ warnings.push(`Models "small" from pack "${packName}" skipped (already defined).`);
592
+ }
593
+ if (config.agents) {
594
+ if (!result.agents)
595
+ result.agents = {};
596
+ for (const [name, assignment] of Object.entries(config.agents)) {
597
+ if (name in result.agents) {
598
+ warnings.push(`Models agent "${name}" from pack "${packName}" skipped (already defined).`);
599
+ continue;
600
+ }
601
+ result.agents[name] = assignment;
602
+ }
603
+ }
604
+ if (config.profiles) {
605
+ if (!result.profiles)
606
+ result.profiles = {};
607
+ for (const [name, profile] of Object.entries(config.profiles)) {
608
+ if (name in result.profiles) {
609
+ warnings.push(`Models profile "${name}" from pack "${packName}" skipped (already defined).`);
610
+ continue;
611
+ }
612
+ result.profiles[name] = profile;
613
+ }
614
+ }
615
+ if (config.providers) {
616
+ if (!result.providers)
617
+ result.providers = {};
618
+ for (const [providerName, providerConfig] of Object.entries(config.providers)) {
619
+ if (!(providerName in result.providers)) {
620
+ result.providers[providerName] = providerConfig;
621
+ } else {
622
+ const existing = result.providers[providerName];
623
+ if (!existing) {
624
+ result.providers[providerName] = providerConfig;
625
+ continue;
626
+ }
627
+ if (providerConfig.options) {
628
+ existing.options = {
629
+ ...providerConfig.options,
630
+ ...existing.options
631
+ };
632
+ }
633
+ if (providerConfig.models) {
634
+ if (!existing.models)
635
+ existing.models = {};
636
+ for (const [modelName, modelConfig] of Object.entries(providerConfig.models)) {
637
+ if (!(modelName in existing.models)) {
638
+ existing.models[modelName] = modelConfig;
639
+ }
640
+ }
641
+ }
642
+ }
643
+ }
644
+ }
645
+ if (config.routing) {
646
+ if (!result.routing)
647
+ result.routing = [];
648
+ result.routing.push(...config.routing);
649
+ }
650
+ if (config.overrides) {
651
+ if (!result.overrides)
652
+ result.overrides = {};
653
+ for (const [targetId, override] of Object.entries(config.overrides)) {
654
+ if (targetId in result.overrides) {
655
+ warnings.push(`Models override for target "${targetId}" from pack "${packName}" skipped (already defined).`);
656
+ continue;
657
+ }
658
+ result.overrides[targetId] = override;
659
+ }
660
+ }
661
+ }
662
+ return { config: result, warnings };
663
+ }
664
+ function scanModelsForSecrets(config) {
665
+ const warnings = [];
666
+ const json = JSON.stringify(config);
667
+ for (const pattern of SECRET_PATTERNS) {
668
+ if (pattern.test(json)) {
669
+ warnings.push(`Potential secret detected in models.json matching pattern: ${pattern.source}`);
670
+ }
671
+ }
672
+ return warnings;
673
+ }
674
+
547
675
  // src/core/pack-loader.ts
548
- init_config();
549
676
  import { existsSync as existsSync6 } from "fs";
550
- import { resolve as resolve3, isAbsolute } from "path";
677
+ import { resolve as resolve2, isAbsolute } from "path";
551
678
  class PackLoader {
552
679
  projectRoot;
553
680
  config;
@@ -580,10 +707,10 @@ class PackLoader {
580
707
  }
581
708
  loadPack(packDir, manifest) {
582
709
  const name = manifest.name;
583
- const rulesDir = resolve3(packDir, "rules");
584
- const commandsDir = resolve3(packDir, "commands");
585
- const agentsDir = resolve3(packDir, "agents");
586
- const skillsDir = resolve3(packDir, "skills");
710
+ const rulesDir = resolve2(packDir, "rules");
711
+ const commandsDir = resolve2(packDir, "commands");
712
+ const agentsDir = resolve2(packDir, "agents");
713
+ const skillsDir = resolve2(packDir, "skills");
587
714
  return {
588
715
  manifest,
589
716
  directory: packDir,
@@ -594,23 +721,25 @@ class PackLoader {
594
721
  hooks: parseHooks(packDir, name),
595
722
  plugins: parsePlugins(packDir, name),
596
723
  mcp: parseMcp(packDir, name),
597
- ignore: parseIgnore(packDir, name)
724
+ ignore: parseIgnore(packDir, name),
725
+ models: parseModels(packDir, name)
598
726
  };
599
727
  }
600
728
  loadForBaseDir(baseDir) {
601
- const baseDirRoot = resolve3(this.projectRoot, baseDir);
602
- const localConfigPath = resolve3(baseDirRoot, "agentpacks.jsonc");
729
+ const baseDirRoot = resolve2(this.projectRoot, baseDir);
730
+ const localConfigPath = resolve2(baseDirRoot, "agentpacks.jsonc");
603
731
  if (!existsSync6(localConfigPath)) {
604
732
  return { packs: [], warnings: [] };
605
733
  }
606
- const { loadWorkspaceConfig: loadWorkspaceConfig2 } = (init_config(), __toCommonJS(exports_config));
607
- const localConfig = loadWorkspaceConfig2(baseDirRoot);
734
+ const localConfig = loadWorkspaceConfig(baseDirRoot);
608
735
  const loader = new PackLoader(baseDirRoot, localConfig);
609
736
  return loader.loadAll();
610
737
  }
611
738
  resolveCuratedPack(packRef) {
612
- const curatedDir = resolve3(this.projectRoot, ".agentpacks", ".curated");
739
+ const curatedDir = resolve2(this.projectRoot, ".agentpacks", ".curated");
613
740
  let packName = packRef;
741
+ if (packName.startsWith("registry:"))
742
+ packName = packName.slice(9);
614
743
  if (packName.startsWith("npm:"))
615
744
  packName = packName.slice(4);
616
745
  if (packName.startsWith("github:"))
@@ -621,24 +750,28 @@ class PackLoader {
621
750
  const parts = packName.split("/");
622
751
  packName = packName.includes("@") ? parts.join("-") : parts[parts.length - 1] ?? packName;
623
752
  }
624
- packName = packName.split("@")[0].split(":")[0];
625
- const resolved = resolve3(curatedDir, packName);
753
+ const withoutVersion = packName.split("@")[0] ?? packName;
754
+ packName = withoutVersion.split(":")[0] ?? withoutVersion;
755
+ const resolved = resolve2(curatedDir, packName);
626
756
  return existsSync6(resolved) ? resolved : null;
627
757
  }
628
758
  resolvePackPath(packRef) {
629
759
  if (packRef.startsWith("./") || packRef.startsWith("../")) {
630
- return resolve3(this.projectRoot, packRef);
760
+ return resolve2(this.projectRoot, packRef);
631
761
  }
632
762
  if (isAbsolute(packRef)) {
633
763
  return packRef;
634
764
  }
765
+ if (packRef.startsWith("registry:")) {
766
+ return this.resolveCuratedPack(packRef);
767
+ }
635
768
  if (packRef.startsWith("@") || packRef.startsWith("npm:") || !packRef.includes("/")) {
636
769
  return this.resolveCuratedPack(packRef);
637
770
  }
638
771
  if (packRef.startsWith("github:") || packRef.includes("/")) {
639
772
  return this.resolveCuratedPack(packRef);
640
773
  }
641
- return resolve3(this.projectRoot, packRef);
774
+ return resolve2(this.projectRoot, packRef);
642
775
  }
643
776
  }
644
777
 
@@ -659,7 +792,8 @@ class FeatureMerger {
659
792
  hooks: this.mergeHooks(),
660
793
  plugins: this.mergePlugins(),
661
794
  mcpServers: this.mergeMcp(),
662
- ignorePatterns: this.mergeIgnore()
795
+ ignorePatterns: this.mergeIgnore(),
796
+ models: this.mergeModels()
663
797
  };
664
798
  return { features, warnings: this.warnings };
665
799
  }
@@ -746,6 +880,118 @@ class FeatureMerger {
746
880
  }
747
881
  return result;
748
882
  }
883
+ mergeModels() {
884
+ const configs = this.packs.map((p) => p.models).filter((m) => m != null);
885
+ if (configs.length === 0)
886
+ return null;
887
+ const { config, warnings } = mergeModelsConfigs(configs);
888
+ this.warnings.push(...warnings);
889
+ return config;
890
+ }
891
+ }
892
+
893
+ // src/core/profile-resolver.ts
894
+ function resolveModels(merged, modelProfile, targetId) {
895
+ let defaultModel = merged.default;
896
+ let smallModel = merged.small;
897
+ let agents = { ...merged.agents };
898
+ if (modelProfile && merged.profiles?.[modelProfile]) {
899
+ const resolvedProfile = resolveProfileInheritance(modelProfile, merged.profiles);
900
+ if (resolvedProfile.default)
901
+ defaultModel = resolvedProfile.default;
902
+ if (resolvedProfile.small)
903
+ smallModel = resolvedProfile.small;
904
+ if (resolvedProfile.agents) {
905
+ agents = { ...agents, ...resolvedProfile.agents };
906
+ }
907
+ }
908
+ if (targetId) {
909
+ const targetOverride = merged.overrides?.[targetId];
910
+ if (targetOverride) {
911
+ if (targetOverride.default)
912
+ defaultModel = targetOverride.default;
913
+ if (targetOverride.small)
914
+ smallModel = targetOverride.small;
915
+ if (targetOverride.agents) {
916
+ agents = { ...agents, ...targetOverride.agents };
917
+ }
918
+ }
919
+ }
920
+ const providers = {};
921
+ if (merged.providers) {
922
+ for (const [name, config] of Object.entries(merged.providers)) {
923
+ providers[name] = {
924
+ ...config.options ? { options: config.options } : {},
925
+ ...config.models ? { models: config.models } : {}
926
+ };
927
+ }
928
+ }
929
+ const profileNames = Object.keys(merged.profiles ?? {});
930
+ const profiles = {};
931
+ if (merged.profiles) {
932
+ for (const [name, profile] of Object.entries(merged.profiles)) {
933
+ profiles[name] = {
934
+ description: profile.description,
935
+ default: profile.default,
936
+ small: profile.small
937
+ };
938
+ }
939
+ }
940
+ return {
941
+ default: defaultModel,
942
+ small: smallModel,
943
+ agents,
944
+ providers,
945
+ routing: merged.routing ?? [],
946
+ profileNames,
947
+ activeProfile: modelProfile,
948
+ profiles
949
+ };
950
+ }
951
+ function resolveAgentModel(resolved, agentName, frontmatterModel) {
952
+ const fromModels = resolved.agents[agentName];
953
+ if (fromModels) {
954
+ return {
955
+ model: fromModels.model,
956
+ temperature: fromModels.temperature,
957
+ top_p: fromModels.top_p
958
+ };
959
+ }
960
+ if (frontmatterModel) {
961
+ return { model: frontmatterModel };
962
+ }
963
+ return {};
964
+ }
965
+ function resolveProfileInheritance(profileName, profiles) {
966
+ const visited = new Set;
967
+ return resolveProfileChain(profileName, profiles, visited, 0);
968
+ }
969
+ var MAX_INHERITANCE_DEPTH = 10;
970
+ function resolveProfileChain(name, profiles, visited, depth) {
971
+ if (depth > MAX_INHERITANCE_DEPTH) {
972
+ throw new Error(`Profile inheritance too deep (max ${MAX_INHERITANCE_DEPTH}): ${name}`);
973
+ }
974
+ if (visited.has(name)) {
975
+ throw new Error(`Circular profile inheritance detected: ${[...visited, name].join(" → ")}`);
976
+ }
977
+ const profile = profiles[name];
978
+ if (!profile) {
979
+ throw new Error(`Profile "${name}" not found`);
980
+ }
981
+ visited.add(name);
982
+ if (!profile.extends) {
983
+ return { ...profile };
984
+ }
985
+ const parent = resolveProfileChain(profile.extends, profiles, visited, depth + 1);
986
+ return {
987
+ description: profile.description ?? parent.description,
988
+ default: profile.default ?? parent.default,
989
+ small: profile.small ?? parent.small,
990
+ agents: {
991
+ ...parent.agents,
992
+ ...profile.agents
993
+ }
994
+ };
749
995
  }
750
996
 
751
997
  // src/targets/base-target.ts
@@ -792,7 +1038,7 @@ ${content}`;
792
1038
  }
793
1039
 
794
1040
  // src/targets/opencode.ts
795
- import { resolve as resolve4, join as join7 } from "path";
1041
+ import { resolve as resolve3, join as join8 } from "path";
796
1042
  var TARGET_ID = "opencode";
797
1043
 
798
1044
  class OpenCodeTarget extends BaseTarget {
@@ -806,32 +1052,48 @@ class OpenCodeTarget extends BaseTarget {
806
1052
  "hooks",
807
1053
  "plugins",
808
1054
  "mcp",
809
- "ignore"
1055
+ "ignore",
1056
+ "models"
810
1057
  ];
811
1058
  generate(options) {
812
1059
  const { projectRoot, baseDir, features, enabledFeatures, deleteExisting } = options;
813
- const root = resolve4(projectRoot, baseDir);
1060
+ const root = resolve3(projectRoot, baseDir);
814
1061
  const effective = this.getEffectiveFeatures(enabledFeatures);
815
1062
  const filesWritten = [];
816
1063
  const filesDeleted = [];
817
1064
  const warnings = [];
818
- const opencodeDir = resolve4(root, ".opencode");
1065
+ const opencodeDir = resolve3(root, ".opencode");
819
1066
  if (effective.includes("agents")) {
820
- const agentDir = resolve4(opencodeDir, "agent");
1067
+ const agentDir = resolve3(opencodeDir, "agent");
821
1068
  if (deleteExisting) {
822
1069
  removeIfExists(agentDir);
823
1070
  filesDeleted.push(agentDir);
824
1071
  }
825
1072
  ensureDir(agentDir);
1073
+ const resolvedModels = features.models ? resolveModels(features.models, options.modelProfile, TARGET_ID) : null;
826
1074
  const agents = features.agents.filter((a) => agentMatchesTarget(a, TARGET_ID));
827
1075
  for (const agent of agents) {
828
- const filepath = join7(agentDir, `${agent.name}.md`);
829
- writeGeneratedFile(filepath, agent.content);
1076
+ const filepath = join8(agentDir, `${agent.name}.md`);
1077
+ const fm = {};
1078
+ const oc = agent.meta.opencode ?? {};
1079
+ const modelsAgent = resolvedModels?.agents[agent.name];
1080
+ const agentModel = modelsAgent?.model ?? oc.model;
1081
+ const agentTemp = modelsAgent?.temperature ?? oc.temperature;
1082
+ if (agentModel)
1083
+ fm.model = agentModel;
1084
+ if (agentTemp !== undefined)
1085
+ fm.temperature = agentTemp;
1086
+ if (oc.mode)
1087
+ fm.mode = oc.mode;
1088
+ if (oc.top_p !== undefined)
1089
+ fm.top_p = oc.top_p;
1090
+ const content = Object.keys(fm).length > 0 ? serializeFrontmatter(fm, agent.content) : agent.content;
1091
+ writeGeneratedFile(filepath, content);
830
1092
  filesWritten.push(filepath);
831
1093
  }
832
1094
  }
833
1095
  if (effective.includes("skills")) {
834
- const skillDir = resolve4(opencodeDir, "skill");
1096
+ const skillDir = resolve3(opencodeDir, "skill");
835
1097
  if (deleteExisting) {
836
1098
  removeIfExists(skillDir);
837
1099
  filesDeleted.push(skillDir);
@@ -839,15 +1101,15 @@ class OpenCodeTarget extends BaseTarget {
839
1101
  ensureDir(skillDir);
840
1102
  const skills = features.skills.filter((s) => skillMatchesTarget(s, TARGET_ID));
841
1103
  for (const skill of skills) {
842
- const skillSubDir = join7(skillDir, skill.name);
1104
+ const skillSubDir = join8(skillDir, skill.name);
843
1105
  ensureDir(skillSubDir);
844
- const filepath = join7(skillSubDir, "SKILL.md");
1106
+ const filepath = join8(skillSubDir, "SKILL.md");
845
1107
  writeGeneratedFile(filepath, skill.content);
846
1108
  filesWritten.push(filepath);
847
1109
  }
848
1110
  }
849
1111
  if (effective.includes("commands")) {
850
- const cmdDir = resolve4(opencodeDir, "command");
1112
+ const cmdDir = resolve3(opencodeDir, "command");
851
1113
  if (deleteExisting) {
852
1114
  removeIfExists(cmdDir);
853
1115
  filesDeleted.push(cmdDir);
@@ -855,19 +1117,19 @@ class OpenCodeTarget extends BaseTarget {
855
1117
  ensureDir(cmdDir);
856
1118
  const commands = features.commands.filter((c) => commandMatchesTarget(c, TARGET_ID));
857
1119
  for (const cmd of commands) {
858
- const filepath = join7(cmdDir, `${cmd.name}.md`);
1120
+ const filepath = join8(cmdDir, `${cmd.name}.md`);
859
1121
  writeGeneratedFile(filepath, cmd.content);
860
1122
  filesWritten.push(filepath);
861
1123
  }
862
1124
  }
863
1125
  if (effective.includes("hooks") || effective.includes("plugins")) {
864
- const pluginsDir = resolve4(opencodeDir, "plugins");
1126
+ const pluginsDir = resolve3(opencodeDir, "plugins");
865
1127
  ensureDir(pluginsDir);
866
1128
  if (effective.includes("hooks")) {
867
1129
  for (const hookSet of features.hooks) {
868
1130
  const events = resolveHooksForTarget(hookSet, TARGET_ID);
869
1131
  if (Object.keys(events).length > 0) {
870
- const filepath = join7(pluginsDir, `agentpacks-${hookSet.packName}.ts`);
1132
+ const filepath = join8(pluginsDir, `agentpacks-${hookSet.packName}.ts`);
871
1133
  const content = generateOpenCodeHookPlugin(hookSet.packName, events);
872
1134
  writeGeneratedFile(filepath, content, { type: "ts" });
873
1135
  filesWritten.push(filepath);
@@ -876,7 +1138,7 @@ class OpenCodeTarget extends BaseTarget {
876
1138
  }
877
1139
  if (effective.includes("plugins")) {
878
1140
  for (const plugin of features.plugins) {
879
- const filepath = join7(pluginsDir, `agentpacks-${plugin.packName}-${plugin.name}.${plugin.extension}`);
1141
+ const filepath = join8(pluginsDir, `agentpacks-${plugin.packName}-${plugin.name}.${plugin.extension}`);
880
1142
  writeGeneratedFile(filepath, plugin.content, {
881
1143
  type: plugin.extension
882
1144
  });
@@ -884,28 +1146,59 @@ class OpenCodeTarget extends BaseTarget {
884
1146
  }
885
1147
  }
886
1148
  }
887
- if (effective.includes("mcp")) {
888
- const mcpEntries = Object.entries(features.mcpServers);
889
- if (mcpEntries.length > 0) {
890
- const opencodeConfig = buildOpenCodeMcp(features.mcpServers);
891
- const filepath = resolve4(root, "opencode.json");
1149
+ if (effective.includes("mcp") || effective.includes("models")) {
1150
+ const filepath = resolve3(root, "opencode.json");
1151
+ const opencodeConfig = {
1152
+ $schema: "https://opencode.ai/config.json"
1153
+ };
1154
+ if (effective.includes("mcp")) {
1155
+ const mcpEntries = Object.entries(features.mcpServers);
1156
+ if (mcpEntries.length > 0) {
1157
+ opencodeConfig.mcp = buildOpenCodeMcpServers(features.mcpServers);
1158
+ }
1159
+ }
1160
+ if (effective.includes("models") && features.models) {
1161
+ const resolved = resolveModels(features.models, options.modelProfile, TARGET_ID);
1162
+ if (resolved.default)
1163
+ opencodeConfig.model = resolved.default;
1164
+ if (resolved.small)
1165
+ opencodeConfig.small_model = resolved.small;
1166
+ if (Object.keys(resolved.providers).length > 0) {
1167
+ opencodeConfig.provider = resolved.providers;
1168
+ }
1169
+ const agentEntries = Object.entries(resolved.agents);
1170
+ if (agentEntries.length > 0) {
1171
+ const agentConfig = {};
1172
+ for (const [name, assignment] of agentEntries) {
1173
+ const config = { model: assignment.model };
1174
+ if (assignment.temperature !== undefined) {
1175
+ config.temperature = assignment.temperature;
1176
+ }
1177
+ if (assignment.top_p !== undefined) {
1178
+ config.top_p = assignment.top_p;
1179
+ }
1180
+ agentConfig[name] = config;
1181
+ }
1182
+ opencodeConfig.agent = agentConfig;
1183
+ }
1184
+ }
1185
+ if (Object.keys(opencodeConfig).length > 1) {
892
1186
  writeGeneratedJson(filepath, opencodeConfig, { header: false });
893
1187
  filesWritten.push(filepath);
894
1188
  }
895
1189
  }
896
1190
  if (effective.includes("rules")) {
897
1191
  const rules = features.rules.filter((r) => ruleMatchesTarget(r, TARGET_ID));
898
- const rootRules = getRootRules(rules);
899
1192
  const detailRules = getDetailRules(rules);
900
1193
  if (detailRules.length > 0) {
901
- const memoriesDir = resolve4(opencodeDir, "memories");
1194
+ const memoriesDir = resolve3(opencodeDir, "memories");
902
1195
  if (deleteExisting) {
903
1196
  removeIfExists(memoriesDir);
904
1197
  filesDeleted.push(memoriesDir);
905
1198
  }
906
1199
  ensureDir(memoriesDir);
907
1200
  for (const rule of detailRules) {
908
- const filepath = join7(memoriesDir, `${rule.name}.md`);
1201
+ const filepath = join8(memoriesDir, `${rule.name}.md`);
909
1202
  writeGeneratedFile(filepath, rule.content);
910
1203
  filesWritten.push(filepath);
911
1204
  }
@@ -914,7 +1207,7 @@ class OpenCodeTarget extends BaseTarget {
914
1207
  return this.createResult(filesWritten, filesDeleted, warnings);
915
1208
  }
916
1209
  }
917
- function buildOpenCodeMcp(servers) {
1210
+ function buildOpenCodeMcpServers(servers) {
918
1211
  const mcp = {};
919
1212
  for (const [name, entry] of Object.entries(servers)) {
920
1213
  if (entry.url) {
@@ -934,10 +1227,7 @@ function buildOpenCodeMcp(servers) {
934
1227
  };
935
1228
  }
936
1229
  }
937
- return {
938
- $schema: "https://opencode.ai/config.json",
939
- mcp
940
- };
1230
+ return mcp;
941
1231
  }
942
1232
  function generateOpenCodeHookPlugin(packName, events) {
943
1233
  const identifier = packNameToIdentifier(packName);
@@ -984,7 +1274,7 @@ function mapHookEvents(events) {
984
1274
  }
985
1275
 
986
1276
  // src/targets/cursor.ts
987
- import { resolve as resolve5, join as join8 } from "path";
1277
+ import { resolve as resolve4, join as join9 } from "path";
988
1278
  var TARGET_ID2 = "cursor";
989
1279
 
990
1280
  class CursorTarget extends BaseTarget {
@@ -997,18 +1287,19 @@ class CursorTarget extends BaseTarget {
997
1287
  "skills",
998
1288
  "hooks",
999
1289
  "mcp",
1000
- "ignore"
1290
+ "ignore",
1291
+ "models"
1001
1292
  ];
1002
1293
  generate(options) {
1003
1294
  const { projectRoot, baseDir, features, enabledFeatures, deleteExisting } = options;
1004
- const root = resolve5(projectRoot, baseDir);
1295
+ const root = resolve4(projectRoot, baseDir);
1005
1296
  const effective = this.getEffectiveFeatures(enabledFeatures);
1006
1297
  const filesWritten = [];
1007
1298
  const filesDeleted = [];
1008
1299
  const warnings = [];
1009
- const cursorDir = resolve5(root, ".cursor");
1300
+ const cursorDir = resolve4(root, ".cursor");
1010
1301
  if (effective.includes("rules")) {
1011
- const rulesDir = resolve5(cursorDir, "rules");
1302
+ const rulesDir = resolve4(cursorDir, "rules");
1012
1303
  if (deleteExisting) {
1013
1304
  removeIfExists(rulesDir);
1014
1305
  filesDeleted.push(rulesDir);
@@ -1025,33 +1316,40 @@ class CursorTarget extends BaseTarget {
1025
1316
  if (globs) {
1026
1317
  frontmatter.globs = globs;
1027
1318
  }
1028
- const filepath = join8(rulesDir, `${rule.name}.mdc`);
1319
+ const filepath = join9(rulesDir, `${rule.name}.mdc`);
1029
1320
  const content = serializeFrontmatter(frontmatter, rule.content);
1030
1321
  writeGeneratedFile(filepath, content);
1031
1322
  filesWritten.push(filepath);
1032
1323
  }
1033
1324
  }
1034
1325
  if (effective.includes("agents")) {
1035
- const agentsDir = resolve5(cursorDir, "agents");
1326
+ const agentsDir = resolve4(cursorDir, "agents");
1036
1327
  if (deleteExisting) {
1037
1328
  removeIfExists(agentsDir);
1038
1329
  filesDeleted.push(agentsDir);
1039
1330
  }
1040
1331
  ensureDir(agentsDir);
1332
+ const resolvedModels = features.models ? resolveModels(features.models, options.modelProfile, TARGET_ID2) : null;
1041
1333
  const agents = features.agents.filter((a) => agentMatchesTarget(a, TARGET_ID2));
1042
1334
  for (const agent of agents) {
1043
1335
  const frontmatter = {
1044
1336
  name: agent.name,
1045
1337
  description: agent.meta.description ?? ""
1046
1338
  };
1047
- const filepath = join8(agentsDir, `${agent.name}.md`);
1339
+ const cursorMeta = agent.meta.cursor ?? {};
1340
+ const modelsAgent = resolvedModels?.agents[agent.name];
1341
+ const model = modelsAgent?.model ?? cursorMeta.model;
1342
+ if (model) {
1343
+ frontmatter.model = model;
1344
+ }
1345
+ const filepath = join9(agentsDir, `${agent.name}.md`);
1048
1346
  const content = serializeFrontmatter(frontmatter, agent.content);
1049
1347
  writeGeneratedFile(filepath, content);
1050
1348
  filesWritten.push(filepath);
1051
1349
  }
1052
1350
  }
1053
1351
  if (effective.includes("skills")) {
1054
- const skillsDir = resolve5(cursorDir, "skills");
1352
+ const skillsDir = resolve4(cursorDir, "skills");
1055
1353
  if (deleteExisting) {
1056
1354
  removeIfExists(skillsDir);
1057
1355
  filesDeleted.push(skillsDir);
@@ -1059,20 +1357,20 @@ class CursorTarget extends BaseTarget {
1059
1357
  ensureDir(skillsDir);
1060
1358
  const skills = features.skills.filter((s) => skillMatchesTarget(s, TARGET_ID2));
1061
1359
  for (const skill of skills) {
1062
- const skillSubDir = join8(skillsDir, skill.name);
1360
+ const skillSubDir = join9(skillsDir, skill.name);
1063
1361
  ensureDir(skillSubDir);
1064
1362
  const frontmatter = {
1065
1363
  name: skill.name,
1066
1364
  description: skill.meta.description ?? ""
1067
1365
  };
1068
- const filepath = join8(skillSubDir, "SKILL.md");
1366
+ const filepath = join9(skillSubDir, "SKILL.md");
1069
1367
  const content = serializeFrontmatter(frontmatter, skill.content);
1070
1368
  writeGeneratedFile(filepath, content);
1071
1369
  filesWritten.push(filepath);
1072
1370
  }
1073
1371
  }
1074
1372
  if (effective.includes("commands")) {
1075
- const commandsDir = resolve5(cursorDir, "commands");
1373
+ const commandsDir = resolve4(cursorDir, "commands");
1076
1374
  if (deleteExisting) {
1077
1375
  removeIfExists(commandsDir);
1078
1376
  filesDeleted.push(commandsDir);
@@ -1080,7 +1378,7 @@ class CursorTarget extends BaseTarget {
1080
1378
  ensureDir(commandsDir);
1081
1379
  const commands = features.commands.filter((c) => commandMatchesTarget(c, TARGET_ID2));
1082
1380
  for (const cmd of commands) {
1083
- const filepath = join8(commandsDir, `${cmd.name}.md`);
1381
+ const filepath = join9(commandsDir, `${cmd.name}.md`);
1084
1382
  writeGeneratedFile(filepath, cmd.content);
1085
1383
  filesWritten.push(filepath);
1086
1384
  }
@@ -1089,14 +1387,14 @@ class CursorTarget extends BaseTarget {
1089
1387
  const mcpEntries = Object.entries(features.mcpServers);
1090
1388
  if (mcpEntries.length > 0) {
1091
1389
  const mcpConfig = buildCursorMcp(features.mcpServers);
1092
- const filepath = resolve5(cursorDir, "mcp.json");
1390
+ const filepath = resolve4(cursorDir, "mcp.json");
1093
1391
  writeGeneratedJson(filepath, mcpConfig, { header: false });
1094
1392
  filesWritten.push(filepath);
1095
1393
  }
1096
1394
  }
1097
1395
  if (effective.includes("ignore")) {
1098
1396
  if (features.ignorePatterns.length > 0) {
1099
- const filepath = resolve5(root, ".cursorignore");
1397
+ const filepath = resolve4(root, ".cursorignore");
1100
1398
  const content = features.ignorePatterns.join(`
1101
1399
  `) + `
1102
1400
  `;
@@ -1104,6 +1402,17 @@ class CursorTarget extends BaseTarget {
1104
1402
  filesWritten.push(filepath);
1105
1403
  }
1106
1404
  }
1405
+ if (effective.includes("models") && features.models) {
1406
+ const resolved = resolveModels(features.models, options.modelProfile, TARGET_ID2);
1407
+ const guidanceContent = buildCursorModelGuidance(resolved);
1408
+ if (guidanceContent) {
1409
+ const rulesDir = resolve4(cursorDir, "rules");
1410
+ ensureDir(rulesDir);
1411
+ const filepath = join9(rulesDir, "model-config.mdc");
1412
+ writeGeneratedFile(filepath, guidanceContent, { header: false });
1413
+ filesWritten.push(filepath);
1414
+ }
1415
+ }
1107
1416
  return this.createResult(filesWritten, filesDeleted, warnings);
1108
1417
  }
1109
1418
  }
@@ -1122,9 +1431,135 @@ function buildCursorMcp(servers) {
1122
1431
  }
1123
1432
  return { mcpServers };
1124
1433
  }
1434
+ function buildCursorModelGuidance(resolved) {
1435
+ if (!resolved.default && !resolved.small && Object.keys(resolved.agents).length === 0) {
1436
+ return null;
1437
+ }
1438
+ const frontmatter = {
1439
+ description: "Model configuration and selection guidelines for this workspace",
1440
+ alwaysApply: true
1441
+ };
1442
+ const lines = [];
1443
+ lines.push("# Model Configuration");
1444
+ lines.push("");
1445
+ lines.push("Use the following model preferences when working in this project.");
1446
+ lines.push("");
1447
+ if (resolved.default || resolved.small) {
1448
+ lines.push("## Default Models");
1449
+ lines.push("");
1450
+ if (resolved.default) {
1451
+ lines.push(`- **Primary model**: ${resolved.default}`);
1452
+ }
1453
+ if (resolved.small) {
1454
+ lines.push(`- **Lightweight tasks** (titles, summaries): ${resolved.small}`);
1455
+ }
1456
+ lines.push("");
1457
+ }
1458
+ const agentEntries = Object.entries(resolved.agents);
1459
+ if (agentEntries.length > 0) {
1460
+ lines.push("## Agent Model Assignments");
1461
+ lines.push("");
1462
+ lines.push("| Agent | Model | Temperature |");
1463
+ lines.push("| --- | --- | --- |");
1464
+ for (const [name, assignment] of agentEntries) {
1465
+ const temp = assignment.temperature !== undefined ? String(assignment.temperature) : "—";
1466
+ lines.push(`| ${name} | ${assignment.model} | ${temp} |`);
1467
+ }
1468
+ lines.push("");
1469
+ }
1470
+ if (Object.keys(resolved.profiles).length > 0) {
1471
+ lines.push("## Available Profiles");
1472
+ lines.push("");
1473
+ lines.push("| Profile | Description | Default Model |");
1474
+ lines.push("| --- | --- | --- |");
1475
+ for (const [name, profile] of Object.entries(resolved.profiles)) {
1476
+ lines.push(`| ${name} | ${profile.description ?? "—"} | ${profile.default ?? "—"} |`);
1477
+ }
1478
+ lines.push("");
1479
+ }
1480
+ if (resolved.activeProfile) {
1481
+ lines.push(`**Active profile**: \`${resolved.activeProfile}\``);
1482
+ lines.push("");
1483
+ }
1484
+ return serializeFrontmatter(frontmatter, lines.join(`
1485
+ `));
1486
+ }
1487
+
1488
+ // src/utils/model-guidance.ts
1489
+ function generateModelGuidanceMarkdown(resolved) {
1490
+ if (!resolved.default && !resolved.small && Object.keys(resolved.agents).length === 0 && Object.keys(resolved.profiles).length === 0) {
1491
+ return null;
1492
+ }
1493
+ const lines = [];
1494
+ lines.push("# Model Configuration");
1495
+ lines.push("");
1496
+ lines.push("Use the following model preferences when working in this project.");
1497
+ lines.push("");
1498
+ if (resolved.default || resolved.small) {
1499
+ lines.push("## Default Models");
1500
+ lines.push("");
1501
+ if (resolved.default) {
1502
+ lines.push(`- **Primary model**: ${resolved.default}`);
1503
+ }
1504
+ if (resolved.small) {
1505
+ lines.push(`- **Lightweight tasks** (titles, summaries): ${resolved.small}`);
1506
+ }
1507
+ lines.push("");
1508
+ }
1509
+ const agentEntries = Object.entries(resolved.agents);
1510
+ if (agentEntries.length > 0) {
1511
+ lines.push("## Agent Model Assignments");
1512
+ lines.push("");
1513
+ lines.push("| Agent | Model | Temperature |");
1514
+ lines.push("| --- | --- | --- |");
1515
+ for (const [name, assignment] of agentEntries) {
1516
+ const temp = assignment.temperature !== undefined ? String(assignment.temperature) : "—";
1517
+ lines.push(`| ${name} | ${assignment.model} | ${temp} |`);
1518
+ }
1519
+ lines.push("");
1520
+ }
1521
+ if (Object.keys(resolved.profiles).length > 0) {
1522
+ lines.push("## Available Profiles");
1523
+ lines.push("");
1524
+ lines.push("| Profile | Description | Default Model |");
1525
+ lines.push("| --- | --- | --- |");
1526
+ for (const [name, profile] of Object.entries(resolved.profiles)) {
1527
+ lines.push(`| ${name} | ${profile.description ?? "—"} | ${profile.default ?? "—"} |`);
1528
+ }
1529
+ lines.push("");
1530
+ }
1531
+ if (resolved.activeProfile) {
1532
+ lines.push(`**Active profile**: \`${resolved.activeProfile}\``);
1533
+ lines.push("");
1534
+ }
1535
+ if (resolved.routing.length > 0) {
1536
+ lines.push("## Task-Aware Routing");
1537
+ lines.push("");
1538
+ lines.push("Select the appropriate profile based on the task context:");
1539
+ lines.push("");
1540
+ lines.push("| Condition | Profile | Description |");
1541
+ lines.push("| --- | --- | --- |");
1542
+ for (const rule of resolved.routing) {
1543
+ const conditions = Object.entries(rule.when).map(([k, v]) => `${k}=${v}`).join(", ");
1544
+ const desc = rule.description ?? "—";
1545
+ lines.push(`| ${conditions} | ${rule.use} | ${desc} |`);
1546
+ }
1547
+ lines.push("");
1548
+ lines.push("### Condition Reference");
1549
+ lines.push("");
1550
+ lines.push("- **complexity**: low | medium | high | critical");
1551
+ lines.push("- **urgency**: low | normal | high");
1552
+ lines.push("- **budget**: minimal | standard | premium");
1553
+ lines.push("- **contextWindowNeed**: small | medium | large | max");
1554
+ lines.push("- **toolUseIntensity**: none | light | heavy");
1555
+ lines.push("");
1556
+ }
1557
+ return lines.join(`
1558
+ `);
1559
+ }
1125
1560
 
1126
1561
  // src/targets/claude-code.ts
1127
- import { resolve as resolve6, join as join9 } from "path";
1562
+ import { resolve as resolve5, join as join10 } from "path";
1128
1563
  var TARGET_ID3 = "claudecode";
1129
1564
 
1130
1565
  class ClaudeCodeTarget extends BaseTarget {
@@ -1137,18 +1572,19 @@ class ClaudeCodeTarget extends BaseTarget {
1137
1572
  "skills",
1138
1573
  "hooks",
1139
1574
  "mcp",
1140
- "ignore"
1575
+ "ignore",
1576
+ "models"
1141
1577
  ];
1142
1578
  generate(options) {
1143
1579
  const { projectRoot, baseDir, features, enabledFeatures, deleteExisting } = options;
1144
- const root = resolve6(projectRoot, baseDir);
1580
+ const root = resolve5(projectRoot, baseDir);
1145
1581
  const effective = this.getEffectiveFeatures(enabledFeatures);
1146
1582
  const filesWritten = [];
1147
1583
  const filesDeleted = [];
1148
1584
  const warnings = [];
1149
- const claudeDir = resolve6(root, ".claude");
1585
+ const claudeDir = resolve5(root, ".claude");
1150
1586
  if (effective.includes("rules")) {
1151
- const rulesDir = resolve6(claudeDir, "rules");
1587
+ const rulesDir = resolve5(claudeDir, "rules");
1152
1588
  if (deleteExisting) {
1153
1589
  removeIfExists(rulesDir);
1154
1590
  filesDeleted.push(rulesDir);
@@ -1161,32 +1597,41 @@ class ClaudeCodeTarget extends BaseTarget {
1161
1597
  const claudeMd = rootRules.map((r) => r.content).join(`
1162
1598
 
1163
1599
  `);
1164
- const filepath = resolve6(claudeDir, "CLAUDE.md");
1600
+ const filepath = resolve5(claudeDir, "CLAUDE.md");
1165
1601
  writeGeneratedFile(filepath, claudeMd);
1166
1602
  filesWritten.push(filepath);
1167
1603
  }
1168
1604
  for (const rule of detailRules) {
1169
- const filepath = join9(rulesDir, `${rule.name}.md`);
1605
+ const filepath = join10(rulesDir, `${rule.name}.md`);
1170
1606
  writeGeneratedFile(filepath, rule.content);
1171
1607
  filesWritten.push(filepath);
1172
1608
  }
1173
1609
  }
1174
1610
  if (effective.includes("agents")) {
1175
- const agentsDir = resolve6(claudeDir, "agents");
1611
+ const agentsDir = resolve5(claudeDir, "agents");
1176
1612
  if (deleteExisting) {
1177
1613
  removeIfExists(agentsDir);
1178
1614
  filesDeleted.push(agentsDir);
1179
1615
  }
1180
1616
  ensureDir(agentsDir);
1617
+ const resolvedModels = features.models ? resolveModels(features.models, options.modelProfile, TARGET_ID3) : null;
1181
1618
  const agents = features.agents.filter((a) => agentMatchesTarget(a, TARGET_ID3));
1182
1619
  for (const agent of agents) {
1183
- const filepath = join9(agentsDir, `${agent.name}.md`);
1184
- writeGeneratedFile(filepath, agent.content);
1620
+ const filepath = join10(agentsDir, `${agent.name}.md`);
1621
+ const cc = agent.meta.claudecode ?? {};
1622
+ const modelsAgent = resolvedModels?.agents[agent.name];
1623
+ const agentModel = modelsAgent?.model ?? cc.model;
1624
+ let content = agent.content;
1625
+ if (agentModel) {
1626
+ content = `<!-- model: ${agentModel} -->
1627
+ ${content}`;
1628
+ }
1629
+ writeGeneratedFile(filepath, content);
1185
1630
  filesWritten.push(filepath);
1186
1631
  }
1187
1632
  }
1188
1633
  if (effective.includes("skills")) {
1189
- const skillsDir = resolve6(claudeDir, "skills");
1634
+ const skillsDir = resolve5(claudeDir, "skills");
1190
1635
  if (deleteExisting) {
1191
1636
  removeIfExists(skillsDir);
1192
1637
  filesDeleted.push(skillsDir);
@@ -1194,15 +1639,15 @@ class ClaudeCodeTarget extends BaseTarget {
1194
1639
  ensureDir(skillsDir);
1195
1640
  const skills = features.skills.filter((s) => skillMatchesTarget(s, TARGET_ID3));
1196
1641
  for (const skill of skills) {
1197
- const skillSubDir = join9(skillsDir, skill.name);
1642
+ const skillSubDir = join10(skillsDir, skill.name);
1198
1643
  ensureDir(skillSubDir);
1199
- const filepath = join9(skillSubDir, "SKILL.md");
1644
+ const filepath = join10(skillSubDir, "SKILL.md");
1200
1645
  writeGeneratedFile(filepath, skill.content);
1201
1646
  filesWritten.push(filepath);
1202
1647
  }
1203
1648
  }
1204
1649
  if (effective.includes("commands")) {
1205
- const commandsDir = resolve6(claudeDir, "commands");
1650
+ const commandsDir = resolve5(claudeDir, "commands");
1206
1651
  if (deleteExisting) {
1207
1652
  removeIfExists(commandsDir);
1208
1653
  filesDeleted.push(commandsDir);
@@ -1210,15 +1655,26 @@ class ClaudeCodeTarget extends BaseTarget {
1210
1655
  ensureDir(commandsDir);
1211
1656
  const commands = features.commands.filter((c) => commandMatchesTarget(c, TARGET_ID3));
1212
1657
  for (const cmd of commands) {
1213
- const filepath = join9(commandsDir, `${cmd.name}.md`);
1658
+ const filepath = join10(commandsDir, `${cmd.name}.md`);
1214
1659
  writeGeneratedFile(filepath, cmd.content);
1215
1660
  filesWritten.push(filepath);
1216
1661
  }
1217
1662
  }
1663
+ if (effective.includes("models") && features.models) {
1664
+ const resolved = resolveModels(features.models, options.modelProfile, TARGET_ID3);
1665
+ const guidance = generateModelGuidanceMarkdown(resolved);
1666
+ if (guidance) {
1667
+ const rulesDir = resolve5(claudeDir, "rules");
1668
+ ensureDir(rulesDir);
1669
+ const filepath = join10(rulesDir, "model-config.md");
1670
+ writeGeneratedFile(filepath, guidance);
1671
+ filesWritten.push(filepath);
1672
+ }
1673
+ }
1218
1674
  if (effective.includes("hooks") || effective.includes("mcp") || effective.includes("ignore")) {
1219
1675
  const settings = buildClaudeSettings(options, effective);
1220
1676
  if (Object.keys(settings).length > 0) {
1221
- const filepath = resolve6(claudeDir, "settings.json");
1677
+ const filepath = resolve5(claudeDir, "settings.json");
1222
1678
  const existing = readJsonOrNull(filepath) ?? {};
1223
1679
  const merged = { ...existing, ...settings };
1224
1680
  writeGeneratedJson(filepath, merged, { header: false });
@@ -1275,7 +1731,7 @@ function toPascalCase(str) {
1275
1731
  }
1276
1732
 
1277
1733
  // src/targets/codex-cli.ts
1278
- import { resolve as resolve7, join as join10 } from "path";
1734
+ import { resolve as resolve6, join as join11 } from "path";
1279
1735
  var TARGET_ID4 = "codexcli";
1280
1736
 
1281
1737
  class CodexCliTarget extends BaseTarget {
@@ -1284,14 +1740,14 @@ class CodexCliTarget extends BaseTarget {
1284
1740
  supportedFeatures = ["rules", "skills", "mcp", "hooks"];
1285
1741
  generate(options) {
1286
1742
  const { projectRoot, baseDir, features, enabledFeatures, deleteExisting } = options;
1287
- const root = resolve7(projectRoot, baseDir);
1743
+ const root = resolve6(projectRoot, baseDir);
1288
1744
  const effective = this.getEffectiveFeatures(enabledFeatures);
1289
1745
  const filesWritten = [];
1290
1746
  const filesDeleted = [];
1291
1747
  const warnings = [];
1292
- const codexDir = resolve7(root, ".codex");
1748
+ const codexDir = resolve6(root, ".codex");
1293
1749
  if (effective.includes("rules")) {
1294
- const memoriesDir = resolve7(codexDir, "memories");
1750
+ const memoriesDir = resolve6(codexDir, "memories");
1295
1751
  if (deleteExisting) {
1296
1752
  removeIfExists(memoriesDir);
1297
1753
  filesDeleted.push(memoriesDir);
@@ -1299,13 +1755,13 @@ class CodexCliTarget extends BaseTarget {
1299
1755
  ensureDir(memoriesDir);
1300
1756
  const rules = features.rules.filter((r) => ruleMatchesTarget(r, TARGET_ID4));
1301
1757
  for (const rule of rules) {
1302
- const filepath = join10(memoriesDir, `${rule.name}.md`);
1758
+ const filepath = join11(memoriesDir, `${rule.name}.md`);
1303
1759
  writeGeneratedFile(filepath, rule.content);
1304
1760
  filesWritten.push(filepath);
1305
1761
  }
1306
1762
  }
1307
1763
  if (effective.includes("skills")) {
1308
- const skillsDir = resolve7(codexDir, "skills");
1764
+ const skillsDir = resolve6(codexDir, "skills");
1309
1765
  if (deleteExisting) {
1310
1766
  removeIfExists(skillsDir);
1311
1767
  filesDeleted.push(skillsDir);
@@ -1313,9 +1769,9 @@ class CodexCliTarget extends BaseTarget {
1313
1769
  ensureDir(skillsDir);
1314
1770
  const skills = features.skills.filter((s) => skillMatchesTarget(s, TARGET_ID4));
1315
1771
  for (const skill of skills) {
1316
- const skillSubDir = join10(skillsDir, skill.name);
1772
+ const skillSubDir = join11(skillsDir, skill.name);
1317
1773
  ensureDir(skillSubDir);
1318
- const filepath = join10(skillSubDir, "SKILL.md");
1774
+ const filepath = join11(skillSubDir, "SKILL.md");
1319
1775
  writeGeneratedFile(filepath, skill.content);
1320
1776
  filesWritten.push(filepath);
1321
1777
  }
@@ -1325,7 +1781,7 @@ class CodexCliTarget extends BaseTarget {
1325
1781
  }
1326
1782
 
1327
1783
  // src/targets/gemini-cli.ts
1328
- import { resolve as resolve8, join as join11 } from "path";
1784
+ import { resolve as resolve7, join as join12 } from "path";
1329
1785
  var TARGET_ID5 = "geminicli";
1330
1786
 
1331
1787
  class GeminiCliTarget extends BaseTarget {
@@ -1341,12 +1797,12 @@ class GeminiCliTarget extends BaseTarget {
1341
1797
  ];
1342
1798
  generate(options) {
1343
1799
  const { projectRoot, baseDir, features, enabledFeatures, deleteExisting } = options;
1344
- const root = resolve8(projectRoot, baseDir);
1800
+ const root = resolve7(projectRoot, baseDir);
1345
1801
  const effective = this.getEffectiveFeatures(enabledFeatures);
1346
1802
  const filesWritten = [];
1347
1803
  const filesDeleted = [];
1348
1804
  const warnings = [];
1349
- const geminiDir = resolve8(root, ".gemini");
1805
+ const geminiDir = resolve7(root, ".gemini");
1350
1806
  if (effective.includes("rules")) {
1351
1807
  const rules = features.rules.filter((r) => ruleMatchesTarget(r, TARGET_ID5));
1352
1808
  const rootRules = getRootRules(rules);
@@ -1355,26 +1811,26 @@ class GeminiCliTarget extends BaseTarget {
1355
1811
  const geminiMd = rootRules.map((r) => r.content).join(`
1356
1812
 
1357
1813
  `);
1358
- const filepath = resolve8(root, "GEMINI.md");
1814
+ const filepath = resolve7(root, "GEMINI.md");
1359
1815
  writeGeneratedFile(filepath, geminiMd);
1360
1816
  filesWritten.push(filepath);
1361
1817
  }
1362
1818
  if (detailRules.length > 0) {
1363
- const memoriesDir = resolve8(geminiDir, "memories");
1819
+ const memoriesDir = resolve7(geminiDir, "memories");
1364
1820
  if (deleteExisting) {
1365
1821
  removeIfExists(memoriesDir);
1366
1822
  filesDeleted.push(memoriesDir);
1367
1823
  }
1368
1824
  ensureDir(memoriesDir);
1369
1825
  for (const rule of detailRules) {
1370
- const filepath = join11(memoriesDir, `${rule.name}.md`);
1826
+ const filepath = join12(memoriesDir, `${rule.name}.md`);
1371
1827
  writeGeneratedFile(filepath, rule.content);
1372
1828
  filesWritten.push(filepath);
1373
1829
  }
1374
1830
  }
1375
1831
  }
1376
1832
  if (effective.includes("commands")) {
1377
- const commandsDir = resolve8(geminiDir, "commands");
1833
+ const commandsDir = resolve7(geminiDir, "commands");
1378
1834
  if (deleteExisting) {
1379
1835
  removeIfExists(commandsDir);
1380
1836
  filesDeleted.push(commandsDir);
@@ -1383,7 +1839,7 @@ class GeminiCliTarget extends BaseTarget {
1383
1839
  const commands = features.commands.filter((c) => commandMatchesTarget(c, TARGET_ID5));
1384
1840
  for (const cmd of commands) {
1385
1841
  const toml = buildGeminiCommand(cmd.name, cmd.meta.description ?? "", cmd.content);
1386
- const filepath = join11(commandsDir, `${cmd.name}.toml`);
1842
+ const filepath = join12(commandsDir, `${cmd.name}.toml`);
1387
1843
  writeGeneratedFile(filepath, toml, { type: "md" });
1388
1844
  filesWritten.push(filepath);
1389
1845
  }
@@ -1392,14 +1848,14 @@ class GeminiCliTarget extends BaseTarget {
1392
1848
  const mcpEntries = Object.entries(features.mcpServers);
1393
1849
  if (mcpEntries.length > 0) {
1394
1850
  const settings = buildGeminiSettings(features.mcpServers);
1395
- const filepath = resolve8(geminiDir, "settings.json");
1851
+ const filepath = resolve7(geminiDir, "settings.json");
1396
1852
  writeGeneratedJson(filepath, settings, { header: false });
1397
1853
  filesWritten.push(filepath);
1398
1854
  }
1399
1855
  }
1400
1856
  if (effective.includes("ignore")) {
1401
1857
  if (features.ignorePatterns.length > 0) {
1402
- const filepath = resolve8(root, ".geminiignore");
1858
+ const filepath = resolve7(root, ".geminiignore");
1403
1859
  const content = features.ignorePatterns.join(`
1404
1860
  `) + `
1405
1861
  `;
@@ -1438,7 +1894,7 @@ function buildGeminiSettings(servers) {
1438
1894
  }
1439
1895
 
1440
1896
  // src/targets/copilot.ts
1441
- import { resolve as resolve9, join as join12 } from "path";
1897
+ import { resolve as resolve8, join as join13 } from "path";
1442
1898
  var TARGET_ID6 = "copilot";
1443
1899
 
1444
1900
  class CopilotTarget extends BaseTarget {
@@ -1450,16 +1906,17 @@ class CopilotTarget extends BaseTarget {
1450
1906
  "agents",
1451
1907
  "skills",
1452
1908
  "mcp",
1453
- "ignore"
1909
+ "ignore",
1910
+ "models"
1454
1911
  ];
1455
1912
  generate(options) {
1456
1913
  const { projectRoot, baseDir, features, enabledFeatures, deleteExisting } = options;
1457
- const root = resolve9(projectRoot, baseDir);
1914
+ const root = resolve8(projectRoot, baseDir);
1458
1915
  const effective = this.getEffectiveFeatures(enabledFeatures);
1459
1916
  const filesWritten = [];
1460
1917
  const filesDeleted = [];
1461
1918
  const warnings = [];
1462
- const githubDir = resolve9(root, ".github");
1919
+ const githubDir = resolve8(root, ".github");
1463
1920
  if (effective.includes("rules")) {
1464
1921
  const rules = features.rules.filter((r) => ruleMatchesTarget(r, TARGET_ID6));
1465
1922
  if (rules.length > 0) {
@@ -1468,15 +1925,15 @@ class CopilotTarget extends BaseTarget {
1468
1925
  ---
1469
1926
 
1470
1927
  `);
1471
- const filepath = resolve9(githubDir, "copilot-instructions.md");
1928
+ const filepath = resolve8(githubDir, "copilot-instructions.md");
1472
1929
  ensureDir(githubDir);
1473
1930
  writeGeneratedFile(filepath, combinedContent);
1474
1931
  filesWritten.push(filepath);
1475
1932
  }
1476
1933
  }
1477
1934
  if (effective.includes("agents")) {
1478
- const copilotDir = resolve9(githubDir, "copilot");
1479
- const agentsDir = resolve9(copilotDir, "agents");
1935
+ const copilotDir = resolve8(githubDir, "copilot");
1936
+ const agentsDir = resolve8(copilotDir, "agents");
1480
1937
  if (deleteExisting) {
1481
1938
  removeIfExists(agentsDir);
1482
1939
  filesDeleted.push(agentsDir);
@@ -1484,14 +1941,14 @@ class CopilotTarget extends BaseTarget {
1484
1941
  ensureDir(agentsDir);
1485
1942
  const agents = features.agents.filter((a) => agentMatchesTarget(a, TARGET_ID6));
1486
1943
  for (const agent of agents) {
1487
- const filepath = join12(agentsDir, `${agent.name}.md`);
1944
+ const filepath = join13(agentsDir, `${agent.name}.md`);
1488
1945
  writeGeneratedFile(filepath, agent.content);
1489
1946
  filesWritten.push(filepath);
1490
1947
  }
1491
1948
  }
1492
1949
  if (effective.includes("skills")) {
1493
- const copilotDir = resolve9(githubDir, "copilot");
1494
- const skillsDir = resolve9(copilotDir, "skills");
1950
+ const copilotDir = resolve8(githubDir, "copilot");
1951
+ const skillsDir = resolve8(copilotDir, "skills");
1495
1952
  if (deleteExisting) {
1496
1953
  removeIfExists(skillsDir);
1497
1954
  filesDeleted.push(skillsDir);
@@ -1499,16 +1956,16 @@ class CopilotTarget extends BaseTarget {
1499
1956
  ensureDir(skillsDir);
1500
1957
  const skills = features.skills.filter((s) => skillMatchesTarget(s, TARGET_ID6));
1501
1958
  for (const skill of skills) {
1502
- const skillSubDir = join12(skillsDir, skill.name);
1959
+ const skillSubDir = join13(skillsDir, skill.name);
1503
1960
  ensureDir(skillSubDir);
1504
- const filepath = join12(skillSubDir, "SKILL.md");
1961
+ const filepath = join13(skillSubDir, "SKILL.md");
1505
1962
  writeGeneratedFile(filepath, skill.content);
1506
1963
  filesWritten.push(filepath);
1507
1964
  }
1508
1965
  }
1509
1966
  if (effective.includes("commands")) {
1510
- const copilotDir = resolve9(githubDir, "copilot");
1511
- const commandsDir = resolve9(copilotDir, "commands");
1967
+ const copilotDir = resolve8(githubDir, "copilot");
1968
+ const commandsDir = resolve8(copilotDir, "commands");
1512
1969
  if (deleteExisting) {
1513
1970
  removeIfExists(commandsDir);
1514
1971
  filesDeleted.push(commandsDir);
@@ -1516,25 +1973,36 @@ class CopilotTarget extends BaseTarget {
1516
1973
  ensureDir(commandsDir);
1517
1974
  const commands = features.commands.filter((c) => commandMatchesTarget(c, TARGET_ID6));
1518
1975
  for (const cmd of commands) {
1519
- const filepath = join12(commandsDir, `${cmd.name}.md`);
1976
+ const filepath = join13(commandsDir, `${cmd.name}.md`);
1520
1977
  writeGeneratedFile(filepath, cmd.content);
1521
1978
  filesWritten.push(filepath);
1522
1979
  }
1523
1980
  }
1524
1981
  if (effective.includes("ignore")) {}
1982
+ if (effective.includes("models") && features.models) {
1983
+ const resolved = resolveModels(features.models, options.modelProfile, TARGET_ID6);
1984
+ const guidance = generateModelGuidanceMarkdown(resolved);
1985
+ if (guidance) {
1986
+ const copilotDir = resolve8(githubDir, "copilot");
1987
+ ensureDir(copilotDir);
1988
+ const filepath = join13(copilotDir, "model-config.md");
1989
+ writeGeneratedFile(filepath, guidance);
1990
+ filesWritten.push(filepath);
1991
+ }
1992
+ }
1525
1993
  return this.createResult(filesWritten, filesDeleted, warnings);
1526
1994
  }
1527
1995
  }
1528
1996
 
1529
1997
  // src/targets/agents-md.ts
1530
- import { resolve as resolve10 } from "path";
1998
+ import { resolve as resolve9 } from "path";
1531
1999
  class AgentsMdTarget extends BaseTarget {
1532
2000
  id = "agentsmd";
1533
2001
  name = "AGENTS.md";
1534
2002
  supportedFeatures = ["rules"];
1535
2003
  generate(options) {
1536
2004
  const { projectRoot, baseDir, features } = options;
1537
- const root = resolve10(projectRoot, baseDir);
2005
+ const root = resolve9(projectRoot, baseDir);
1538
2006
  const filesWritten = [];
1539
2007
  const warnings = [];
1540
2008
  const rootRules = getRootRules(features.rules);
@@ -1546,7 +2014,7 @@ class AgentsMdTarget extends BaseTarget {
1546
2014
  const content = sections.join(`
1547
2015
 
1548
2016
  `);
1549
- const filepath = resolve10(root, "AGENTS.md");
2017
+ const filepath = resolve9(root, "AGENTS.md");
1550
2018
  writeGeneratedFile(filepath, content);
1551
2019
  filesWritten.push(filepath);
1552
2020
  return this.createResult(filesWritten, [], warnings);
@@ -1554,7 +2022,7 @@ class AgentsMdTarget extends BaseTarget {
1554
2022
  }
1555
2023
 
1556
2024
  // src/targets/generic-md-target.ts
1557
- import { resolve as resolve11, join as join13 } from "path";
2025
+ import { resolve as resolve10, join as join14 } from "path";
1558
2026
  function createGenericMdTarget(config) {
1559
2027
  return new GenericMdTarget(config);
1560
2028
  }
@@ -1573,16 +2041,16 @@ class GenericMdTarget extends BaseTarget {
1573
2041
  }
1574
2042
  generate(options) {
1575
2043
  const { projectRoot, baseDir, features, enabledFeatures, deleteExisting } = options;
1576
- const root = resolve11(projectRoot, baseDir);
2044
+ const root = resolve10(projectRoot, baseDir);
1577
2045
  const effective = this.getEffectiveFeatures(enabledFeatures);
1578
2046
  const filesWritten = [];
1579
2047
  const filesDeleted = [];
1580
2048
  const warnings = [];
1581
- const configDir = resolve11(root, this.config.configDir);
2049
+ const configDir = resolve10(root, this.config.configDir);
1582
2050
  const rulesSubDir = this.config.rulesDir ?? "rules";
1583
2051
  const ext = this.config.ruleExtension ?? ".md";
1584
2052
  if (effective.includes("rules")) {
1585
- const rulesDir = resolve11(configDir, rulesSubDir);
2053
+ const rulesDir = resolve10(configDir, rulesSubDir);
1586
2054
  if (deleteExisting) {
1587
2055
  removeIfExists(rulesDir);
1588
2056
  filesDeleted.push(rulesDir);
@@ -1590,13 +2058,13 @@ class GenericMdTarget extends BaseTarget {
1590
2058
  ensureDir(rulesDir);
1591
2059
  const rules = features.rules.filter((r) => ruleMatchesTarget(r, this.id));
1592
2060
  for (const rule of rules) {
1593
- const filepath = join13(rulesDir, `${rule.name}${ext}`);
2061
+ const filepath = join14(rulesDir, `${rule.name}${ext}`);
1594
2062
  writeGeneratedFile(filepath, rule.content);
1595
2063
  filesWritten.push(filepath);
1596
2064
  }
1597
2065
  }
1598
2066
  if (effective.includes("commands")) {
1599
- const commandsDir = resolve11(configDir, "commands");
2067
+ const commandsDir = resolve10(configDir, "commands");
1600
2068
  if (deleteExisting) {
1601
2069
  removeIfExists(commandsDir);
1602
2070
  filesDeleted.push(commandsDir);
@@ -1604,7 +2072,7 @@ class GenericMdTarget extends BaseTarget {
1604
2072
  ensureDir(commandsDir);
1605
2073
  const commands = features.commands.filter((c) => commandMatchesTarget(c, this.id));
1606
2074
  for (const cmd of commands) {
1607
- const filepath = join13(commandsDir, `${cmd.name}.md`);
2075
+ const filepath = join14(commandsDir, `${cmd.name}.md`);
1608
2076
  writeGeneratedFile(filepath, cmd.content);
1609
2077
  filesWritten.push(filepath);
1610
2078
  }
@@ -1613,7 +2081,7 @@ class GenericMdTarget extends BaseTarget {
1613
2081
  const mcpEntries = Object.entries(features.mcpServers);
1614
2082
  if (mcpEntries.length > 0) {
1615
2083
  const mcpDir = this.config.mcpInConfigDir ? configDir : root;
1616
- const filepath = resolve11(mcpDir, "mcp.json");
2084
+ const filepath = resolve10(mcpDir, "mcp.json");
1617
2085
  writeGeneratedJson(filepath, { mcpServers: features.mcpServers }, {
1618
2086
  header: false
1619
2087
  });
@@ -1622,13 +2090,23 @@ class GenericMdTarget extends BaseTarget {
1622
2090
  }
1623
2091
  if (effective.includes("ignore") && this.config.ignoreFile) {
1624
2092
  if (features.ignorePatterns.length > 0) {
1625
- const filepath = resolve11(root, this.config.ignoreFile);
2093
+ const filepath = resolve10(root, this.config.ignoreFile);
1626
2094
  writeGeneratedFile(filepath, features.ignorePatterns.join(`
1627
2095
  `) + `
1628
2096
  `);
1629
2097
  filesWritten.push(filepath);
1630
2098
  }
1631
2099
  }
2100
+ if (effective.includes("models") && features.models) {
2101
+ const resolved = resolveModels(features.models, options.modelProfile, this.id);
2102
+ const guidance = generateModelGuidanceMarkdown(resolved);
2103
+ if (guidance) {
2104
+ ensureDir(configDir);
2105
+ const filepath = join14(configDir, "model-config.md");
2106
+ writeGeneratedFile(filepath, guidance);
2107
+ filesWritten.push(filepath);
2108
+ }
2109
+ }
1632
2110
  return this.createResult(filesWritten, filesDeleted, warnings);
1633
2111
  }
1634
2112
  }
@@ -1822,14 +2300,29 @@ function findHunks(oldLines, newLines) {
1822
2300
  let ni = 0;
1823
2301
  while (oi < oldLines.length || ni < newLines.length) {
1824
2302
  if (oi < oldLines.length && ni < newLines.length && oldLines[oi] === newLines[ni]) {
1825
- changes.push({ type: " ", line: oldLines[oi], oldIdx: oi, newIdx: ni });
2303
+ changes.push({
2304
+ type: " ",
2305
+ line: oldLines[oi] ?? "",
2306
+ oldIdx: oi,
2307
+ newIdx: ni
2308
+ });
1826
2309
  oi++;
1827
2310
  ni++;
1828
- } else if (ni < newLines.length && (oi >= oldLines.length || !newLines.slice(ni).includes(oldLines[oi]))) {
1829
- changes.push({ type: "+", line: newLines[ni], oldIdx: oi, newIdx: ni });
2311
+ } else if (ni < newLines.length && (oi >= oldLines.length || !newLines.slice(ni).includes(oldLines[oi] ?? ""))) {
2312
+ changes.push({
2313
+ type: "+",
2314
+ line: newLines[ni] ?? "",
2315
+ oldIdx: oi,
2316
+ newIdx: ni
2317
+ });
1830
2318
  ni++;
1831
2319
  } else {
1832
- changes.push({ type: "-", line: oldLines[oi], oldIdx: oi, newIdx: oi });
2320
+ changes.push({
2321
+ type: "-",
2322
+ line: oldLines[oi] ?? "",
2323
+ oldIdx: oi,
2324
+ newIdx: oi
2325
+ });
1833
2326
  oi++;
1834
2327
  }
1835
2328
  }
@@ -1858,8 +2351,9 @@ function findHunks(oldLines, newLines) {
1858
2351
  lines: []
1859
2352
  };
1860
2353
  for (let i = contextStart;i < changes.indexOf(change); i++) {
1861
- if (changes[i].type === " ") {
1862
- currentHunk.lines.push(` ${changes[i].line}`);
2354
+ const entry = changes[i];
2355
+ if (entry?.type === " ") {
2356
+ currentHunk.lines.push(` ${entry.line}`);
1863
2357
  currentHunk.oldCount++;
1864
2358
  currentHunk.newCount++;
1865
2359
  }
@@ -1879,7 +2373,6 @@ function findHunks(oldLines, newLines) {
1879
2373
  }
1880
2374
 
1881
2375
  // src/cli/generate.ts
1882
- init_config();
1883
2376
  import { existsSync as existsSync8, readFileSync as readFileSync10 } from "fs";
1884
2377
  import chalk from "chalk";
1885
2378
  function runGenerate(projectRoot, options) {
@@ -1950,9 +2443,9 @@ function runGenerate(projectRoot, options) {
1950
2443
  enabledFeatures,
1951
2444
  deleteExisting: options.diff ? false : config.delete,
1952
2445
  global: config.global,
1953
- verbose: config.verbose
2446
+ verbose: config.verbose,
2447
+ modelProfile: config.modelProfile
1954
2448
  };
1955
- const preSnapshot = new Map;
1956
2449
  try {
1957
2450
  const result = target.generate(generateOptions);
1958
2451
  allResults.push(result);