aicm 0.18.0 → 0.19.1

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.
package/README.md CHANGED
@@ -14,11 +14,11 @@ A CLI tool for managing Agentic configurations across projects.
14
14
  - [Creating a Preset](#creating-a-preset)
15
15
  - [Using a Preset](#using-a-preset)
16
16
  - [Features](#features)
17
- - [Rules](#using-rules)
18
- - [Commands](#using-commands)
17
+ - [Rules](#rules)
18
+ - [Commands](#commands)
19
+ - [Hooks](#hooks)
19
20
  - [MCP Servers](#mcp-servers)
20
- - [Auxiliary Files](#referencing-auxiliary-files)
21
- - [Overrides](#overrides)
21
+ - [Assets](#assets)
22
22
  - [Workspaces Support](#workspaces-support)
23
23
  - [Configuration](#configuration)
24
24
  - [CLI Commands](#cli-commands)
@@ -78,19 +78,22 @@ After installation, open Cursor and ask it to do something. Your AI assistant wi
78
78
  1. **Create an npm package** with the following structure:
79
79
 
80
80
  ```
81
- @team/ai-preset
81
+ @team/ai-preset/
82
82
  ├── package.json
83
83
  ├── aicm.json
84
- └── rules/
85
- ├── typescript.mdc
86
- └── react.mdc
84
+ ├── rules/ # Rule files (.mdc)
85
+ ├── typescript.mdc
86
+ └── react.mdc
87
+ ├── commands/ # Command files (.md) [optional]
88
+ ├── assets/ # Auxiliary files [optional]
89
+ └── hooks.json # Hook configuration [optional]
87
90
  ```
88
91
 
89
92
  2. **Configure the preset's `aicm.json`**:
90
93
 
91
94
  ```json
92
95
  {
93
- "rulesDir": "rules",
96
+ "rootDir": "./",
94
97
  "mcpServers": {
95
98
  "my-mcp": { "url": "https://example.com/sse" }
96
99
  }
@@ -135,112 +138,220 @@ The rules are now installed in `.cursor/rules/aicm/` and any MCP servers are con
135
138
 
136
139
  ### Notes
137
140
 
138
- - Generated rules are always placed in a subdirectory for deterministic cleanup and easy gitignore.
139
- - Users should add `.cursor/rules/aicm/` and `.aicm/` (for Windsurf/Codex) to `.gitignore` to avoid tracking generated rules.
141
+ - Generated files are always placed in subdirectories for deterministic cleanup and easy gitignore.
142
+ - Users should add `.cursor/*/aicm/` to `.gitignore` to avoid tracking generated files. This single pattern covers all aicm-managed directories (rules, commands, assets, hooks).
140
143
 
141
144
  ## Features
142
145
 
143
- ### Using Rules
146
+ ### Rules
144
147
 
145
148
  aicm uses Cursor's `.mdc` files for rules. Read more about the format [here](https://cursor.com/docs/context/rules).
146
149
 
147
- Add a rules directory to your project configuration:
150
+ Create a `rules/` directory in your project (at the `rootDir` location):
151
+
152
+ ```
153
+ my-project/
154
+ ├── aicm.json
155
+ └── rules/
156
+ ├── typescript.mdc
157
+ └── react.mdc
158
+ ```
159
+
160
+ Configure your `aicm.json`:
148
161
 
149
162
  ```json
150
163
  {
151
- "rulesDir": "./rules",
164
+ "rootDir": "./",
152
165
  "targets": ["cursor"]
153
166
  }
154
167
  ```
155
168
 
156
169
  Rules are installed in `.cursor/rules/aicm/` and are loaded automatically by Cursor.
157
170
 
158
- ### Using Commands
171
+ ### Commands
159
172
 
160
173
  Cursor supports custom commands that can be invoked directly in the chat interface. aicm can manage these command files alongside your rules and MCP configurations.
161
174
 
162
- Add a commands directory to your project configuration:
175
+ Create a `commands/` directory in your project (at the `rootDir` location):
176
+
177
+ ```
178
+ my-project/
179
+ ├── aicm.json
180
+ └── commands/
181
+ ├── review.md
182
+ └── generate.md
183
+ ```
184
+
185
+ Configure your `aicm.json`:
163
186
 
164
187
  ```json
165
188
  {
166
- "commandsDir": "./commands",
189
+ "rootDir": "./",
167
190
  "targets": ["cursor"]
168
191
  }
169
192
  ```
170
193
 
171
194
  Command files ending in `.md` are installed to `.cursor/commands/aicm/` and appear in Cursor under the `/` command menu.
172
195
 
173
- ### MCP Servers
196
+ ### Hooks
174
197
 
175
- You can configure MCP servers directly in your `aicm.json`, which is useful for sharing mcp configurations across your team or bundling them into presets.
198
+ aicm provides first-class support for [Cursor Agent Hooks](https://docs.cursor.com/advanced/hooks), allowing you to intercept and extend the agent's behavior. Hooks enable you to run custom scripts before/after shell execution, file edits, MCP calls, and more.
199
+
200
+ #### Basic Setup
201
+
202
+ Hooks follow a convention similar to Cursor's own structure:
203
+
204
+ ```
205
+ my-project/
206
+ ├── aicm.json
207
+ ├── hooks.json
208
+ └── hooks/
209
+ ├── audit.sh
210
+ └── format.js
211
+ ```
212
+
213
+ Your `hooks.json` file should reference scripts within the `hooks/` directory:
176
214
 
177
215
  ```json
178
216
  {
179
- "mcpServers": {
180
- "Playwright": {
181
- "command": "npx",
182
- "args": ["@playwright/mcp"]
183
- }
217
+ "version": 1,
218
+ "hooks": {
219
+ "beforeShellExecution": [{ "command": "./hooks/audit.sh" }],
220
+ "afterFileEdit": [{ "command": "./hooks/format.js" }]
184
221
  }
185
222
  }
186
223
  ```
187
224
 
188
- When installed, these servers are automatically added to your `.cursor/mcp.json`.
225
+ > **Important:** All hook scripts must be within the `hooks/` directory. References to files outside this directory will be warned about and skipped.
189
226
 
190
- ### Referencing Auxiliary Files
227
+ #### Installation Behavior
191
228
 
192
- You can place any file (e.g., `example.ts`, `schema.json`, `guide.md`) in your `rulesDir` alongside your `.mdc` files. These assets are automatically copied to the target location. You can reference them in your rules using relative paths, and aicm will automatically rewrite the links to point to the correct location for each target IDE.
229
+ When you run `aicm install`, the following happens:
193
230
 
194
- Example `rules/my-rule.mdc`:
231
+ 1. **Directory Copy**: All files in the `hooks/` directory (except `hooks.json`) are copied
232
+ 2. **Path Rewriting**: Command paths in `hooks.json` are rewritten to point to `.cursor/hooks/aicm/`
233
+ 3. **File Installation**: Scripts are copied to `.cursor/hooks/aicm/` (for local hooks) or `.cursor/hooks/aicm/<preset-name>/` (for preset hooks) with their directory structure preserved
234
+ 4. **Config Merging**: Your hooks configuration is merged into `.cursor/hooks.json`
195
235
 
196
- ```markdown
197
- # My Rule
236
+ #### Preset Namespacing
198
237
 
199
- See [Example](./example.ts) for details.
238
+ aicm uses directory-based namespacing to prevent collisions:
239
+
240
+ ```
241
+ .cursor/hooks/aicm/
242
+ ├── preset-a/
243
+ │ └── validate.sh # From preset-a
244
+ └── preset-b/
245
+ └── validate.sh # From preset-b
200
246
  ```
201
247
 
202
- #### Commands Referencing Files
248
+ #### Workspace Support
203
249
 
204
- You can also use this feature to create commands that reference auxiliary files in your `rulesDir`. Since assets in `rulesDir` are copied to the target directory, your commands can link to them.
250
+ In monorepo/workspace mode, hooks are:
205
251
 
206
- For example, if you have a schema file at `rules/schema.json` and a command at `commands/generate-schema.md`:
252
+ - Installed individually for each package (in `package-x/.cursor/hooks.json`)
253
+ - Merged and installed at the root (in `.cursor/hooks.json`)
254
+ - Deduplicated by full path (including preset namespace)
207
255
 
208
- ```markdown
209
- # Generate Schema
256
+ **Example workspace structure:**
210
257
 
211
- Use the schema defined in [Schema Template](../rules/schema.json) to generate the response.
258
+ ```
259
+ my-monorepo/
260
+ ├── aicm.json (workspaces: true)
261
+ ├── .cursor/hooks.json (merged from all packages)
262
+ ├── package-a/
263
+ │ ├── aicm.json
264
+ │ ├── hooks.json
265
+ │ ├── hooks/
266
+ │ │ └── check.sh
267
+ │ └── .cursor/hooks.json (package-specific)
268
+ └── package-b/
269
+ ├── aicm.json
270
+ ├── hooks.json
271
+ ├── hooks/
272
+ │ └── validate.js
273
+ └── .cursor/hooks.json (package-specific)
212
274
  ```
213
275
 
214
- When installed, `aicm` will automatically rewrite the link to point to the correct location of `schema.json` in the target environment (e.g., `../../rules/aicm/schema.json` for Cursor).
215
-
216
- > **Note:** Path rewriting works for any relative path format in your commands - markdown links, inline code references, or bare paths - as long as they point to actual files in your `rulesDir`.
217
-
218
- #### usage in workspaces mode
219
-
220
- When using workspaces, commands installed at the monorepo root need to access auxiliary files located in nested packages (e.g., `packages/frontend/rules/helper.js`).
221
-
222
- `aicm` handles this automatically by:
276
+ #### Content Collision Detection
223
277
 
224
- 1. Copying referenced auxiliary files from nested packages to the root `.cursor/rules/aicm/` directory
225
- 2. Rewriting paths in the root command to point to these copied files
278
+ If the same hook file (by path) has different content across workspace packages, aicm will:
226
279
 
227
- **Warning:** If your command references a `.mdc` file (Cursor rule), `aicm` will check if it's a "manual" rule or an "automatic" rule (one that is always applied or auto-attached via globs). If it's an automatic rule, `aicm` will warn you that copying it to the root might cause the rule to be included twice in the context (once from the nested package and once from the root copy). For best results, only reference manual `.mdc` files or other file types (like `.js`, `.json`, `.md`) from commands.
280
+ 1. Warn you about the collision with full source information
281
+ 2. Use the last occurrence (last-writer-wins)
282
+ 3. Continue installation
228
283
 
229
- ### Overrides
284
+ ### MCP Servers
230
285
 
231
- You can disable or replace specific rules or commands provided by presets using the `overrides` field:
286
+ You can configure MCP servers directly in your `aicm.json`, which is useful for sharing mcp configurations across your team or bundling them into presets.
232
287
 
233
288
  ```json
234
289
  {
235
- "presets": ["@company/ai-rules"],
236
- "overrides": {
237
- "rule-from-preset-a": "./rules/override-rule.mdc",
238
- "rule-from-preset-b": false,
239
- "legacy-command": false
290
+ "mcpServers": {
291
+ "Playwright": {
292
+ "command": "npx",
293
+ "args": ["@playwright/mcp"]
294
+ }
240
295
  }
241
296
  }
242
297
  ```
243
298
 
299
+ When installed, these servers are automatically added to your `.cursor/mcp.json`.
300
+
301
+ ### Assets
302
+
303
+ You can include assets (examples, schemas, scripts, etc.) that can be referenced by your rules, commands, and hooks by placing them in the `assets/` directory.
304
+
305
+ All files in `assets/` are copied to `.cursor/assets/aicm/` (for Cursor) or `.aicm/` (for Windsurf/Codex/Claude).
306
+
307
+ **Example structure:**
308
+
309
+ ```
310
+ my-project/
311
+ ├── aicm.json
312
+ ├── rules/
313
+ │ └── api-guide.mdc # References ../assets/schema.json
314
+ ├── commands/
315
+ │ └── generate.md # References ../assets/schema.json
316
+ ├── assets/
317
+ │ ├── schema.json
318
+ │ ├── examples/
319
+ │ │ └── config.ts
320
+ │ └── hooks/
321
+ │ └── validate.sh
322
+ └── hooks.json # References ./hooks/validate.sh
323
+ ```
324
+
325
+ **Referencing assets from rules and commands:**
326
+
327
+ ```markdown
328
+ <!-- rules/api.mdc -->
329
+
330
+ Use [this schema](../assets/schema.json) for validation.
331
+ Check the example at `../assets/examples/response.json`.
332
+ ```
333
+
334
+ **Note:** The `../assets/` path is automatically adjusted during installation to `../../assets/aicm/` to match the final directory structure. You don't need to worry about the installation paths - just use `../assets/`.
335
+
336
+ **After installation:**
337
+
338
+ ```
339
+ .cursor/
340
+ ├── assets/aicm/ # All assets copied here
341
+ │ ├── schema.json
342
+ │ ├── examples/
343
+ │ │ └── config.ts
344
+ │ └── hooks/
345
+ │ └── validate.sh
346
+ ├── rules/aicm/
347
+ │ └── api-guide.mdc # References ../../assets/aicm/schema.json
348
+ ├── commands/aicm/
349
+ │ └── generate.md # References ../../assets/aicm/schema.json
350
+ └── hooks/
351
+ ├── aicm/
352
+ └── hooks.json
353
+ ```
354
+
244
355
  ## Workspaces Support
245
356
 
246
357
  aicm supports workspaces by automatically discovering and installing configurations across multiple packages in your repository.
@@ -295,7 +406,7 @@ When you have a preset package within your workspace (a package that provides ru
295
406
  ```json
296
407
  {
297
408
  "skipInstall": true,
298
- "rulesDir": "./rules",
409
+ "rootDir": "./",
299
410
  "targets": ["cursor"]
300
411
  }
301
412
  ```
@@ -308,25 +419,71 @@ Create an `aicm.json` file in your project root, or an `aicm` key in your projec
308
419
 
309
420
  ```json
310
421
  {
311
- "rulesDir": "./rules",
312
- "commandsDir": "./commands",
422
+ "rootDir": "./",
313
423
  "targets": ["cursor"],
314
424
  "presets": [],
315
- "overrides": {},
316
425
  "mcpServers": {},
317
426
  "skipInstall": false
318
427
  }
319
428
  ```
320
429
 
321
- - **rulesDir**: Directory containing all rule files.
322
- - **commandsDir**: Directory containing Cursor command files.
323
- - **targets**: IDEs/Agent targets where rules should be installed. Defaults to `["cursor"]`.
430
+ ### Configuration Options
431
+
432
+ - **rootDir**: Directory containing your aicm structure. Must contain one or more of: `rules/`, `commands/`, `assets/`, `hooks/`, or `hooks.json`. If not specified, aicm will only install rules from presets and will not pick up any local directories.
433
+ - **targets**: IDEs/Agent targets where rules should be installed. Defaults to `["cursor"]`. Supported targets: `cursor`, `windsurf`, `codex`, `claude`.
324
434
  - **presets**: List of preset packages or paths to include.
325
- - **overrides**: Map of rule names to `false` (disable) or a replacement file path.
326
435
  - **mcpServers**: MCP server configurations.
327
436
  - **workspaces**: Set to `true` to enable workspace mode. If not specified, aicm will automatically detect workspaces from your `package.json`.
328
437
  - **skipInstall**: Set to `true` to skip rule installation for this package. Useful for preset packages that provide rules but shouldn't have rules installed into them.
329
438
 
439
+ ### Configuration Examples
440
+
441
+ #### Preset-Only Configuration
442
+
443
+ For projects that only consume presets and don't have their own rules, you can omit `rootDir`:
444
+
445
+ ```json
446
+ {
447
+ "presets": ["@company/ai-preset"]
448
+ }
449
+ ```
450
+
451
+ This ensures that only rules from the preset are installed, and any local directories like `commands/` or `rules/` in your project (used for your application) won't be accidentally picked up by aicm.
452
+
453
+ #### Mixed Local and Preset Configuration
454
+
455
+ To combine your own rules with preset rules:
456
+
457
+ ```json
458
+ {
459
+ "rootDir": "./ai-config",
460
+ "presets": ["@company/ai-preset"],
461
+ "targets": ["cursor", "windsurf"]
462
+ }
463
+ ```
464
+
465
+ This will load rules from both `./ai-config/rules/` and the preset, installing them to both Cursor and Windsurf.
466
+
467
+ ### Directory Structure
468
+
469
+ aicm uses a convention-based directory structure:
470
+
471
+ ```
472
+ my-project/
473
+ ├── aicm.json
474
+ ├── rules/ # Rule files (.mdc) [required for rules]
475
+ │ ├── api.mdc
476
+ │ └── testing.mdc
477
+ ├── commands/ # Command files (.md) [optional]
478
+ │ └── generate.md
479
+ ├── assets/ # Auxiliary files [optional]
480
+ │ ├── schema.json
481
+ │ └── examples/
482
+ ├── hooks/ # Hook scripts [optional]
483
+ │ └── validate.sh
484
+ └── hooks.json # Hook configuration [optional]
485
+ ```
486
+
330
487
  ## CLI Commands
331
488
 
332
489
  ### Global Options
@@ -386,7 +543,7 @@ install().then((result) => {
386
543
  // Install with custom options
387
544
  const customConfig = {
388
545
  targets: ["cursor"],
389
- rulesDir: "rules",
546
+ rootDir: "./",
390
547
  presets: ["@team/ai-preset"],
391
548
  };
392
549
 
package/dist/api.d.ts CHANGED
@@ -5,5 +5,12 @@ import { InstallOptions, InstallResult } from "./commands/install";
5
5
  * @returns Result of the install operation
6
6
  */
7
7
  export declare function install(options?: InstallOptions): Promise<InstallResult>;
8
+ /**
9
+ * Check if workspaces mode is enabled without loading all rules/presets
10
+ * @param cwd Current working directory (optional, defaults to process.cwd())
11
+ * @returns True if workspaces mode is enabled
12
+ */
13
+ export declare function checkWorkspacesEnabled(cwd?: string): Promise<boolean>;
8
14
  export type { InstallOptions, InstallResult } from "./commands/install";
9
15
  export type { ResolvedConfig, Config, RuleFile, CommandFile, MCPServers, } from "./utils/config";
16
+ export type { HookFile, HooksJson, HookType, HookCommand } from "./utils/hooks";
package/dist/api.js CHANGED
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.install = install;
4
+ exports.checkWorkspacesEnabled = checkWorkspacesEnabled;
4
5
  const install_1 = require("./commands/install");
6
+ const config_1 = require("./utils/config");
5
7
  /**
6
8
  * Install AICM rules based on configuration
7
9
  * @param options Installation options
@@ -10,3 +12,11 @@ const install_1 = require("./commands/install");
10
12
  async function install(options = {}) {
11
13
  return (0, install_1.install)(options);
12
14
  }
15
+ /**
16
+ * Check if workspaces mode is enabled without loading all rules/presets
17
+ * @param cwd Current working directory (optional, defaults to process.cwd())
18
+ * @returns True if workspaces mode is enabled
19
+ */
20
+ async function checkWorkspacesEnabled(cwd) {
21
+ return (0, config_1.checkWorkspacesEnabled)(cwd);
22
+ }
@@ -97,11 +97,68 @@ function cleanMcpServers(cwd, verbose) {
97
97
  return false;
98
98
  }
99
99
  }
100
+ function cleanHooks(cwd, verbose) {
101
+ const hooksJsonPath = node_path_1.default.join(cwd, ".cursor", "hooks.json");
102
+ const hooksDir = node_path_1.default.join(cwd, ".cursor", "hooks", "aicm");
103
+ let hasChanges = false;
104
+ // Clean hooks directory
105
+ if (fs_extra_1.default.existsSync(hooksDir)) {
106
+ fs_extra_1.default.removeSync(hooksDir);
107
+ if (verbose)
108
+ console.log(chalk_1.default.gray(` Removed ${hooksDir}`));
109
+ hasChanges = true;
110
+ }
111
+ // Clean hooks.json
112
+ if (fs_extra_1.default.existsSync(hooksJsonPath)) {
113
+ try {
114
+ const content = fs_extra_1.default.readJsonSync(hooksJsonPath);
115
+ // Filter out aicm-managed hooks (those pointing to hooks/aicm/)
116
+ const userConfig = {
117
+ version: content.version || 1,
118
+ hooks: {},
119
+ };
120
+ let removedAny = false;
121
+ if (content.hooks) {
122
+ for (const [hookType, hookCommands] of Object.entries(content.hooks)) {
123
+ if (Array.isArray(hookCommands)) {
124
+ const userCommands = hookCommands.filter((cmd) => !cmd.command || !cmd.command.includes("hooks/aicm/"));
125
+ if (userCommands.length < hookCommands.length) {
126
+ removedAny = true;
127
+ }
128
+ if (userCommands.length > 0) {
129
+ userConfig.hooks[hookType] = userCommands;
130
+ }
131
+ }
132
+ }
133
+ }
134
+ if (removedAny) {
135
+ const hasUserHooks = userConfig.hooks && Object.keys(userConfig.hooks).length > 0;
136
+ if (!hasUserHooks) {
137
+ fs_extra_1.default.removeSync(hooksJsonPath);
138
+ if (verbose)
139
+ console.log(chalk_1.default.gray(` Removed empty ${hooksJsonPath}`));
140
+ }
141
+ else {
142
+ fs_extra_1.default.writeJsonSync(hooksJsonPath, userConfig, { spaces: 2 });
143
+ if (verbose)
144
+ console.log(chalk_1.default.gray(` Cleaned aicm hooks from ${hooksJsonPath}`));
145
+ }
146
+ hasChanges = true;
147
+ }
148
+ }
149
+ catch (_a) {
150
+ console.warn(chalk_1.default.yellow(`Warning: Failed to clean hooks.json`));
151
+ }
152
+ }
153
+ return hasChanges;
154
+ }
100
155
  function cleanEmptyDirectories(cwd, verbose) {
101
156
  let cleanedCount = 0;
102
157
  const dirsToCheck = [
103
158
  node_path_1.default.join(cwd, ".cursor", "rules"),
104
159
  node_path_1.default.join(cwd, ".cursor", "commands"),
160
+ node_path_1.default.join(cwd, ".cursor", "assets"),
161
+ node_path_1.default.join(cwd, ".cursor", "hooks"),
105
162
  node_path_1.default.join(cwd, ".cursor"),
106
163
  ];
107
164
  for (const dir of dirsToCheck) {
@@ -130,6 +187,7 @@ async function cleanPackage(options = {}) {
130
187
  const filesToClean = [
131
188
  node_path_1.default.join(cwd, ".cursor", "rules", "aicm"),
132
189
  node_path_1.default.join(cwd, ".cursor", "commands", "aicm"),
190
+ node_path_1.default.join(cwd, ".cursor", "assets", "aicm"),
133
191
  node_path_1.default.join(cwd, ".aicm"),
134
192
  ];
135
193
  const rulesFilesToClean = [
@@ -150,6 +208,9 @@ async function cleanPackage(options = {}) {
150
208
  // Clean MCP servers
151
209
  if (cleanMcpServers(cwd, verbose))
152
210
  cleanedCount++;
211
+ // Clean hooks
212
+ if (cleanHooks(cwd, verbose))
213
+ cleanedCount++;
153
214
  // Clean empty directories
154
215
  cleanedCount += cleanEmptyDirectories(cwd, verbose);
155
216
  return {
@@ -190,11 +251,9 @@ async function cleanWorkspaces(cwd, verbose = false) {
190
251
  };
191
252
  }
192
253
  async function clean(options = {}) {
193
- var _a;
194
254
  const cwd = options.cwd || process.cwd();
195
255
  const verbose = options.verbose || false;
196
- const shouldUseWorkspaces = ((_a = (await (0, config_1.loadConfig)(cwd))) === null || _a === void 0 ? void 0 : _a.config.workspaces) ||
197
- (0, config_1.detectWorkspacesFromPackageJson)(cwd);
256
+ const shouldUseWorkspaces = await (0, config_1.checkWorkspacesEnabled)(cwd);
198
257
  if (shouldUseWorkspaces) {
199
258
  return cleanWorkspaces(cwd, verbose);
200
259
  }
@@ -8,7 +8,8 @@ const fs_extra_1 = __importDefault(require("fs-extra"));
8
8
  const path_1 = __importDefault(require("path"));
9
9
  const chalk_1 = __importDefault(require("chalk"));
10
10
  const defaultConfig = {
11
- rulesDir: "rules",
11
+ rootDir: "./",
12
+ targets: ["cursor"],
12
13
  };
13
14
  function initCommand() {
14
15
  const configPath = path_1.default.join(process.cwd(), "aicm.json");
@@ -17,11 +18,30 @@ function initCommand() {
17
18
  return;
18
19
  }
19
20
  try {
21
+ // Create standard directory structure
22
+ const dirs = ["rules", "commands", "assets", "hooks"];
23
+ for (const dir of dirs) {
24
+ const dirPath = path_1.default.join(process.cwd(), dir);
25
+ if (!fs_extra_1.default.existsSync(dirPath)) {
26
+ fs_extra_1.default.mkdirSync(dirPath, { recursive: true });
27
+ }
28
+ }
29
+ // Create placeholder file in rules directory
30
+ const rulesReadmePath = path_1.default.join(process.cwd(), "rules", ".gitkeep");
31
+ if (!fs_extra_1.default.existsSync(rulesReadmePath)) {
32
+ fs_extra_1.default.writeFileSync(rulesReadmePath, "# Place your .mdc rule files here\n");
33
+ }
20
34
  fs_extra_1.default.writeJsonSync(configPath, defaultConfig, { spaces: 2 });
21
35
  console.log(`Configuration file location: ${chalk_1.default.blue(configPath)}`);
36
+ console.log(`\nCreated directory structure:`);
37
+ console.log(` - ${chalk_1.default.blue("rules/")} for rule files (.mdc)`);
38
+ console.log(` - ${chalk_1.default.blue("commands/")} for command files (.md)`);
39
+ console.log(` - ${chalk_1.default.blue("assets/")} for auxiliary files`);
40
+ console.log(` - ${chalk_1.default.blue("hooks/")} for hook scripts`);
22
41
  console.log(`\nNext steps:`);
23
- console.log(` 1. Edit ${chalk_1.default.blue("aicm.json")} to configure your rules & presets`);
24
- console.log(` 2. Run ${chalk_1.default.blue("npx aicm install")} to install rules & mcps`);
42
+ console.log(` 1. Add your rule files to ${chalk_1.default.blue("rules/")} directory`);
43
+ console.log(` 2. Edit ${chalk_1.default.blue("aicm.json")} to configure presets if needed`);
44
+ console.log(` 3. Run ${chalk_1.default.blue("npx aicm install")} to install rules & mcps`);
25
45
  }
26
46
  catch (error) {
27
47
  console.error(chalk_1.default.red("Error creating configuration file:"), error);