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,52 +1,86 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from "node:module";
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
- var __hasOwnProp = Object.prototype.hasOwnProperty;
7
- var __moduleCache = /* @__PURE__ */ new WeakMap;
8
- var __toCommonJS = (from) => {
9
- var entry = __moduleCache.get(from), desc;
10
- if (entry)
11
- return entry;
12
- entry = __defProp({}, "__esModule", { value: true });
13
- if (from && typeof from === "object" || typeof from === "function")
14
- __getOwnPropNames(from).map((key) => !__hasOwnProp.call(entry, key) && __defProp(entry, key, {
15
- get: () => from[key],
16
- enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
17
- }));
18
- __moduleCache.set(from, entry);
19
- return entry;
20
- };
21
- var __export = (target, all) => {
22
- for (var name in all)
23
- __defProp(target, name, {
24
- get: all[name],
25
- enumerable: true,
26
- configurable: true,
27
- set: (newValue) => all[name] = () => newValue
28
- });
29
- };
30
- var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
31
3
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
32
4
 
33
5
  // src/core/config.ts
34
- var exports_config = {};
35
- __export(exports_config, {
36
- resolveTargets: () => resolveTargets,
37
- resolveFeatures: () => resolveFeatures,
38
- loadWorkspaceConfig: () => loadWorkspaceConfig,
39
- loadPackManifest: () => loadPackManifest,
40
- WorkspaceConfigSchema: () => WorkspaceConfigSchema,
41
- TARGET_IDS: () => TARGET_IDS,
42
- REPO_MODES: () => REPO_MODES,
43
- PackManifestSchema: () => PackManifestSchema,
44
- FEATURE_IDS: () => FEATURE_IDS
45
- });
46
6
  import { z } from "zod";
47
7
  import { readFileSync, existsSync } from "fs";
48
8
  import { resolve } from "path";
49
9
  import { parse as parseJsonc } from "jsonc-parser";
10
+ var TARGET_IDS = [
11
+ "opencode",
12
+ "cursor",
13
+ "claudecode",
14
+ "codexcli",
15
+ "geminicli",
16
+ "copilot",
17
+ "agentsmd",
18
+ "cline",
19
+ "kilo",
20
+ "roo",
21
+ "qwencode",
22
+ "kiro",
23
+ "factorydroid",
24
+ "antigravity",
25
+ "junie",
26
+ "augmentcode",
27
+ "windsurf",
28
+ "warp",
29
+ "replit",
30
+ "zed"
31
+ ];
32
+ var FEATURE_IDS = [
33
+ "rules",
34
+ "commands",
35
+ "agents",
36
+ "skills",
37
+ "hooks",
38
+ "plugins",
39
+ "mcp",
40
+ "ignore",
41
+ "models"
42
+ ];
43
+ var REPO_MODES = ["repo", "monorepo", "metarepo"];
44
+ var PackManifestSchema = z.object({
45
+ name: z.string().min(1),
46
+ version: z.string().default("1.0.0"),
47
+ description: z.string().default(""),
48
+ author: z.union([
49
+ z.string(),
50
+ z.object({ name: z.string(), email: z.string().optional() })
51
+ ]).optional(),
52
+ tags: z.array(z.string()).default([]),
53
+ dependencies: z.array(z.string()).default([]),
54
+ conflicts: z.array(z.string()).default([]),
55
+ targets: z.union([z.literal("*"), z.array(z.string())]).default("*"),
56
+ features: z.union([z.literal("*"), z.array(z.string())]).default("*")
57
+ });
58
+ var FeaturesSchema = z.union([
59
+ z.literal("*"),
60
+ z.array(z.string()),
61
+ z.record(z.string(), z.union([z.literal("*"), z.array(z.string())]))
62
+ ]);
63
+ var WorkspaceConfigSchema = z.object({
64
+ $schema: z.string().optional(),
65
+ packs: z.array(z.string()).default(["./packs/default"]),
66
+ disabled: z.array(z.string()).default([]),
67
+ targets: z.union([z.literal("*"), z.array(z.string())]).default("*"),
68
+ features: FeaturesSchema.default("*"),
69
+ mode: z.enum(REPO_MODES).default("repo"),
70
+ baseDirs: z.array(z.string()).default(["."]),
71
+ global: z.boolean().default(false),
72
+ delete: z.boolean().default(true),
73
+ verbose: z.boolean().default(false),
74
+ silent: z.boolean().default(false),
75
+ overrides: z.record(z.string(), z.record(z.string(), z.string())).default({}),
76
+ sources: z.array(z.object({
77
+ source: z.string(),
78
+ packs: z.array(z.string()).optional(),
79
+ skills: z.array(z.string()).optional()
80
+ })).default([]),
81
+ modelProfile: z.string().optional()
82
+ });
83
+ var CONFIG_FILES = ["agentpacks.local.jsonc", "agentpacks.jsonc"];
50
84
  function loadWorkspaceConfig(projectRoot) {
51
85
  for (const filename of CONFIG_FILES) {
52
86
  const filepath = resolve(projectRoot, filename);
@@ -92,81 +126,6 @@ function resolveTargets(config) {
92
126
  return [...TARGET_IDS];
93
127
  return config.targets;
94
128
  }
95
- var TARGET_IDS, FEATURE_IDS, REPO_MODES, PackManifestSchema, FeaturesSchema, WorkspaceConfigSchema, CONFIG_FILES;
96
- var init_config = __esm(() => {
97
- TARGET_IDS = [
98
- "opencode",
99
- "cursor",
100
- "claudecode",
101
- "codexcli",
102
- "geminicli",
103
- "copilot",
104
- "agentsmd",
105
- "cline",
106
- "kilo",
107
- "roo",
108
- "qwencode",
109
- "kiro",
110
- "factorydroid",
111
- "antigravity",
112
- "junie",
113
- "augmentcode",
114
- "windsurf",
115
- "warp",
116
- "replit",
117
- "zed"
118
- ];
119
- FEATURE_IDS = [
120
- "rules",
121
- "commands",
122
- "agents",
123
- "skills",
124
- "hooks",
125
- "plugins",
126
- "mcp",
127
- "ignore"
128
- ];
129
- REPO_MODES = ["repo", "monorepo", "metarepo"];
130
- PackManifestSchema = z.object({
131
- name: z.string().min(1),
132
- version: z.string().default("1.0.0"),
133
- description: z.string().default(""),
134
- author: z.union([
135
- z.string(),
136
- z.object({ name: z.string(), email: z.string().optional() })
137
- ]).optional(),
138
- tags: z.array(z.string()).default([]),
139
- dependencies: z.array(z.string()).default([]),
140
- conflicts: z.array(z.string()).default([]),
141
- targets: z.union([z.literal("*"), z.array(z.string())]).default("*"),
142
- features: z.union([z.literal("*"), z.array(z.string())]).default("*")
143
- });
144
- FeaturesSchema = z.union([
145
- z.literal("*"),
146
- z.array(z.string()),
147
- z.record(z.string(), z.union([z.literal("*"), z.array(z.string())]))
148
- ]);
149
- WorkspaceConfigSchema = z.object({
150
- $schema: z.string().optional(),
151
- packs: z.array(z.string()).default(["./packs/default"]),
152
- disabled: z.array(z.string()).default([]),
153
- targets: z.union([z.literal("*"), z.array(z.string())]).default("*"),
154
- features: FeaturesSchema.default("*"),
155
- mode: z.enum(REPO_MODES).default("repo"),
156
- baseDirs: z.array(z.string()).default(["."]),
157
- global: z.boolean().default(false),
158
- delete: z.boolean().default(true),
159
- verbose: z.boolean().default(false),
160
- silent: z.boolean().default(false),
161
- overrides: z.record(z.string(), z.record(z.string(), z.string())).default({}),
162
- sources: z.array(z.object({
163
- source: z.string(),
164
- packs: z.array(z.string()).optional(),
165
- skills: z.array(z.string()).optional()
166
- })).default([])
167
- });
168
- CONFIG_FILES = ["agentpacks.local.jsonc", "agentpacks.jsonc"];
169
- });
170
129
 
171
130
  // src/utils/filesystem.ts
172
131
  import {
@@ -175,10 +134,10 @@ import {
175
134
  readFileSync as readFileSync2,
176
135
  writeFileSync,
177
136
  readdirSync,
137
+ rmSync,
178
138
  statSync
179
139
  } from "fs";
180
140
  import { dirname, relative, join } from "path";
181
- import { removeSync } from "fs-extra";
182
141
  var GENERATED_HEADER_MD = "<!-- Generated by agentpacks. DO NOT EDIT. -->";
183
142
  var GENERATED_HEADER_JSON = "// Generated by agentpacks. DO NOT EDIT.";
184
143
  var GENERATED_HEADER_JS = "// Generated by agentpacks. DO NOT EDIT.";
@@ -219,7 +178,7 @@ function ensureDir(dirPath) {
219
178
  }
220
179
  function removeIfExists(targetPath) {
221
180
  if (existsSync2(targetPath)) {
222
- removeSync(targetPath);
181
+ rmSync(targetPath, { recursive: true, force: true });
223
182
  }
224
183
  }
225
184
  function listFiles(dirPath, options = {}) {
@@ -545,10 +504,178 @@ function mergeIgnorePatterns(configs) {
545
504
  return result;
546
505
  }
547
506
 
507
+ // src/features/models.ts
508
+ import { join as join7 } from "path";
509
+ import { z as z2 } from "zod";
510
+ var SECRET_PATTERNS = [
511
+ /["']api[_-]?key["']\s*:/i,
512
+ /["']apiKey["']\s*:/i,
513
+ /["']secret["']\s*:/i,
514
+ /["']password["']\s*:/i,
515
+ /["'](?:auth_token|access_token|bearer_token)["']\s*:/i,
516
+ /["']private[_-]?key["']\s*:/i,
517
+ /-----BEGIN\s+(RSA|EC|DSA|OPENSSH|PGP)\s+PRIVATE\s+KEY-----/,
518
+ /sk-[a-zA-Z0-9]{20,}/,
519
+ /Bearer\s+[a-zA-Z0-9._-]{20,}/
520
+ ];
521
+ var AgentModelSchema = z2.object({
522
+ model: z2.string(),
523
+ temperature: z2.number().min(0).max(2).optional(),
524
+ top_p: z2.number().min(0).max(1).optional()
525
+ });
526
+ var ModelProfileSchema = z2.object({
527
+ extends: z2.string().optional(),
528
+ description: z2.string().optional(),
529
+ default: z2.string().optional(),
530
+ small: z2.string().optional(),
531
+ agents: z2.record(z2.string(), AgentModelSchema).optional()
532
+ });
533
+ var RoutingConditionSchema = z2.object({
534
+ complexity: z2.enum(["low", "medium", "high", "critical"]).optional().describe("Task complexity level"),
535
+ urgency: z2.enum(["low", "normal", "high"]).optional().describe("Time sensitivity"),
536
+ budget: z2.enum(["minimal", "standard", "premium"]).optional().describe("Cost/token budget tier"),
537
+ contextWindowNeed: z2.enum(["small", "medium", "large", "max"]).optional().describe("Required context window size"),
538
+ toolUseIntensity: z2.enum(["none", "light", "heavy"]).optional().describe("Expected tool/function calling intensity")
539
+ });
540
+ var RoutingRuleSchema = z2.object({
541
+ when: z2.record(z2.string(), z2.string()),
542
+ use: z2.string(),
543
+ description: z2.string().optional(),
544
+ priority: z2.number().optional()
545
+ });
546
+ var ProviderModelSchema = z2.object({
547
+ options: z2.record(z2.string(), z2.unknown()).optional(),
548
+ variants: z2.record(z2.string(), z2.record(z2.string(), z2.unknown())).optional()
549
+ });
550
+ var ProviderConfigSchema = z2.object({
551
+ options: z2.record(z2.string(), z2.unknown()).optional(),
552
+ models: z2.record(z2.string(), ProviderModelSchema).optional()
553
+ });
554
+ var ModelsSchema = z2.object({
555
+ default: z2.string().optional(),
556
+ small: z2.string().optional(),
557
+ agents: z2.record(z2.string(), AgentModelSchema).optional(),
558
+ profiles: z2.record(z2.string(), ModelProfileSchema).optional(),
559
+ providers: z2.record(z2.string(), ProviderConfigSchema).optional(),
560
+ routing: z2.array(RoutingRuleSchema).optional(),
561
+ overrides: z2.record(z2.string(), z2.object({
562
+ default: z2.string().optional(),
563
+ small: z2.string().optional(),
564
+ agents: z2.record(z2.string(), AgentModelSchema).optional()
565
+ })).optional()
566
+ });
567
+ function parseModels(packDir, packName) {
568
+ const modelsPath = join7(packDir, "models.json");
569
+ const raw = readJsonOrNull(modelsPath);
570
+ if (!raw)
571
+ return null;
572
+ const parsed = ModelsSchema.parse(raw);
573
+ return {
574
+ packName,
575
+ sourcePath: modelsPath,
576
+ config: parsed
577
+ };
578
+ }
579
+ function mergeModelsConfigs(configs) {
580
+ const warnings = [];
581
+ const result = {};
582
+ for (const entry of configs) {
583
+ const { config, packName } = entry;
584
+ if (config.default !== undefined && result.default === undefined) {
585
+ result.default = config.default;
586
+ } else if (config.default !== undefined && result.default !== undefined) {
587
+ warnings.push(`Models "default" from pack "${packName}" skipped (already defined).`);
588
+ }
589
+ if (config.small !== undefined && result.small === undefined) {
590
+ result.small = config.small;
591
+ } else if (config.small !== undefined && result.small !== undefined) {
592
+ warnings.push(`Models "small" from pack "${packName}" skipped (already defined).`);
593
+ }
594
+ if (config.agents) {
595
+ if (!result.agents)
596
+ result.agents = {};
597
+ for (const [name, assignment] of Object.entries(config.agents)) {
598
+ if (name in result.agents) {
599
+ warnings.push(`Models agent "${name}" from pack "${packName}" skipped (already defined).`);
600
+ continue;
601
+ }
602
+ result.agents[name] = assignment;
603
+ }
604
+ }
605
+ if (config.profiles) {
606
+ if (!result.profiles)
607
+ result.profiles = {};
608
+ for (const [name, profile] of Object.entries(config.profiles)) {
609
+ if (name in result.profiles) {
610
+ warnings.push(`Models profile "${name}" from pack "${packName}" skipped (already defined).`);
611
+ continue;
612
+ }
613
+ result.profiles[name] = profile;
614
+ }
615
+ }
616
+ if (config.providers) {
617
+ if (!result.providers)
618
+ result.providers = {};
619
+ for (const [providerName, providerConfig] of Object.entries(config.providers)) {
620
+ if (!(providerName in result.providers)) {
621
+ result.providers[providerName] = providerConfig;
622
+ } else {
623
+ const existing = result.providers[providerName];
624
+ if (!existing) {
625
+ result.providers[providerName] = providerConfig;
626
+ continue;
627
+ }
628
+ if (providerConfig.options) {
629
+ existing.options = {
630
+ ...providerConfig.options,
631
+ ...existing.options
632
+ };
633
+ }
634
+ if (providerConfig.models) {
635
+ if (!existing.models)
636
+ existing.models = {};
637
+ for (const [modelName, modelConfig] of Object.entries(providerConfig.models)) {
638
+ if (!(modelName in existing.models)) {
639
+ existing.models[modelName] = modelConfig;
640
+ }
641
+ }
642
+ }
643
+ }
644
+ }
645
+ }
646
+ if (config.routing) {
647
+ if (!result.routing)
648
+ result.routing = [];
649
+ result.routing.push(...config.routing);
650
+ }
651
+ if (config.overrides) {
652
+ if (!result.overrides)
653
+ result.overrides = {};
654
+ for (const [targetId, override] of Object.entries(config.overrides)) {
655
+ if (targetId in result.overrides) {
656
+ warnings.push(`Models override for target "${targetId}" from pack "${packName}" skipped (already defined).`);
657
+ continue;
658
+ }
659
+ result.overrides[targetId] = override;
660
+ }
661
+ }
662
+ }
663
+ return { config: result, warnings };
664
+ }
665
+ function scanModelsForSecrets(config) {
666
+ const warnings = [];
667
+ const json = JSON.stringify(config);
668
+ for (const pattern of SECRET_PATTERNS) {
669
+ if (pattern.test(json)) {
670
+ warnings.push(`Potential secret detected in models.json matching pattern: ${pattern.source}`);
671
+ }
672
+ }
673
+ return warnings;
674
+ }
675
+
548
676
  // src/core/pack-loader.ts
549
- init_config();
550
677
  import { existsSync as existsSync6 } from "fs";
551
- import { resolve as resolve3, isAbsolute } from "path";
678
+ import { resolve as resolve2, isAbsolute } from "path";
552
679
  class PackLoader {
553
680
  projectRoot;
554
681
  config;
@@ -581,10 +708,10 @@ class PackLoader {
581
708
  }
582
709
  loadPack(packDir, manifest) {
583
710
  const name = manifest.name;
584
- const rulesDir = resolve3(packDir, "rules");
585
- const commandsDir = resolve3(packDir, "commands");
586
- const agentsDir = resolve3(packDir, "agents");
587
- const skillsDir = resolve3(packDir, "skills");
711
+ const rulesDir = resolve2(packDir, "rules");
712
+ const commandsDir = resolve2(packDir, "commands");
713
+ const agentsDir = resolve2(packDir, "agents");
714
+ const skillsDir = resolve2(packDir, "skills");
588
715
  return {
589
716
  manifest,
590
717
  directory: packDir,
@@ -595,23 +722,25 @@ class PackLoader {
595
722
  hooks: parseHooks(packDir, name),
596
723
  plugins: parsePlugins(packDir, name),
597
724
  mcp: parseMcp(packDir, name),
598
- ignore: parseIgnore(packDir, name)
725
+ ignore: parseIgnore(packDir, name),
726
+ models: parseModels(packDir, name)
599
727
  };
600
728
  }
601
729
  loadForBaseDir(baseDir) {
602
- const baseDirRoot = resolve3(this.projectRoot, baseDir);
603
- const localConfigPath = resolve3(baseDirRoot, "agentpacks.jsonc");
730
+ const baseDirRoot = resolve2(this.projectRoot, baseDir);
731
+ const localConfigPath = resolve2(baseDirRoot, "agentpacks.jsonc");
604
732
  if (!existsSync6(localConfigPath)) {
605
733
  return { packs: [], warnings: [] };
606
734
  }
607
- const { loadWorkspaceConfig: loadWorkspaceConfig2 } = (init_config(), __toCommonJS(exports_config));
608
- const localConfig = loadWorkspaceConfig2(baseDirRoot);
735
+ const localConfig = loadWorkspaceConfig(baseDirRoot);
609
736
  const loader = new PackLoader(baseDirRoot, localConfig);
610
737
  return loader.loadAll();
611
738
  }
612
739
  resolveCuratedPack(packRef) {
613
- const curatedDir = resolve3(this.projectRoot, ".agentpacks", ".curated");
740
+ const curatedDir = resolve2(this.projectRoot, ".agentpacks", ".curated");
614
741
  let packName = packRef;
742
+ if (packName.startsWith("registry:"))
743
+ packName = packName.slice(9);
615
744
  if (packName.startsWith("npm:"))
616
745
  packName = packName.slice(4);
617
746
  if (packName.startsWith("github:"))
@@ -622,24 +751,28 @@ class PackLoader {
622
751
  const parts = packName.split("/");
623
752
  packName = packName.includes("@") ? parts.join("-") : parts[parts.length - 1] ?? packName;
624
753
  }
625
- packName = packName.split("@")[0].split(":")[0];
626
- const resolved = resolve3(curatedDir, packName);
754
+ const withoutVersion = packName.split("@")[0] ?? packName;
755
+ packName = withoutVersion.split(":")[0] ?? withoutVersion;
756
+ const resolved = resolve2(curatedDir, packName);
627
757
  return existsSync6(resolved) ? resolved : null;
628
758
  }
629
759
  resolvePackPath(packRef) {
630
760
  if (packRef.startsWith("./") || packRef.startsWith("../")) {
631
- return resolve3(this.projectRoot, packRef);
761
+ return resolve2(this.projectRoot, packRef);
632
762
  }
633
763
  if (isAbsolute(packRef)) {
634
764
  return packRef;
635
765
  }
766
+ if (packRef.startsWith("registry:")) {
767
+ return this.resolveCuratedPack(packRef);
768
+ }
636
769
  if (packRef.startsWith("@") || packRef.startsWith("npm:") || !packRef.includes("/")) {
637
770
  return this.resolveCuratedPack(packRef);
638
771
  }
639
772
  if (packRef.startsWith("github:") || packRef.includes("/")) {
640
773
  return this.resolveCuratedPack(packRef);
641
774
  }
642
- return resolve3(this.projectRoot, packRef);
775
+ return resolve2(this.projectRoot, packRef);
643
776
  }
644
777
  }
645
778
 
@@ -660,7 +793,8 @@ class FeatureMerger {
660
793
  hooks: this.mergeHooks(),
661
794
  plugins: this.mergePlugins(),
662
795
  mcpServers: this.mergeMcp(),
663
- ignorePatterns: this.mergeIgnore()
796
+ ignorePatterns: this.mergeIgnore(),
797
+ models: this.mergeModels()
664
798
  };
665
799
  return { features, warnings: this.warnings };
666
800
  }
@@ -747,16 +881,24 @@ class FeatureMerger {
747
881
  }
748
882
  return result;
749
883
  }
884
+ mergeModels() {
885
+ const configs = this.packs.map((p) => p.models).filter((m) => m != null);
886
+ if (configs.length === 0)
887
+ return null;
888
+ const { config, warnings } = mergeModelsConfigs(configs);
889
+ this.warnings.push(...warnings);
890
+ return config;
891
+ }
750
892
  }
751
893
 
752
894
  // src/core/lockfile.ts
753
895
  import { existsSync as existsSync7, readFileSync as readFileSync9, writeFileSync as writeFileSync2 } from "fs";
754
- import { resolve as resolve4 } from "path";
896
+ import { resolve as resolve3 } from "path";
755
897
  import { createHash } from "crypto";
756
898
  var LOCKFILE_VERSION = 1;
757
899
  var LOCKFILE_NAME = "agentpacks.lock";
758
900
  function loadLockfile(projectRoot) {
759
- const filepath = resolve4(projectRoot, LOCKFILE_NAME);
901
+ const filepath = resolve3(projectRoot, LOCKFILE_NAME);
760
902
  if (!existsSync7(filepath)) {
761
903
  return { lockfileVersion: LOCKFILE_VERSION, sources: {} };
762
904
  }
@@ -764,7 +906,7 @@ function loadLockfile(projectRoot) {
764
906
  return JSON.parse(raw);
765
907
  }
766
908
  function saveLockfile(projectRoot, lockfile) {
767
- const filepath = resolve4(projectRoot, LOCKFILE_NAME);
909
+ const filepath = resolve3(projectRoot, LOCKFILE_NAME);
768
910
  writeFileSync2(filepath, JSON.stringify(lockfile, null, 2) + `
769
911
  `);
770
912
  }
@@ -783,15 +925,119 @@ function isLockfileFrozenValid(lockfile, sourceKeys) {
783
925
  return { valid: missing.length === 0, missing };
784
926
  }
785
927
 
928
+ // src/core/profile-resolver.ts
929
+ function resolveModels(merged, modelProfile, targetId) {
930
+ let defaultModel = merged.default;
931
+ let smallModel = merged.small;
932
+ let agents = { ...merged.agents };
933
+ if (modelProfile && merged.profiles?.[modelProfile]) {
934
+ const resolvedProfile = resolveProfileInheritance(modelProfile, merged.profiles);
935
+ if (resolvedProfile.default)
936
+ defaultModel = resolvedProfile.default;
937
+ if (resolvedProfile.small)
938
+ smallModel = resolvedProfile.small;
939
+ if (resolvedProfile.agents) {
940
+ agents = { ...agents, ...resolvedProfile.agents };
941
+ }
942
+ }
943
+ if (targetId) {
944
+ const targetOverride = merged.overrides?.[targetId];
945
+ if (targetOverride) {
946
+ if (targetOverride.default)
947
+ defaultModel = targetOverride.default;
948
+ if (targetOverride.small)
949
+ smallModel = targetOverride.small;
950
+ if (targetOverride.agents) {
951
+ agents = { ...agents, ...targetOverride.agents };
952
+ }
953
+ }
954
+ }
955
+ const providers = {};
956
+ if (merged.providers) {
957
+ for (const [name, config] of Object.entries(merged.providers)) {
958
+ providers[name] = {
959
+ ...config.options ? { options: config.options } : {},
960
+ ...config.models ? { models: config.models } : {}
961
+ };
962
+ }
963
+ }
964
+ const profileNames = Object.keys(merged.profiles ?? {});
965
+ const profiles = {};
966
+ if (merged.profiles) {
967
+ for (const [name, profile] of Object.entries(merged.profiles)) {
968
+ profiles[name] = {
969
+ description: profile.description,
970
+ default: profile.default,
971
+ small: profile.small
972
+ };
973
+ }
974
+ }
975
+ return {
976
+ default: defaultModel,
977
+ small: smallModel,
978
+ agents,
979
+ providers,
980
+ routing: merged.routing ?? [],
981
+ profileNames,
982
+ activeProfile: modelProfile,
983
+ profiles
984
+ };
985
+ }
986
+ function resolveAgentModel(resolved, agentName, frontmatterModel) {
987
+ const fromModels = resolved.agents[agentName];
988
+ if (fromModels) {
989
+ return {
990
+ model: fromModels.model,
991
+ temperature: fromModels.temperature,
992
+ top_p: fromModels.top_p
993
+ };
994
+ }
995
+ if (frontmatterModel) {
996
+ return { model: frontmatterModel };
997
+ }
998
+ return {};
999
+ }
1000
+ function resolveProfileInheritance(profileName, profiles) {
1001
+ const visited = new Set;
1002
+ return resolveProfileChain(profileName, profiles, visited, 0);
1003
+ }
1004
+ var MAX_INHERITANCE_DEPTH = 10;
1005
+ function resolveProfileChain(name, profiles, visited, depth) {
1006
+ if (depth > MAX_INHERITANCE_DEPTH) {
1007
+ throw new Error(`Profile inheritance too deep (max ${MAX_INHERITANCE_DEPTH}): ${name}`);
1008
+ }
1009
+ if (visited.has(name)) {
1010
+ throw new Error(`Circular profile inheritance detected: ${[...visited, name].join(" → ")}`);
1011
+ }
1012
+ const profile = profiles[name];
1013
+ if (!profile) {
1014
+ throw new Error(`Profile "${name}" not found`);
1015
+ }
1016
+ visited.add(name);
1017
+ if (!profile.extends) {
1018
+ return { ...profile };
1019
+ }
1020
+ const parent = resolveProfileChain(profile.extends, profiles, visited, depth + 1);
1021
+ return {
1022
+ description: profile.description ?? parent.description,
1023
+ default: profile.default ?? parent.default,
1024
+ small: profile.small ?? parent.small,
1025
+ agents: {
1026
+ ...parent.agents,
1027
+ ...profile.agents
1028
+ }
1029
+ };
1030
+ }
1031
+
786
1032
  // src/sources/local.ts
787
1033
  import { existsSync as existsSync8 } from "fs";
788
- import { resolve as resolve5, isAbsolute as isAbsolute2 } from "path";
1034
+ import { resolve as resolve4, isAbsolute as isAbsolute2 } from "path";
789
1035
  function resolveLocalPack(packRef, projectRoot) {
790
1036
  let resolved;
791
1037
  if (isAbsolute2(packRef)) {
792
1038
  resolved = packRef;
793
1039
  } else {
794
- resolved = resolve5(projectRoot, packRef);
1040
+ resolved = resolve4(projectRoot, packRef);
795
1041
  }
796
1042
  if (!existsSync8(resolved))
797
1043
  return null;
@@ -823,9 +1069,14 @@ function parseGitSourceRef(source) {
823
1069
  if (parts.length < 2) {
824
1070
  throw new Error(`Invalid git source reference: "${source}". Expected owner/repo format.`);
825
1071
  }
1072
+ const owner = parts[0];
1073
+ const repo = parts[1];
1074
+ if (!owner || !repo) {
1075
+ throw new Error(`Invalid git source reference: "${source}". Expected owner/repo format.`);
1076
+ }
826
1077
  return {
827
- owner: parts[0],
828
- repo: parts[1],
1078
+ owner,
1079
+ repo,
829
1080
  ref,
830
1081
  path: path || ""
831
1082
  };
@@ -894,9 +1145,39 @@ function npmSourceKey(parsed) {
894
1145
  return `npm:${parsed.packageName}`;
895
1146
  }
896
1147
 
1148
+ // src/sources/registry-ref.ts
1149
+ function parseRegistrySourceRef(source) {
1150
+ let s = source;
1151
+ if (s.startsWith("registry:")) {
1152
+ s = s.slice(9);
1153
+ }
1154
+ if (!s) {
1155
+ throw new Error(`Invalid registry source reference: "${source}". Expected pack name.`);
1156
+ }
1157
+ let version = "latest";
1158
+ const atIdx = s.indexOf("@");
1159
+ if (atIdx > 0) {
1160
+ version = s.slice(atIdx + 1);
1161
+ s = s.slice(0, atIdx);
1162
+ }
1163
+ if (!s) {
1164
+ throw new Error(`Invalid registry source reference: "${source}". Pack name is empty.`);
1165
+ }
1166
+ if (!/^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/.test(s)) {
1167
+ throw new Error(`Invalid registry pack name: "${s}". Must be lowercase alphanumeric with hyphens.`);
1168
+ }
1169
+ return { packName: s, version };
1170
+ }
1171
+ function isRegistryPackRef(packRef) {
1172
+ return packRef.startsWith("registry:");
1173
+ }
1174
+ function registrySourceKey(parsed) {
1175
+ return `registry:${parsed.packName}`;
1176
+ }
1177
+
897
1178
  // src/sources/git.ts
898
1179
  import { mkdirSync as mkdirSync2, writeFileSync as writeFileSync3 } from "fs";
899
- import { resolve as resolve6, join as join7 } from "path";
1180
+ import { resolve as resolve5, join as join8 } from "path";
900
1181
  var GITHUB_API = "https://api.github.com";
901
1182
  function githubHeaders(token) {
902
1183
  const h = {
@@ -949,11 +1230,11 @@ async function fetchAndWriteSubdir(parsed, sha, remotePath, localDir, installed,
949
1230
  for (const entry of entries) {
950
1231
  if (entry.type === "file" && entry.download_url) {
951
1232
  const content = await fetchGitFile(entry.download_url, token);
952
- const filepath = join7(localDir, entry.name);
1233
+ const filepath = join8(localDir, entry.name);
953
1234
  writeFileSync3(filepath, content);
954
1235
  installed.push(filepath);
955
1236
  } else if (entry.type === "dir") {
956
- await fetchAndWriteSubdir(parsed, sha, `${remotePath}/${entry.name}`, join7(localDir, entry.name), installed, token);
1237
+ await fetchAndWriteSubdir(parsed, sha, `${remotePath}/${entry.name}`, join8(localDir, entry.name), installed, token);
957
1238
  }
958
1239
  }
959
1240
  }
@@ -974,7 +1255,7 @@ async function installGitSource(projectRoot, source, lockfile, options = {}) {
974
1255
  }
975
1256
  const basePath = parsed.path || "packs";
976
1257
  const entries = await fetchGitDirectory(parsed, resolvedSha, basePath, options.token);
977
- const curatedDir = resolve6(projectRoot, ".agentpacks", ".curated");
1258
+ const curatedDir = resolve5(projectRoot, ".agentpacks", ".curated");
978
1259
  mkdirSync2(curatedDir, { recursive: true });
979
1260
  const newLockEntry = {
980
1261
  requestedRef: parsed.ref,
@@ -986,21 +1267,21 @@ async function installGitSource(projectRoot, source, lockfile, options = {}) {
986
1267
  const packDirs = entries.filter((e) => e.type === "dir");
987
1268
  for (const packEntry of packDirs) {
988
1269
  const packName = packEntry.name;
989
- const packOutDir = resolve6(curatedDir, packName);
1270
+ const packOutDir = resolve5(curatedDir, packName);
990
1271
  const packFiles = await fetchGitDirectory(parsed, resolvedSha, `${basePath}/${packName}`, options.token);
991
1272
  mkdirSync2(packOutDir, { recursive: true });
992
1273
  for (const file of packFiles) {
993
1274
  if (file.type === "file" && file.download_url) {
994
1275
  const content = await fetchGitFile(file.download_url, options.token);
995
- writeFileSync3(join7(packOutDir, file.name), content);
996
- installed.push(join7(packOutDir, file.name));
1276
+ writeFileSync3(join8(packOutDir, file.name), content);
1277
+ installed.push(join8(packOutDir, file.name));
997
1278
  if (newLockEntry.packs) {
998
1279
  newLockEntry.packs[packName] = {
999
1280
  integrity: computeIntegrity(content)
1000
1281
  };
1001
1282
  }
1002
1283
  } else if (file.type === "dir") {
1003
- await fetchAndWriteSubdir(parsed, resolvedSha, `${basePath}/${packName}/${file.name}`, join7(packOutDir, file.name), installed, options.token);
1284
+ await fetchAndWriteSubdir(parsed, resolvedSha, `${basePath}/${packName}/${file.name}`, join8(packOutDir, file.name), installed, options.token);
1004
1285
  }
1005
1286
  }
1006
1287
  }
@@ -1008,15 +1289,15 @@ async function installGitSource(projectRoot, source, lockfile, options = {}) {
1008
1289
  const fileEntries = entries.filter((e) => e.type === "file");
1009
1290
  if (fileEntries.length > 0) {
1010
1291
  const packName = parsed.path.split("/").pop() ?? parsed.repo;
1011
- const packOutDir = resolve6(curatedDir, packName);
1292
+ const packOutDir = resolve5(curatedDir, packName);
1012
1293
  mkdirSync2(packOutDir, { recursive: true });
1013
1294
  for (const file of entries) {
1014
1295
  if (file.type === "file" && file.download_url) {
1015
1296
  const content = await fetchGitFile(file.download_url, options.token);
1016
- writeFileSync3(join7(packOutDir, file.name), content);
1017
- installed.push(join7(packOutDir, file.name));
1297
+ writeFileSync3(join8(packOutDir, file.name), content);
1298
+ installed.push(join8(packOutDir, file.name));
1018
1299
  } else if (file.type === "dir") {
1019
- await fetchAndWriteSubdir(parsed, resolvedSha, `${basePath}/${file.name}`, join7(packOutDir, file.name), installed, options.token);
1300
+ await fetchAndWriteSubdir(parsed, resolvedSha, `${basePath}/${file.name}`, join8(packOutDir, file.name), installed, options.token);
1020
1301
  }
1021
1302
  }
1022
1303
  }
@@ -1026,8 +1307,8 @@ async function installGitSource(projectRoot, source, lockfile, options = {}) {
1026
1307
  }
1027
1308
 
1028
1309
  // src/sources/npm.ts
1029
- import { mkdirSync as mkdirSync3, existsSync as existsSync9 } from "fs";
1030
- import { resolve as resolve7, join as join8 } from "path";
1310
+ import { mkdirSync as mkdirSync3, existsSync as existsSync9, readdirSync as readdirSync2 } from "fs";
1311
+ import { resolve as resolve6, join as join9 } from "path";
1031
1312
  import { execSync } from "child_process";
1032
1313
  var NPM_REGISTRY = "https://registry.npmjs.org";
1033
1314
  async function resolveNpmVersion(parsed) {
@@ -1051,18 +1332,15 @@ async function installNpmSource(projectRoot, source, lockfile, options = {}) {
1051
1332
  throw new Error(`Frozen mode: no lockfile entry for source "${sourceKey}".`);
1052
1333
  }
1053
1334
  let resolvedVersion;
1054
- let tarballUrl;
1055
1335
  if (locked && !options.update) {
1056
1336
  resolvedVersion = locked.resolvedRef;
1057
- tarballUrl = "";
1058
1337
  } else {
1059
1338
  const resolved = await resolveNpmVersion(parsed);
1060
1339
  resolvedVersion = resolved.version;
1061
- tarballUrl = resolved.tarball;
1062
1340
  }
1063
- const curatedDir = resolve7(projectRoot, ".agentpacks", ".curated");
1341
+ const curatedDir = resolve6(projectRoot, ".agentpacks", ".curated");
1064
1342
  mkdirSync3(curatedDir, { recursive: true });
1065
- const packDir = extractNpmPack(parsed, resolvedVersion, curatedDir, installed, warnings);
1343
+ extractNpmPack(parsed, resolvedVersion, curatedDir, installed, warnings);
1066
1344
  const newEntry = {
1067
1345
  requestedRef: parsed.version,
1068
1346
  resolvedRef: resolvedVersion,
@@ -1076,20 +1354,25 @@ async function installNpmSource(projectRoot, source, lockfile, options = {}) {
1076
1354
  function extractNpmPack(parsed, version, curatedDir, installed, warnings) {
1077
1355
  const pkgSpec = `${parsed.packageName}@${version}`;
1078
1356
  const packName = parsed.packageName.replace(/^@/, "").replace(/\//g, "-");
1079
- const packOutDir = resolve7(curatedDir, packName);
1357
+ const packOutDir = resolve6(curatedDir, packName);
1080
1358
  try {
1081
- const tmpDir = resolve7(curatedDir, ".tmp-npm");
1359
+ const tmpDir = resolve6(curatedDir, ".tmp-npm");
1082
1360
  mkdirSync3(tmpDir, { recursive: true });
1083
1361
  execSync(`npm pack ${pkgSpec} --pack-destination "${tmpDir}"`, {
1084
1362
  stdio: "pipe",
1085
1363
  timeout: 30000
1086
1364
  });
1087
- const tgzFiles = __require("fs").readdirSync(tmpDir).filter((f) => f.endsWith(".tgz"));
1365
+ const tgzFiles = readdirSync2(tmpDir).filter((f) => f.endsWith(".tgz"));
1088
1366
  if (tgzFiles.length === 0) {
1089
1367
  warnings.push(`No tarball found for ${pkgSpec}`);
1090
1368
  return packOutDir;
1091
1369
  }
1092
- const tgzPath = join8(tmpDir, tgzFiles[0]);
1370
+ const firstTgz = tgzFiles[0];
1371
+ if (!firstTgz) {
1372
+ warnings.push(`No tarball found for ${pkgSpec}`);
1373
+ return packOutDir;
1374
+ }
1375
+ const tgzPath = join9(tmpDir, firstTgz);
1093
1376
  mkdirSync3(packOutDir, { recursive: true });
1094
1377
  execSync(`tar xzf "${tgzPath}" -C "${packOutDir}" --strip-components=1`, {
1095
1378
  stdio: "pipe",
@@ -1097,7 +1380,7 @@ function extractNpmPack(parsed, version, curatedDir, installed, warnings) {
1097
1380
  });
1098
1381
  execSync(`rm -rf "${tmpDir}"`, { stdio: "pipe" });
1099
1382
  const subpath = parsed.path || "";
1100
- const targetDir = subpath ? join8(packOutDir, subpath) : packOutDir;
1383
+ const targetDir = subpath ? join9(packOutDir, subpath) : packOutDir;
1101
1384
  if (existsSync9(targetDir)) {
1102
1385
  collectFiles(targetDir, installed);
1103
1386
  }
@@ -1107,10 +1390,9 @@ function extractNpmPack(parsed, version, curatedDir, installed, warnings) {
1107
1390
  return packOutDir;
1108
1391
  }
1109
1392
  function collectFiles(dir, out) {
1110
- const fs = __require("fs");
1111
- const entries = fs.readdirSync(dir, { withFileTypes: true });
1393
+ const entries = readdirSync2(dir, { withFileTypes: true });
1112
1394
  for (const entry of entries) {
1113
- const full = join8(dir, entry.name);
1395
+ const full = join9(dir, entry.name);
1114
1396
  if (entry.isDirectory()) {
1115
1397
  collectFiles(full, out);
1116
1398
  } else {
@@ -1163,7 +1445,7 @@ ${content}`;
1163
1445
  }
1164
1446
 
1165
1447
  // src/targets/opencode.ts
1166
- import { resolve as resolve8, join as join9 } from "path";
1448
+ import { resolve as resolve7, join as join10 } from "path";
1167
1449
  var TARGET_ID = "opencode";
1168
1450
 
1169
1451
  class OpenCodeTarget extends BaseTarget {
@@ -1177,32 +1459,48 @@ class OpenCodeTarget extends BaseTarget {
1177
1459
  "hooks",
1178
1460
  "plugins",
1179
1461
  "mcp",
1180
- "ignore"
1462
+ "ignore",
1463
+ "models"
1181
1464
  ];
1182
1465
  generate(options) {
1183
1466
  const { projectRoot, baseDir, features, enabledFeatures, deleteExisting } = options;
1184
- const root = resolve8(projectRoot, baseDir);
1467
+ const root = resolve7(projectRoot, baseDir);
1185
1468
  const effective = this.getEffectiveFeatures(enabledFeatures);
1186
1469
  const filesWritten = [];
1187
1470
  const filesDeleted = [];
1188
1471
  const warnings = [];
1189
- const opencodeDir = resolve8(root, ".opencode");
1472
+ const opencodeDir = resolve7(root, ".opencode");
1190
1473
  if (effective.includes("agents")) {
1191
- const agentDir = resolve8(opencodeDir, "agent");
1474
+ const agentDir = resolve7(opencodeDir, "agent");
1192
1475
  if (deleteExisting) {
1193
1476
  removeIfExists(agentDir);
1194
1477
  filesDeleted.push(agentDir);
1195
1478
  }
1196
1479
  ensureDir(agentDir);
1480
+ const resolvedModels = features.models ? resolveModels(features.models, options.modelProfile, TARGET_ID) : null;
1197
1481
  const agents = features.agents.filter((a) => agentMatchesTarget(a, TARGET_ID));
1198
1482
  for (const agent of agents) {
1199
- const filepath = join9(agentDir, `${agent.name}.md`);
1200
- writeGeneratedFile(filepath, agent.content);
1483
+ const filepath = join10(agentDir, `${agent.name}.md`);
1484
+ const fm = {};
1485
+ const oc = agent.meta.opencode ?? {};
1486
+ const modelsAgent = resolvedModels?.agents[agent.name];
1487
+ const agentModel = modelsAgent?.model ?? oc.model;
1488
+ const agentTemp = modelsAgent?.temperature ?? oc.temperature;
1489
+ if (agentModel)
1490
+ fm.model = agentModel;
1491
+ if (agentTemp !== undefined)
1492
+ fm.temperature = agentTemp;
1493
+ if (oc.mode)
1494
+ fm.mode = oc.mode;
1495
+ if (oc.top_p !== undefined)
1496
+ fm.top_p = oc.top_p;
1497
+ const content = Object.keys(fm).length > 0 ? serializeFrontmatter(fm, agent.content) : agent.content;
1498
+ writeGeneratedFile(filepath, content);
1201
1499
  filesWritten.push(filepath);
1202
1500
  }
1203
1501
  }
1204
1502
  if (effective.includes("skills")) {
1205
- const skillDir = resolve8(opencodeDir, "skill");
1503
+ const skillDir = resolve7(opencodeDir, "skill");
1206
1504
  if (deleteExisting) {
1207
1505
  removeIfExists(skillDir);
1208
1506
  filesDeleted.push(skillDir);
@@ -1210,15 +1508,15 @@ class OpenCodeTarget extends BaseTarget {
1210
1508
  ensureDir(skillDir);
1211
1509
  const skills = features.skills.filter((s) => skillMatchesTarget(s, TARGET_ID));
1212
1510
  for (const skill of skills) {
1213
- const skillSubDir = join9(skillDir, skill.name);
1511
+ const skillSubDir = join10(skillDir, skill.name);
1214
1512
  ensureDir(skillSubDir);
1215
- const filepath = join9(skillSubDir, "SKILL.md");
1513
+ const filepath = join10(skillSubDir, "SKILL.md");
1216
1514
  writeGeneratedFile(filepath, skill.content);
1217
1515
  filesWritten.push(filepath);
1218
1516
  }
1219
1517
  }
1220
1518
  if (effective.includes("commands")) {
1221
- const cmdDir = resolve8(opencodeDir, "command");
1519
+ const cmdDir = resolve7(opencodeDir, "command");
1222
1520
  if (deleteExisting) {
1223
1521
  removeIfExists(cmdDir);
1224
1522
  filesDeleted.push(cmdDir);
@@ -1226,19 +1524,19 @@ class OpenCodeTarget extends BaseTarget {
1226
1524
  ensureDir(cmdDir);
1227
1525
  const commands = features.commands.filter((c) => commandMatchesTarget(c, TARGET_ID));
1228
1526
  for (const cmd of commands) {
1229
- const filepath = join9(cmdDir, `${cmd.name}.md`);
1527
+ const filepath = join10(cmdDir, `${cmd.name}.md`);
1230
1528
  writeGeneratedFile(filepath, cmd.content);
1231
1529
  filesWritten.push(filepath);
1232
1530
  }
1233
1531
  }
1234
1532
  if (effective.includes("hooks") || effective.includes("plugins")) {
1235
- const pluginsDir = resolve8(opencodeDir, "plugins");
1533
+ const pluginsDir = resolve7(opencodeDir, "plugins");
1236
1534
  ensureDir(pluginsDir);
1237
1535
  if (effective.includes("hooks")) {
1238
1536
  for (const hookSet of features.hooks) {
1239
1537
  const events = resolveHooksForTarget(hookSet, TARGET_ID);
1240
1538
  if (Object.keys(events).length > 0) {
1241
- const filepath = join9(pluginsDir, `agentpacks-${hookSet.packName}.ts`);
1539
+ const filepath = join10(pluginsDir, `agentpacks-${hookSet.packName}.ts`);
1242
1540
  const content = generateOpenCodeHookPlugin(hookSet.packName, events);
1243
1541
  writeGeneratedFile(filepath, content, { type: "ts" });
1244
1542
  filesWritten.push(filepath);
@@ -1247,7 +1545,7 @@ class OpenCodeTarget extends BaseTarget {
1247
1545
  }
1248
1546
  if (effective.includes("plugins")) {
1249
1547
  for (const plugin of features.plugins) {
1250
- const filepath = join9(pluginsDir, `agentpacks-${plugin.packName}-${plugin.name}.${plugin.extension}`);
1548
+ const filepath = join10(pluginsDir, `agentpacks-${plugin.packName}-${plugin.name}.${plugin.extension}`);
1251
1549
  writeGeneratedFile(filepath, plugin.content, {
1252
1550
  type: plugin.extension
1253
1551
  });
@@ -1255,28 +1553,59 @@ class OpenCodeTarget extends BaseTarget {
1255
1553
  }
1256
1554
  }
1257
1555
  }
1258
- if (effective.includes("mcp")) {
1259
- const mcpEntries = Object.entries(features.mcpServers);
1260
- if (mcpEntries.length > 0) {
1261
- const opencodeConfig = buildOpenCodeMcp(features.mcpServers);
1262
- const filepath = resolve8(root, "opencode.json");
1556
+ if (effective.includes("mcp") || effective.includes("models")) {
1557
+ const filepath = resolve7(root, "opencode.json");
1558
+ const opencodeConfig = {
1559
+ $schema: "https://opencode.ai/config.json"
1560
+ };
1561
+ if (effective.includes("mcp")) {
1562
+ const mcpEntries = Object.entries(features.mcpServers);
1563
+ if (mcpEntries.length > 0) {
1564
+ opencodeConfig.mcp = buildOpenCodeMcpServers(features.mcpServers);
1565
+ }
1566
+ }
1567
+ if (effective.includes("models") && features.models) {
1568
+ const resolved = resolveModels(features.models, options.modelProfile, TARGET_ID);
1569
+ if (resolved.default)
1570
+ opencodeConfig.model = resolved.default;
1571
+ if (resolved.small)
1572
+ opencodeConfig.small_model = resolved.small;
1573
+ if (Object.keys(resolved.providers).length > 0) {
1574
+ opencodeConfig.provider = resolved.providers;
1575
+ }
1576
+ const agentEntries = Object.entries(resolved.agents);
1577
+ if (agentEntries.length > 0) {
1578
+ const agentConfig = {};
1579
+ for (const [name, assignment] of agentEntries) {
1580
+ const config = { model: assignment.model };
1581
+ if (assignment.temperature !== undefined) {
1582
+ config.temperature = assignment.temperature;
1583
+ }
1584
+ if (assignment.top_p !== undefined) {
1585
+ config.top_p = assignment.top_p;
1586
+ }
1587
+ agentConfig[name] = config;
1588
+ }
1589
+ opencodeConfig.agent = agentConfig;
1590
+ }
1591
+ }
1592
+ if (Object.keys(opencodeConfig).length > 1) {
1263
1593
  writeGeneratedJson(filepath, opencodeConfig, { header: false });
1264
1594
  filesWritten.push(filepath);
1265
1595
  }
1266
1596
  }
1267
1597
  if (effective.includes("rules")) {
1268
1598
  const rules = features.rules.filter((r) => ruleMatchesTarget(r, TARGET_ID));
1269
- const rootRules = getRootRules(rules);
1270
1599
  const detailRules = getDetailRules(rules);
1271
1600
  if (detailRules.length > 0) {
1272
- const memoriesDir = resolve8(opencodeDir, "memories");
1601
+ const memoriesDir = resolve7(opencodeDir, "memories");
1273
1602
  if (deleteExisting) {
1274
1603
  removeIfExists(memoriesDir);
1275
1604
  filesDeleted.push(memoriesDir);
1276
1605
  }
1277
1606
  ensureDir(memoriesDir);
1278
1607
  for (const rule of detailRules) {
1279
- const filepath = join9(memoriesDir, `${rule.name}.md`);
1608
+ const filepath = join10(memoriesDir, `${rule.name}.md`);
1280
1609
  writeGeneratedFile(filepath, rule.content);
1281
1610
  filesWritten.push(filepath);
1282
1611
  }
@@ -1285,7 +1614,7 @@ class OpenCodeTarget extends BaseTarget {
1285
1614
  return this.createResult(filesWritten, filesDeleted, warnings);
1286
1615
  }
1287
1616
  }
1288
- function buildOpenCodeMcp(servers) {
1617
+ function buildOpenCodeMcpServers(servers) {
1289
1618
  const mcp = {};
1290
1619
  for (const [name, entry] of Object.entries(servers)) {
1291
1620
  if (entry.url) {
@@ -1305,10 +1634,7 @@ function buildOpenCodeMcp(servers) {
1305
1634
  };
1306
1635
  }
1307
1636
  }
1308
- return {
1309
- $schema: "https://opencode.ai/config.json",
1310
- mcp
1311
- };
1637
+ return mcp;
1312
1638
  }
1313
1639
  function generateOpenCodeHookPlugin(packName, events) {
1314
1640
  const identifier = packNameToIdentifier(packName);
@@ -1355,7 +1681,7 @@ function mapHookEvents(events) {
1355
1681
  }
1356
1682
 
1357
1683
  // src/targets/cursor.ts
1358
- import { resolve as resolve9, join as join10 } from "path";
1684
+ import { resolve as resolve8, join as join11 } from "path";
1359
1685
  var TARGET_ID2 = "cursor";
1360
1686
 
1361
1687
  class CursorTarget extends BaseTarget {
@@ -1368,18 +1694,19 @@ class CursorTarget extends BaseTarget {
1368
1694
  "skills",
1369
1695
  "hooks",
1370
1696
  "mcp",
1371
- "ignore"
1697
+ "ignore",
1698
+ "models"
1372
1699
  ];
1373
1700
  generate(options) {
1374
1701
  const { projectRoot, baseDir, features, enabledFeatures, deleteExisting } = options;
1375
- const root = resolve9(projectRoot, baseDir);
1702
+ const root = resolve8(projectRoot, baseDir);
1376
1703
  const effective = this.getEffectiveFeatures(enabledFeatures);
1377
1704
  const filesWritten = [];
1378
1705
  const filesDeleted = [];
1379
1706
  const warnings = [];
1380
- const cursorDir = resolve9(root, ".cursor");
1707
+ const cursorDir = resolve8(root, ".cursor");
1381
1708
  if (effective.includes("rules")) {
1382
- const rulesDir = resolve9(cursorDir, "rules");
1709
+ const rulesDir = resolve8(cursorDir, "rules");
1383
1710
  if (deleteExisting) {
1384
1711
  removeIfExists(rulesDir);
1385
1712
  filesDeleted.push(rulesDir);
@@ -1396,33 +1723,40 @@ class CursorTarget extends BaseTarget {
1396
1723
  if (globs) {
1397
1724
  frontmatter.globs = globs;
1398
1725
  }
1399
- const filepath = join10(rulesDir, `${rule.name}.mdc`);
1726
+ const filepath = join11(rulesDir, `${rule.name}.mdc`);
1400
1727
  const content = serializeFrontmatter(frontmatter, rule.content);
1401
1728
  writeGeneratedFile(filepath, content);
1402
1729
  filesWritten.push(filepath);
1403
1730
  }
1404
1731
  }
1405
1732
  if (effective.includes("agents")) {
1406
- const agentsDir = resolve9(cursorDir, "agents");
1733
+ const agentsDir = resolve8(cursorDir, "agents");
1407
1734
  if (deleteExisting) {
1408
1735
  removeIfExists(agentsDir);
1409
1736
  filesDeleted.push(agentsDir);
1410
1737
  }
1411
1738
  ensureDir(agentsDir);
1739
+ const resolvedModels = features.models ? resolveModels(features.models, options.modelProfile, TARGET_ID2) : null;
1412
1740
  const agents = features.agents.filter((a) => agentMatchesTarget(a, TARGET_ID2));
1413
1741
  for (const agent of agents) {
1414
1742
  const frontmatter = {
1415
1743
  name: agent.name,
1416
1744
  description: agent.meta.description ?? ""
1417
1745
  };
1418
- const filepath = join10(agentsDir, `${agent.name}.md`);
1746
+ const cursorMeta = agent.meta.cursor ?? {};
1747
+ const modelsAgent = resolvedModels?.agents[agent.name];
1748
+ const model = modelsAgent?.model ?? cursorMeta.model;
1749
+ if (model) {
1750
+ frontmatter.model = model;
1751
+ }
1752
+ const filepath = join11(agentsDir, `${agent.name}.md`);
1419
1753
  const content = serializeFrontmatter(frontmatter, agent.content);
1420
1754
  writeGeneratedFile(filepath, content);
1421
1755
  filesWritten.push(filepath);
1422
1756
  }
1423
1757
  }
1424
1758
  if (effective.includes("skills")) {
1425
- const skillsDir = resolve9(cursorDir, "skills");
1759
+ const skillsDir = resolve8(cursorDir, "skills");
1426
1760
  if (deleteExisting) {
1427
1761
  removeIfExists(skillsDir);
1428
1762
  filesDeleted.push(skillsDir);
@@ -1430,20 +1764,20 @@ class CursorTarget extends BaseTarget {
1430
1764
  ensureDir(skillsDir);
1431
1765
  const skills = features.skills.filter((s) => skillMatchesTarget(s, TARGET_ID2));
1432
1766
  for (const skill of skills) {
1433
- const skillSubDir = join10(skillsDir, skill.name);
1767
+ const skillSubDir = join11(skillsDir, skill.name);
1434
1768
  ensureDir(skillSubDir);
1435
1769
  const frontmatter = {
1436
1770
  name: skill.name,
1437
1771
  description: skill.meta.description ?? ""
1438
1772
  };
1439
- const filepath = join10(skillSubDir, "SKILL.md");
1773
+ const filepath = join11(skillSubDir, "SKILL.md");
1440
1774
  const content = serializeFrontmatter(frontmatter, skill.content);
1441
1775
  writeGeneratedFile(filepath, content);
1442
1776
  filesWritten.push(filepath);
1443
1777
  }
1444
1778
  }
1445
1779
  if (effective.includes("commands")) {
1446
- const commandsDir = resolve9(cursorDir, "commands");
1780
+ const commandsDir = resolve8(cursorDir, "commands");
1447
1781
  if (deleteExisting) {
1448
1782
  removeIfExists(commandsDir);
1449
1783
  filesDeleted.push(commandsDir);
@@ -1451,7 +1785,7 @@ class CursorTarget extends BaseTarget {
1451
1785
  ensureDir(commandsDir);
1452
1786
  const commands = features.commands.filter((c) => commandMatchesTarget(c, TARGET_ID2));
1453
1787
  for (const cmd of commands) {
1454
- const filepath = join10(commandsDir, `${cmd.name}.md`);
1788
+ const filepath = join11(commandsDir, `${cmd.name}.md`);
1455
1789
  writeGeneratedFile(filepath, cmd.content);
1456
1790
  filesWritten.push(filepath);
1457
1791
  }
@@ -1460,14 +1794,14 @@ class CursorTarget extends BaseTarget {
1460
1794
  const mcpEntries = Object.entries(features.mcpServers);
1461
1795
  if (mcpEntries.length > 0) {
1462
1796
  const mcpConfig = buildCursorMcp(features.mcpServers);
1463
- const filepath = resolve9(cursorDir, "mcp.json");
1797
+ const filepath = resolve8(cursorDir, "mcp.json");
1464
1798
  writeGeneratedJson(filepath, mcpConfig, { header: false });
1465
1799
  filesWritten.push(filepath);
1466
1800
  }
1467
1801
  }
1468
1802
  if (effective.includes("ignore")) {
1469
1803
  if (features.ignorePatterns.length > 0) {
1470
- const filepath = resolve9(root, ".cursorignore");
1804
+ const filepath = resolve8(root, ".cursorignore");
1471
1805
  const content = features.ignorePatterns.join(`
1472
1806
  `) + `
1473
1807
  `;
@@ -1475,6 +1809,17 @@ class CursorTarget extends BaseTarget {
1475
1809
  filesWritten.push(filepath);
1476
1810
  }
1477
1811
  }
1812
+ if (effective.includes("models") && features.models) {
1813
+ const resolved = resolveModels(features.models, options.modelProfile, TARGET_ID2);
1814
+ const guidanceContent = buildCursorModelGuidance(resolved);
1815
+ if (guidanceContent) {
1816
+ const rulesDir = resolve8(cursorDir, "rules");
1817
+ ensureDir(rulesDir);
1818
+ const filepath = join11(rulesDir, "model-config.mdc");
1819
+ writeGeneratedFile(filepath, guidanceContent, { header: false });
1820
+ filesWritten.push(filepath);
1821
+ }
1822
+ }
1478
1823
  return this.createResult(filesWritten, filesDeleted, warnings);
1479
1824
  }
1480
1825
  }
@@ -1493,9 +1838,135 @@ function buildCursorMcp(servers) {
1493
1838
  }
1494
1839
  return { mcpServers };
1495
1840
  }
1841
+ function buildCursorModelGuidance(resolved) {
1842
+ if (!resolved.default && !resolved.small && Object.keys(resolved.agents).length === 0) {
1843
+ return null;
1844
+ }
1845
+ const frontmatter = {
1846
+ description: "Model configuration and selection guidelines for this workspace",
1847
+ alwaysApply: true
1848
+ };
1849
+ const lines = [];
1850
+ lines.push("# Model Configuration");
1851
+ lines.push("");
1852
+ lines.push("Use the following model preferences when working in this project.");
1853
+ lines.push("");
1854
+ if (resolved.default || resolved.small) {
1855
+ lines.push("## Default Models");
1856
+ lines.push("");
1857
+ if (resolved.default) {
1858
+ lines.push(`- **Primary model**: ${resolved.default}`);
1859
+ }
1860
+ if (resolved.small) {
1861
+ lines.push(`- **Lightweight tasks** (titles, summaries): ${resolved.small}`);
1862
+ }
1863
+ lines.push("");
1864
+ }
1865
+ const agentEntries = Object.entries(resolved.agents);
1866
+ if (agentEntries.length > 0) {
1867
+ lines.push("## Agent Model Assignments");
1868
+ lines.push("");
1869
+ lines.push("| Agent | Model | Temperature |");
1870
+ lines.push("| --- | --- | --- |");
1871
+ for (const [name, assignment] of agentEntries) {
1872
+ const temp = assignment.temperature !== undefined ? String(assignment.temperature) : "—";
1873
+ lines.push(`| ${name} | ${assignment.model} | ${temp} |`);
1874
+ }
1875
+ lines.push("");
1876
+ }
1877
+ if (Object.keys(resolved.profiles).length > 0) {
1878
+ lines.push("## Available Profiles");
1879
+ lines.push("");
1880
+ lines.push("| Profile | Description | Default Model |");
1881
+ lines.push("| --- | --- | --- |");
1882
+ for (const [name, profile] of Object.entries(resolved.profiles)) {
1883
+ lines.push(`| ${name} | ${profile.description ?? "—"} | ${profile.default ?? "—"} |`);
1884
+ }
1885
+ lines.push("");
1886
+ }
1887
+ if (resolved.activeProfile) {
1888
+ lines.push(`**Active profile**: \`${resolved.activeProfile}\``);
1889
+ lines.push("");
1890
+ }
1891
+ return serializeFrontmatter(frontmatter, lines.join(`
1892
+ `));
1893
+ }
1894
+
1895
+ // src/utils/model-guidance.ts
1896
+ function generateModelGuidanceMarkdown(resolved) {
1897
+ if (!resolved.default && !resolved.small && Object.keys(resolved.agents).length === 0 && Object.keys(resolved.profiles).length === 0) {
1898
+ return null;
1899
+ }
1900
+ const lines = [];
1901
+ lines.push("# Model Configuration");
1902
+ lines.push("");
1903
+ lines.push("Use the following model preferences when working in this project.");
1904
+ lines.push("");
1905
+ if (resolved.default || resolved.small) {
1906
+ lines.push("## Default Models");
1907
+ lines.push("");
1908
+ if (resolved.default) {
1909
+ lines.push(`- **Primary model**: ${resolved.default}`);
1910
+ }
1911
+ if (resolved.small) {
1912
+ lines.push(`- **Lightweight tasks** (titles, summaries): ${resolved.small}`);
1913
+ }
1914
+ lines.push("");
1915
+ }
1916
+ const agentEntries = Object.entries(resolved.agents);
1917
+ if (agentEntries.length > 0) {
1918
+ lines.push("## Agent Model Assignments");
1919
+ lines.push("");
1920
+ lines.push("| Agent | Model | Temperature |");
1921
+ lines.push("| --- | --- | --- |");
1922
+ for (const [name, assignment] of agentEntries) {
1923
+ const temp = assignment.temperature !== undefined ? String(assignment.temperature) : "—";
1924
+ lines.push(`| ${name} | ${assignment.model} | ${temp} |`);
1925
+ }
1926
+ lines.push("");
1927
+ }
1928
+ if (Object.keys(resolved.profiles).length > 0) {
1929
+ lines.push("## Available Profiles");
1930
+ lines.push("");
1931
+ lines.push("| Profile | Description | Default Model |");
1932
+ lines.push("| --- | --- | --- |");
1933
+ for (const [name, profile] of Object.entries(resolved.profiles)) {
1934
+ lines.push(`| ${name} | ${profile.description ?? "—"} | ${profile.default ?? "—"} |`);
1935
+ }
1936
+ lines.push("");
1937
+ }
1938
+ if (resolved.activeProfile) {
1939
+ lines.push(`**Active profile**: \`${resolved.activeProfile}\``);
1940
+ lines.push("");
1941
+ }
1942
+ if (resolved.routing.length > 0) {
1943
+ lines.push("## Task-Aware Routing");
1944
+ lines.push("");
1945
+ lines.push("Select the appropriate profile based on the task context:");
1946
+ lines.push("");
1947
+ lines.push("| Condition | Profile | Description |");
1948
+ lines.push("| --- | --- | --- |");
1949
+ for (const rule of resolved.routing) {
1950
+ const conditions = Object.entries(rule.when).map(([k, v]) => `${k}=${v}`).join(", ");
1951
+ const desc = rule.description ?? "—";
1952
+ lines.push(`| ${conditions} | ${rule.use} | ${desc} |`);
1953
+ }
1954
+ lines.push("");
1955
+ lines.push("### Condition Reference");
1956
+ lines.push("");
1957
+ lines.push("- **complexity**: low | medium | high | critical");
1958
+ lines.push("- **urgency**: low | normal | high");
1959
+ lines.push("- **budget**: minimal | standard | premium");
1960
+ lines.push("- **contextWindowNeed**: small | medium | large | max");
1961
+ lines.push("- **toolUseIntensity**: none | light | heavy");
1962
+ lines.push("");
1963
+ }
1964
+ return lines.join(`
1965
+ `);
1966
+ }
1496
1967
 
1497
1968
  // src/targets/claude-code.ts
1498
- import { resolve as resolve10, join as join11 } from "path";
1969
+ import { resolve as resolve9, join as join12 } from "path";
1499
1970
  var TARGET_ID3 = "claudecode";
1500
1971
 
1501
1972
  class ClaudeCodeTarget extends BaseTarget {
@@ -1508,18 +1979,19 @@ class ClaudeCodeTarget extends BaseTarget {
1508
1979
  "skills",
1509
1980
  "hooks",
1510
1981
  "mcp",
1511
- "ignore"
1982
+ "ignore",
1983
+ "models"
1512
1984
  ];
1513
1985
  generate(options) {
1514
1986
  const { projectRoot, baseDir, features, enabledFeatures, deleteExisting } = options;
1515
- const root = resolve10(projectRoot, baseDir);
1987
+ const root = resolve9(projectRoot, baseDir);
1516
1988
  const effective = this.getEffectiveFeatures(enabledFeatures);
1517
1989
  const filesWritten = [];
1518
1990
  const filesDeleted = [];
1519
1991
  const warnings = [];
1520
- const claudeDir = resolve10(root, ".claude");
1992
+ const claudeDir = resolve9(root, ".claude");
1521
1993
  if (effective.includes("rules")) {
1522
- const rulesDir = resolve10(claudeDir, "rules");
1994
+ const rulesDir = resolve9(claudeDir, "rules");
1523
1995
  if (deleteExisting) {
1524
1996
  removeIfExists(rulesDir);
1525
1997
  filesDeleted.push(rulesDir);
@@ -1532,32 +2004,41 @@ class ClaudeCodeTarget extends BaseTarget {
1532
2004
  const claudeMd = rootRules.map((r) => r.content).join(`
1533
2005
 
1534
2006
  `);
1535
- const filepath = resolve10(claudeDir, "CLAUDE.md");
2007
+ const filepath = resolve9(claudeDir, "CLAUDE.md");
1536
2008
  writeGeneratedFile(filepath, claudeMd);
1537
2009
  filesWritten.push(filepath);
1538
2010
  }
1539
2011
  for (const rule of detailRules) {
1540
- const filepath = join11(rulesDir, `${rule.name}.md`);
2012
+ const filepath = join12(rulesDir, `${rule.name}.md`);
1541
2013
  writeGeneratedFile(filepath, rule.content);
1542
2014
  filesWritten.push(filepath);
1543
2015
  }
1544
2016
  }
1545
2017
  if (effective.includes("agents")) {
1546
- const agentsDir = resolve10(claudeDir, "agents");
2018
+ const agentsDir = resolve9(claudeDir, "agents");
1547
2019
  if (deleteExisting) {
1548
2020
  removeIfExists(agentsDir);
1549
2021
  filesDeleted.push(agentsDir);
1550
2022
  }
1551
2023
  ensureDir(agentsDir);
2024
+ const resolvedModels = features.models ? resolveModels(features.models, options.modelProfile, TARGET_ID3) : null;
1552
2025
  const agents = features.agents.filter((a) => agentMatchesTarget(a, TARGET_ID3));
1553
2026
  for (const agent of agents) {
1554
- const filepath = join11(agentsDir, `${agent.name}.md`);
1555
- writeGeneratedFile(filepath, agent.content);
2027
+ const filepath = join12(agentsDir, `${agent.name}.md`);
2028
+ const cc = agent.meta.claudecode ?? {};
2029
+ const modelsAgent = resolvedModels?.agents[agent.name];
2030
+ const agentModel = modelsAgent?.model ?? cc.model;
2031
+ let content = agent.content;
2032
+ if (agentModel) {
2033
+ content = `<!-- model: ${agentModel} -->
2034
+ ${content}`;
2035
+ }
2036
+ writeGeneratedFile(filepath, content);
1556
2037
  filesWritten.push(filepath);
1557
2038
  }
1558
2039
  }
1559
2040
  if (effective.includes("skills")) {
1560
- const skillsDir = resolve10(claudeDir, "skills");
2041
+ const skillsDir = resolve9(claudeDir, "skills");
1561
2042
  if (deleteExisting) {
1562
2043
  removeIfExists(skillsDir);
1563
2044
  filesDeleted.push(skillsDir);
@@ -1565,15 +2046,15 @@ class ClaudeCodeTarget extends BaseTarget {
1565
2046
  ensureDir(skillsDir);
1566
2047
  const skills = features.skills.filter((s) => skillMatchesTarget(s, TARGET_ID3));
1567
2048
  for (const skill of skills) {
1568
- const skillSubDir = join11(skillsDir, skill.name);
2049
+ const skillSubDir = join12(skillsDir, skill.name);
1569
2050
  ensureDir(skillSubDir);
1570
- const filepath = join11(skillSubDir, "SKILL.md");
2051
+ const filepath = join12(skillSubDir, "SKILL.md");
1571
2052
  writeGeneratedFile(filepath, skill.content);
1572
2053
  filesWritten.push(filepath);
1573
2054
  }
1574
2055
  }
1575
2056
  if (effective.includes("commands")) {
1576
- const commandsDir = resolve10(claudeDir, "commands");
2057
+ const commandsDir = resolve9(claudeDir, "commands");
1577
2058
  if (deleteExisting) {
1578
2059
  removeIfExists(commandsDir);
1579
2060
  filesDeleted.push(commandsDir);
@@ -1581,15 +2062,26 @@ class ClaudeCodeTarget extends BaseTarget {
1581
2062
  ensureDir(commandsDir);
1582
2063
  const commands = features.commands.filter((c) => commandMatchesTarget(c, TARGET_ID3));
1583
2064
  for (const cmd of commands) {
1584
- const filepath = join11(commandsDir, `${cmd.name}.md`);
2065
+ const filepath = join12(commandsDir, `${cmd.name}.md`);
1585
2066
  writeGeneratedFile(filepath, cmd.content);
1586
2067
  filesWritten.push(filepath);
1587
2068
  }
1588
2069
  }
2070
+ if (effective.includes("models") && features.models) {
2071
+ const resolved = resolveModels(features.models, options.modelProfile, TARGET_ID3);
2072
+ const guidance = generateModelGuidanceMarkdown(resolved);
2073
+ if (guidance) {
2074
+ const rulesDir = resolve9(claudeDir, "rules");
2075
+ ensureDir(rulesDir);
2076
+ const filepath = join12(rulesDir, "model-config.md");
2077
+ writeGeneratedFile(filepath, guidance);
2078
+ filesWritten.push(filepath);
2079
+ }
2080
+ }
1589
2081
  if (effective.includes("hooks") || effective.includes("mcp") || effective.includes("ignore")) {
1590
2082
  const settings = buildClaudeSettings(options, effective);
1591
2083
  if (Object.keys(settings).length > 0) {
1592
- const filepath = resolve10(claudeDir, "settings.json");
2084
+ const filepath = resolve9(claudeDir, "settings.json");
1593
2085
  const existing = readJsonOrNull(filepath) ?? {};
1594
2086
  const merged = { ...existing, ...settings };
1595
2087
  writeGeneratedJson(filepath, merged, { header: false });
@@ -1646,7 +2138,7 @@ function toPascalCase(str) {
1646
2138
  }
1647
2139
 
1648
2140
  // src/targets/codex-cli.ts
1649
- import { resolve as resolve11, join as join12 } from "path";
2141
+ import { resolve as resolve10, join as join13 } from "path";
1650
2142
  var TARGET_ID4 = "codexcli";
1651
2143
 
1652
2144
  class CodexCliTarget extends BaseTarget {
@@ -1655,14 +2147,14 @@ class CodexCliTarget extends BaseTarget {
1655
2147
  supportedFeatures = ["rules", "skills", "mcp", "hooks"];
1656
2148
  generate(options) {
1657
2149
  const { projectRoot, baseDir, features, enabledFeatures, deleteExisting } = options;
1658
- const root = resolve11(projectRoot, baseDir);
2150
+ const root = resolve10(projectRoot, baseDir);
1659
2151
  const effective = this.getEffectiveFeatures(enabledFeatures);
1660
2152
  const filesWritten = [];
1661
2153
  const filesDeleted = [];
1662
2154
  const warnings = [];
1663
- const codexDir = resolve11(root, ".codex");
2155
+ const codexDir = resolve10(root, ".codex");
1664
2156
  if (effective.includes("rules")) {
1665
- const memoriesDir = resolve11(codexDir, "memories");
2157
+ const memoriesDir = resolve10(codexDir, "memories");
1666
2158
  if (deleteExisting) {
1667
2159
  removeIfExists(memoriesDir);
1668
2160
  filesDeleted.push(memoriesDir);
@@ -1670,13 +2162,13 @@ class CodexCliTarget extends BaseTarget {
1670
2162
  ensureDir(memoriesDir);
1671
2163
  const rules = features.rules.filter((r) => ruleMatchesTarget(r, TARGET_ID4));
1672
2164
  for (const rule of rules) {
1673
- const filepath = join12(memoriesDir, `${rule.name}.md`);
2165
+ const filepath = join13(memoriesDir, `${rule.name}.md`);
1674
2166
  writeGeneratedFile(filepath, rule.content);
1675
2167
  filesWritten.push(filepath);
1676
2168
  }
1677
2169
  }
1678
2170
  if (effective.includes("skills")) {
1679
- const skillsDir = resolve11(codexDir, "skills");
2171
+ const skillsDir = resolve10(codexDir, "skills");
1680
2172
  if (deleteExisting) {
1681
2173
  removeIfExists(skillsDir);
1682
2174
  filesDeleted.push(skillsDir);
@@ -1684,9 +2176,9 @@ class CodexCliTarget extends BaseTarget {
1684
2176
  ensureDir(skillsDir);
1685
2177
  const skills = features.skills.filter((s) => skillMatchesTarget(s, TARGET_ID4));
1686
2178
  for (const skill of skills) {
1687
- const skillSubDir = join12(skillsDir, skill.name);
2179
+ const skillSubDir = join13(skillsDir, skill.name);
1688
2180
  ensureDir(skillSubDir);
1689
- const filepath = join12(skillSubDir, "SKILL.md");
2181
+ const filepath = join13(skillSubDir, "SKILL.md");
1690
2182
  writeGeneratedFile(filepath, skill.content);
1691
2183
  filesWritten.push(filepath);
1692
2184
  }
@@ -1696,7 +2188,7 @@ class CodexCliTarget extends BaseTarget {
1696
2188
  }
1697
2189
 
1698
2190
  // src/targets/gemini-cli.ts
1699
- import { resolve as resolve12, join as join13 } from "path";
2191
+ import { resolve as resolve11, join as join14 } from "path";
1700
2192
  var TARGET_ID5 = "geminicli";
1701
2193
 
1702
2194
  class GeminiCliTarget extends BaseTarget {
@@ -1712,12 +2204,12 @@ class GeminiCliTarget extends BaseTarget {
1712
2204
  ];
1713
2205
  generate(options) {
1714
2206
  const { projectRoot, baseDir, features, enabledFeatures, deleteExisting } = options;
1715
- const root = resolve12(projectRoot, baseDir);
2207
+ const root = resolve11(projectRoot, baseDir);
1716
2208
  const effective = this.getEffectiveFeatures(enabledFeatures);
1717
2209
  const filesWritten = [];
1718
2210
  const filesDeleted = [];
1719
2211
  const warnings = [];
1720
- const geminiDir = resolve12(root, ".gemini");
2212
+ const geminiDir = resolve11(root, ".gemini");
1721
2213
  if (effective.includes("rules")) {
1722
2214
  const rules = features.rules.filter((r) => ruleMatchesTarget(r, TARGET_ID5));
1723
2215
  const rootRules = getRootRules(rules);
@@ -1726,26 +2218,26 @@ class GeminiCliTarget extends BaseTarget {
1726
2218
  const geminiMd = rootRules.map((r) => r.content).join(`
1727
2219
 
1728
2220
  `);
1729
- const filepath = resolve12(root, "GEMINI.md");
2221
+ const filepath = resolve11(root, "GEMINI.md");
1730
2222
  writeGeneratedFile(filepath, geminiMd);
1731
2223
  filesWritten.push(filepath);
1732
2224
  }
1733
2225
  if (detailRules.length > 0) {
1734
- const memoriesDir = resolve12(geminiDir, "memories");
2226
+ const memoriesDir = resolve11(geminiDir, "memories");
1735
2227
  if (deleteExisting) {
1736
2228
  removeIfExists(memoriesDir);
1737
2229
  filesDeleted.push(memoriesDir);
1738
2230
  }
1739
2231
  ensureDir(memoriesDir);
1740
2232
  for (const rule of detailRules) {
1741
- const filepath = join13(memoriesDir, `${rule.name}.md`);
2233
+ const filepath = join14(memoriesDir, `${rule.name}.md`);
1742
2234
  writeGeneratedFile(filepath, rule.content);
1743
2235
  filesWritten.push(filepath);
1744
2236
  }
1745
2237
  }
1746
2238
  }
1747
2239
  if (effective.includes("commands")) {
1748
- const commandsDir = resolve12(geminiDir, "commands");
2240
+ const commandsDir = resolve11(geminiDir, "commands");
1749
2241
  if (deleteExisting) {
1750
2242
  removeIfExists(commandsDir);
1751
2243
  filesDeleted.push(commandsDir);
@@ -1754,7 +2246,7 @@ class GeminiCliTarget extends BaseTarget {
1754
2246
  const commands = features.commands.filter((c) => commandMatchesTarget(c, TARGET_ID5));
1755
2247
  for (const cmd of commands) {
1756
2248
  const toml = buildGeminiCommand(cmd.name, cmd.meta.description ?? "", cmd.content);
1757
- const filepath = join13(commandsDir, `${cmd.name}.toml`);
2249
+ const filepath = join14(commandsDir, `${cmd.name}.toml`);
1758
2250
  writeGeneratedFile(filepath, toml, { type: "md" });
1759
2251
  filesWritten.push(filepath);
1760
2252
  }
@@ -1763,14 +2255,14 @@ class GeminiCliTarget extends BaseTarget {
1763
2255
  const mcpEntries = Object.entries(features.mcpServers);
1764
2256
  if (mcpEntries.length > 0) {
1765
2257
  const settings = buildGeminiSettings(features.mcpServers);
1766
- const filepath = resolve12(geminiDir, "settings.json");
2258
+ const filepath = resolve11(geminiDir, "settings.json");
1767
2259
  writeGeneratedJson(filepath, settings, { header: false });
1768
2260
  filesWritten.push(filepath);
1769
2261
  }
1770
2262
  }
1771
2263
  if (effective.includes("ignore")) {
1772
2264
  if (features.ignorePatterns.length > 0) {
1773
- const filepath = resolve12(root, ".geminiignore");
2265
+ const filepath = resolve11(root, ".geminiignore");
1774
2266
  const content = features.ignorePatterns.join(`
1775
2267
  `) + `
1776
2268
  `;
@@ -1809,7 +2301,7 @@ function buildGeminiSettings(servers) {
1809
2301
  }
1810
2302
 
1811
2303
  // src/targets/copilot.ts
1812
- import { resolve as resolve13, join as join14 } from "path";
2304
+ import { resolve as resolve12, join as join15 } from "path";
1813
2305
  var TARGET_ID6 = "copilot";
1814
2306
 
1815
2307
  class CopilotTarget extends BaseTarget {
@@ -1821,16 +2313,17 @@ class CopilotTarget extends BaseTarget {
1821
2313
  "agents",
1822
2314
  "skills",
1823
2315
  "mcp",
1824
- "ignore"
2316
+ "ignore",
2317
+ "models"
1825
2318
  ];
1826
2319
  generate(options) {
1827
2320
  const { projectRoot, baseDir, features, enabledFeatures, deleteExisting } = options;
1828
- const root = resolve13(projectRoot, baseDir);
2321
+ const root = resolve12(projectRoot, baseDir);
1829
2322
  const effective = this.getEffectiveFeatures(enabledFeatures);
1830
2323
  const filesWritten = [];
1831
2324
  const filesDeleted = [];
1832
2325
  const warnings = [];
1833
- const githubDir = resolve13(root, ".github");
2326
+ const githubDir = resolve12(root, ".github");
1834
2327
  if (effective.includes("rules")) {
1835
2328
  const rules = features.rules.filter((r) => ruleMatchesTarget(r, TARGET_ID6));
1836
2329
  if (rules.length > 0) {
@@ -1839,15 +2332,15 @@ class CopilotTarget extends BaseTarget {
1839
2332
  ---
1840
2333
 
1841
2334
  `);
1842
- const filepath = resolve13(githubDir, "copilot-instructions.md");
2335
+ const filepath = resolve12(githubDir, "copilot-instructions.md");
1843
2336
  ensureDir(githubDir);
1844
2337
  writeGeneratedFile(filepath, combinedContent);
1845
2338
  filesWritten.push(filepath);
1846
2339
  }
1847
2340
  }
1848
2341
  if (effective.includes("agents")) {
1849
- const copilotDir = resolve13(githubDir, "copilot");
1850
- const agentsDir = resolve13(copilotDir, "agents");
2342
+ const copilotDir = resolve12(githubDir, "copilot");
2343
+ const agentsDir = resolve12(copilotDir, "agents");
1851
2344
  if (deleteExisting) {
1852
2345
  removeIfExists(agentsDir);
1853
2346
  filesDeleted.push(agentsDir);
@@ -1855,14 +2348,14 @@ class CopilotTarget extends BaseTarget {
1855
2348
  ensureDir(agentsDir);
1856
2349
  const agents = features.agents.filter((a) => agentMatchesTarget(a, TARGET_ID6));
1857
2350
  for (const agent of agents) {
1858
- const filepath = join14(agentsDir, `${agent.name}.md`);
2351
+ const filepath = join15(agentsDir, `${agent.name}.md`);
1859
2352
  writeGeneratedFile(filepath, agent.content);
1860
2353
  filesWritten.push(filepath);
1861
2354
  }
1862
2355
  }
1863
2356
  if (effective.includes("skills")) {
1864
- const copilotDir = resolve13(githubDir, "copilot");
1865
- const skillsDir = resolve13(copilotDir, "skills");
2357
+ const copilotDir = resolve12(githubDir, "copilot");
2358
+ const skillsDir = resolve12(copilotDir, "skills");
1866
2359
  if (deleteExisting) {
1867
2360
  removeIfExists(skillsDir);
1868
2361
  filesDeleted.push(skillsDir);
@@ -1870,16 +2363,16 @@ class CopilotTarget extends BaseTarget {
1870
2363
  ensureDir(skillsDir);
1871
2364
  const skills = features.skills.filter((s) => skillMatchesTarget(s, TARGET_ID6));
1872
2365
  for (const skill of skills) {
1873
- const skillSubDir = join14(skillsDir, skill.name);
2366
+ const skillSubDir = join15(skillsDir, skill.name);
1874
2367
  ensureDir(skillSubDir);
1875
- const filepath = join14(skillSubDir, "SKILL.md");
2368
+ const filepath = join15(skillSubDir, "SKILL.md");
1876
2369
  writeGeneratedFile(filepath, skill.content);
1877
2370
  filesWritten.push(filepath);
1878
2371
  }
1879
2372
  }
1880
2373
  if (effective.includes("commands")) {
1881
- const copilotDir = resolve13(githubDir, "copilot");
1882
- const commandsDir = resolve13(copilotDir, "commands");
2374
+ const copilotDir = resolve12(githubDir, "copilot");
2375
+ const commandsDir = resolve12(copilotDir, "commands");
1883
2376
  if (deleteExisting) {
1884
2377
  removeIfExists(commandsDir);
1885
2378
  filesDeleted.push(commandsDir);
@@ -1887,25 +2380,36 @@ class CopilotTarget extends BaseTarget {
1887
2380
  ensureDir(commandsDir);
1888
2381
  const commands = features.commands.filter((c) => commandMatchesTarget(c, TARGET_ID6));
1889
2382
  for (const cmd of commands) {
1890
- const filepath = join14(commandsDir, `${cmd.name}.md`);
2383
+ const filepath = join15(commandsDir, `${cmd.name}.md`);
1891
2384
  writeGeneratedFile(filepath, cmd.content);
1892
2385
  filesWritten.push(filepath);
1893
2386
  }
1894
2387
  }
1895
2388
  if (effective.includes("ignore")) {}
2389
+ if (effective.includes("models") && features.models) {
2390
+ const resolved = resolveModels(features.models, options.modelProfile, TARGET_ID6);
2391
+ const guidance = generateModelGuidanceMarkdown(resolved);
2392
+ if (guidance) {
2393
+ const copilotDir = resolve12(githubDir, "copilot");
2394
+ ensureDir(copilotDir);
2395
+ const filepath = join15(copilotDir, "model-config.md");
2396
+ writeGeneratedFile(filepath, guidance);
2397
+ filesWritten.push(filepath);
2398
+ }
2399
+ }
1896
2400
  return this.createResult(filesWritten, filesDeleted, warnings);
1897
2401
  }
1898
2402
  }
1899
2403
 
1900
2404
  // src/targets/agents-md.ts
1901
- import { resolve as resolve14 } from "path";
2405
+ import { resolve as resolve13 } from "path";
1902
2406
  class AgentsMdTarget extends BaseTarget {
1903
2407
  id = "agentsmd";
1904
2408
  name = "AGENTS.md";
1905
2409
  supportedFeatures = ["rules"];
1906
2410
  generate(options) {
1907
2411
  const { projectRoot, baseDir, features } = options;
1908
- const root = resolve14(projectRoot, baseDir);
2412
+ const root = resolve13(projectRoot, baseDir);
1909
2413
  const filesWritten = [];
1910
2414
  const warnings = [];
1911
2415
  const rootRules = getRootRules(features.rules);
@@ -1917,7 +2421,7 @@ class AgentsMdTarget extends BaseTarget {
1917
2421
  const content = sections.join(`
1918
2422
 
1919
2423
  `);
1920
- const filepath = resolve14(root, "AGENTS.md");
2424
+ const filepath = resolve13(root, "AGENTS.md");
1921
2425
  writeGeneratedFile(filepath, content);
1922
2426
  filesWritten.push(filepath);
1923
2427
  return this.createResult(filesWritten, [], warnings);
@@ -1925,7 +2429,7 @@ class AgentsMdTarget extends BaseTarget {
1925
2429
  }
1926
2430
 
1927
2431
  // src/targets/generic-md-target.ts
1928
- import { resolve as resolve15, join as join15 } from "path";
2432
+ import { resolve as resolve14, join as join16 } from "path";
1929
2433
  function createGenericMdTarget(config) {
1930
2434
  return new GenericMdTarget(config);
1931
2435
  }
@@ -1944,16 +2448,16 @@ class GenericMdTarget extends BaseTarget {
1944
2448
  }
1945
2449
  generate(options) {
1946
2450
  const { projectRoot, baseDir, features, enabledFeatures, deleteExisting } = options;
1947
- const root = resolve15(projectRoot, baseDir);
2451
+ const root = resolve14(projectRoot, baseDir);
1948
2452
  const effective = this.getEffectiveFeatures(enabledFeatures);
1949
2453
  const filesWritten = [];
1950
2454
  const filesDeleted = [];
1951
2455
  const warnings = [];
1952
- const configDir = resolve15(root, this.config.configDir);
2456
+ const configDir = resolve14(root, this.config.configDir);
1953
2457
  const rulesSubDir = this.config.rulesDir ?? "rules";
1954
2458
  const ext = this.config.ruleExtension ?? ".md";
1955
2459
  if (effective.includes("rules")) {
1956
- const rulesDir = resolve15(configDir, rulesSubDir);
2460
+ const rulesDir = resolve14(configDir, rulesSubDir);
1957
2461
  if (deleteExisting) {
1958
2462
  removeIfExists(rulesDir);
1959
2463
  filesDeleted.push(rulesDir);
@@ -1961,13 +2465,13 @@ class GenericMdTarget extends BaseTarget {
1961
2465
  ensureDir(rulesDir);
1962
2466
  const rules = features.rules.filter((r) => ruleMatchesTarget(r, this.id));
1963
2467
  for (const rule of rules) {
1964
- const filepath = join15(rulesDir, `${rule.name}${ext}`);
2468
+ const filepath = join16(rulesDir, `${rule.name}${ext}`);
1965
2469
  writeGeneratedFile(filepath, rule.content);
1966
2470
  filesWritten.push(filepath);
1967
2471
  }
1968
2472
  }
1969
2473
  if (effective.includes("commands")) {
1970
- const commandsDir = resolve15(configDir, "commands");
2474
+ const commandsDir = resolve14(configDir, "commands");
1971
2475
  if (deleteExisting) {
1972
2476
  removeIfExists(commandsDir);
1973
2477
  filesDeleted.push(commandsDir);
@@ -1975,7 +2479,7 @@ class GenericMdTarget extends BaseTarget {
1975
2479
  ensureDir(commandsDir);
1976
2480
  const commands = features.commands.filter((c) => commandMatchesTarget(c, this.id));
1977
2481
  for (const cmd of commands) {
1978
- const filepath = join15(commandsDir, `${cmd.name}.md`);
2482
+ const filepath = join16(commandsDir, `${cmd.name}.md`);
1979
2483
  writeGeneratedFile(filepath, cmd.content);
1980
2484
  filesWritten.push(filepath);
1981
2485
  }
@@ -1984,7 +2488,7 @@ class GenericMdTarget extends BaseTarget {
1984
2488
  const mcpEntries = Object.entries(features.mcpServers);
1985
2489
  if (mcpEntries.length > 0) {
1986
2490
  const mcpDir = this.config.mcpInConfigDir ? configDir : root;
1987
- const filepath = resolve15(mcpDir, "mcp.json");
2491
+ const filepath = resolve14(mcpDir, "mcp.json");
1988
2492
  writeGeneratedJson(filepath, { mcpServers: features.mcpServers }, {
1989
2493
  header: false
1990
2494
  });
@@ -1993,13 +2497,23 @@ class GenericMdTarget extends BaseTarget {
1993
2497
  }
1994
2498
  if (effective.includes("ignore") && this.config.ignoreFile) {
1995
2499
  if (features.ignorePatterns.length > 0) {
1996
- const filepath = resolve15(root, this.config.ignoreFile);
2500
+ const filepath = resolve14(root, this.config.ignoreFile);
1997
2501
  writeGeneratedFile(filepath, features.ignorePatterns.join(`
1998
2502
  `) + `
1999
2503
  `);
2000
2504
  filesWritten.push(filepath);
2001
2505
  }
2002
2506
  }
2507
+ if (effective.includes("models") && features.models) {
2508
+ const resolved = resolveModels(features.models, options.modelProfile, this.id);
2509
+ const guidance = generateModelGuidanceMarkdown(resolved);
2510
+ if (guidance) {
2511
+ ensureDir(configDir);
2512
+ const filepath = join16(configDir, "model-config.md");
2513
+ writeGeneratedFile(filepath, guidance);
2514
+ filesWritten.push(filepath);
2515
+ }
2516
+ }
2003
2517
  return this.createResult(filesWritten, filesDeleted, warnings);
2004
2518
  }
2005
2519
  }
@@ -2139,11 +2653,11 @@ function listTargetIds() {
2139
2653
  }
2140
2654
 
2141
2655
  // src/exporters/cursor-plugin.ts
2142
- import { resolve as resolve16, join as join16 } from "path";
2143
- import { mkdirSync as mkdirSync4, writeFileSync as writeFileSync5 } from "fs";
2656
+ import { resolve as resolve15, join as join17 } from "path";
2657
+ import { mkdirSync as mkdirSync4, writeFileSync as writeFileSync4 } from "fs";
2144
2658
  function exportCursorPlugin(pack, outputDir) {
2145
2659
  const filesWritten = [];
2146
- const pluginDir = resolve16(outputDir, pack.manifest.name);
2660
+ const pluginDir = resolve15(outputDir, pack.manifest.name);
2147
2661
  mkdirSync4(pluginDir, { recursive: true });
2148
2662
  const manifest = {
2149
2663
  name: pack.manifest.name,
@@ -2157,7 +2671,7 @@ function exportCursorPlugin(pack, outputDir) {
2157
2671
  manifest.tags = pack.manifest.tags;
2158
2672
  }
2159
2673
  if (pack.rules.length > 0) {
2160
- const rulesDir = join16(pluginDir, "rules");
2674
+ const rulesDir = join17(pluginDir, "rules");
2161
2675
  ensureDir(rulesDir);
2162
2676
  manifest.rules = [];
2163
2677
  for (const rule of pack.rules) {
@@ -2170,14 +2684,14 @@ function exportCursorPlugin(pack, outputDir) {
2170
2684
  if (globs)
2171
2685
  fm.globs = globs;
2172
2686
  const filename = `${rule.name}.mdc`;
2173
- const filepath = join16(rulesDir, filename);
2174
- writeFileSync5(filepath, serializeFrontmatter(fm, rule.content));
2687
+ const filepath = join17(rulesDir, filename);
2688
+ writeFileSync4(filepath, serializeFrontmatter(fm, rule.content));
2175
2689
  filesWritten.push(filepath);
2176
2690
  manifest.rules.push(filename);
2177
2691
  }
2178
2692
  }
2179
2693
  if (pack.agents.length > 0) {
2180
- const agentsDir = join16(pluginDir, "agents");
2694
+ const agentsDir = join17(pluginDir, "agents");
2181
2695
  ensureDir(agentsDir);
2182
2696
  manifest.agents = [];
2183
2697
  for (const agent of pack.agents) {
@@ -2186,61 +2700,61 @@ function exportCursorPlugin(pack, outputDir) {
2186
2700
  description: agent.meta.description ?? ""
2187
2701
  };
2188
2702
  const filename = `${agent.name}.md`;
2189
- const filepath = join16(agentsDir, filename);
2190
- writeFileSync5(filepath, serializeFrontmatter(fm, agent.content));
2703
+ const filepath = join17(agentsDir, filename);
2704
+ writeFileSync4(filepath, serializeFrontmatter(fm, agent.content));
2191
2705
  filesWritten.push(filepath);
2192
2706
  manifest.agents.push(filename);
2193
2707
  }
2194
2708
  }
2195
2709
  if (pack.skills.length > 0) {
2196
- const skillsDir = join16(pluginDir, "skills");
2710
+ const skillsDir = join17(pluginDir, "skills");
2197
2711
  ensureDir(skillsDir);
2198
2712
  manifest.skills = [];
2199
2713
  for (const skill of pack.skills) {
2200
- const skillSubDir = join16(skillsDir, skill.name);
2714
+ const skillSubDir = join17(skillsDir, skill.name);
2201
2715
  ensureDir(skillSubDir);
2202
2716
  const fm = {
2203
2717
  name: skill.name,
2204
2718
  description: skill.meta.description ?? ""
2205
2719
  };
2206
- const filepath = join16(skillSubDir, "SKILL.md");
2207
- writeFileSync5(filepath, serializeFrontmatter(fm, skill.content));
2720
+ const filepath = join17(skillSubDir, "SKILL.md");
2721
+ writeFileSync4(filepath, serializeFrontmatter(fm, skill.content));
2208
2722
  filesWritten.push(filepath);
2209
2723
  manifest.skills.push(skill.name);
2210
2724
  }
2211
2725
  }
2212
2726
  if (pack.commands.length > 0) {
2213
- const commandsDir = join16(pluginDir, "commands");
2727
+ const commandsDir = join17(pluginDir, "commands");
2214
2728
  ensureDir(commandsDir);
2215
2729
  manifest.commands = [];
2216
2730
  for (const cmd of pack.commands) {
2217
2731
  const filename = `${cmd.name}.md`;
2218
- const filepath = join16(commandsDir, filename);
2219
- writeFileSync5(filepath, cmd.content);
2732
+ const filepath = join17(commandsDir, filename);
2733
+ writeFileSync4(filepath, cmd.content);
2220
2734
  filesWritten.push(filepath);
2221
2735
  manifest.commands.push(filename);
2222
2736
  }
2223
2737
  }
2224
2738
  if (pack.mcp && Object.keys(pack.mcp.servers).length > 0) {
2225
2739
  manifest.mcp = true;
2226
- const filepath = join16(pluginDir, "mcp.json");
2227
- writeFileSync5(filepath, JSON.stringify({ mcpServers: pack.mcp.servers }, null, 2) + `
2740
+ const filepath = join17(pluginDir, "mcp.json");
2741
+ writeFileSync4(filepath, JSON.stringify({ mcpServers: pack.mcp.servers }, null, 2) + `
2228
2742
  `);
2229
2743
  filesWritten.push(filepath);
2230
2744
  }
2231
- const manifestPath = join16(pluginDir, "manifest.json");
2232
- writeFileSync5(manifestPath, JSON.stringify(manifest, null, 2) + `
2745
+ const manifestPath = join17(pluginDir, "manifest.json");
2746
+ writeFileSync4(manifestPath, JSON.stringify(manifest, null, 2) + `
2233
2747
  `);
2234
2748
  filesWritten.push(manifestPath);
2235
2749
  return { outputDir: pluginDir, filesWritten, manifest };
2236
2750
  }
2237
2751
 
2238
2752
  // src/importers/rulesync.ts
2239
- import { existsSync as existsSync10, readFileSync as readFileSync10, copyFileSync, writeFileSync as writeFileSync6 } from "fs";
2240
- import { resolve as resolve17, join as join17, basename as basename6 } from "path";
2753
+ import { existsSync as existsSync10, readFileSync as readFileSync10, copyFileSync, writeFileSync as writeFileSync5 } from "fs";
2754
+ import { resolve as resolve16, join as join18, basename as basename6 } from "path";
2241
2755
  import { parse as parseJsonc2 } from "jsonc-parser";
2242
2756
  function importFromRulesync(projectRoot, outputPackDir) {
2243
- const rulesyncDir = resolve17(projectRoot, ".rulesync");
2757
+ const rulesyncDir = resolve16(projectRoot, ".rulesync");
2244
2758
  const warnings = [];
2245
2759
  const filesImported = [];
2246
2760
  if (!existsSync10(rulesyncDir)) {
@@ -2251,79 +2765,79 @@ function importFromRulesync(projectRoot, outputPackDir) {
2251
2765
  configGenerated: false
2252
2766
  };
2253
2767
  }
2254
- const packDir = outputPackDir ?? resolve17(projectRoot, "packs", "default");
2768
+ const packDir = outputPackDir ?? resolve16(projectRoot, "packs", "default");
2255
2769
  ensureDir(packDir);
2256
- const rulesDir = resolve17(rulesyncDir, "rules");
2770
+ const rulesDir = resolve16(rulesyncDir, "rules");
2257
2771
  if (existsSync10(rulesDir)) {
2258
- const outRulesDir = resolve17(packDir, "rules");
2772
+ const outRulesDir = resolve16(packDir, "rules");
2259
2773
  ensureDir(outRulesDir);
2260
2774
  const files = listFiles(rulesDir, { extension: ".md" });
2261
2775
  for (const file of files) {
2262
- const dest = join17(outRulesDir, basename6(file));
2776
+ const dest = join18(outRulesDir, basename6(file));
2263
2777
  copyFileSync(file, dest);
2264
2778
  filesImported.push(dest);
2265
2779
  }
2266
2780
  }
2267
- const commandsDir = resolve17(rulesyncDir, "commands");
2781
+ const commandsDir = resolve16(rulesyncDir, "commands");
2268
2782
  if (existsSync10(commandsDir)) {
2269
- const outCommandsDir = resolve17(packDir, "commands");
2783
+ const outCommandsDir = resolve16(packDir, "commands");
2270
2784
  ensureDir(outCommandsDir);
2271
2785
  const files = listFiles(commandsDir, { extension: ".md" });
2272
2786
  for (const file of files) {
2273
- const dest = join17(outCommandsDir, basename6(file));
2787
+ const dest = join18(outCommandsDir, basename6(file));
2274
2788
  copyFileSync(file, dest);
2275
2789
  filesImported.push(dest);
2276
2790
  }
2277
2791
  }
2278
- const subagentsDir = resolve17(rulesyncDir, "subagents");
2792
+ const subagentsDir = resolve16(rulesyncDir, "subagents");
2279
2793
  if (existsSync10(subagentsDir)) {
2280
- const outAgentsDir = resolve17(packDir, "agents");
2794
+ const outAgentsDir = resolve16(packDir, "agents");
2281
2795
  ensureDir(outAgentsDir);
2282
2796
  const files = listFiles(subagentsDir, { extension: ".md" });
2283
2797
  for (const file of files) {
2284
- const dest = join17(outAgentsDir, basename6(file));
2798
+ const dest = join18(outAgentsDir, basename6(file));
2285
2799
  copyFileSync(file, dest);
2286
2800
  filesImported.push(dest);
2287
2801
  }
2288
2802
  }
2289
- const skillsDir = resolve17(rulesyncDir, "skills");
2803
+ const skillsDir = resolve16(rulesyncDir, "skills");
2290
2804
  if (existsSync10(skillsDir)) {
2291
- const outSkillsDir = resolve17(packDir, "skills");
2805
+ const outSkillsDir = resolve16(packDir, "skills");
2292
2806
  ensureDir(outSkillsDir);
2293
2807
  const skillDirs = listDirs(skillsDir);
2294
2808
  for (const skillDir of skillDirs) {
2295
2809
  const skillName = basename6(skillDir);
2296
2810
  if (skillName.startsWith("."))
2297
2811
  continue;
2298
- const skillMd = join17(skillDir, "SKILL.md");
2812
+ const skillMd = join18(skillDir, "SKILL.md");
2299
2813
  if (existsSync10(skillMd)) {
2300
- const outSkillDir = join17(outSkillsDir, skillName);
2814
+ const outSkillDir = join18(outSkillsDir, skillName);
2301
2815
  ensureDir(outSkillDir);
2302
- copyFileSync(skillMd, join17(outSkillDir, "SKILL.md"));
2303
- filesImported.push(join17(outSkillDir, "SKILL.md"));
2816
+ copyFileSync(skillMd, join18(outSkillDir, "SKILL.md"));
2817
+ filesImported.push(join18(outSkillDir, "SKILL.md"));
2304
2818
  }
2305
2819
  }
2306
2820
  }
2307
- const hooksJson = resolve17(rulesyncDir, "hooks.json");
2821
+ const hooksJson = resolve16(rulesyncDir, "hooks.json");
2308
2822
  if (existsSync10(hooksJson)) {
2309
- const outHooksDir = resolve17(packDir, "hooks");
2823
+ const outHooksDir = resolve16(packDir, "hooks");
2310
2824
  ensureDir(outHooksDir);
2311
- copyFileSync(hooksJson, join17(outHooksDir, "hooks.json"));
2312
- filesImported.push(join17(outHooksDir, "hooks.json"));
2825
+ copyFileSync(hooksJson, join18(outHooksDir, "hooks.json"));
2826
+ filesImported.push(join18(outHooksDir, "hooks.json"));
2313
2827
  }
2314
- const mcpJson = resolve17(rulesyncDir, "mcp.json");
2828
+ const mcpJson = resolve16(rulesyncDir, "mcp.json");
2315
2829
  if (existsSync10(mcpJson)) {
2316
- copyFileSync(mcpJson, join17(packDir, "mcp.json"));
2317
- filesImported.push(join17(packDir, "mcp.json"));
2830
+ copyFileSync(mcpJson, join18(packDir, "mcp.json"));
2831
+ filesImported.push(join18(packDir, "mcp.json"));
2318
2832
  }
2319
- const aiIgnore = resolve17(rulesyncDir, ".aiignore");
2320
- const rulesyncIgnore = resolve17(projectRoot, ".rulesyncignore");
2833
+ const aiIgnore = resolve16(rulesyncDir, ".aiignore");
2834
+ const rulesyncIgnore = resolve16(projectRoot, ".rulesyncignore");
2321
2835
  if (existsSync10(aiIgnore)) {
2322
- copyFileSync(aiIgnore, join17(packDir, "ignore"));
2323
- filesImported.push(join17(packDir, "ignore"));
2836
+ copyFileSync(aiIgnore, join18(packDir, "ignore"));
2837
+ filesImported.push(join18(packDir, "ignore"));
2324
2838
  } else if (existsSync10(rulesyncIgnore)) {
2325
- copyFileSync(rulesyncIgnore, join17(packDir, "ignore"));
2326
- filesImported.push(join17(packDir, "ignore"));
2839
+ copyFileSync(rulesyncIgnore, join18(packDir, "ignore"));
2840
+ filesImported.push(join18(packDir, "ignore"));
2327
2841
  }
2328
2842
  const packJson = {
2329
2843
  name: "default",
@@ -2335,20 +2849,20 @@ function importFromRulesync(projectRoot, outputPackDir) {
2335
2849
  targets: "*",
2336
2850
  features: "*"
2337
2851
  };
2338
- writeFileSync6(join17(packDir, "pack.json"), JSON.stringify(packJson, null, 2) + `
2852
+ writeFileSync5(join18(packDir, "pack.json"), JSON.stringify(packJson, null, 2) + `
2339
2853
  `);
2340
- filesImported.push(join17(packDir, "pack.json"));
2854
+ filesImported.push(join18(packDir, "pack.json"));
2341
2855
  let configGenerated = false;
2342
- const rulesyncConfig = resolve17(projectRoot, "rulesync.jsonc");
2856
+ const rulesyncConfig = resolve16(projectRoot, "rulesync.jsonc");
2343
2857
  if (existsSync10(rulesyncConfig)) {
2344
- const agentpacksConfig = convertRulesyncConfig(rulesyncConfig, packDir, projectRoot);
2345
- const configPath = resolve17(projectRoot, "agentpacks.jsonc");
2346
- writeFileSync6(configPath, agentpacksConfig);
2858
+ const agentpacksConfig = convertRulesyncConfig(rulesyncConfig, packDir);
2859
+ const configPath = resolve16(projectRoot, "agentpacks.jsonc");
2860
+ writeFileSync5(configPath, agentpacksConfig);
2347
2861
  configGenerated = true;
2348
2862
  }
2349
2863
  return { packDir, filesImported, warnings, configGenerated };
2350
2864
  }
2351
- function convertRulesyncConfig(rulesyncPath, packDir, projectRoot) {
2865
+ function convertRulesyncConfig(rulesyncPath, _packDir) {
2352
2866
  const raw = readFileSync10(rulesyncPath, "utf-8");
2353
2867
  const parsed = parseJsonc2(raw);
2354
2868
  const targets = parsed.targets ?? ["opencode", "cursor", "claudecode"];
@@ -2356,7 +2870,7 @@ function convertRulesyncConfig(rulesyncPath, packDir, projectRoot) {
2356
2870
  const baseDirs = parsed.baseDirs ?? ["."];
2357
2871
  const global = parsed.global ?? false;
2358
2872
  const deleteVal = parsed.delete ?? true;
2359
- const relPackDir = "./" + join17("packs", "default");
2873
+ const relPackDir = "./" + join18("packs", "default");
2360
2874
  const config = {
2361
2875
  $schema: "https://unpkg.com/agentpacks/schema.json",
2362
2876
  packs: [relPackDir],
@@ -2373,10 +2887,10 @@ function convertRulesyncConfig(rulesyncPath, packDir, projectRoot) {
2373
2887
  }
2374
2888
 
2375
2889
  // src/importers/cursor.ts
2376
- import { existsSync as existsSync11, readFileSync as readFileSync11, writeFileSync as writeFileSync7, copyFileSync as copyFileSync2 } from "fs";
2377
- import { resolve as resolve18, join as join18, basename as basename7 } from "path";
2890
+ import { existsSync as existsSync11, readFileSync as readFileSync11, writeFileSync as writeFileSync6, copyFileSync as copyFileSync2 } from "fs";
2891
+ import { resolve as resolve17, join as join19, basename as basename7 } from "path";
2378
2892
  function importFromCursor(projectRoot, outputPackDir) {
2379
- const cursorDir = resolve18(projectRoot, ".cursor");
2893
+ const cursorDir = resolve17(projectRoot, ".cursor");
2380
2894
  const warnings = [];
2381
2895
  const filesImported = [];
2382
2896
  if (!existsSync11(cursorDir)) {
@@ -2387,11 +2901,11 @@ function importFromCursor(projectRoot, outputPackDir) {
2387
2901
  configGenerated: false
2388
2902
  };
2389
2903
  }
2390
- const packDir = outputPackDir ?? resolve18(projectRoot, "packs", "cursor-import");
2904
+ const packDir = outputPackDir ?? resolve17(projectRoot, "packs", "cursor-import");
2391
2905
  ensureDir(packDir);
2392
- const rulesDir = resolve18(cursorDir, "rules");
2906
+ const rulesDir = resolve17(cursorDir, "rules");
2393
2907
  if (existsSync11(rulesDir)) {
2394
- const outRulesDir = resolve18(packDir, "rules");
2908
+ const outRulesDir = resolve17(packDir, "rules");
2395
2909
  ensureDir(outRulesDir);
2396
2910
  const files = listFiles(rulesDir, { extension: ".mdc" });
2397
2911
  for (const file of files) {
@@ -2407,64 +2921,64 @@ function importFromCursor(projectRoot, outputPackDir) {
2407
2921
  meta.cursor = { ...data };
2408
2922
  const mdContent = buildAgentpacksRule(meta, content);
2409
2923
  const name = basename7(file, ".mdc");
2410
- const dest = join18(outRulesDir, `${name}.md`);
2411
- writeFileSync7(dest, mdContent);
2924
+ const dest = join19(outRulesDir, `${name}.md`);
2925
+ writeFileSync6(dest, mdContent);
2412
2926
  filesImported.push(dest);
2413
2927
  }
2414
2928
  const mdFiles = listFiles(rulesDir, { extension: ".md" });
2415
2929
  for (const file of mdFiles) {
2416
- const dest = join18(outRulesDir, basename7(file));
2930
+ const dest = join19(outRulesDir, basename7(file));
2417
2931
  copyFileSync2(file, dest);
2418
2932
  filesImported.push(dest);
2419
2933
  }
2420
2934
  }
2421
- const agentsDir = resolve18(cursorDir, "agents");
2935
+ const agentsDir = resolve17(cursorDir, "agents");
2422
2936
  if (existsSync11(agentsDir)) {
2423
- const outDir = resolve18(packDir, "agents");
2937
+ const outDir = resolve17(packDir, "agents");
2424
2938
  ensureDir(outDir);
2425
2939
  const files = listFiles(agentsDir, { extension: ".md" });
2426
2940
  for (const file of files) {
2427
- const dest = join18(outDir, basename7(file));
2941
+ const dest = join19(outDir, basename7(file));
2428
2942
  copyFileSync2(file, dest);
2429
2943
  filesImported.push(dest);
2430
2944
  }
2431
2945
  }
2432
- const skillsDir = resolve18(cursorDir, "skills");
2946
+ const skillsDir = resolve17(cursorDir, "skills");
2433
2947
  if (existsSync11(skillsDir)) {
2434
- const outDir = resolve18(packDir, "skills");
2948
+ const outDir = resolve17(packDir, "skills");
2435
2949
  ensureDir(outDir);
2436
2950
  const dirs = listDirs(skillsDir);
2437
2951
  for (const dir of dirs) {
2438
2952
  const name = basename7(dir);
2439
- const skillMd = join18(dir, "SKILL.md");
2953
+ const skillMd = join19(dir, "SKILL.md");
2440
2954
  if (existsSync11(skillMd)) {
2441
- const outSkillDir = join18(outDir, name);
2955
+ const outSkillDir = join19(outDir, name);
2442
2956
  ensureDir(outSkillDir);
2443
- copyFileSync2(skillMd, join18(outSkillDir, "SKILL.md"));
2444
- filesImported.push(join18(outSkillDir, "SKILL.md"));
2957
+ copyFileSync2(skillMd, join19(outSkillDir, "SKILL.md"));
2958
+ filesImported.push(join19(outSkillDir, "SKILL.md"));
2445
2959
  }
2446
2960
  }
2447
2961
  }
2448
- const commandsDir = resolve18(cursorDir, "commands");
2962
+ const commandsDir = resolve17(cursorDir, "commands");
2449
2963
  if (existsSync11(commandsDir)) {
2450
- const outDir = resolve18(packDir, "commands");
2964
+ const outDir = resolve17(packDir, "commands");
2451
2965
  ensureDir(outDir);
2452
2966
  const files = listFiles(commandsDir, { extension: ".md" });
2453
2967
  for (const file of files) {
2454
- const dest = join18(outDir, basename7(file));
2968
+ const dest = join19(outDir, basename7(file));
2455
2969
  copyFileSync2(file, dest);
2456
2970
  filesImported.push(dest);
2457
2971
  }
2458
2972
  }
2459
- const mcpJson = resolve18(cursorDir, "mcp.json");
2973
+ const mcpJson = resolve17(cursorDir, "mcp.json");
2460
2974
  if (existsSync11(mcpJson)) {
2461
- copyFileSync2(mcpJson, join18(packDir, "mcp.json"));
2462
- filesImported.push(join18(packDir, "mcp.json"));
2975
+ copyFileSync2(mcpJson, join19(packDir, "mcp.json"));
2976
+ filesImported.push(join19(packDir, "mcp.json"));
2463
2977
  }
2464
- const cursorIgnore = resolve18(projectRoot, ".cursorignore");
2978
+ const cursorIgnore = resolve17(projectRoot, ".cursorignore");
2465
2979
  if (existsSync11(cursorIgnore)) {
2466
- copyFileSync2(cursorIgnore, join18(packDir, "ignore"));
2467
- filesImported.push(join18(packDir, "ignore"));
2980
+ copyFileSync2(cursorIgnore, join19(packDir, "ignore"));
2981
+ filesImported.push(join19(packDir, "ignore"));
2468
2982
  }
2469
2983
  writePackJson(packDir, "cursor-import", filesImported);
2470
2984
  return { packDir, filesImported, warnings, configGenerated: false };
@@ -2493,20 +3007,20 @@ function writePackJson(packDir, name, filesImported) {
2493
3007
  targets: "*",
2494
3008
  features: "*"
2495
3009
  };
2496
- const dest = join18(packDir, "pack.json");
2497
- writeFileSync7(dest, JSON.stringify(packJson, null, 2) + `
3010
+ const dest = join19(packDir, "pack.json");
3011
+ writeFileSync6(dest, JSON.stringify(packJson, null, 2) + `
2498
3012
  `);
2499
3013
  filesImported.push(dest);
2500
3014
  }
2501
3015
 
2502
3016
  // src/importers/claude-code.ts
2503
- import { existsSync as existsSync12, readFileSync as readFileSync12, writeFileSync as writeFileSync8, copyFileSync as copyFileSync3 } from "fs";
2504
- import { resolve as resolve19, join as join19, basename as basename8 } from "path";
3017
+ import { existsSync as existsSync12, readFileSync as readFileSync12, writeFileSync as writeFileSync7, copyFileSync as copyFileSync3 } from "fs";
3018
+ import { resolve as resolve18, join as join20, basename as basename8 } from "path";
2505
3019
  function importFromClaudeCode(projectRoot, outputPackDir) {
2506
3020
  const warnings = [];
2507
3021
  const filesImported = [];
2508
- const claudeDir = resolve19(projectRoot, ".claude");
2509
- const hasClaudeMd = existsSync12(resolve19(projectRoot, "CLAUDE.md"));
3022
+ const claudeDir = resolve18(projectRoot, ".claude");
3023
+ const hasClaudeMd = existsSync12(resolve18(projectRoot, "CLAUDE.md"));
2510
3024
  const hasClaudeDir = existsSync12(claudeDir);
2511
3025
  if (!hasClaudeMd && !hasClaudeDir) {
2512
3026
  return {
@@ -2516,12 +3030,12 @@ function importFromClaudeCode(projectRoot, outputPackDir) {
2516
3030
  configGenerated: false
2517
3031
  };
2518
3032
  }
2519
- const packDir = outputPackDir ?? resolve19(projectRoot, "packs", "claude-import");
3033
+ const packDir = outputPackDir ?? resolve18(projectRoot, "packs", "claude-import");
2520
3034
  ensureDir(packDir);
2521
- const rulesDir = resolve19(packDir, "rules");
3035
+ const rulesDir = resolve18(packDir, "rules");
2522
3036
  ensureDir(rulesDir);
2523
3037
  if (hasClaudeMd) {
2524
- const raw = readFileSync12(resolve19(projectRoot, "CLAUDE.md"), "utf-8");
3038
+ const raw = readFileSync12(resolve18(projectRoot, "CLAUDE.md"), "utf-8");
2525
3039
  const ruleContent = [
2526
3040
  "---",
2527
3041
  "root: true",
@@ -2531,21 +3045,21 @@ function importFromClaudeCode(projectRoot, outputPackDir) {
2531
3045
  raw
2532
3046
  ].join(`
2533
3047
  `);
2534
- const dest = join19(rulesDir, "claude-root.md");
2535
- writeFileSync8(dest, ruleContent);
3048
+ const dest = join20(rulesDir, "claude-root.md");
3049
+ writeFileSync7(dest, ruleContent);
2536
3050
  filesImported.push(dest);
2537
3051
  }
2538
3052
  if (hasClaudeDir) {
2539
- const claudeRulesDir = resolve19(claudeDir, "rules");
3053
+ const claudeRulesDir = resolve18(claudeDir, "rules");
2540
3054
  if (existsSync12(claudeRulesDir)) {
2541
3055
  const files = listFiles(claudeRulesDir, { extension: ".md" });
2542
3056
  for (const file of files) {
2543
- const dest = join19(rulesDir, basename8(file));
3057
+ const dest = join20(rulesDir, basename8(file));
2544
3058
  copyFileSync3(file, dest);
2545
3059
  filesImported.push(dest);
2546
3060
  }
2547
3061
  }
2548
- const settingsPath = resolve19(claudeDir, "settings.json");
3062
+ const settingsPath = resolve18(claudeDir, "settings.json");
2549
3063
  if (existsSync12(settingsPath)) {
2550
3064
  try {
2551
3065
  const raw = readFileSync12(settingsPath, "utf-8");
@@ -2553,8 +3067,8 @@ function importFromClaudeCode(projectRoot, outputPackDir) {
2553
3067
  const mcpServers = settings.mcpServers ?? settings.mcp_servers;
2554
3068
  if (mcpServers && typeof mcpServers === "object") {
2555
3069
  const mcpConfig = { servers: mcpServers };
2556
- const dest = join19(packDir, "mcp.json");
2557
- writeFileSync8(dest, JSON.stringify(mcpConfig, null, 2) + `
3070
+ const dest = join20(packDir, "mcp.json");
3071
+ writeFileSync7(dest, JSON.stringify(mcpConfig, null, 2) + `
2558
3072
  `);
2559
3073
  filesImported.push(dest);
2560
3074
  }
@@ -2573,20 +3087,20 @@ function importFromClaudeCode(projectRoot, outputPackDir) {
2573
3087
  targets: "*",
2574
3088
  features: "*"
2575
3089
  };
2576
- const packJsonPath = join19(packDir, "pack.json");
2577
- writeFileSync8(packJsonPath, JSON.stringify(packJson, null, 2) + `
3090
+ const packJsonPath = join20(packDir, "pack.json");
3091
+ writeFileSync7(packJsonPath, JSON.stringify(packJson, null, 2) + `
2578
3092
  `);
2579
3093
  filesImported.push(packJsonPath);
2580
3094
  return { packDir, filesImported, warnings, configGenerated: false };
2581
3095
  }
2582
3096
 
2583
3097
  // src/importers/opencode.ts
2584
- import { existsSync as existsSync13, readFileSync as readFileSync13, writeFileSync as writeFileSync9, copyFileSync as copyFileSync4 } from "fs";
2585
- import { resolve as resolve20, join as join20, basename as basename9 } from "path";
3098
+ import { existsSync as existsSync13, readFileSync as readFileSync13, writeFileSync as writeFileSync8, copyFileSync as copyFileSync4 } from "fs";
3099
+ import { resolve as resolve19, join as join21, basename as basename9 } from "path";
2586
3100
  function importFromOpenCode(projectRoot, outputPackDir) {
2587
3101
  const warnings = [];
2588
3102
  const filesImported = [];
2589
- const ocDir = resolve20(projectRoot, ".opencode");
3103
+ const ocDir = resolve19(projectRoot, ".opencode");
2590
3104
  if (!existsSync13(ocDir)) {
2591
3105
  return {
2592
3106
  packDir: "",
@@ -2595,45 +3109,45 @@ function importFromOpenCode(projectRoot, outputPackDir) {
2595
3109
  configGenerated: false
2596
3110
  };
2597
3111
  }
2598
- const packDir = outputPackDir ?? resolve20(projectRoot, "packs", "opencode-import");
3112
+ const packDir = outputPackDir ?? resolve19(projectRoot, "packs", "opencode-import");
2599
3113
  ensureDir(packDir);
2600
- importDirMd(resolve20(ocDir, "rules"), resolve20(packDir, "rules"), filesImported);
2601
- importDirMd(resolve20(ocDir, "commands"), resolve20(packDir, "commands"), filesImported);
2602
- importDirMd(resolve20(ocDir, "agents"), resolve20(packDir, "agents"), filesImported);
2603
- const skillDir = resolve20(ocDir, "skill");
3114
+ importDirMd(resolve19(ocDir, "rules"), resolve19(packDir, "rules"), filesImported);
3115
+ importDirMd(resolve19(ocDir, "commands"), resolve19(packDir, "commands"), filesImported);
3116
+ importDirMd(resolve19(ocDir, "agents"), resolve19(packDir, "agents"), filesImported);
3117
+ const skillDir = resolve19(ocDir, "skill");
2604
3118
  if (existsSync13(skillDir)) {
2605
- const outSkillDir = resolve20(packDir, "skills");
3119
+ const outSkillDir = resolve19(packDir, "skills");
2606
3120
  ensureDir(outSkillDir);
2607
3121
  const dirs = listDirs(skillDir);
2608
3122
  for (const dir of dirs) {
2609
3123
  const name = basename9(dir);
2610
3124
  if (name.startsWith("."))
2611
3125
  continue;
2612
- const skillMd = join20(dir, "SKILL.md");
3126
+ const skillMd = join21(dir, "SKILL.md");
2613
3127
  if (existsSync13(skillMd)) {
2614
- const outDir = join20(outSkillDir, name);
3128
+ const outDir = join21(outSkillDir, name);
2615
3129
  ensureDir(outDir);
2616
- copyFileSync4(skillMd, join20(outDir, "SKILL.md"));
2617
- filesImported.push(join20(outDir, "SKILL.md"));
3130
+ copyFileSync4(skillMd, join21(outDir, "SKILL.md"));
3131
+ filesImported.push(join21(outDir, "SKILL.md"));
2618
3132
  }
2619
3133
  }
2620
3134
  }
2621
- const pluginsDir = resolve20(ocDir, "plugins");
3135
+ const pluginsDir = resolve19(ocDir, "plugins");
2622
3136
  if (existsSync13(pluginsDir)) {
2623
- const outPluginsDir = resolve20(packDir, "plugins");
3137
+ const outPluginsDir = resolve19(packDir, "plugins");
2624
3138
  ensureDir(outPluginsDir);
2625
3139
  const files = listFiles(pluginsDir);
2626
3140
  for (const file of files) {
2627
3141
  if (file.endsWith(".ts") || file.endsWith(".js")) {
2628
- const dest2 = join20(outPluginsDir, basename9(file));
3142
+ const dest2 = join21(outPluginsDir, basename9(file));
2629
3143
  copyFileSync4(file, dest2);
2630
3144
  filesImported.push(dest2);
2631
3145
  }
2632
3146
  }
2633
3147
  }
2634
- const agentsMd = resolve20(projectRoot, "AGENTS.md");
3148
+ const agentsMd = resolve19(projectRoot, "AGENTS.md");
2635
3149
  if (existsSync13(agentsMd)) {
2636
- const outRulesDir = resolve20(packDir, "rules");
3150
+ const outRulesDir = resolve19(packDir, "rules");
2637
3151
  ensureDir(outRulesDir);
2638
3152
  const raw = readFileSync13(agentsMd, "utf-8");
2639
3153
  const ruleContent = [
@@ -2645,19 +3159,19 @@ function importFromOpenCode(projectRoot, outputPackDir) {
2645
3159
  raw
2646
3160
  ].join(`
2647
3161
  `);
2648
- const dest2 = join20(outRulesDir, "agents-md-root.md");
2649
- writeFileSync9(dest2, ruleContent);
3162
+ const dest2 = join21(outRulesDir, "agents-md-root.md");
3163
+ writeFileSync8(dest2, ruleContent);
2650
3164
  filesImported.push(dest2);
2651
3165
  }
2652
- const ocJson = resolve20(projectRoot, "opencode.json");
3166
+ const ocJson = resolve19(projectRoot, "opencode.json");
2653
3167
  if (existsSync13(ocJson)) {
2654
3168
  try {
2655
3169
  const raw = readFileSync13(ocJson, "utf-8");
2656
3170
  const config = JSON.parse(raw);
2657
3171
  const mcpObj = config.mcp;
2658
3172
  if (mcpObj) {
2659
- const dest2 = join20(packDir, "mcp.json");
2660
- writeFileSync9(dest2, JSON.stringify({ servers: mcpObj }, null, 2) + `
3173
+ const dest2 = join21(packDir, "mcp.json");
3174
+ writeFileSync8(dest2, JSON.stringify({ servers: mcpObj }, null, 2) + `
2661
3175
  `);
2662
3176
  filesImported.push(dest2);
2663
3177
  }
@@ -2665,10 +3179,10 @@ function importFromOpenCode(projectRoot, outputPackDir) {
2665
3179
  warnings.push("Failed to parse opencode.json");
2666
3180
  }
2667
3181
  }
2668
- const ocIgnore = resolve20(projectRoot, ".opencodeignore");
3182
+ const ocIgnore = resolve19(projectRoot, ".opencodeignore");
2669
3183
  if (existsSync13(ocIgnore)) {
2670
- copyFileSync4(ocIgnore, join20(packDir, "ignore"));
2671
- filesImported.push(join20(packDir, "ignore"));
3184
+ copyFileSync4(ocIgnore, join21(packDir, "ignore"));
3185
+ filesImported.push(join21(packDir, "ignore"));
2672
3186
  }
2673
3187
  const packJson = {
2674
3188
  name: "opencode-import",
@@ -2680,8 +3194,8 @@ function importFromOpenCode(projectRoot, outputPackDir) {
2680
3194
  targets: "*",
2681
3195
  features: "*"
2682
3196
  };
2683
- const dest = join20(packDir, "pack.json");
2684
- writeFileSync9(dest, JSON.stringify(packJson, null, 2) + `
3197
+ const dest = join21(packDir, "pack.json");
3198
+ writeFileSync8(dest, JSON.stringify(packJson, null, 2) + `
2685
3199
  `);
2686
3200
  filesImported.push(dest);
2687
3201
  return { packDir, filesImported, warnings, configGenerated: false };
@@ -2692,15 +3206,14 @@ function importDirMd(srcDir, outDir, filesImported) {
2692
3206
  ensureDir(outDir);
2693
3207
  const files = listFiles(srcDir, { extension: ".md" });
2694
3208
  for (const file of files) {
2695
- const dest = join20(outDir, basename9(file));
3209
+ const dest = join21(outDir, basename9(file));
2696
3210
  copyFileSync4(file, dest);
2697
3211
  filesImported.push(dest);
2698
3212
  }
2699
3213
  }
2700
3214
 
2701
3215
  // src/cli/export-cmd.ts
2702
- init_config();
2703
- import { resolve as resolve21 } from "path";
3216
+ import { resolve as resolve20 } from "path";
2704
3217
  import chalk from "chalk";
2705
3218
  function runExport(projectRoot, options) {
2706
3219
  const config = loadWorkspaceConfig(projectRoot);
@@ -2719,7 +3232,7 @@ function runExport(projectRoot, options) {
2719
3232
  console.log(chalk.red(`Pack "${options.pack}" not found.`));
2720
3233
  return;
2721
3234
  }
2722
- const outputDir = resolve21(projectRoot, options.output ?? "dist/cursor-plugins");
3235
+ const outputDir = resolve20(projectRoot, options.output ?? "dist/cursor-plugins");
2723
3236
  switch (options.format) {
2724
3237
  case "cursor-plugin": {
2725
3238
  let totalFiles = 0;
@@ -2796,14 +3309,29 @@ function findHunks(oldLines, newLines) {
2796
3309
  let ni = 0;
2797
3310
  while (oi < oldLines.length || ni < newLines.length) {
2798
3311
  if (oi < oldLines.length && ni < newLines.length && oldLines[oi] === newLines[ni]) {
2799
- changes.push({ type: " ", line: oldLines[oi], oldIdx: oi, newIdx: ni });
3312
+ changes.push({
3313
+ type: " ",
3314
+ line: oldLines[oi] ?? "",
3315
+ oldIdx: oi,
3316
+ newIdx: ni
3317
+ });
2800
3318
  oi++;
2801
3319
  ni++;
2802
- } else if (ni < newLines.length && (oi >= oldLines.length || !newLines.slice(ni).includes(oldLines[oi]))) {
2803
- changes.push({ type: "+", line: newLines[ni], oldIdx: oi, newIdx: ni });
3320
+ } else if (ni < newLines.length && (oi >= oldLines.length || !newLines.slice(ni).includes(oldLines[oi] ?? ""))) {
3321
+ changes.push({
3322
+ type: "+",
3323
+ line: newLines[ni] ?? "",
3324
+ oldIdx: oi,
3325
+ newIdx: ni
3326
+ });
2804
3327
  ni++;
2805
3328
  } else {
2806
- changes.push({ type: "-", line: oldLines[oi], oldIdx: oi, newIdx: oi });
3329
+ changes.push({
3330
+ type: "-",
3331
+ line: oldLines[oi] ?? "",
3332
+ oldIdx: oi,
3333
+ newIdx: oi
3334
+ });
2807
3335
  oi++;
2808
3336
  }
2809
3337
  }
@@ -2832,8 +3360,9 @@ function findHunks(oldLines, newLines) {
2832
3360
  lines: []
2833
3361
  };
2834
3362
  for (let i = contextStart;i < changes.indexOf(change); i++) {
2835
- if (changes[i].type === " ") {
2836
- currentHunk.lines.push(` ${changes[i].line}`);
3363
+ const entry = changes[i];
3364
+ if (entry?.type === " ") {
3365
+ currentHunk.lines.push(` ${entry.line}`);
2837
3366
  currentHunk.oldCount++;
2838
3367
  currentHunk.newCount++;
2839
3368
  }
@@ -2853,7 +3382,6 @@ function findHunks(oldLines, newLines) {
2853
3382
  }
2854
3383
 
2855
3384
  // src/cli/generate.ts
2856
- init_config();
2857
3385
  import { existsSync as existsSync15, readFileSync as readFileSync15 } from "fs";
2858
3386
  import chalk2 from "chalk";
2859
3387
  function runGenerate(projectRoot, options) {
@@ -2924,9 +3452,9 @@ function runGenerate(projectRoot, options) {
2924
3452
  enabledFeatures,
2925
3453
  deleteExisting: options.diff ? false : config.delete,
2926
3454
  global: config.global,
2927
- verbose: config.verbose
3455
+ verbose: config.verbose,
3456
+ modelProfile: config.modelProfile
2928
3457
  };
2929
- const preSnapshot = new Map;
2930
3458
  try {
2931
3459
  const result = target.generate(generateOptions);
2932
3460
  allResults.push(result);
@@ -3055,19 +3583,246 @@ Next steps:`), `
3055
3583
  2. Run`, chalk3.bold("agentpacks generate"), "to generate tool configs");
3056
3584
  }
3057
3585
 
3058
- // src/cli/init.ts
3059
- import { existsSync as existsSync16, copyFileSync as copyFileSync5, writeFileSync as writeFileSync10 } from "fs";
3060
- import { resolve as resolve22, join as join21 } from "path";
3586
+ // src/utils/registry-client.ts
3587
+ var DEFAULT_REGISTRY_URL = "https://registry.agentpacks.dev";
3588
+ function createRegistryClient(config) {
3589
+ return new RegistryClient({
3590
+ registryUrl: config?.registryUrl ?? DEFAULT_REGISTRY_URL,
3591
+ authToken: config?.authToken,
3592
+ timeout: config?.timeout ?? 30000
3593
+ });
3594
+ }
3595
+
3596
+ class RegistryClient {
3597
+ config;
3598
+ constructor(config) {
3599
+ this.config = {
3600
+ registryUrl: config.registryUrl.replace(/\/+$/, ""),
3601
+ authToken: config.authToken,
3602
+ timeout: config.timeout ?? 30000
3603
+ };
3604
+ }
3605
+ async search(params) {
3606
+ const searchParams = new URLSearchParams;
3607
+ if (params.query)
3608
+ searchParams.set("q", params.query);
3609
+ if (params.tags?.length)
3610
+ searchParams.set("tags", params.tags.join(","));
3611
+ if (params.targets?.length)
3612
+ searchParams.set("targets", params.targets.join(","));
3613
+ if (params.features?.length)
3614
+ searchParams.set("features", params.features.join(","));
3615
+ if (params.author)
3616
+ searchParams.set("author", params.author);
3617
+ if (params.sort)
3618
+ searchParams.set("sort", params.sort);
3619
+ if (params.limit)
3620
+ searchParams.set("limit", String(params.limit));
3621
+ if (params.offset)
3622
+ searchParams.set("offset", String(params.offset));
3623
+ const url = `${this.config.registryUrl}/packs?${searchParams.toString()}`;
3624
+ const res = await this.fetch(url);
3625
+ return res;
3626
+ }
3627
+ async info(packName) {
3628
+ const url = `${this.config.registryUrl}/packs/${encodeURIComponent(packName)}`;
3629
+ const res = await this.fetch(url);
3630
+ return res;
3631
+ }
3632
+ async download(packName, version = "latest") {
3633
+ const url = `${this.config.registryUrl}/packs/${encodeURIComponent(packName)}/versions/${encodeURIComponent(version)}/download`;
3634
+ const response = await fetch(url, {
3635
+ headers: this.headers(),
3636
+ signal: AbortSignal.timeout(this.config.timeout)
3637
+ });
3638
+ if (!response.ok) {
3639
+ throw new RegistryApiError(response.status, `Failed to download ${packName}@${version}: ${response.statusText}`);
3640
+ }
3641
+ const integrity = response.headers.get("x-integrity") ?? "";
3642
+ const data = await response.arrayBuffer();
3643
+ return { data, integrity };
3644
+ }
3645
+ async publish(tarball, metadata) {
3646
+ if (!this.config.authToken) {
3647
+ throw new Error("Authentication required. Run `agentpacks login` first.");
3648
+ }
3649
+ const formData = new FormData;
3650
+ formData.append("tarball", new Blob([tarball], { type: "application/gzip" }), `${metadata.name}-${metadata.version}.tgz`);
3651
+ formData.append("metadata", JSON.stringify(metadata));
3652
+ const url = `${this.config.registryUrl}/packs`;
3653
+ const response = await fetch(url, {
3654
+ method: "POST",
3655
+ headers: {
3656
+ Authorization: `Bearer ${this.config.authToken}`
3657
+ },
3658
+ body: formData,
3659
+ signal: AbortSignal.timeout(this.config.timeout)
3660
+ });
3661
+ if (!response.ok) {
3662
+ const body = await response.text();
3663
+ throw new RegistryApiError(response.status, `Publish failed: ${body || response.statusText}`);
3664
+ }
3665
+ return await response.json();
3666
+ }
3667
+ async featured(limit) {
3668
+ const url = limit ? `${this.config.registryUrl}/featured?limit=${limit}` : `${this.config.registryUrl}/featured`;
3669
+ const res = await this.fetch(url);
3670
+ return res.packs;
3671
+ }
3672
+ async tags() {
3673
+ const url = `${this.config.registryUrl}/tags`;
3674
+ const res = await this.fetch(url);
3675
+ return res.tags;
3676
+ }
3677
+ async stats() {
3678
+ const url = `${this.config.registryUrl}/stats`;
3679
+ return await this.fetch(url);
3680
+ }
3681
+ async health() {
3682
+ try {
3683
+ const url = `${this.config.registryUrl}/health`;
3684
+ await this.fetch(url);
3685
+ return true;
3686
+ } catch {
3687
+ return false;
3688
+ }
3689
+ }
3690
+ async fetch(url) {
3691
+ const response = await fetch(url, {
3692
+ headers: this.headers(),
3693
+ signal: AbortSignal.timeout(this.config.timeout)
3694
+ });
3695
+ if (!response.ok) {
3696
+ const body = await response.text();
3697
+ throw new RegistryApiError(response.status, body || response.statusText);
3698
+ }
3699
+ return response.json();
3700
+ }
3701
+ headers() {
3702
+ const h = {
3703
+ Accept: "application/json"
3704
+ };
3705
+ if (this.config.authToken) {
3706
+ h["Authorization"] = `Bearer ${this.config.authToken}`;
3707
+ }
3708
+ return h;
3709
+ }
3710
+ }
3711
+
3712
+ class RegistryApiError extends Error {
3713
+ status;
3714
+ constructor(status, message) {
3715
+ super(message);
3716
+ this.name = "RegistryApiError";
3717
+ this.status = status;
3718
+ }
3719
+ }
3720
+
3721
+ // src/utils/credentials.ts
3722
+ import { existsSync as existsSync16, readFileSync as readFileSync16, writeFileSync as writeFileSync9, mkdirSync as mkdirSync5 } from "fs";
3723
+ import { join as join22, dirname as dirname2 } from "path";
3724
+ import { homedir } from "os";
3725
+ var CONFIG_DIR = join22(homedir(), ".config", "agentpacks");
3726
+ var CREDENTIALS_FILE = join22(CONFIG_DIR, "credentials.json");
3727
+ function loadCredentials() {
3728
+ if (!existsSync16(CREDENTIALS_FILE)) {
3729
+ return { registryUrl: "https://registry.agentpacks.dev" };
3730
+ }
3731
+ try {
3732
+ const raw = readFileSync16(CREDENTIALS_FILE, "utf-8");
3733
+ return JSON.parse(raw);
3734
+ } catch {
3735
+ return { registryUrl: "https://registry.agentpacks.dev" };
3736
+ }
3737
+ }
3738
+ function saveCredentials(credentials) {
3739
+ mkdirSync5(dirname2(CREDENTIALS_FILE), { recursive: true });
3740
+ writeFileSync9(CREDENTIALS_FILE, JSON.stringify(credentials, null, 2) + `
3741
+ `, {
3742
+ mode: 384
3743
+ });
3744
+ }
3745
+ function clearCredentials() {
3746
+ if (existsSync16(CREDENTIALS_FILE)) {
3747
+ writeFileSync9(CREDENTIALS_FILE, JSON.stringify({ registryUrl: "https://registry.agentpacks.dev" }) + `
3748
+ `);
3749
+ }
3750
+ }
3751
+
3752
+ // src/cli/info.ts
3061
3753
  import chalk4 from "chalk";
3754
+ async function runInfo(packName) {
3755
+ const credentials = loadCredentials();
3756
+ const client = createRegistryClient({
3757
+ registryUrl: credentials.registryUrl,
3758
+ authToken: credentials.token
3759
+ });
3760
+ try {
3761
+ const pack = await client.info(packName);
3762
+ console.log(chalk4.bold(`
3763
+ ${pack.displayName}`));
3764
+ console.log(chalk4.dim(` ${pack.name}`));
3765
+ console.log(` ${pack.description}`);
3766
+ console.log();
3767
+ console.log(` ${chalk4.dim("Author:")} ${pack.author}`);
3768
+ console.log(` ${chalk4.dim("License:")} ${pack.license}`);
3769
+ console.log(` ${chalk4.dim("Downloads:")} ${pack.downloads}`);
3770
+ if (pack.homepage) {
3771
+ console.log(` ${chalk4.dim("Homepage:")} ${pack.homepage}`);
3772
+ }
3773
+ if (pack.repository) {
3774
+ console.log(` ${chalk4.dim("Repository:")} ${pack.repository}`);
3775
+ }
3776
+ console.log();
3777
+ if (pack.tags.length > 0) {
3778
+ console.log(` ${chalk4.dim("Tags:")} ${pack.tags.join(", ")}`);
3779
+ }
3780
+ if (pack.targets.length > 0) {
3781
+ console.log(` ${chalk4.dim("Targets:")} ${pack.targets.join(", ")}`);
3782
+ }
3783
+ if (pack.features.length > 0) {
3784
+ console.log(` ${chalk4.dim("Features:")} ${pack.features.join(", ")}`);
3785
+ }
3786
+ console.log();
3787
+ if (pack.versions.length > 0) {
3788
+ console.log(chalk4.bold(" Versions:"));
3789
+ for (const v of pack.versions.slice(0, 10)) {
3790
+ console.log(` ${v.version} — ${v.createdAt} (${v.fileCount} files, ${formatBytes(v.tarballSize)})`);
3791
+ }
3792
+ if (pack.versions.length > 10) {
3793
+ console.log(chalk4.dim(` ... and ${pack.versions.length - 10} more`));
3794
+ }
3795
+ }
3796
+ console.log();
3797
+ console.log(chalk4.bold(" Install:"));
3798
+ console.log(` registry:${pack.name}`);
3799
+ console.log();
3800
+ } catch (err) {
3801
+ console.log(chalk4.red(`Failed to get pack info: ${err instanceof Error ? err.message : String(err)}`));
3802
+ process.exit(1);
3803
+ }
3804
+ }
3805
+ function formatBytes(bytes) {
3806
+ if (bytes < 1024)
3807
+ return `${bytes} B`;
3808
+ if (bytes < 1024 * 1024)
3809
+ return `${(bytes / 1024).toFixed(1)} KB`;
3810
+ return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
3811
+ }
3812
+
3813
+ // src/cli/init.ts
3814
+ import { existsSync as existsSync17, copyFileSync as copyFileSync5, writeFileSync as writeFileSync10 } from "fs";
3815
+ import { resolve as resolve21, join as join23 } from "path";
3816
+ import chalk5 from "chalk";
3062
3817
  function runInit(projectRoot) {
3063
- const configPath = resolve22(projectRoot, "agentpacks.jsonc");
3064
- const packsDir = resolve22(projectRoot, "packs", "default");
3065
- if (existsSync16(configPath)) {
3066
- console.log(chalk4.yellow("agentpacks.jsonc already exists. Skipping config creation."));
3818
+ const configPath = resolve21(projectRoot, "agentpacks.jsonc");
3819
+ const packsDir = resolve21(projectRoot, "packs", "default");
3820
+ if (existsSync17(configPath)) {
3821
+ console.log(chalk5.yellow("agentpacks.jsonc already exists. Skipping config creation."));
3067
3822
  } else {
3068
- const templateDir = resolve22(import.meta.dirname, "..", "..", "templates");
3069
- const templateConfig = resolve22(templateDir, "workspace", "agentpacks.jsonc");
3070
- if (existsSync16(templateConfig)) {
3823
+ const templateDir = resolve21(import.meta.dirname, "..", "..", "templates");
3824
+ const templateConfig = resolve21(templateDir, "workspace", "agentpacks.jsonc");
3825
+ if (existsSync17(templateConfig)) {
3071
3826
  copyFileSync5(templateConfig, configPath);
3072
3827
  } else {
3073
3828
  const config = {
@@ -3091,16 +3846,16 @@ function runInit(projectRoot) {
3091
3846
  writeFileSync10(configPath, JSON.stringify(config, null, 2) + `
3092
3847
  `);
3093
3848
  }
3094
- console.log(chalk4.green("Created agentpacks.jsonc"));
3849
+ console.log(chalk5.green("Created agentpacks.jsonc"));
3095
3850
  }
3096
- if (existsSync16(packsDir)) {
3097
- console.log(chalk4.yellow("packs/default/ already exists. Skipping pack scaffold."));
3851
+ if (existsSync17(packsDir)) {
3852
+ console.log(chalk5.yellow("packs/default/ already exists. Skipping pack scaffold."));
3098
3853
  } else {
3099
3854
  ensureDir(packsDir);
3100
- ensureDir(join21(packsDir, "rules"));
3101
- ensureDir(join21(packsDir, "commands"));
3102
- ensureDir(join21(packsDir, "agents"));
3103
- ensureDir(join21(packsDir, "skills"));
3855
+ ensureDir(join23(packsDir, "rules"));
3856
+ ensureDir(join23(packsDir, "commands"));
3857
+ ensureDir(join23(packsDir, "agents"));
3858
+ ensureDir(join23(packsDir, "skills"));
3104
3859
  const packJson = {
3105
3860
  name: "default",
3106
3861
  version: "1.0.0",
@@ -3111,43 +3866,162 @@ function runInit(projectRoot) {
3111
3866
  targets: "*",
3112
3867
  features: "*"
3113
3868
  };
3114
- writeFileSync10(join21(packsDir, "pack.json"), JSON.stringify(packJson, null, 2) + `
3869
+ writeFileSync10(join23(packsDir, "pack.json"), JSON.stringify(packJson, null, 2) + `
3115
3870
  `);
3116
- const templateRule = resolve22(import.meta.dirname, "..", "..", "templates", "pack", "rules", "overview.md");
3117
- if (existsSync16(templateRule)) {
3118
- copyFileSync5(templateRule, join21(packsDir, "rules", "overview.md"));
3871
+ const templateRule = resolve21(import.meta.dirname, "..", "..", "templates", "pack", "rules", "overview.md");
3872
+ if (existsSync17(templateRule)) {
3873
+ copyFileSync5(templateRule, join23(packsDir, "rules", "overview.md"));
3119
3874
  }
3120
- console.log(chalk4.green("Created packs/default/ with scaffold"));
3875
+ console.log(chalk5.green("Created packs/default/ with scaffold"));
3121
3876
  }
3122
- console.log(chalk4.cyan(`
3877
+ console.log(chalk5.cyan(`
3123
3878
  Next steps:`), `
3124
3879
  1. Edit packs/default/rules/overview.md with your project guidelines`, `
3125
- 2. Run`, chalk4.bold("agentpacks generate"), "to generate tool configs", `
3126
- 3. Or run`, chalk4.bold("agentpacks import --from rulesync"), "to migrate from rulesync");
3880
+ 2. Run`, chalk5.bold("agentpacks generate"), "to generate tool configs", `
3881
+ 3. Or run`, chalk5.bold("agentpacks import --from rulesync"), "to migrate from rulesync");
3882
+ }
3883
+
3884
+ // src/utils/tarball.ts
3885
+ import { execSync as execSync2 } from "child_process";
3886
+ import { readFileSync as readFileSync17, existsSync as existsSync18, mkdirSync as mkdirSync6, rmSync as rmSync2 } from "fs";
3887
+ import { join as join24, resolve as resolve22 } from "path";
3888
+ import { createHash as createHash2 } from "crypto";
3889
+ import { tmpdir } from "os";
3890
+ async function createTarball(packDir) {
3891
+ const absDir = resolve22(packDir);
3892
+ const tmpFile = join24(tmpdir(), `agentpacks-${Date.now()}.tgz`);
3893
+ try {
3894
+ execSync2(`tar -czf "${tmpFile}" -C "${absDir}" .`, {
3895
+ stdio: "pipe"
3896
+ });
3897
+ const buffer = readFileSync17(tmpFile);
3898
+ return buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength);
3899
+ } finally {
3900
+ if (existsSync18(tmpFile)) {
3901
+ rmSync2(tmpFile);
3902
+ }
3903
+ }
3904
+ }
3905
+ async function extractTarball(data, targetDir) {
3906
+ mkdirSync6(targetDir, { recursive: true });
3907
+ const tmpFile = join24(tmpdir(), `agentpacks-${Date.now()}.tgz`);
3908
+ try {
3909
+ const buffer = Buffer.from(data);
3910
+ const { writeFileSync: writeFileSync11 } = await import("fs");
3911
+ writeFileSync11(tmpFile, buffer);
3912
+ execSync2(`tar -xzf "${tmpFile}" -C "${targetDir}"`, {
3913
+ stdio: "pipe"
3914
+ });
3915
+ } finally {
3916
+ if (existsSync18(tmpFile)) {
3917
+ rmSync2(tmpFile);
3918
+ }
3919
+ }
3920
+ }
3921
+ function computeTarballIntegrity(data) {
3922
+ const hash = createHash2("sha256").update(Buffer.from(data)).digest("hex");
3923
+ return `sha256-${hash}`;
3924
+ }
3925
+
3926
+ // src/sources/registry.ts
3927
+ import { existsSync as existsSync19, mkdirSync as mkdirSync7, readdirSync as readdirSync3, rmSync as rmSync3 } from "fs";
3928
+ import { resolve as resolve23, join as join25 } from "path";
3929
+ async function installRegistrySource(projectRoot, source, lockfile, options = {}) {
3930
+ const parsed = parseRegistrySourceRef(source);
3931
+ const sourceKey = registrySourceKey(parsed);
3932
+ const installed = [];
3933
+ const warnings = [];
3934
+ const locked = getLockedSource(lockfile, sourceKey);
3935
+ if (options.frozen && !locked) {
3936
+ throw new Error(`Frozen mode: no lockfile entry for source "${sourceKey}".`);
3937
+ }
3938
+ let targetVersion = parsed.version;
3939
+ if (locked && !options.update) {
3940
+ targetVersion = locked.resolvedRef;
3941
+ } else if (targetVersion === "latest") {
3942
+ const clientCfg2 = buildClientConfig(options.registryUrl);
3943
+ const client2 = createRegistryClient(clientCfg2);
3944
+ const info = await client2.info(parsed.packName);
3945
+ targetVersion = info.latestVersion;
3946
+ }
3947
+ const clientCfg = buildClientConfig(options.registryUrl);
3948
+ const client = createRegistryClient(clientCfg);
3949
+ const { data } = await client.download(parsed.packName, targetVersion);
3950
+ const localIntegrity = computeTarballIntegrity(data);
3951
+ if (locked && !options.update && locked.skills?.["__integrity"]) {
3952
+ const expectedIntegrity = locked.skills["__integrity"].integrity;
3953
+ if (expectedIntegrity && localIntegrity !== expectedIntegrity) {
3954
+ throw new Error(`Integrity mismatch for ${parsed.packName}@${targetVersion}. ` + `Expected ${expectedIntegrity}, got ${localIntegrity}.`);
3955
+ }
3956
+ }
3957
+ const curatedDir = resolve23(projectRoot, ".agentpacks", ".curated");
3958
+ const packOutDir = resolve23(curatedDir, parsed.packName);
3959
+ if (existsSync19(packOutDir)) {
3960
+ rmSync3(packOutDir, { recursive: true, force: true });
3961
+ }
3962
+ mkdirSync7(packOutDir, { recursive: true });
3963
+ await extractTarball(data, packOutDir);
3964
+ collectFiles2(packOutDir, installed);
3965
+ const newEntry = {
3966
+ requestedRef: parsed.version,
3967
+ resolvedRef: targetVersion,
3968
+ resolvedAt: new Date().toISOString(),
3969
+ skills: {
3970
+ __integrity: { integrity: localIntegrity }
3971
+ },
3972
+ packs: {
3973
+ [parsed.packName]: { integrity: localIntegrity }
3974
+ }
3975
+ };
3976
+ setLockedSource(lockfile, sourceKey, newEntry);
3977
+ return { installed, warnings };
3978
+ }
3979
+ function buildClientConfig(registryUrl) {
3980
+ const cfg = {};
3981
+ if (registryUrl) {
3982
+ cfg.registryUrl = registryUrl;
3983
+ }
3984
+ try {
3985
+ const creds = loadCredentials();
3986
+ if (creds?.token) {
3987
+ cfg.authToken = creds.token;
3988
+ }
3989
+ } catch {}
3990
+ return cfg;
3991
+ }
3992
+ function collectFiles2(dir, out) {
3993
+ const entries = readdirSync3(dir, { withFileTypes: true });
3994
+ for (const entry of entries) {
3995
+ const full = join25(dir, entry.name);
3996
+ if (entry.isDirectory()) {
3997
+ collectFiles2(full, out);
3998
+ } else {
3999
+ out.push(full);
4000
+ }
4001
+ }
3127
4002
  }
3128
4003
 
3129
4004
  // src/cli/install.ts
3130
- init_config();
3131
- import chalk5 from "chalk";
4005
+ import chalk6 from "chalk";
3132
4006
  async function runInstall(projectRoot, options) {
3133
4007
  const config = loadWorkspaceConfig(projectRoot);
3134
4008
  const lockfile = loadLockfile(projectRoot);
3135
4009
  const verbose = options.verbose ?? config.verbose;
3136
- const remotePacks = config.packs.filter((ref) => isGitPackRef(ref) || isNpmPackRef(ref));
4010
+ const remotePacks = config.packs.filter((ref) => isGitPackRef(ref) || isNpmPackRef(ref) || isRegistryPackRef(ref));
3137
4011
  const localPacks = config.packs.filter((ref) => isLocalPackRef(ref));
3138
4012
  if (remotePacks.length === 0) {
3139
- console.log(chalk5.dim("No remote packs to install. All packs are local."));
4013
+ console.log(chalk6.dim("No remote packs to install. All packs are local."));
3140
4014
  return;
3141
4015
  }
3142
4016
  if (verbose) {
3143
- console.log(chalk5.dim(`Found ${remotePacks.length} remote pack(s) to install`));
3144
- console.log(chalk5.dim(` (${localPacks.length} local pack(s) skipped)`));
4017
+ console.log(chalk6.dim(`Found ${remotePacks.length} remote pack(s) to install`));
4018
+ console.log(chalk6.dim(` (${localPacks.length} local pack(s) skipped)`));
3145
4019
  }
3146
4020
  if (options.frozen) {
3147
4021
  const sourceKeys = remotePacks.map((ref) => ref);
3148
4022
  const frozenCheck = isLockfileFrozenValid(lockfile, sourceKeys);
3149
4023
  if (!frozenCheck.valid) {
3150
- console.log(chalk5.red(`Frozen install failed. Missing lockfile entries: ${frozenCheck.missing.join(", ")}`));
4024
+ console.log(chalk6.red(`Frozen install failed. Missing lockfile entries: ${frozenCheck.missing.join(", ")}`));
3151
4025
  process.exit(1);
3152
4026
  }
3153
4027
  }
@@ -3155,11 +4029,16 @@ async function runInstall(projectRoot, options) {
3155
4029
  const allWarnings = [];
3156
4030
  for (const packRef of remotePacks) {
3157
4031
  if (verbose) {
3158
- console.log(chalk5.dim(` Installing ${packRef}...`));
4032
+ console.log(chalk6.dim(` Installing ${packRef}...`));
3159
4033
  }
3160
4034
  try {
3161
4035
  let result;
3162
- if (isGitPackRef(packRef)) {
4036
+ if (isRegistryPackRef(packRef)) {
4037
+ result = await installRegistrySource(projectRoot, packRef, lockfile, {
4038
+ update: options.update,
4039
+ frozen: options.frozen
4040
+ });
4041
+ } else if (isGitPackRef(packRef)) {
3163
4042
  const token = process.env.GITHUB_TOKEN ?? process.env.GH_TOKEN ?? undefined;
3164
4043
  result = await installGitSource(projectRoot, packRef, lockfile, {
3165
4044
  update: options.update,
@@ -3177,39 +4056,204 @@ async function runInstall(projectRoot, options) {
3177
4056
  totalInstalled += result.installed.length;
3178
4057
  allWarnings.push(...result.warnings);
3179
4058
  if (verbose && result.installed.length > 0) {
3180
- console.log(chalk5.dim(` ${result.installed.length} file(s) installed`));
4059
+ console.log(chalk6.dim(` ${result.installed.length} file(s) installed`));
3181
4060
  }
3182
4061
  } catch (err) {
3183
4062
  const msg = err instanceof Error ? err.message : String(err);
3184
- console.log(chalk5.red(` error [${packRef}]: ${msg}`));
4063
+ console.log(chalk6.red(` error [${packRef}]: ${msg}`));
3185
4064
  allWarnings.push(`Failed to install ${packRef}: ${msg}`);
3186
4065
  }
3187
4066
  }
3188
4067
  for (const w of allWarnings) {
3189
- console.log(chalk5.yellow(` warn: ${w}`));
4068
+ console.log(chalk6.yellow(` warn: ${w}`));
3190
4069
  }
3191
4070
  saveLockfile(projectRoot, lockfile);
3192
- console.log(chalk5.green(`Installed ${totalInstalled} file(s) from ${remotePacks.length} source(s)`));
4071
+ console.log(chalk6.green(`Installed ${totalInstalled} file(s) from ${remotePacks.length} source(s)`));
3193
4072
  if (verbose) {
3194
- console.log(chalk5.dim("Lockfile updated: agentpacks.lock"));
4073
+ console.log(chalk6.dim("Lockfile updated: agentpacks.lock"));
4074
+ }
4075
+ }
4076
+
4077
+ // src/cli/login.ts
4078
+ import chalk7 from "chalk";
4079
+ async function runLogin(options) {
4080
+ const registryUrl = options.registry ?? "https://registry.agentpacks.dev";
4081
+ if (!options.token) {
4082
+ console.log(chalk7.bold(`agentpacks login
4083
+ `));
4084
+ console.log("To authenticate, you need an API token.");
4085
+ console.log(`Get one at: ${chalk7.cyan(`${registryUrl}/account/tokens`)}
4086
+ `);
4087
+ console.log("Then run:");
4088
+ console.log(chalk7.dim(` agentpacks login --token <your-token>
4089
+ `));
4090
+ return;
4091
+ }
4092
+ const client = createRegistryClient({
4093
+ registryUrl,
4094
+ authToken: options.token
4095
+ });
4096
+ const healthy = await client.health();
4097
+ if (!healthy) {
4098
+ console.log(chalk7.yellow(`Warning: Could not reach registry at ${registryUrl}`));
3195
4099
  }
4100
+ saveCredentials({
4101
+ registryUrl,
4102
+ token: options.token
4103
+ });
4104
+ console.log(chalk7.green(`Authenticated with ${registryUrl}`));
4105
+ console.log(chalk7.dim("Credentials saved to ~/.config/agentpacks/credentials.json"));
4106
+ }
4107
+
4108
+ // src/cli/models-explain.ts
4109
+ import chalk8 from "chalk";
4110
+ import { resolve as resolve24 } from "path";
4111
+ function runModelsExplain(options) {
4112
+ const projectRoot = resolve24(options.config ?? ".");
4113
+ const config = loadWorkspaceConfig(projectRoot);
4114
+ const loader = new PackLoader(projectRoot, config);
4115
+ const { packs } = loader.loadAll();
4116
+ if (packs.length === 0) {
4117
+ console.log(chalk8.red("No packs loaded. Run `agentpacks init` first."));
4118
+ process.exit(1);
4119
+ }
4120
+ const merger = new FeatureMerger(packs);
4121
+ const { features: merged } = merger.merge();
4122
+ if (!merged.models) {
4123
+ console.log(chalk8.dim("No model configuration found in your packs."));
4124
+ return;
4125
+ }
4126
+ const profile = options.profile;
4127
+ const target = options.target;
4128
+ const resolved = resolveModels(merged.models, profile, target);
4129
+ console.log(chalk8.bold(`
4130
+ \uD83D\uDCCB Model Configuration Summary
4131
+ `));
4132
+ if (resolved.default) {
4133
+ console.log(` ${chalk8.dim("Default model:")} ${chalk8.cyan(resolved.default)}`);
4134
+ }
4135
+ if (resolved.small) {
4136
+ console.log(` ${chalk8.dim("Small model:")} ${chalk8.cyan(resolved.small)}`);
4137
+ }
4138
+ if (resolved.activeProfile) {
4139
+ console.log(` ${chalk8.dim("Active profile:")} ${chalk8.green(resolved.activeProfile)}`);
4140
+ }
4141
+ if (target) {
4142
+ console.log(` ${chalk8.dim("Target:")} ${chalk8.yellow(target)}`);
4143
+ }
4144
+ const agentEntries = Object.entries(resolved.agents);
4145
+ if (agentEntries.length > 0) {
4146
+ console.log(chalk8.bold(`
4147
+ Agent Assignments:`));
4148
+ for (const [name, config2] of agentEntries) {
4149
+ const temp = config2.temperature !== undefined ? ` (temp: ${config2.temperature})` : "";
4150
+ console.log(` ${chalk8.dim("•")} ${name}: ${chalk8.cyan(config2.model)}${chalk8.dim(temp)}`);
4151
+ }
4152
+ }
4153
+ if (resolved.profileNames.length > 0) {
4154
+ console.log(chalk8.bold(`
4155
+ Available Profiles:`));
4156
+ for (const name of resolved.profileNames) {
4157
+ const profileData = resolved.profiles[name];
4158
+ const desc = profileData?.description ?? "";
4159
+ const active = name === resolved.activeProfile ? chalk8.green(" ← active") : "";
4160
+ console.log(` ${chalk8.dim("•")} ${name}${active}${desc ? chalk8.dim(` — ${desc}`) : ""}`);
4161
+ }
4162
+ }
4163
+ if (resolved.routing.length > 0) {
4164
+ console.log(chalk8.bold(`
4165
+ Routing Rules:`));
4166
+ for (const rule of resolved.routing) {
4167
+ const conditions = Object.entries(rule.when).map(([k, v]) => `${chalk8.yellow(k)}=${chalk8.cyan(v)}`).join(", ");
4168
+ const desc = rule.description;
4169
+ console.log(` ${chalk8.dim("•")} When ${conditions} → use ${chalk8.green(rule.use)}${desc ? chalk8.dim(` (${desc})`) : ""}`);
4170
+ }
4171
+ if (options.task) {
4172
+ console.log(chalk8.bold(`
4173
+ Task Analysis:`));
4174
+ console.log(` ${chalk8.dim("Task:")} "${options.task}"`);
4175
+ const matched = matchTaskToRouting(options.task, resolved.routing);
4176
+ if (matched) {
4177
+ console.log(` ${chalk8.green("✓")} Matched rule: ${chalk8.green(matched.use)}`);
4178
+ const conditions = Object.entries(matched.when).map(([k, v]) => `${k}=${v}`).join(", ");
4179
+ console.log(` ${chalk8.dim(" Conditions:")} ${conditions}`);
4180
+ } else {
4181
+ console.log(` ${chalk8.yellow("○")} No routing rule matched — using default profile`);
4182
+ }
4183
+ }
4184
+ }
4185
+ const guidance = generateModelGuidanceMarkdown(resolved);
4186
+ if (guidance) {
4187
+ console.log(chalk8.bold(`
4188
+ Generated Guidance Preview:`));
4189
+ console.log(chalk8.dim(" " + "─".repeat(50)));
4190
+ for (const line of guidance.split(`
4191
+ `).slice(0, 20)) {
4192
+ console.log(` ${chalk8.dim(line)}`);
4193
+ }
4194
+ if (guidance.split(`
4195
+ `).length > 20) {
4196
+ console.log(chalk8.dim(` ... (${guidance.split(`
4197
+ `).length - 20} more lines)`));
4198
+ }
4199
+ }
4200
+ console.log("");
4201
+ }
4202
+ function matchTaskToRouting(task, routing) {
4203
+ const lowerTask = task.toLowerCase();
4204
+ const complexityKeywords = {
4205
+ critical: ["critical", "security", "production", "hotfix"],
4206
+ high: ["refactor", "architecture", "complex", "rewrite", "migrate"],
4207
+ medium: ["feature", "implement", "update", "modify"],
4208
+ low: ["fix", "typo", "comment", "rename", "format"]
4209
+ };
4210
+ const urgencyKeywords = {
4211
+ high: ["urgent", "asap", "emergency", "hotfix", "critical"],
4212
+ normal: ["feature", "implement", "add"],
4213
+ low: ["cleanup", "refactor", "docs", "todo"]
4214
+ };
4215
+ const inferred = {};
4216
+ for (const [level, keywords] of Object.entries(complexityKeywords)) {
4217
+ if (keywords.some((kw) => lowerTask.includes(kw))) {
4218
+ inferred["complexity"] = level;
4219
+ break;
4220
+ }
4221
+ }
4222
+ for (const [level, keywords] of Object.entries(urgencyKeywords)) {
4223
+ if (keywords.some((kw) => lowerTask.includes(kw))) {
4224
+ inferred["urgency"] = level;
4225
+ break;
4226
+ }
4227
+ }
4228
+ for (const rule of routing) {
4229
+ const matches = Object.entries(rule.when).every(([key, value]) => {
4230
+ if (inferred[key] === value)
4231
+ return true;
4232
+ if (lowerTask.includes(value.toLowerCase()))
4233
+ return true;
4234
+ return false;
4235
+ });
4236
+ if (matches)
4237
+ return rule;
4238
+ }
4239
+ return null;
3196
4240
  }
3197
4241
 
3198
4242
  // src/cli/pack/create.ts
3199
- import { existsSync as existsSync17, writeFileSync as writeFileSync11 } from "fs";
3200
- import { resolve as resolve23, join as join22 } from "path";
3201
- import chalk6 from "chalk";
4243
+ import { existsSync as existsSync20, writeFileSync as writeFileSync11 } from "fs";
4244
+ import { resolve as resolve25, join as join26 } from "path";
4245
+ import chalk9 from "chalk";
3202
4246
  function runPackCreate(projectRoot, name) {
3203
- const packDir = resolve23(projectRoot, "packs", name);
3204
- if (existsSync17(packDir)) {
3205
- console.log(chalk6.red(`Pack "${name}" already exists at packs/${name}/`));
4247
+ const packDir = resolve25(projectRoot, "packs", name);
4248
+ if (existsSync20(packDir)) {
4249
+ console.log(chalk9.red(`Pack "${name}" already exists at packs/${name}/`));
3206
4250
  return;
3207
4251
  }
3208
4252
  ensureDir(packDir);
3209
- ensureDir(join22(packDir, "rules"));
3210
- ensureDir(join22(packDir, "commands"));
3211
- ensureDir(join22(packDir, "agents"));
3212
- ensureDir(join22(packDir, "skills"));
4253
+ ensureDir(join26(packDir, "rules"));
4254
+ ensureDir(join26(packDir, "commands"));
4255
+ ensureDir(join26(packDir, "agents"));
4256
+ ensureDir(join26(packDir, "skills"));
3213
4257
  const packJson = {
3214
4258
  name,
3215
4259
  version: "1.0.0",
@@ -3220,31 +4264,31 @@ function runPackCreate(projectRoot, name) {
3220
4264
  targets: "*",
3221
4265
  features: "*"
3222
4266
  };
3223
- writeFileSync11(join22(packDir, "pack.json"), JSON.stringify(packJson, null, 2) + `
4267
+ writeFileSync11(join26(packDir, "pack.json"), JSON.stringify(packJson, null, 2) + `
3224
4268
  `);
3225
- console.log(chalk6.green(`Created pack "${name}" at packs/${name}/`));
3226
- console.log(chalk6.dim(" Add rules, commands, agents, skills, hooks, plugins, mcp.json, or ignore files."));
3227
- console.log(chalk6.dim(` Then add "${join22("./packs", name)}" to packs[] in agentpacks.jsonc.`));
4269
+ console.log(chalk9.green(`Created pack "${name}" at packs/${name}/`));
4270
+ console.log(chalk9.dim(" Add rules, commands, agents, skills, hooks, plugins, mcp.json, or ignore files."));
4271
+ console.log(chalk9.dim(` Then add "${join26("./packs", name)}" to packs[] in agentpacks.jsonc.`));
3228
4272
  }
3229
4273
 
3230
4274
  // src/cli/pack/enable.ts
3231
- import { readFileSync as readFileSync16, writeFileSync as writeFileSync12, existsSync as existsSync18 } from "fs";
3232
- import { resolve as resolve24 } from "path";
3233
- import chalk7 from "chalk";
4275
+ import { readFileSync as readFileSync18, writeFileSync as writeFileSync12, existsSync as existsSync21 } from "fs";
4276
+ import { resolve as resolve26 } from "path";
4277
+ import chalk10 from "chalk";
3234
4278
  var CONFIG_FILENAME = "agentpacks.jsonc";
3235
4279
  function readConfigRaw(projectRoot) {
3236
- const filepath = resolve24(projectRoot, CONFIG_FILENAME);
3237
- if (!existsSync18(filepath)) {
4280
+ const filepath = resolve26(projectRoot, CONFIG_FILENAME);
4281
+ if (!existsSync21(filepath)) {
3238
4282
  throw new Error(`No ${CONFIG_FILENAME} found. Run 'agentpacks init' first.`);
3239
4283
  }
3240
- return readFileSync16(filepath, "utf-8");
4284
+ return readFileSync18(filepath, "utf-8");
3241
4285
  }
3242
4286
  function parseDisabledFromRaw(raw) {
3243
4287
  const regex = /"disabled"\s*:\s*\[([^\]]*)\]/;
3244
4288
  const match = regex.exec(raw);
3245
4289
  if (!match)
3246
4290
  return { list: [], match: null };
3247
- const inner = match[1].trim();
4291
+ const inner = (match[1] ?? "").trim();
3248
4292
  if (!inner)
3249
4293
  return { list: [], match };
3250
4294
  const list = inner.split(",").map((s) => s.trim().replace(/^["']|["']$/g, "")).filter(Boolean);
@@ -3264,47 +4308,46 @@ function runPackDisable(projectRoot, packName) {
3264
4308
  const raw = readConfigRaw(projectRoot);
3265
4309
  const { list, match } = parseDisabledFromRaw(raw);
3266
4310
  if (list.includes(packName)) {
3267
- console.log(chalk7.dim(`Pack "${packName}" is already disabled.`));
4311
+ console.log(chalk10.dim(`Pack "${packName}" is already disabled.`));
3268
4312
  return;
3269
4313
  }
3270
4314
  list.push(packName);
3271
4315
  const updated = writeDisabled(raw, list, match);
3272
- const filepath = resolve24(projectRoot, CONFIG_FILENAME);
4316
+ const filepath = resolve26(projectRoot, CONFIG_FILENAME);
3273
4317
  writeFileSync12(filepath, updated);
3274
- console.log(chalk7.green(`Disabled pack "${packName}".`));
3275
- console.log(chalk7.dim("Run 'agentpacks generate' to regenerate configs."));
4318
+ console.log(chalk10.green(`Disabled pack "${packName}".`));
4319
+ console.log(chalk10.dim("Run 'agentpacks generate' to regenerate configs."));
3276
4320
  }
3277
4321
  function runPackEnable(projectRoot, packName) {
3278
4322
  const raw = readConfigRaw(projectRoot);
3279
4323
  const { list, match } = parseDisabledFromRaw(raw);
3280
4324
  if (!list.includes(packName)) {
3281
- console.log(chalk7.dim(`Pack "${packName}" is not disabled.`));
4325
+ console.log(chalk10.dim(`Pack "${packName}" is not disabled.`));
3282
4326
  return;
3283
4327
  }
3284
4328
  const newList = list.filter((n) => n !== packName);
3285
4329
  const updated = writeDisabled(raw, newList, match);
3286
- const filepath = resolve24(projectRoot, CONFIG_FILENAME);
4330
+ const filepath = resolve26(projectRoot, CONFIG_FILENAME);
3287
4331
  writeFileSync12(filepath, updated);
3288
- console.log(chalk7.green(`Enabled pack "${packName}".`));
3289
- console.log(chalk7.dim("Run 'agentpacks generate' to regenerate configs."));
4332
+ console.log(chalk10.green(`Enabled pack "${packName}".`));
4333
+ console.log(chalk10.dim("Run 'agentpacks generate' to regenerate configs."));
3290
4334
  }
3291
4335
 
3292
4336
  // src/cli/pack/list.ts
3293
- init_config();
3294
- import chalk8 from "chalk";
4337
+ import chalk11 from "chalk";
3295
4338
  function runPackList(projectRoot) {
3296
4339
  const config = loadWorkspaceConfig(projectRoot);
3297
4340
  const loader = new PackLoader(projectRoot, config);
3298
4341
  const { packs, warnings } = loader.loadAll();
3299
4342
  const disabledSet = new Set(config.disabled);
3300
4343
  for (const w of warnings) {
3301
- console.log(chalk8.yellow(` warn: ${w}`));
4344
+ console.log(chalk11.yellow(` warn: ${w}`));
3302
4345
  }
3303
4346
  if (packs.length === 0 && config.packs.length === 0) {
3304
- console.log(chalk8.dim("No packs configured. Run 'agentpacks init' to get started."));
4347
+ console.log(chalk11.dim("No packs configured. Run 'agentpacks init' to get started."));
3305
4348
  return;
3306
4349
  }
3307
- console.log(chalk8.bold(`Active packs:
4350
+ console.log(chalk11.bold(`Active packs:
3308
4351
  `));
3309
4352
  for (const pack of packs) {
3310
4353
  const m = pack.manifest;
@@ -3325,140 +4368,269 @@ function runPackList(projectRoot) {
3325
4368
  features.push(`${Object.keys(pack.mcp.servers).length} MCP servers`);
3326
4369
  if (pack.ignore)
3327
4370
  features.push("ignore");
3328
- const status = disabledSet.has(m.name) ? chalk8.red("[disabled]") : chalk8.green("[active]");
3329
- console.log(` ${status} ${chalk8.bold(m.name)} v${m.version}`);
4371
+ const status = disabledSet.has(m.name) ? chalk11.red("[disabled]") : chalk11.green("[active]");
4372
+ console.log(` ${status} ${chalk11.bold(m.name)} v${m.version}`);
3330
4373
  if (m.description) {
3331
- console.log(` ${chalk8.dim(m.description)}`);
4374
+ console.log(` ${chalk11.dim(m.description)}`);
3332
4375
  }
3333
4376
  if (features.length > 0) {
3334
- console.log(` ${chalk8.dim(features.join(", "))}`);
4377
+ console.log(` ${chalk11.dim(features.join(", "))}`);
3335
4378
  }
3336
4379
  console.log();
3337
4380
  }
3338
4381
  for (const ref of config.disabled) {
3339
4382
  if (!packs.some((p) => p.manifest.name === ref)) {
3340
- console.log(` ${chalk8.red("[disabled]")} ${chalk8.dim(ref)}`);
4383
+ console.log(` ${chalk11.red("[disabled]")} ${chalk11.dim(ref)}`);
3341
4384
  }
3342
4385
  }
3343
4386
  }
3344
4387
 
3345
4388
  // src/cli/pack/validate.ts
3346
- init_config();
3347
- import { existsSync as existsSync19 } from "fs";
3348
- import { resolve as resolve25, join as join23 } from "path";
3349
- import chalk9 from "chalk";
4389
+ import { existsSync as existsSync22 } from "fs";
4390
+ import { resolve as resolve27, join as join27 } from "path";
4391
+ import chalk12 from "chalk";
3350
4392
  function runPackValidate(projectRoot) {
3351
4393
  const config = loadWorkspaceConfig(projectRoot);
3352
4394
  let hasErrors = false;
3353
4395
  for (const packRef of config.packs) {
3354
4396
  const packDir = resolvePackDir(projectRoot, packRef);
3355
- console.log(chalk9.bold(`
4397
+ console.log(chalk12.bold(`
3356
4398
  Validating pack: ${packRef}`));
3357
- if (!packDir || !existsSync19(packDir)) {
3358
- console.log(chalk9.red(` ERROR: Pack directory not found: ${packRef}`));
4399
+ if (!packDir || !existsSync22(packDir)) {
4400
+ console.log(chalk12.red(` ERROR: Pack directory not found: ${packRef}`));
3359
4401
  hasErrors = true;
3360
4402
  continue;
3361
4403
  }
3362
- const packJsonPath = resolve25(packDir, "pack.json");
3363
- if (!existsSync19(packJsonPath)) {
3364
- console.log(chalk9.yellow(" warn: No pack.json found. Name will be inferred from directory."));
4404
+ const packJsonPath = resolve27(packDir, "pack.json");
4405
+ if (!existsSync22(packJsonPath)) {
4406
+ console.log(chalk12.yellow(" warn: No pack.json found. Name will be inferred from directory."));
3365
4407
  } else {
3366
4408
  try {
3367
4409
  loadPackManifest(packDir);
3368
- console.log(chalk9.green(" pack.json: valid"));
4410
+ console.log(chalk12.green(" pack.json: valid"));
3369
4411
  } catch (err) {
3370
4412
  const message = err instanceof Error ? err.message : String(err);
3371
- console.log(chalk9.red(` ERROR pack.json: ${message}`));
4413
+ console.log(chalk12.red(` ERROR pack.json: ${message}`));
3372
4414
  hasErrors = true;
3373
4415
  }
3374
4416
  }
3375
4417
  const subdirs = ["rules", "commands", "agents", "skills"];
3376
4418
  for (const sub of subdirs) {
3377
- const subDir = join23(packDir, sub);
3378
- if (existsSync19(subDir)) {
4419
+ const subDir = join27(packDir, sub);
4420
+ if (existsSync22(subDir)) {
3379
4421
  if (sub === "skills") {
3380
4422
  const skillDirs = listDirs(subDir);
3381
4423
  for (const skillDir of skillDirs) {
3382
- const skillMd = join23(skillDir, "SKILL.md");
3383
- if (!existsSync19(skillMd)) {
3384
- console.log(chalk9.yellow(` warn: skills/${skillDir.split("/").pop()} missing SKILL.md`));
4424
+ const skillMd = join27(skillDir, "SKILL.md");
4425
+ if (!existsSync22(skillMd)) {
4426
+ console.log(chalk12.yellow(` warn: skills/${skillDir.split("/").pop()} missing SKILL.md`));
3385
4427
  }
3386
4428
  }
3387
- console.log(chalk9.green(` ${sub}/: ${skillDirs.length} skill(s)`));
4429
+ console.log(chalk12.green(` ${sub}/: ${skillDirs.length} skill(s)`));
3388
4430
  } else {
3389
4431
  const files = listFiles(subDir, { extension: ".md" });
3390
- console.log(chalk9.green(` ${sub}/: ${files.length} file(s)`));
4432
+ console.log(chalk12.green(` ${sub}/: ${files.length} file(s)`));
3391
4433
  }
3392
4434
  }
3393
4435
  }
3394
4436
  const optionalFiles = ["mcp.json", "ignore", ".aiignore"];
3395
4437
  for (const file of optionalFiles) {
3396
- if (existsSync19(join23(packDir, file))) {
3397
- console.log(chalk9.green(` ${file}: present`));
4438
+ if (existsSync22(join27(packDir, file))) {
4439
+ console.log(chalk12.green(` ${file}: present`));
3398
4440
  }
3399
4441
  }
3400
- const hooksJson = join23(packDir, "hooks", "hooks.json");
3401
- if (existsSync19(hooksJson)) {
3402
- console.log(chalk9.green(" hooks/hooks.json: present"));
4442
+ const hooksJson = join27(packDir, "hooks", "hooks.json");
4443
+ if (existsSync22(hooksJson)) {
4444
+ console.log(chalk12.green(" hooks/hooks.json: present"));
3403
4445
  }
3404
- const pluginsDir = join23(packDir, "plugins");
3405
- if (existsSync19(pluginsDir)) {
4446
+ const pluginsDir = join27(packDir, "plugins");
4447
+ if (existsSync22(pluginsDir)) {
3406
4448
  const pluginFiles = [
3407
4449
  ...listFiles(pluginsDir, { extension: ".ts" }),
3408
4450
  ...listFiles(pluginsDir, { extension: ".js" })
3409
4451
  ];
3410
- console.log(chalk9.green(` plugins/: ${pluginFiles.length} file(s)`));
4452
+ console.log(chalk12.green(` plugins/: ${pluginFiles.length} file(s)`));
4453
+ }
4454
+ const modelsJsonPath = join27(packDir, "models.json");
4455
+ if (existsSync22(modelsJsonPath)) {
4456
+ try {
4457
+ const parsed = parseModels(packDir, "validate");
4458
+ if (parsed) {
4459
+ console.log(chalk12.green(" models.json: valid"));
4460
+ const secretWarnings = scanModelsForSecrets(parsed.config);
4461
+ if (secretWarnings.length > 0) {
4462
+ for (const w of secretWarnings) {
4463
+ console.log(chalk12.red(` ERROR models.json: ${w}`));
4464
+ }
4465
+ hasErrors = true;
4466
+ }
4467
+ }
4468
+ } catch (err) {
4469
+ const message = err instanceof Error ? err.message : String(err);
4470
+ console.log(chalk12.red(` ERROR models.json: ${message}`));
4471
+ hasErrors = true;
4472
+ }
3411
4473
  }
3412
4474
  }
3413
4475
  console.log();
3414
4476
  if (hasErrors) {
3415
- console.log(chalk9.red("Validation failed with errors."));
4477
+ console.log(chalk12.red("Validation failed with errors."));
3416
4478
  process.exit(1);
3417
4479
  } else {
3418
- console.log(chalk9.green("All packs valid."));
4480
+ console.log(chalk12.green("All packs valid."));
3419
4481
  }
3420
4482
  }
3421
4483
  function resolvePackDir(projectRoot, packRef) {
3422
4484
  if (packRef.startsWith("./") || packRef.startsWith("../")) {
3423
- return resolve25(projectRoot, packRef);
4485
+ return resolve27(projectRoot, packRef);
4486
+ }
4487
+ return resolve27(projectRoot, packRef);
4488
+ }
4489
+
4490
+ // src/cli/publish.ts
4491
+ import { resolve as resolve28 } from "path";
4492
+ import { existsSync as existsSync23 } from "fs";
4493
+ import chalk13 from "chalk";
4494
+ async function runPublish(projectRoot, options) {
4495
+ const credentials = loadCredentials();
4496
+ if (!credentials.token) {
4497
+ console.log(chalk13.red("Not authenticated. Run `agentpacks login` first."));
4498
+ process.exit(1);
4499
+ }
4500
+ const packDir = resolve28(projectRoot);
4501
+ const packJsonPath = resolve28(packDir, "pack.json");
4502
+ if (!existsSync23(packJsonPath)) {
4503
+ console.log(chalk13.red("No pack.json found. Are you in a pack directory?"));
4504
+ process.exit(1);
4505
+ }
4506
+ const manifest = loadPackManifest(packDir);
4507
+ console.log(chalk13.bold(`Publishing ${manifest.name}@${manifest.version}...`));
4508
+ const models = parseModels(packDir, manifest.name);
4509
+ if (models) {
4510
+ const secretWarnings = scanModelsForSecrets(models.config);
4511
+ if (secretWarnings.length > 0) {
4512
+ console.log(chalk13.red(`
4513
+ Blocked: secrets detected in models.json:`));
4514
+ for (const w of secretWarnings) {
4515
+ console.log(chalk13.red(` - ${w}`));
4516
+ }
4517
+ process.exit(1);
4518
+ }
4519
+ }
4520
+ if (options.verbose)
4521
+ console.log(chalk13.dim(" Creating tarball..."));
4522
+ const tarball = await createTarball(packDir);
4523
+ if (options.verbose)
4524
+ console.log(chalk13.dim(" Uploading..."));
4525
+ const client = createRegistryClient({
4526
+ registryUrl: credentials.registryUrl,
4527
+ authToken: credentials.token
4528
+ });
4529
+ try {
4530
+ const result = await client.publish(tarball, {
4531
+ name: manifest.name,
4532
+ version: manifest.version,
4533
+ manifest
4534
+ });
4535
+ console.log(chalk13.green(`
4536
+ Published ${result.name}@${result.version}`));
4537
+ console.log(chalk13.dim(` integrity: ${result.integrity}`));
4538
+ } catch (err) {
4539
+ console.log(chalk13.red(`
4540
+ Publish failed: ${err instanceof Error ? err.message : String(err)}`));
4541
+ process.exit(1);
4542
+ }
4543
+ }
4544
+
4545
+ // src/cli/search.ts
4546
+ import chalk14 from "chalk";
4547
+ async function runSearch(query, options) {
4548
+ const credentials = loadCredentials();
4549
+ const client = createRegistryClient({
4550
+ registryUrl: credentials.registryUrl,
4551
+ authToken: credentials.token
4552
+ });
4553
+ try {
4554
+ const { packs, total } = await client.search({
4555
+ query,
4556
+ tags: options.tags?.split(","),
4557
+ targets: options.targets?.split(","),
4558
+ sort: options.sort,
4559
+ limit: options.limit ? Number(options.limit) : 20
4560
+ });
4561
+ if (packs.length === 0) {
4562
+ console.log(chalk14.dim("No packs found."));
4563
+ return;
4564
+ }
4565
+ console.log(chalk14.bold(`Found ${total} pack(s)${query ? ` matching "${query}"` : ""}:
4566
+ `));
4567
+ for (const pack of packs) {
4568
+ const verified = pack.verified ? chalk14.green(" [verified]") : "";
4569
+ const featured = pack.featured ? chalk14.yellow(" [featured]") : "";
4570
+ console.log(` ${chalk14.bold(pack.name)}${verified}${featured}`);
4571
+ console.log(` ${pack.description}`);
4572
+ console.log(chalk14.dim(` v${pack.latestVersion} | ${pack.downloads} downloads | by ${pack.author}`));
4573
+ if (options.verbose && pack.tags.length > 0) {
4574
+ console.log(chalk14.dim(` tags: ${pack.tags.join(", ")}`));
4575
+ }
4576
+ console.log();
4577
+ }
4578
+ } catch (err) {
4579
+ console.log(chalk14.red(`Search failed: ${err instanceof Error ? err.message : String(err)}`));
4580
+ process.exit(1);
3424
4581
  }
3425
- return resolve25(projectRoot, packRef);
3426
4582
  }
3427
4583
 
3428
4584
  // src/index.ts
3429
4585
  import { Command } from "commander";
3430
- import { resolve as resolve26 } from "path";
4586
+ import { resolve as resolve29 } from "path";
3431
4587
  var program = new Command;
3432
4588
  program.name("agentpacks").description("Composable AI agent configuration manager. Pack-based rules, commands, skills, hooks, and MCP sync across OpenCode, Cursor, Claude Code, Codex, Gemini, Copilot, and more.").version("0.1.0");
3433
4589
  program.command("init").description("Initialize agentpacks in the current project").action(() => {
3434
- runInit(resolve26("."));
4590
+ runInit(resolve29("."));
3435
4591
  });
3436
4592
  program.command("generate").description("Generate tool configs from active packs").option("-t, --targets <targets>", "Comma-separated target IDs or '*' for all").option("-f, --features <features>", "Comma-separated feature IDs or '*' for all").option("--dry-run", "Preview changes without writing files").option("--diff", "Show diff of what would change").option("-v, --verbose", "Enable verbose logging").action((options) => {
3437
- runGenerate(resolve26("."), options);
4593
+ runGenerate(resolve29("."), options);
3438
4594
  });
3439
4595
  program.command("install").description("Install remote packs (git, npm) into local cache").option("--update", "Re-resolve all refs (ignore lockfile)").option("--frozen", "Fail if lockfile is missing or incomplete").option("-v, --verbose", "Enable verbose logging").action(async (options) => {
3440
- await runInstall(resolve26("."), options);
4596
+ await runInstall(resolve29("."), options);
3441
4597
  });
3442
4598
  program.command("export").description("Export packs to target-native format (e.g. Cursor plugin)").requiredOption("--format <format>", "Export format (cursor-plugin)").option("-o, --output <dir>", "Output directory").option("--pack <name>", "Export a specific pack only").option("-v, --verbose", "Enable verbose logging").action((options) => {
3443
- runExport(resolve26("."), options);
4599
+ runExport(resolve29("."), options);
3444
4600
  });
3445
4601
  program.command("import").description("Import from existing tool configurations").requiredOption("--from <source>", "Import source (rulesync)").option("-o, --output <dir>", "Output pack directory").action((options) => {
3446
- runImport(resolve26("."), options);
4602
+ runImport(resolve29("."), options);
4603
+ });
4604
+ program.command("search [query]").description("Search for packs in the registry").option("--tags <tags>", "Filter by tags (comma-separated)").option("--targets <targets>", "Filter by targets (comma-separated)").option("--sort <sort>", "Sort by: downloads, updated, name, weekly").option("-l, --limit <limit>", "Max results to show").option("-v, --verbose", "Show additional details").action(async (query, options) => {
4605
+ await runSearch(query ?? "", options);
4606
+ });
4607
+ program.command("info <pack>").description("Show detailed pack information from the registry").action(async (packName) => {
4608
+ await runInfo(packName);
4609
+ });
4610
+ program.command("publish").description("Publish a pack to the registry").option("-v, --verbose", "Enable verbose logging").action(async (options) => {
4611
+ await runPublish(resolve29("."), options);
4612
+ });
4613
+ program.command("login").description("Authenticate with the agentpacks registry").option("--token <token>", "API token").option("--registry <url>", "Registry URL").action(async (options) => {
4614
+ await runLogin(options);
4615
+ });
4616
+ var modelsCmd = program.command("models").description("Model configuration and routing");
4617
+ modelsCmd.command("explain").description("Explain model profile and routing resolution").option("-c, --config <path>", "Path to agentpacks.yaml").option("-p, --profile <name>", "Profile to activate").option("-t, --target <id>", "Target to resolve for").option("--task <description>", "Task description for routing match").action((options) => {
4618
+ runModelsExplain(options);
3447
4619
  });
3448
4620
  var packCmd = program.command("pack").description("Manage packs");
3449
4621
  packCmd.command("create <name>").description("Create a new pack scaffold").action((name) => {
3450
- runPackCreate(resolve26("."), name);
4622
+ runPackCreate(resolve29("."), name);
3451
4623
  });
3452
4624
  packCmd.command("list").description("List all configured packs and their status").action(() => {
3453
- runPackList(resolve26("."));
4625
+ runPackList(resolve29("."));
3454
4626
  });
3455
4627
  packCmd.command("validate").description("Validate all configured packs").action(() => {
3456
- runPackValidate(resolve26("."));
4628
+ runPackValidate(resolve29("."));
3457
4629
  });
3458
4630
  packCmd.command("enable <name>").description("Enable a previously disabled pack").action((name) => {
3459
- runPackEnable(resolve26("."), name);
4631
+ runPackEnable(resolve29("."), name);
3460
4632
  });
3461
4633
  packCmd.command("disable <name>").description("Disable a pack without removing it").action((name) => {
3462
- runPackDisable(resolve26("."), name);
4634
+ runPackDisable(resolve29("."), name);
3463
4635
  });
3464
4636
  program.parse();