@agentrules/core 0.0.11 → 0.2.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 (4) hide show
  1. package/README.md +80 -54
  2. package/dist/index.d.ts +666 -397
  3. package/dist/index.js +577 -375
  4. package/package.json +15 -10
package/dist/index.d.ts CHANGED
@@ -1,143 +1,124 @@
1
1
  import { z } from "zod";
2
2
 
3
- //#region src/preset/schema.d.ts
4
- declare const platformIdSchema: z.ZodEnum<{
5
- opencode: "opencode";
6
- codex: "codex";
7
- claude: "claude";
8
- cursor: "cursor";
9
- }>;
10
- declare const titleSchema: z.ZodString;
11
- declare const descriptionSchema: z.ZodString;
12
- declare const tagSchema: z.ZodString;
13
- declare const tagsSchema: z.ZodArray<z.ZodString>;
14
- declare const slugSchema: z.ZodString;
15
- declare const COMMON_LICENSES: readonly ["MIT", "Apache-2.0", "GPL-3.0-only", "BSD-3-Clause", "ISC", "Unlicense"];
16
- type CommonLicense = (typeof COMMON_LICENSES)[number];
17
- declare const licenseSchema: z.ZodString;
18
- declare const presetConfigSchema: z.ZodObject<{
19
- $schema: z.ZodOptional<z.ZodString>;
20
- name: z.ZodString;
21
- title: z.ZodString;
22
- version: z.ZodOptional<z.ZodNumber>;
23
- description: z.ZodString;
24
- tags: z.ZodArray<z.ZodString>;
25
- features: z.ZodOptional<z.ZodArray<z.ZodString>>;
26
- license: z.ZodString;
3
+ //#region src/resolve/schema.d.ts
4
+
5
+ declare const ruleVariantSchema: z.ZodUnion<readonly [z.ZodObject<{
27
6
  platform: z.ZodEnum<{
28
7
  opencode: "opencode";
29
8
  codex: "codex";
30
9
  claude: "claude";
31
10
  cursor: "cursor";
32
11
  }>;
33
- path: z.ZodOptional<z.ZodString>;
34
- ignore: z.ZodOptional<z.ZodArray<z.ZodString>>;
35
- }, z.core.$strict>;
36
- declare const bundledFileSchema: z.ZodObject<{
37
- path: z.ZodString;
38
- size: z.ZodNumber;
39
- checksum: z.ZodString;
40
- contents: z.ZodString;
41
- }, z.core.$strip>;
42
- /**
43
- * Schema for what clients send to publish a preset.
44
- * Version is optional major version. Registry assigns full MAJOR.MINOR.
45
- *
46
- * Note: Clients send `name` (e.g., "my-preset"), and the registry defines the format of the slug.
47
- * For example, a namespaced slug could be returned as "username/my-preset"
48
- */
49
- declare const presetPublishInputSchema: z.ZodObject<{
50
- name: z.ZodString;
12
+ bundleUrl: z.ZodString;
13
+ fileCount: z.ZodNumber;
14
+ totalSize: z.ZodNumber;
15
+ }, z.core.$strip>, z.ZodObject<{
51
16
  platform: z.ZodEnum<{
52
17
  opencode: "opencode";
53
18
  codex: "codex";
54
19
  claude: "claude";
55
20
  cursor: "cursor";
56
21
  }>;
57
- title: z.ZodString;
58
- description: z.ZodString;
59
- tags: z.ZodArray<z.ZodString>;
60
- license: z.ZodString;
61
- licenseContent: z.ZodOptional<z.ZodString>;
62
- readmeContent: z.ZodOptional<z.ZodString>;
63
- features: z.ZodOptional<z.ZodArray<z.ZodString>>;
64
- installMessage: z.ZodOptional<z.ZodString>;
65
- files: z.ZodArray<z.ZodObject<{
66
- path: z.ZodString;
67
- size: z.ZodNumber;
68
- checksum: z.ZodString;
69
- contents: z.ZodString;
70
- }, z.core.$strip>>;
71
- version: z.ZodOptional<z.ZodNumber>;
22
+ content: z.ZodString;
23
+ fileCount: z.ZodNumber;
24
+ totalSize: z.ZodNumber;
25
+ }, z.core.$strip>]>;
26
+ declare const ruleVersionSchema: z.ZodObject<{
27
+ version: z.ZodString;
28
+ isLatest: z.ZodBoolean;
29
+ publishedAt: z.ZodOptional<z.ZodString>;
30
+ variants: z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
31
+ platform: z.ZodEnum<{
32
+ opencode: "opencode";
33
+ codex: "codex";
34
+ claude: "claude";
35
+ cursor: "cursor";
36
+ }>;
37
+ bundleUrl: z.ZodString;
38
+ fileCount: z.ZodNumber;
39
+ totalSize: z.ZodNumber;
40
+ }, z.core.$strip>, z.ZodObject<{
41
+ platform: z.ZodEnum<{
42
+ opencode: "opencode";
43
+ codex: "codex";
44
+ claude: "claude";
45
+ cursor: "cursor";
46
+ }>;
47
+ content: z.ZodString;
48
+ fileCount: z.ZodNumber;
49
+ totalSize: z.ZodNumber;
50
+ }, z.core.$strip>]>>;
72
51
  }, z.core.$strip>;
73
- /**
74
- * Schema for what registries store and return.
75
- * Includes full namespaced slug and version assigned by registry.
76
- */
77
- declare const presetBundleSchema: z.ZodObject<{
52
+ declare const resolvedRuleSchema: z.ZodObject<{
53
+ slug: z.ZodString;
54
+ name: z.ZodString;
78
55
  title: z.ZodString;
79
56
  description: z.ZodString;
80
57
  tags: z.ZodArray<z.ZodString>;
81
58
  license: z.ZodString;
82
- platform: z.ZodEnum<{
83
- opencode: "opencode";
84
- codex: "codex";
85
- claude: "claude";
86
- cursor: "cursor";
87
- }>;
88
- features: z.ZodOptional<z.ZodArray<z.ZodString>>;
89
- licenseContent: z.ZodOptional<z.ZodString>;
90
- readmeContent: z.ZodOptional<z.ZodString>;
91
- installMessage: z.ZodOptional<z.ZodString>;
92
- files: z.ZodArray<z.ZodObject<{
93
- path: z.ZodString;
94
- size: z.ZodNumber;
95
- checksum: z.ZodString;
96
- contents: z.ZodString;
59
+ features: z.ZodArray<z.ZodString>;
60
+ versions: z.ZodArray<z.ZodObject<{
61
+ version: z.ZodString;
62
+ isLatest: z.ZodBoolean;
63
+ publishedAt: z.ZodOptional<z.ZodString>;
64
+ variants: z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
65
+ platform: z.ZodEnum<{
66
+ opencode: "opencode";
67
+ codex: "codex";
68
+ claude: "claude";
69
+ cursor: "cursor";
70
+ }>;
71
+ bundleUrl: z.ZodString;
72
+ fileCount: z.ZodNumber;
73
+ totalSize: z.ZodNumber;
74
+ }, z.core.$strip>, z.ZodObject<{
75
+ platform: z.ZodEnum<{
76
+ opencode: "opencode";
77
+ codex: "codex";
78
+ claude: "claude";
79
+ cursor: "cursor";
80
+ }>;
81
+ content: z.ZodString;
82
+ fileCount: z.ZodNumber;
83
+ totalSize: z.ZodNumber;
84
+ }, z.core.$strip>]>>;
97
85
  }, z.core.$strip>>;
98
- slug: z.ZodString;
99
- version: z.ZodString;
100
86
  }, z.core.$strip>;
101
- declare const presetSchema: z.ZodObject<{
102
- title: z.ZodString;
103
- description: z.ZodString;
104
- tags: z.ZodArray<z.ZodString>;
105
- license: z.ZodString;
106
- platform: z.ZodEnum<{
107
- opencode: "opencode";
108
- codex: "codex";
109
- claude: "claude";
110
- cursor: "cursor";
111
- }>;
112
- version: z.ZodString;
113
- features: z.ZodOptional<z.ZodArray<z.ZodString>>;
87
+ declare const resolveResponseSchema: z.ZodObject<{
114
88
  slug: z.ZodString;
115
89
  name: z.ZodString;
116
- bundleUrl: z.ZodString;
117
- fileCount: z.ZodNumber;
118
- totalSize: z.ZodNumber;
119
- }, z.core.$strip>;
120
- declare const presetIndexSchema: z.ZodRecord<z.ZodString, z.ZodObject<{
121
90
  title: z.ZodString;
122
91
  description: z.ZodString;
123
92
  tags: z.ZodArray<z.ZodString>;
124
93
  license: z.ZodString;
125
- platform: z.ZodEnum<{
126
- opencode: "opencode";
127
- codex: "codex";
128
- claude: "claude";
129
- cursor: "cursor";
130
- }>;
131
- version: z.ZodString;
132
- features: z.ZodOptional<z.ZodArray<z.ZodString>>;
133
- slug: z.ZodString;
134
- name: z.ZodString;
135
- bundleUrl: z.ZodString;
136
- fileCount: z.ZodNumber;
137
- totalSize: z.ZodNumber;
138
- }, z.core.$strip>>;
139
-
140
- //#endregion
94
+ features: z.ZodArray<z.ZodString>;
95
+ versions: z.ZodArray<z.ZodObject<{
96
+ version: z.ZodString;
97
+ isLatest: z.ZodBoolean;
98
+ publishedAt: z.ZodOptional<z.ZodString>;
99
+ variants: z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
100
+ platform: z.ZodEnum<{
101
+ opencode: "opencode";
102
+ codex: "codex";
103
+ claude: "claude";
104
+ cursor: "cursor";
105
+ }>;
106
+ bundleUrl: z.ZodString;
107
+ fileCount: z.ZodNumber;
108
+ totalSize: z.ZodNumber;
109
+ }, z.core.$strip>, z.ZodObject<{
110
+ platform: z.ZodEnum<{
111
+ opencode: "opencode";
112
+ codex: "codex";
113
+ claude: "claude";
114
+ cursor: "cursor";
115
+ }>;
116
+ content: z.ZodString;
117
+ fileCount: z.ZodNumber;
118
+ totalSize: z.ZodNumber;
119
+ }, z.core.$strip>]>>;
120
+ }, z.core.$strip>>;
121
+ }, z.core.$strip>; //#endregion
141
122
  //#region src/platform/types.d.ts
142
123
  /**
143
124
  * Platform and rule type definitions.
@@ -145,39 +126,33 @@ declare const presetIndexSchema: z.ZodRecord<z.ZodString, z.ZodObject<{
145
126
  declare const PLATFORM_ID_TUPLE: readonly ["opencode", "codex", "claude", "cursor"];
146
127
  /** Union type of supported platform IDs */
147
128
  type PlatformId = (typeof PLATFORM_ID_TUPLE)[number];
148
- /** File format for a rule type */
149
- type RuleFileFormat = "markdown" | "typescript" | "mdc";
150
- /** Configuration for a single rule type */
151
- type RuleTypeConfig = {
129
+ /** Configuration for a single type */
130
+ type TypeConfig = {
152
131
  /** Human-readable description */
153
132
  description: string;
154
- /** File format */
155
- format: RuleFileFormat;
156
- /** File extension (without dot) */
157
- extension: string;
158
133
  /**
159
- * Install path pattern relative to project root.
160
- * Use {name} as placeholder for the rule slug/filename.
134
+ * Install path template for project install.
135
+ * Supports: {platformDir}, {name}
161
136
  * null if project install not supported.
162
137
  */
163
- projectPath: string | null;
138
+ project: string | null;
164
139
  /**
165
- * Install path pattern for global/user install.
166
- * Use ~ for home directory.
140
+ * Install path template for global install.
141
+ * Supports: {platformDir}, {name}
167
142
  * null if global install not supported.
168
143
  */
169
- globalPath: string | null;
144
+ global: string | null;
170
145
  };
171
146
  /** Platform configuration with all its rule types */
172
- type PlatformRuleConfig = {
147
+ type PlatformConfig = {
173
148
  /** Human-readable platform name */
174
149
  label: string;
175
- /** Platform's project directory (e.g., ".opencode") */
176
- projectDir: string;
177
- /** Platform's global config directory (null if not supported) */
178
- globalDir: string | null;
179
- /** Rule types supported by this platform */
180
- types: Record<string, RuleTypeConfig>;
150
+ /** Platform's project directory (e.g., ".claude") */
151
+ platformDir: string;
152
+ /** Platform's global config directory (e.g., "~/.claude") */
153
+ globalDir: string;
154
+ /** Types supported by this platform */
155
+ types: Record<string, TypeConfig>;
181
156
  };
182
157
  /**
183
158
  * Discriminated union of valid platform + type combinations.
@@ -188,10 +163,10 @@ type PlatformRuleType = {
188
163
  type: "instruction" | "agent" | "command" | "tool";
189
164
  } | {
190
165
  platform: "claude";
191
- type: "instruction" | "command" | "skill";
166
+ type: "instruction" | "command" | "skill" | "rule";
192
167
  } | {
193
168
  platform: "cursor";
194
- type: "rule";
169
+ type: "instruction" | "command" | "rule";
195
170
  } | {
196
171
  platform: "codex";
197
172
  type: "instruction" | "command";
@@ -200,232 +175,601 @@ type PlatformRuleType = {
200
175
  type RuleTypeForPlatform<P extends PlatformId> = Extract<PlatformRuleType, {
201
176
  platform: P;
202
177
  }>["type"];
203
- /** Union of all valid rule types across all platforms */
178
+ /**
179
+ * All valid rule types.
180
+ * When type is omitted, freeform file structure is used.
181
+ */
204
182
  type RuleType = PlatformRuleType["type"];
183
+ /** Tuple of all rule types for schema validation */
184
+ declare const RULE_TYPE_TUPLE: readonly ["instruction", "rule", "command", "skill", "agent", "tool"];
205
185
 
206
186
  //#endregion
207
187
  //#region src/platform/config.d.ts
208
188
  declare const PLATFORM_IDS: [PlatformId, ...PlatformId[]];
209
189
  /**
210
- * Platform configuration including supported rule types and install paths.
190
+ * Platform configuration including supported types and install paths.
211
191
  */
212
192
  declare const PLATFORMS: {
213
193
  readonly opencode: {
214
194
  readonly label: "OpenCode";
215
- readonly projectDir: ".opencode";
195
+ readonly platformDir: ".opencode";
216
196
  readonly globalDir: "~/.config/opencode";
217
197
  readonly types: {
218
198
  readonly instruction: {
219
- readonly description: "Project instructions (AGENTS.md)";
220
- readonly format: "markdown";
221
- readonly extension: "md";
222
- readonly projectPath: "AGENTS.md";
223
- readonly globalPath: "~/.config/opencode/AGENTS.md";
199
+ readonly description: "Project instructions";
200
+ readonly project: "AGENTS.md";
201
+ readonly global: "{platformDir}/AGENTS.md";
224
202
  };
225
203
  readonly agent: {
226
- readonly description: "Specialized AI agent definition";
227
- readonly format: "markdown";
228
- readonly extension: "md";
229
- readonly projectPath: ".opencode/agent/{name}.md";
230
- readonly globalPath: "~/.config/opencode/agent/{name}.md";
204
+ readonly description: "Specialized AI agent";
205
+ readonly project: "{platformDir}/agent/{name}.md";
206
+ readonly global: "{platformDir}/agent/{name}.md";
231
207
  };
232
208
  readonly command: {
233
209
  readonly description: "Custom slash command";
234
- readonly format: "markdown";
235
- readonly extension: "md";
236
- readonly projectPath: ".opencode/command/{name}.md";
237
- readonly globalPath: "~/.config/opencode/command/{name}.md";
210
+ readonly project: "{platformDir}/command/{name}.md";
211
+ readonly global: "{platformDir}/command/{name}.md";
238
212
  };
239
213
  readonly tool: {
240
- readonly description: "Custom tool definition";
241
- readonly format: "typescript";
242
- readonly extension: "ts";
243
- readonly projectPath: ".opencode/tool/{name}.ts";
244
- readonly globalPath: "~/.config/opencode/tool/{name}.ts";
214
+ readonly description: "Custom tool";
215
+ readonly project: "{platformDir}/tool/{name}.ts";
216
+ readonly global: "{platformDir}/tool/{name}.ts";
245
217
  };
246
218
  };
247
219
  };
248
220
  readonly claude: {
249
221
  readonly label: "Claude Code";
250
- readonly projectDir: ".claude";
222
+ readonly platformDir: ".claude";
251
223
  readonly globalDir: "~/.claude";
252
224
  readonly types: {
253
225
  readonly instruction: {
254
- readonly description: "Project instructions (CLAUDE.md)";
255
- readonly format: "markdown";
256
- readonly extension: "md";
257
- readonly projectPath: "CLAUDE.md";
258
- readonly globalPath: "~/.claude/CLAUDE.md";
226
+ readonly description: "Project instructions";
227
+ readonly project: "CLAUDE.md";
228
+ readonly global: "{platformDir}/CLAUDE.md";
229
+ };
230
+ readonly rule: {
231
+ readonly description: "Project rule";
232
+ readonly project: "{platformDir}/rules/{name}.md";
233
+ readonly global: "{platformDir}/rules/{name}.md";
259
234
  };
260
235
  readonly command: {
261
236
  readonly description: "Custom slash command";
262
- readonly format: "markdown";
263
- readonly extension: "md";
264
- readonly projectPath: ".claude/commands/{name}.md";
265
- readonly globalPath: "~/.claude/commands/{name}.md";
237
+ readonly project: "{platformDir}/commands/{name}.md";
238
+ readonly global: "{platformDir}/commands/{name}.md";
266
239
  };
267
240
  readonly skill: {
268
- readonly description: "Custom skill definition";
269
- readonly format: "markdown";
270
- readonly extension: "md";
271
- readonly projectPath: ".claude/skills/{name}/SKILL.md";
272
- readonly globalPath: "~/.claude/skills/{name}/SKILL.md";
241
+ readonly description: "Custom skill";
242
+ readonly project: "{platformDir}/skills/{name}/SKILL.md";
243
+ readonly global: "{platformDir}/skills/{name}/SKILL.md";
273
244
  };
274
245
  };
275
246
  };
276
247
  readonly cursor: {
277
248
  readonly label: "Cursor";
278
- readonly projectDir: ".cursor";
279
- readonly globalDir: null;
249
+ readonly platformDir: ".cursor";
250
+ readonly globalDir: "~/.cursor";
280
251
  readonly types: {
252
+ readonly instruction: {
253
+ readonly description: "Project instructions";
254
+ readonly project: "AGENTS.md";
255
+ readonly global: null;
256
+ };
281
257
  readonly rule: {
282
- readonly description: "Project rule (MDC format)";
283
- readonly format: "mdc";
284
- readonly extension: "mdc";
285
- readonly projectPath: ".cursor/rules/{name}.mdc";
286
- readonly globalPath: null;
258
+ readonly description: "Custom rule";
259
+ readonly project: "{platformDir}/rules/{name}.mdc";
260
+ readonly global: null;
261
+ };
262
+ readonly command: {
263
+ readonly description: "Custom slash command";
264
+ readonly project: "{platformDir}/commands/{name}.md";
265
+ readonly global: "{platformDir}/commands/{name}.md";
287
266
  };
288
267
  };
289
268
  };
290
269
  readonly codex: {
291
270
  readonly label: "Codex";
292
- readonly projectDir: "";
271
+ readonly platformDir: ".codex";
293
272
  readonly globalDir: "~/.codex";
294
273
  readonly types: {
295
274
  readonly instruction: {
296
- readonly description: "Project instructions (AGENTS.md)";
297
- readonly format: "markdown";
298
- readonly extension: "md";
299
- readonly projectPath: "AGENTS.md";
300
- readonly globalPath: "~/.codex/AGENTS.md";
275
+ readonly description: "Project instructions";
276
+ readonly project: "AGENTS.md";
277
+ readonly global: "{platformDir}/AGENTS.md";
301
278
  };
302
279
  readonly command: {
303
- readonly description: "Custom prompt (global only)";
304
- readonly format: "markdown";
305
- readonly extension: "md";
306
- readonly projectPath: null;
307
- readonly globalPath: "~/.codex/prompts/{name}.md";
280
+ readonly description: "Custom prompt";
281
+ readonly project: null;
282
+ readonly global: "{platformDir}/prompts/{name}.md";
308
283
  };
309
284
  };
310
285
  };
311
286
  };
312
- /** Valid rule types for each platform. Must be kept in sync with PLATFORMS. */
287
+ /** Get valid types for a specific platform */
288
+ declare function getValidTypes(platform: PlatformId): string[];
289
+ /** Check if a type is valid for a given platform */
290
+ declare function isValidType(platform: PlatformId, type: string): boolean;
291
+ type InstallScope = "project" | "global";
292
+ /** Get the configuration for a specific platform + type combination */
293
+ declare function getTypeConfig(platform: PlatformId, type: string): TypeConfig | undefined;
294
+ type SupportsInstallPathInput = {
295
+ platform: PlatformId;
296
+ type: string;
297
+ scope?: InstallScope;
298
+ };
299
+ declare function supportsInstallPath({
300
+ platform,
301
+ type,
302
+ scope
303
+ }: SupportsInstallPathInput): boolean;
304
+ /** Get the install path for a type, resolving all placeholders */
305
+ type GetInstallPathInput = {
306
+ platform: PlatformId;
307
+ type: string;
308
+ name?: string;
309
+ scope?: InstallScope;
310
+ };
311
+ declare function getInstallPath({
312
+ platform,
313
+ type,
314
+ name,
315
+ scope
316
+ }: GetInstallPathInput): string | null;
317
+ /** Get platform configuration */
318
+ declare function getPlatformConfig(platform: PlatformId): PlatformConfig;
319
+ /**
320
+ * Platform-specific type tuples for zod schema validation.
321
+ * Must be kept in sync with PLATFORMS types above.
322
+ */
313
323
  declare const PLATFORM_RULE_TYPES: {
314
324
  readonly opencode: readonly ["instruction", "agent", "command", "tool"];
315
- readonly claude: readonly ["instruction", "command", "skill"];
316
- readonly cursor: readonly ["rule"];
325
+ readonly claude: readonly ["instruction", "rule", "command", "skill"];
326
+ readonly cursor: readonly ["instruction", "rule", "command"];
317
327
  readonly codex: readonly ["instruction", "command"];
318
328
  };
319
- /** Get valid rule types for a specific platform */
320
- declare function getValidRuleTypes(platform: PlatformId): readonly string[];
321
- /** Check if a type is valid for a given platform */
322
- declare function isValidRuleType(platform: PlatformId, type: string): boolean;
323
- /** Get the configuration for a specific platform + type combination */
324
- declare function getRuleTypeConfig(platform: PlatformId, type: string): RuleTypeConfig | undefined;
325
- /** Get the install path for a rule, replacing {name} placeholder */
326
- declare function getInstallPath(platform: PlatformId, type: string, name: string, location?: "project" | "global"): string | null;
327
- /** Get platform configuration */
328
- declare function getPlatformConfig(platform: PlatformId): PlatformRuleConfig;
329
329
 
330
330
  //#endregion
331
331
  //#region src/platform/utils.d.ts
332
332
  declare function isSupportedPlatform(value: string): value is PlatformId;
333
333
  declare function normalizePlatformInput(value: string): PlatformId;
334
334
  /**
335
- * Check if a directory name matches a platform's projectDir.
336
- * Used to detect if a preset config is inside a platform directory (in-project mode).
335
+ * Check if a directory name matches a platform's platformDir.
336
+ * Used to detect if a rule config is inside a platform directory (in-project mode).
337
337
  */
338
338
  declare function isPlatformDir(dirName: string): boolean;
339
339
  /**
340
- * Get the platform ID from a directory name, if it matches a platform's projectDir.
340
+ * Get the platform ID from a directory name, if it matches a platform's platformDir.
341
341
  */
342
342
  declare function getPlatformFromDir(dirName: string): PlatformId | undefined;
343
+ /**
344
+ * Infer the platform from a file path by searching for platformDir segments.
345
+ *
346
+ * Example: "/repo/.claude/commands/foo.md" -> "claude"
347
+ */
348
+ declare function inferPlatformFromPath(value: string): PlatformId | undefined;
349
+ /**
350
+ * Return all platforms whose instruction file matches this basename.
351
+ *
352
+ * Example: "CLAUDE.md" -> ["claude"], "AGENTS.md" -> ["opencode", "cursor", "codex"]
353
+ */
354
+ declare function inferInstructionPlatformsFromFileName(fileName: string): PlatformId[];
355
+ /**
356
+ * Infer a rule type from a file path for a known platform.
357
+ * Uses PLATFORMS templates as source-of-truth.
358
+ */
359
+ declare function inferTypeFromPath(platform: PlatformId, filePath: string): string | undefined;
360
+
361
+ //#endregion
362
+ //#region src/resolve/types.d.ts
363
+ /** Base fields for all variants */
364
+ type BaseVariant = {
365
+ platform: PlatformId;
366
+ };
367
+ /** Rule variant with bundle URL (for larger rules) */
368
+ type RuleVariantBundle = BaseVariant & {
369
+ bundleUrl: string;
370
+ fileCount: number;
371
+ totalSize: number;
372
+ };
373
+ /** Rule variant with inline content (for smaller rules) */
374
+ type RuleVariantInline = BaseVariant & {
375
+ content: string;
376
+ fileCount: number;
377
+ totalSize: number;
378
+ };
379
+ /** Rule variant - registry decides bundleUrl vs inline content */
380
+ type RuleVariant = RuleVariantBundle | RuleVariantInline;
381
+ type RuleVersion = {
382
+ version: string;
383
+ isLatest: boolean;
384
+ publishedAt?: string;
385
+ variants: RuleVariant[];
386
+ };
387
+ type ResolvedRule = {
388
+ slug: string;
389
+ name: string;
390
+ /** Rule type - optional, defaults to freeform file structure */
391
+ type?: RuleType;
392
+ title: string;
393
+ description: string;
394
+ tags: string[];
395
+ license: string;
396
+ features: string[];
397
+ versions: RuleVersion[];
398
+ };
399
+ /** Response from items endpoint */
400
+ type ResolveResponse = ResolvedRule;
401
+
402
+ //#endregion
403
+ //#region src/resolve/utils.d.ts
404
+ /**
405
+ * Type guard for rule variant with bundleUrl
406
+ */
407
+ declare function hasBundle(variant: RuleVariant): variant is RuleVariant & {
408
+ bundleUrl: string;
409
+ };
410
+ /**
411
+ * Type guard for rule variant with inline content
412
+ */
413
+ declare function hasInlineContent(variant: RuleVariant): variant is RuleVariant & {
414
+ content: string;
415
+ };
416
+ /**
417
+ * Get the latest version from a resolved rule
418
+ */
419
+ declare function getLatestVersion(item: ResolvedRule): RuleVersion | undefined;
420
+ /**
421
+ * Get a specific version from a resolved rule
422
+ */
423
+ declare function getVersion(item: ResolvedRule, version: string): RuleVersion | undefined;
424
+ /**
425
+ * Get a specific platform variant from a rule version
426
+ */
427
+ declare function getVariant(version: RuleVersion, platform: PlatformId): RuleVariant | undefined;
428
+ /**
429
+ * Get all available platforms for a rule version
430
+ */
431
+ declare function getPlatforms(version: RuleVersion): PlatformId[];
432
+ /**
433
+ * Check if a platform is available in any version of a rule
434
+ */
435
+ declare function hasPlatform(item: ResolvedRule, platform: PlatformId): boolean;
343
436
 
344
437
  //#endregion
345
- //#region src/preset/types.d.ts
346
- type PresetConfig = {
438
+ //#region src/rule/schema.d.ts
439
+ declare const platformIdSchema: z.ZodEnum<{
440
+ opencode: "opencode";
441
+ codex: "codex";
442
+ claude: "claude";
443
+ cursor: "cursor";
444
+ }>;
445
+ declare const COMMON_LICENSES: readonly ["MIT", "Apache-2.0", "GPL-3.0-only", "BSD-3-Clause", "ISC", "Unlicense"];
446
+ type CommonLicense = (typeof COMMON_LICENSES)[number];
447
+ declare const licenseSchema: z.ZodString;
448
+ /**
449
+ * Schema for rule type.
450
+ * Valid types: instruction, rule, command, skill, agent, tool, multi.
451
+ * Optional - defaults to "multi" (freeform file structure).
452
+ * Platform-specific validation happens at publish time.
453
+ */
454
+ declare const ruleTypeSchema: z.ZodEnum<{
455
+ instruction: "instruction";
456
+ rule: "rule";
457
+ command: "command";
458
+ skill: "skill";
459
+ agent: "agent";
460
+ tool: "tool";
461
+ }>;
462
+ /**
463
+ * Rule config schema.
464
+ *
465
+ * Uses a unified `platforms` array that accepts either:
466
+ * - Platform ID strings: `["opencode", "claude"]`
467
+ * - Objects with optional path: `[{ platform: "opencode", path: "rules" }]`
468
+ * - Mixed: `["opencode", { platform: "claude", path: "my-claude" }]`
469
+ */
470
+ declare const ruleConfigSchema: z.ZodObject<{
471
+ $schema: z.ZodOptional<z.ZodString>;
472
+ name: z.ZodString;
473
+ type: z.ZodOptional<z.ZodEnum<{
474
+ instruction: "instruction";
475
+ rule: "rule";
476
+ command: "command";
477
+ skill: "skill";
478
+ agent: "agent";
479
+ tool: "tool";
480
+ }>>;
481
+ title: z.ZodString;
482
+ version: z.ZodOptional<z.ZodNumber>;
483
+ description: z.ZodDefault<z.ZodOptional<z.ZodString>>;
484
+ tags: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString>>>;
485
+ features: z.ZodOptional<z.ZodArray<z.ZodString>>;
486
+ license: z.ZodString;
487
+ ignore: z.ZodOptional<z.ZodArray<z.ZodString>>;
488
+ platforms: z.ZodArray<z.ZodUnion<readonly [z.ZodEnum<{
489
+ opencode: "opencode";
490
+ codex: "codex";
491
+ claude: "claude";
492
+ cursor: "cursor";
493
+ }>, z.ZodObject<{
494
+ platform: z.ZodEnum<{
495
+ opencode: "opencode";
496
+ codex: "codex";
497
+ claude: "claude";
498
+ cursor: "cursor";
499
+ }>;
500
+ path: z.ZodOptional<z.ZodString>;
501
+ }, z.core.$strict>]>>;
502
+ }, z.core.$strict>;
503
+ declare const bundledFileSchema: z.ZodObject<{
504
+ path: z.ZodString;
505
+ size: z.ZodNumber;
506
+ checksum: z.ZodString;
507
+ content: z.ZodString;
508
+ }, z.core.$strip>;
509
+ /**
510
+ * Schema for per-platform variant in publish input.
511
+ */
512
+ declare const publishVariantInputSchema: z.ZodObject<{
513
+ platform: z.ZodEnum<{
514
+ opencode: "opencode";
515
+ codex: "codex";
516
+ claude: "claude";
517
+ cursor: "cursor";
518
+ }>;
519
+ files: z.ZodArray<z.ZodObject<{
520
+ path: z.ZodString;
521
+ size: z.ZodNumber;
522
+ checksum: z.ZodString;
523
+ content: z.ZodString;
524
+ }, z.core.$strip>>;
525
+ readmeContent: z.ZodOptional<z.ZodString>;
526
+ licenseContent: z.ZodOptional<z.ZodString>;
527
+ installMessage: z.ZodOptional<z.ZodString>;
528
+ }, z.core.$strip>;
529
+ /**
530
+ * Schema for what clients send to publish a rule.
531
+ *
532
+ * One publish call creates ONE version with ALL platform variants.
533
+ * Version is optional major version. Registry assigns full MAJOR.MINOR.
534
+ *
535
+ * Note: Clients send `name` (e.g., "my-rule"), and the registry defines the format of the slug.
536
+ * For example, a namespaced slug could be returned as "username/my-rule"
537
+ */
538
+ declare const rulePublishInputSchema: z.ZodObject<{
539
+ name: z.ZodString;
540
+ type: z.ZodOptional<z.ZodEnum<{
541
+ instruction: "instruction";
542
+ rule: "rule";
543
+ command: "command";
544
+ skill: "skill";
545
+ agent: "agent";
546
+ tool: "tool";
547
+ }>>;
548
+ title: z.ZodString;
549
+ description: z.ZodDefault<z.ZodOptional<z.ZodString>>;
550
+ tags: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString>>>;
551
+ license: z.ZodString;
552
+ features: z.ZodOptional<z.ZodArray<z.ZodString>>;
553
+ variants: z.ZodArray<z.ZodObject<{
554
+ platform: z.ZodEnum<{
555
+ opencode: "opencode";
556
+ codex: "codex";
557
+ claude: "claude";
558
+ cursor: "cursor";
559
+ }>;
560
+ files: z.ZodArray<z.ZodObject<{
561
+ path: z.ZodString;
562
+ size: z.ZodNumber;
563
+ checksum: z.ZodString;
564
+ content: z.ZodString;
565
+ }, z.core.$strip>>;
566
+ readmeContent: z.ZodOptional<z.ZodString>;
567
+ licenseContent: z.ZodOptional<z.ZodString>;
568
+ installMessage: z.ZodOptional<z.ZodString>;
569
+ }, z.core.$strip>>;
570
+ version: z.ZodOptional<z.ZodNumber>;
571
+ }, z.core.$strip>;
572
+ /**
573
+ * Schema for what registries store and return for a single platform bundle.
574
+ * This is per-platform (flat structure), stored in R2 and fetched via bundleUrl.
575
+ */
576
+ declare const ruleBundleSchema: z.ZodObject<{
577
+ name: z.ZodString;
578
+ type: z.ZodOptional<z.ZodEnum<{
579
+ instruction: "instruction";
580
+ rule: "rule";
581
+ command: "command";
582
+ skill: "skill";
583
+ agent: "agent";
584
+ tool: "tool";
585
+ }>>;
586
+ platform: z.ZodEnum<{
587
+ opencode: "opencode";
588
+ codex: "codex";
589
+ claude: "claude";
590
+ cursor: "cursor";
591
+ }>;
592
+ title: z.ZodString;
593
+ description: z.ZodDefault<z.ZodOptional<z.ZodString>>;
594
+ tags: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString>>>;
595
+ license: z.ZodString;
596
+ features: z.ZodOptional<z.ZodArray<z.ZodString>>;
597
+ files: z.ZodArray<z.ZodObject<{
598
+ path: z.ZodString;
599
+ size: z.ZodNumber;
600
+ checksum: z.ZodString;
601
+ content: z.ZodString;
602
+ }, z.core.$strip>>;
603
+ readmeContent: z.ZodOptional<z.ZodString>;
604
+ licenseContent: z.ZodOptional<z.ZodString>;
605
+ installMessage: z.ZodOptional<z.ZodString>;
606
+ slug: z.ZodString;
607
+ version: z.ZodString;
608
+ }, z.core.$strip>;
609
+
610
+ //#endregion
611
+ //#region src/rule/types.d.ts
612
+ /** Normalized platform entry - always object form */
613
+ type PlatformEntry = {
614
+ platform: PlatformId;
615
+ path?: string;
616
+ };
617
+ /** Raw platform entry - string shorthand or object with optional path */
618
+ type RawPlatformEntry = PlatformId | PlatformEntry;
619
+ /** Normalize a raw platform entry to the object form */
620
+ declare function normalizePlatformEntry(entry: RawPlatformEntry): PlatformEntry;
621
+ /**
622
+ * Raw rule configuration - what users write in agentrules.json.
623
+ *
624
+ * Uses a unified `platforms` array that accepts either:
625
+ * - Platform ID strings: `["opencode", "claude"]`
626
+ * - Objects with optional path: `[{ platform: "opencode", path: "rules" }]`
627
+ * - Mixed: `["opencode", { platform: "claude", path: "my-claude" }]`
628
+ *
629
+ * **Order matters**: The first platform in the array is used as the default
630
+ * when viewing the rule on the registry without specifying a platform.
631
+ */
632
+ type RawRuleConfig = {
347
633
  $schema?: string;
348
634
  name: string;
635
+ /**
636
+ * Rule type - determines install path and constrains valid platforms.
637
+ * Optional - defaults to "multi" (freeform file structure).
638
+ */
639
+ type?: RuleType;
349
640
  title: string;
350
641
  version?: number;
351
642
  description: string;
352
643
  tags?: string[];
353
644
  features?: string[];
354
645
  license: string;
355
- platform: PlatformId;
356
- /** Path to config files. Defaults to platform's projectDir (e.g., ".claude") */
357
- path?: string;
358
646
  /** Additional patterns to exclude from bundle (glob patterns) */
359
647
  ignore?: string[];
648
+ /**
649
+ * Target platforms with optional custom paths.
650
+ * Order matters: the first platform is used as the default when viewing
651
+ * the rule on the registry.
652
+ */
653
+ platforms: RawPlatformEntry[];
654
+ };
655
+ /**
656
+ * Normalized rule configuration - used internally after loading.
657
+ */
658
+ type RuleConfig = Omit<RawRuleConfig, "platforms"> & {
659
+ platforms: PlatformEntry[];
360
660
  };
361
661
  type BundledFile = {
362
662
  path: string;
363
663
  /** File size in bytes */
364
664
  size: number;
365
665
  checksum: string;
366
- contents: string;
666
+ content: string;
667
+ };
668
+ /**
669
+ * Per-platform variant input for publishing.
670
+ * Contains files and optional metadata for a single platform.
671
+ */
672
+ type PublishVariantInput = {
673
+ platform: PlatformId;
674
+ files: BundledFile[];
675
+ /** Optional per-platform README */
676
+ readmeContent?: string;
677
+ /** Optional per-platform LICENSE */
678
+ licenseContent?: string;
679
+ /** Optional per-platform install message */
680
+ installMessage?: string;
367
681
  };
368
682
  /**
369
- * What clients send to publish a preset.
683
+ * What clients send to publish a rule (multi-platform).
684
+ *
685
+ * One publish call creates ONE version with ALL platform variants.
370
686
  * Version is optional major version. Registry assigns full MAJOR.MINOR.
371
687
  *
372
- * Note: Clients send `name` (e.g., "my-preset"), and the registry defines the format of the slug.
373
- * For example, a namespaced slug could be returned as "username/my-preset"
688
+ * Note: Clients send `name` (e.g., "my-rule"), and the registry defines the format of the slug.
689
+ * For example, a namespaced slug could be returned as "username/my-rule"
374
690
  */
375
- type PresetPublishInput = {
691
+ type RulePublishInput = {
376
692
  name: string;
377
- platform: PlatformId;
693
+ /** Rule type - optional, defaults to freeform file structure */
694
+ type?: RuleType;
378
695
  title: string;
379
696
  description: string;
380
697
  tags: string[];
381
698
  license: string;
382
- licenseContent?: string;
383
- readmeContent?: string;
384
699
  features?: string[];
385
- installMessage?: string;
386
- files: BundledFile[];
700
+ /** Platform variants - each contains files for that platform */
701
+ variants: PublishVariantInput[];
387
702
  /** Major version. Defaults to 1 if not specified. */
388
703
  version?: number;
389
704
  };
390
705
  /**
391
- * What registries store and return.
392
- * Includes full namespaced slug and version assigned by registry.
706
+ * What registries store and return for a single platform bundle.
707
+ * This is stored in R2 and fetched via bundleUrl.
708
+ *
709
+ * Note: This is per-platform, while RulePublishInput is multi-platform.
393
710
  */
394
- type PresetBundle = Omit<PresetPublishInput, "name" | "version"> & {
395
- /** Full namespaced slug (e.g., "username/my-preset") */
396
- slug: string;
397
- /** Full version in MAJOR.MINOR format (e.g., "1.3", "2.1") */
398
- version: string;
399
- };
400
- type Preset = {
711
+ type RuleBundle = {
401
712
  name: string;
402
- slug: string;
713
+ /** Rule type - optional, defaults to freeform file structure */
714
+ type?: RuleType;
403
715
  platform: PlatformId;
404
716
  title: string;
405
- version: string;
406
717
  description: string;
407
718
  tags: string[];
408
719
  license: string;
409
720
  features?: string[];
410
- bundleUrl: string;
411
- fileCount: number;
412
- totalSize: number;
721
+ files: BundledFile[];
722
+ readmeContent?: string;
723
+ licenseContent?: string;
724
+ installMessage?: string;
725
+ /** Full namespaced slug (e.g., "username/my-rule") */
726
+ slug: string;
727
+ /** Full version in MAJOR.MINOR format (e.g., "1.3", "2.1") */
728
+ version: string;
413
729
  };
414
- type PresetIndex = Record<string, Preset>;
415
- type PresetFileInput = {
730
+ type RuleFileInput = {
416
731
  path: string;
417
- contents: ArrayBuffer | ArrayBufferView | string;
732
+ content: ArrayBuffer | ArrayBufferView | string;
418
733
  };
419
- type PresetInput = {
734
+ /**
735
+ * Files for a single platform variant
736
+ */
737
+ type PlatformFiles = {
738
+ platform: PlatformId;
739
+ files: RuleFileInput[];
740
+ /** Optional per-platform install message */
741
+ installMessage?: string;
742
+ /** Optional per-platform README */
743
+ readmeContent?: string;
744
+ /** Optional per-platform LICENSE */
745
+ licenseContent?: string;
746
+ };
747
+ /**
748
+ * Rule input - what the CLI builds after loading files.
749
+ * Always uses platformFiles array (works for single or multi-platform).
750
+ */
751
+ type RuleInput = {
420
752
  name: string;
421
- config: PresetConfig;
422
- files: PresetFileInput[];
423
- /** Install message from INSTALL.txt file */
753
+ config: RuleConfig;
754
+ /** Files for each platform */
755
+ platformFiles: PlatformFiles[];
756
+ /** Shared install message (fallback for platforms without their own) */
424
757
  installMessage?: string;
758
+ /** Shared README (fallback for platforms without their own) */
425
759
  readmeContent?: string;
760
+ /** Shared LICENSE (fallback for platforms without their own) */
426
761
  licenseContent?: string;
427
762
  };
428
763
 
764
+ //#endregion
765
+ //#region src/rule/validate.d.ts
766
+ type RuleValidationResult = {
767
+ valid: boolean;
768
+ errors: string[];
769
+ warnings: string[];
770
+ };
771
+ declare function validateRule(config: RuleConfig): RuleValidationResult;
772
+
429
773
  //#endregion
430
774
  //#region src/builder/registry.d.ts
431
775
  /**
@@ -434,47 +778,56 @@ type PresetInput = {
434
778
  */
435
779
  declare const STATIC_BUNDLE_DIR = "registry";
436
780
  /**
437
- * Options for building a PresetPublishInput (for CLI publish command).
781
+ * Options for building a publish input.
438
782
  */
439
- type BuildPresetPublishInputOptions = {
440
- preset: PresetInput;
783
+ type BuildPublishInputOptions = {
784
+ /** Rule input (single or multi-platform) */
785
+ rule: RuleInput;
441
786
  /** Major version. Defaults to 1 if not specified. */
442
787
  version?: number;
443
788
  };
444
789
  /**
445
- * Builds a PresetPublishInput from preset input.
446
- * Used by CLI to prepare data for publishing to a registry.
790
+ * Builds a RulePublishInput from rule input.
791
+ *
792
+ * RuleInput always has platformFiles array (unified format).
447
793
  */
448
- declare function buildPresetPublishInput(options: BuildPresetPublishInputOptions): Promise<PresetPublishInput>;
794
+ declare function buildPublishInput(options: BuildPublishInputOptions): Promise<RulePublishInput>;
449
795
  /**
450
796
  * Options for building a static registry.
451
797
  */
452
- type BuildPresetRegistryOptions = {
453
- presets: PresetInput[];
798
+ type BuildRegistryOptions = {
799
+ /** Rules to include (single or multi-platform) */
800
+ rules: RuleInput[];
454
801
  /**
455
802
  * Optional base path or URL prefix for bundle locations.
456
- * Format: {bundleBase}/{STATIC_BUNDLE_DIR}/{slug}/{platform}
803
+ * Format: {bundleBase}/{STATIC_BUNDLE_DIR}/{slug}/{platform}/{version}
457
804
  * Default: no prefix (bundleUrl starts with STATIC_BUNDLE_DIR)
458
805
  */
459
806
  bundleBase?: string;
460
807
  };
461
- type BuildPresetRegistryResult = {
462
- entries: Preset[];
463
- index: PresetIndex;
464
- bundles: PresetBundle[];
808
+ type BuildRegistryResult = {
809
+ /** Resolved rules in the unified format (one per slug with all versions/variants) */
810
+ rules: ResolvedRule[];
811
+ /** Bundles for each platform variant (used to write individual bundle files) */
812
+ bundles: RuleBundle[];
465
813
  };
466
814
  /**
467
- * Builds a static registry with entries, index, and bundles.
468
- * Used for building static registry files (e.g., community-presets).
469
- * Each preset uses its version from config (default: major 1, minor 0).
815
+ * Builds a static registry with items and bundles.
816
+ *
817
+ * Uses the same model as dynamic publishing:
818
+ * - Each RuleInput (single or multi-platform) becomes one item
819
+ * - Each platform variant becomes one bundle
470
820
  */
471
- declare function buildPresetRegistry(options: BuildPresetRegistryOptions): Promise<BuildPresetRegistryResult>;
821
+ declare function buildRegistry(options: BuildRegistryOptions): Promise<BuildRegistryResult>;
472
822
 
473
823
  //#endregion
474
824
  //#region src/builder/utils.d.ts
475
825
  declare function cleanInstallMessage(value: unknown): string | undefined;
476
- declare function encodeItemName(slug: string, platform: PlatformId): string;
477
- declare function validatePresetConfig(config: unknown, slug: string): PresetConfig;
826
+ /**
827
+ * Validate raw rule config from JSON.
828
+ * Returns the raw config shape (before normalization).
829
+ */
830
+ declare function validateConfig(config: unknown, slug: string): RawRuleConfig;
478
831
 
479
832
  //#endregion
480
833
  //#region src/client/bundle.d.ts
@@ -486,60 +839,47 @@ declare function toUtf8String(payload: ArrayBuffer | ArrayBufferView): string;
486
839
  //#endregion
487
840
  //#region src/client/registry.d.ts
488
841
  /**
489
- * Resolved preset with absolute bundle URL
842
+ * Fetches a bundle from an absolute URL.
490
843
  */
491
- type ResolvedPreset = {
492
- preset: Preset;
493
- bundleUrl: string;
494
- };
844
+ declare function fetchBundle(bundleUrl: string): Promise<RuleBundle>;
495
845
  /**
496
- * Resolves a preset from the registry via API endpoint.
497
- * Returns the entry metadata and the absolute bundle URL.
846
+ * Resolves a slug to get all versions and platform variants.
498
847
  *
499
848
  * @param baseUrl - Registry base URL
500
- * @param slug - Preset slug
501
- * @param platform - Target platform
502
- * @param version - Version to resolve (defaults to "latest")
503
- */
504
- declare function resolvePreset(baseUrl: string, slug: string, platform: PlatformId, version?: string): Promise<ResolvedPreset>;
505
- /**
506
- * Fetches a bundle from an absolute URL or resolves it relative to the registry.
849
+ * @param slug - Content slug (may contain slashes, e.g., "username/my-rule")
850
+ * @param version - Optional version filter (server may ignore for static registries)
851
+ * @returns Resolved data, or null if not found
852
+ * @throws Error on network/server errors
507
853
  */
508
- declare function fetchBundle(bundleUrl: string): Promise<PresetBundle>;
854
+ declare function resolveSlug(baseUrl: string, slug: string, version?: string): Promise<ResolveResponse | null>;
509
855
 
510
856
  //#endregion
511
857
  //#region src/constants.d.ts
512
858
  /**
513
- * Shared constants for agentrules presets and registry.
859
+ * Shared constants for agentrules.
514
860
  */
515
- /** Filename for preset configuration */
516
- declare const PRESET_CONFIG_FILENAME = "agentrules.json";
517
- /** Directory name for preset metadata (README, LICENSE, etc.) */
518
- declare const AGENT_RULES_DIR = ".agentrules";
519
- /** JSON Schema URL for preset configuration */
520
- declare const PRESET_SCHEMA_URL = "https://agentrules.directory/schema/agentrules.json";
521
- /** Default version identifier for latest preset version */
861
+ /** Filename for rule configuration */
862
+ declare const RULE_CONFIG_FILENAME = "agentrules.json";
863
+ /** JSON Schema URL for rule configuration */
864
+ declare const RULE_SCHEMA_URL = "https://agentrules.directory/schema/agentrules.json";
865
+ /** Default version identifier for latest rule version */
522
866
  declare const LATEST_VERSION = "latest";
523
867
  /**
524
868
  * API endpoint paths (relative to registry base URL).
525
869
  *
526
- * Note: Path parameters (slug, platform, version) are NOT URI-encoded.
527
- * - Slugs may contain slashes (e.g., "username/my-preset") which should flow
528
- * through as path segments for static registry compatibility
529
- * - Platform and version are constrained values (enums, validated formats)
530
- * that only contain URL-safe characters
531
- *
532
- * The client is responsible for validating these values before making requests.
870
+ * Note on slug handling:
871
+ * - Slugs may contain slashes (e.g., "username/my-rule") which flow through as path segments
872
+ * - The client is responsible for validating values before making requests
533
873
  */
534
874
  declare const API_ENDPOINTS: {
535
- /** Preset endpoints */
536
- readonly presets: {
537
- /** Base path for preset operations */
538
- readonly base: "api/preset";
539
- /** Get preset by slug, platform, and version (defaults to "latest") */
540
- readonly get: (slug: string, platform: string, version?: string) => string;
541
- /** Unpublish preset version */
542
- readonly unpublish: (slug: string, platform: string, version: string) => string;
875
+ /** Rule endpoints (for publishing) */
876
+ readonly rules: {
877
+ /** Base path for rule operations (POST to publish) */
878
+ readonly base: "api/rules";
879
+ /** Get rule by slug (GET) */
880
+ readonly get: (slug: string) => string;
881
+ /** Unpublish rule version (DELETE) */
882
+ readonly unpublish: (slug: string, version: string) => string;
543
883
  };
544
884
  /** Auth endpoints */
545
885
  readonly auth: {
@@ -550,112 +890,41 @@ declare const API_ENDPOINTS: {
550
890
  /** Device token exchange */
551
891
  readonly deviceToken: "api/auth/device/token";
552
892
  };
553
- /** Rule endpoints */
554
- readonly rule: {
555
- /** Base path for rule operations */
556
- readonly base: "api/rule";
557
- /** Get or update rule by slug */
558
- readonly get: (slug: string) => string;
559
- };
560
893
  };
561
894
 
562
895
  //#endregion
563
- //#region src/rule/schema.d.ts
896
+ //#region src/schemas/common.d.ts
564
897
  /**
565
- * Schema for the rule name.
566
- * This is what users provide when creating a rule.
898
+ * Schema for a single tag.
899
+ * - Max 35 characters
900
+ * - Lowercase alphanumeric with hyphens
901
+ * - Platform names blocked (redundant with platform field)
567
902
  */
568
- declare const ruleNameSchema: z.ZodString;
569
- declare const ruleTitleSchema: z.ZodString;
570
- declare const ruleDescriptionSchema: z.ZodString;
571
- declare const rulePlatformSchema: z.ZodEnum<{
572
- opencode: "opencode";
573
- codex: "codex";
574
- claude: "claude";
575
- cursor: "cursor";
576
- }>;
577
- declare const ruleTypeSchema: z.ZodString;
578
- declare const ruleContentSchema: z.ZodString;
579
- declare const ruleTagSchema: z.ZodString;
580
- declare const ruleTagsSchema: z.ZodArray<z.ZodString>;
903
+ declare const tagSchema: z.ZodString;
581
904
  /**
582
- * Discriminated union schema for platform + type combinations.
583
- * Each platform has its own set of valid types.
905
+ * Schema for tags array.
906
+ * - 0-10 tags allowed
584
907
  */
585
- declare const rulePlatformTypeSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
586
- platform: z.ZodLiteral<"opencode">;
587
- type: z.ZodEnum<{
588
- instruction: "instruction";
589
- agent: "agent";
590
- command: "command";
591
- tool: "tool";
592
- }>;
593
- }, z.core.$strip>, z.ZodObject<{
594
- platform: z.ZodLiteral<"claude">;
595
- type: z.ZodEnum<{
596
- instruction: "instruction";
597
- command: "command";
598
- skill: "skill";
599
- }>;
600
- }, z.core.$strip>, z.ZodObject<{
601
- platform: z.ZodLiteral<"cursor">;
602
- type: z.ZodEnum<{
603
- rule: "rule";
604
- }>;
605
- }, z.core.$strip>, z.ZodObject<{
606
- platform: z.ZodLiteral<"codex">;
607
- type: z.ZodEnum<{
608
- instruction: "instruction";
609
- command: "command";
610
- }>;
611
- }, z.core.$strip>], "platform">;
612
- /** Schema for rule creation with discriminated union for platform+type */
613
- declare const ruleCreateInputSchema: z.ZodIntersection<z.ZodObject<{
614
- name: z.ZodString;
615
- title: z.ZodString;
616
- description: z.ZodOptional<z.ZodString>;
617
- content: z.ZodString;
618
- tags: z.ZodArray<z.ZodString>;
619
- }, z.core.$strip>, z.ZodDiscriminatedUnion<[z.ZodObject<{
620
- platform: z.ZodLiteral<"opencode">;
621
- type: z.ZodEnum<{
622
- instruction: "instruction";
623
- agent: "agent";
624
- command: "command";
625
- tool: "tool";
626
- }>;
627
- }, z.core.$strip>, z.ZodObject<{
628
- platform: z.ZodLiteral<"claude">;
629
- type: z.ZodEnum<{
630
- instruction: "instruction";
631
- command: "command";
632
- skill: "skill";
633
- }>;
634
- }, z.core.$strip>, z.ZodObject<{
635
- platform: z.ZodLiteral<"cursor">;
636
- type: z.ZodEnum<{
637
- rule: "rule";
638
- }>;
639
- }, z.core.$strip>, z.ZodObject<{
640
- platform: z.ZodLiteral<"codex">;
641
- type: z.ZodEnum<{
642
- instruction: "instruction";
643
- command: "command";
644
- }>;
645
- }, z.core.$strip>], "platform">>;
646
- declare const ruleUpdateInputSchema: z.ZodObject<{
647
- name: z.ZodString;
648
- title: z.ZodOptional<z.ZodString>;
649
- description: z.ZodOptional<z.ZodString>;
650
- content: z.ZodOptional<z.ZodString>;
651
- tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
652
- }, z.core.$strip>;
653
- type RuleCreateInput = z.infer<typeof ruleCreateInputSchema>;
654
- type RuleUpdateInput = z.infer<typeof ruleUpdateInputSchema>;
908
+ declare const tagsSchema: z.ZodArray<z.ZodString>;
909
+ /**
910
+ * Schema for rule name.
911
+ * - Max 64 characters
912
+ * - Lowercase alphanumeric with hyphens
913
+ */
914
+ declare const nameSchema: z.ZodString;
915
+ /**
916
+ * Schema for display title.
917
+ * - Max 80 characters
918
+ */
919
+ declare const titleSchema: z.ZodString;
920
+ /**
921
+ * Schema for description.
922
+ * - Max 500 characters
923
+ */
924
+ declare const descriptionSchema: z.ZodString;
655
925
 
656
926
  //#endregion
657
927
  //#region src/utils/diff.d.ts
658
- /** Re-export platform-rule types for convenience */
659
928
  type DiffPreviewOptions = {
660
929
  context?: number;
661
930
  maxLines?: number;
@@ -678,4 +947,4 @@ declare function toUint8Array(payload: ArrayBuffer | ArrayBufferView): Uint8Arra
678
947
  declare function normalizeBundlePath(value: string): string;
679
948
 
680
949
  //#endregion
681
- export { AGENT_RULES_DIR, API_ENDPOINTS, BuildPresetPublishInputOptions, BuildPresetRegistryOptions, BuildPresetRegistryResult, BundledFile, COMMON_LICENSES, CommonLicense, DiffPreviewOptions, LATEST_VERSION, PLATFORMS, PLATFORM_IDS, PLATFORM_ID_TUPLE, PLATFORM_RULE_TYPES, PRESET_CONFIG_FILENAME, PRESET_SCHEMA_URL, PlatformId, PlatformRuleConfig, PlatformRuleType, Preset, PresetBundle, PresetConfig, PresetFileInput, PresetIndex, PresetInput, PresetPublishInput, ResolvedPreset, RuleCreateInput, RuleFileFormat, RuleType, RuleTypeConfig, RuleTypeForPlatform, RuleUpdateInput, STATIC_BUNDLE_DIR, buildPresetPublishInput, buildPresetRegistry, bundledFileSchema, cleanInstallMessage, createDiffPreview, decodeBundledFile, decodeUtf8, descriptionSchema, encodeItemName, encodeUtf8, fetchBundle, getInstallPath, getPlatformConfig, getPlatformFromDir, getRuleTypeConfig, getValidRuleTypes, isLikelyText, isPlatformDir, isSupportedPlatform, isValidRuleType, licenseSchema, normalizeBundlePath, normalizePlatformInput, platformIdSchema, presetBundleSchema, presetConfigSchema, presetIndexSchema, presetPublishInputSchema, presetSchema, resolvePreset, ruleContentSchema, ruleCreateInputSchema, ruleDescriptionSchema, ruleNameSchema, rulePlatformSchema, rulePlatformTypeSchema, ruleTagSchema, ruleTagsSchema, ruleTitleSchema, ruleTypeSchema, ruleUpdateInputSchema, slugSchema, tagSchema, tagsSchema, titleSchema, toPosixPath, toUint8Array, toUtf8String, validatePresetConfig, verifyBundledFileChecksum };
950
+ export { API_ENDPOINTS, BuildPublishInputOptions, BuildRegistryOptions, BuildRegistryResult, BundledFile, COMMON_LICENSES, CommonLicense, DiffPreviewOptions, GetInstallPathInput, InstallScope, LATEST_VERSION, PLATFORMS, PLATFORM_IDS, PLATFORM_ID_TUPLE, PLATFORM_RULE_TYPES, PlatformConfig, PlatformEntry, PlatformFiles, PlatformId, PlatformRuleType, PublishVariantInput, RULE_CONFIG_FILENAME, RULE_SCHEMA_URL, RULE_TYPE_TUPLE, RawPlatformEntry, RawRuleConfig, ResolveResponse, ResolvedRule, RuleBundle, RuleConfig, RuleFileInput, RuleInput, RulePublishInput, RuleType, RuleTypeForPlatform, RuleValidationResult, RuleVariant, RuleVersion, STATIC_BUNDLE_DIR, SupportsInstallPathInput, TypeConfig, buildPublishInput, buildRegistry, bundledFileSchema, cleanInstallMessage, createDiffPreview, decodeBundledFile, decodeUtf8, descriptionSchema, encodeUtf8, fetchBundle, getInstallPath, getLatestVersion, getPlatformConfig, getPlatformFromDir, getPlatforms, getTypeConfig, getValidTypes, getVariant, getVersion, hasBundle, hasInlineContent, hasPlatform, inferInstructionPlatformsFromFileName, inferPlatformFromPath, inferTypeFromPath, isLikelyText, isPlatformDir, isSupportedPlatform, isValidType, licenseSchema, nameSchema, normalizeBundlePath, normalizePlatformEntry, normalizePlatformInput, platformIdSchema, publishVariantInputSchema, resolveResponseSchema, resolveSlug, resolvedRuleSchema, ruleBundleSchema, ruleConfigSchema, rulePublishInputSchema, ruleTypeSchema, ruleVariantSchema, ruleVersionSchema, supportsInstallPath, tagSchema, tagsSchema, titleSchema, toPosixPath, toUint8Array, toUtf8String, validateConfig, validateRule, verifyBundledFileChecksum };