aicm 0.17.3 → 0.19.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.
- package/README.md +228 -54
- package/dist/api.d.ts +1 -0
- package/dist/commands/clean.js +61 -0
- package/dist/commands/init.js +23 -3
- package/dist/commands/install-workspaces.d.ts +5 -0
- package/dist/commands/install-workspaces.js +276 -0
- package/dist/commands/install.d.ts +13 -1
- package/dist/commands/install.js +69 -264
- package/dist/utils/config.d.ts +17 -13
- package/dist/utils/config.js +127 -132
- package/dist/utils/hooks.d.ts +50 -0
- package/dist/utils/hooks.js +346 -0
- package/package.json +2 -2
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](#
|
|
18
|
-
- [Commands](#
|
|
17
|
+
- [Rules](#rules)
|
|
18
|
+
- [Commands](#commands)
|
|
19
|
+
- [Hooks](#hooks)
|
|
19
20
|
- [MCP Servers](#mcp-servers)
|
|
20
|
-
- [
|
|
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
|
-
|
|
85
|
-
|
|
86
|
-
|
|
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
|
-
"
|
|
96
|
+
"rootDir": "./",
|
|
94
97
|
"mcpServers": {
|
|
95
98
|
"my-mcp": { "url": "https://example.com/sse" }
|
|
96
99
|
}
|
|
@@ -135,41 +138,149 @@ The rules are now installed in `.cursor/rules/aicm/` and any MCP servers are con
|
|
|
135
138
|
|
|
136
139
|
### Notes
|
|
137
140
|
|
|
138
|
-
- Generated
|
|
139
|
-
- Users should add `.cursor
|
|
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
|
-
###
|
|
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
|
-
|
|
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
|
-
"
|
|
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
|
-
###
|
|
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
|
-
|
|
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
|
-
"
|
|
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
|
|
|
196
|
+
### Hooks
|
|
197
|
+
|
|
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:
|
|
214
|
+
|
|
215
|
+
```json
|
|
216
|
+
{
|
|
217
|
+
"version": 1,
|
|
218
|
+
"hooks": {
|
|
219
|
+
"beforeShellExecution": [{ "command": "./hooks/audit.sh" }],
|
|
220
|
+
"afterFileEdit": [{ "command": "./hooks/format.js" }]
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
> **Important:** All hook scripts must be within the `hooks/` directory. References to files outside this directory will be warned about and skipped.
|
|
226
|
+
|
|
227
|
+
#### Installation Behavior
|
|
228
|
+
|
|
229
|
+
When you run `aicm install`, the following happens:
|
|
230
|
+
|
|
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`
|
|
235
|
+
|
|
236
|
+
#### Preset Namespacing
|
|
237
|
+
|
|
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
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
#### Workspace Support
|
|
249
|
+
|
|
250
|
+
In monorepo/workspace mode, hooks are:
|
|
251
|
+
|
|
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)
|
|
255
|
+
|
|
256
|
+
**Example workspace structure:**
|
|
257
|
+
|
|
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)
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
#### Content Collision Detection
|
|
277
|
+
|
|
278
|
+
If the same hook file (by path) has different content across workspace packages, aicm will:
|
|
279
|
+
|
|
280
|
+
1. Warn you about the collision with full source information
|
|
281
|
+
2. Use the last occurrence (last-writer-wins)
|
|
282
|
+
3. Continue installation
|
|
283
|
+
|
|
173
284
|
### MCP Servers
|
|
174
285
|
|
|
175
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.
|
|
@@ -187,47 +298,58 @@ You can configure MCP servers directly in your `aicm.json`, which is useful for
|
|
|
187
298
|
|
|
188
299
|
When installed, these servers are automatically added to your `.cursor/mcp.json`.
|
|
189
300
|
|
|
190
|
-
###
|
|
301
|
+
### Assets
|
|
191
302
|
|
|
192
|
-
You can
|
|
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.
|
|
193
304
|
|
|
194
|
-
|
|
305
|
+
All files in `assets/` are copied to `.cursor/assets/aicm/` (for Cursor) or `.aicm/` (for Windsurf/Codex/Claude).
|
|
195
306
|
|
|
196
|
-
|
|
197
|
-
# My Rule
|
|
307
|
+
**Example structure:**
|
|
198
308
|
|
|
199
|
-
|
|
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
|
|
200
323
|
```
|
|
201
324
|
|
|
202
|
-
|
|
203
|
-
|
|
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.
|
|
205
|
-
|
|
206
|
-
For example, if you have a schema file at `rules/schema.json` and a command at `commands/generate-schema.md`:
|
|
325
|
+
**Referencing assets from rules and commands:**
|
|
207
326
|
|
|
208
327
|
```markdown
|
|
209
|
-
|
|
328
|
+
<!-- rules/api.mdc -->
|
|
210
329
|
|
|
211
|
-
Use
|
|
330
|
+
Use [this schema](../assets/schema.json) for validation.
|
|
331
|
+
Check the example at `../assets/examples/response.json`.
|
|
212
332
|
```
|
|
213
333
|
|
|
214
|
-
|
|
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/`.
|
|
215
335
|
|
|
216
|
-
|
|
336
|
+
**After installation:**
|
|
217
337
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
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
|
|
231
353
|
```
|
|
232
354
|
|
|
233
355
|
## Workspaces Support
|
|
@@ -271,6 +393,12 @@ Running `npx aicm install` will install rules for each package in their respecti
|
|
|
271
393
|
- `packages/backend/.cursor/rules/aicm/`
|
|
272
394
|
- `services/api/.cursor/rules/aicm/`
|
|
273
395
|
|
|
396
|
+
**Why install in both places?**
|
|
397
|
+
`aicm` installs configurations at both the package level AND the root level to support different workflows:
|
|
398
|
+
|
|
399
|
+
- **Package-level context:** When a developer opens a specific package folder (e.g., `packages/frontend`) in their IDE, they get the specific rules, commands, and MCP servers for that package.
|
|
400
|
+
- **Root-level context:** When a developer opens the monorepo root, `aicm` ensures they have access to all commands and MCP servers from all packages via the merged root configuration. While rules are typically read from nested directories by Cursor, commands and MCP servers must be configured at the root to be accessible.
|
|
401
|
+
|
|
274
402
|
### Preset Packages in Workspaces
|
|
275
403
|
|
|
276
404
|
When you have a preset package within your workspace (a package that provides rules to be consumed by others), you can prevent aicm from installing rules into it by setting `skipInstall: true`:
|
|
@@ -278,7 +406,7 @@ When you have a preset package within your workspace (a package that provides ru
|
|
|
278
406
|
```json
|
|
279
407
|
{
|
|
280
408
|
"skipInstall": true,
|
|
281
|
-
"
|
|
409
|
+
"rootDir": "./",
|
|
282
410
|
"targets": ["cursor"]
|
|
283
411
|
}
|
|
284
412
|
```
|
|
@@ -291,25 +419,71 @@ Create an `aicm.json` file in your project root, or an `aicm` key in your projec
|
|
|
291
419
|
|
|
292
420
|
```json
|
|
293
421
|
{
|
|
294
|
-
"
|
|
295
|
-
"commandsDir": "./commands",
|
|
422
|
+
"rootDir": "./",
|
|
296
423
|
"targets": ["cursor"],
|
|
297
424
|
"presets": [],
|
|
298
|
-
"overrides": {},
|
|
299
425
|
"mcpServers": {},
|
|
300
426
|
"skipInstall": false
|
|
301
427
|
}
|
|
302
428
|
```
|
|
303
429
|
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
- **
|
|
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`.
|
|
307
434
|
- **presets**: List of preset packages or paths to include.
|
|
308
|
-
- **overrides**: Map of rule names to `false` (disable) or a replacement file path.
|
|
309
435
|
- **mcpServers**: MCP server configurations.
|
|
310
436
|
- **workspaces**: Set to `true` to enable workspace mode. If not specified, aicm will automatically detect workspaces from your `package.json`.
|
|
311
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.
|
|
312
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
|
+
|
|
313
487
|
## CLI Commands
|
|
314
488
|
|
|
315
489
|
### Global Options
|
|
@@ -369,7 +543,7 @@ install().then((result) => {
|
|
|
369
543
|
// Install with custom options
|
|
370
544
|
const customConfig = {
|
|
371
545
|
targets: ["cursor"],
|
|
372
|
-
|
|
546
|
+
rootDir: "./",
|
|
373
547
|
presets: ["@team/ai-preset"],
|
|
374
548
|
};
|
|
375
549
|
|
package/dist/api.d.ts
CHANGED
|
@@ -7,3 +7,4 @@ import { InstallOptions, InstallResult } from "./commands/install";
|
|
|
7
7
|
export declare function install(options?: InstallOptions): Promise<InstallResult>;
|
|
8
8
|
export type { InstallOptions, InstallResult } from "./commands/install";
|
|
9
9
|
export type { ResolvedConfig, Config, RuleFile, CommandFile, MCPServers, } from "./utils/config";
|
|
10
|
+
export type { HookFile, HooksJson, HookType, HookCommand } from "./utils/hooks";
|
package/dist/commands/clean.js
CHANGED
|
@@ -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 {
|
package/dist/commands/init.js
CHANGED
|
@@ -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
|
-
|
|
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.
|
|
24
|
-
console.log(` 2.
|
|
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);
|