aicm 0.6.0 → 0.6.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 +60 -9
- package/dist/api.d.ts +8 -0
- package/dist/api.js +12 -0
- package/dist/commands/init.js +2 -3
- package/dist/commands/install.d.ts +41 -0
- package/dist/commands/install.js +98 -26
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -121,12 +121,12 @@ When you use a preset, you can override or disable any rule or mcpServer from th
|
|
|
121
121
|
|
|
122
122
|
### Demo
|
|
123
123
|
|
|
124
|
-
We'll install an npm package containing a simple
|
|
124
|
+
We'll install [an npm package](https://github.com/ranyitz/pirate-coding) containing a simple preset to demonstrate how aicm works.
|
|
125
125
|
|
|
126
|
-
1. Install an npm package containing a
|
|
126
|
+
1. Install an npm package containing a preset
|
|
127
127
|
|
|
128
128
|
```bash
|
|
129
|
-
npm install --save-dev pirate-coding
|
|
129
|
+
npm install --save-dev pirate-coding
|
|
130
130
|
```
|
|
131
131
|
|
|
132
132
|
2. Initialize aicm config
|
|
@@ -140,13 +140,11 @@ npx -y aicm init
|
|
|
140
140
|
```json
|
|
141
141
|
{
|
|
142
142
|
"ides": ["cursor"],
|
|
143
|
-
"
|
|
144
|
-
"pirate-coding": "pirate-coding-rule/rule.mdc"
|
|
145
|
-
}
|
|
143
|
+
"presets": ["pirate-coding"]
|
|
146
144
|
}
|
|
147
145
|
```
|
|
148
146
|
|
|
149
|
-
4. Install all rules from your configuration
|
|
147
|
+
4. Install all rules & mcps from your configuration
|
|
150
148
|
|
|
151
149
|
```bash
|
|
152
150
|
npx -y aicm install
|
|
@@ -154,7 +152,7 @@ npx -y aicm install
|
|
|
154
152
|
|
|
155
153
|
This command installs all configured rules and MCPs to their IDE-specific locations.
|
|
156
154
|
|
|
157
|
-
After installation, open Cursor and ask it to do something. Your AI assistant will respond with pirate-themed coding advice.
|
|
155
|
+
After installation, open Cursor and ask it to do something. Your AI assistant will respond with pirate-themed coding advice. You can also ask it about the aicm library which uses https://gitmcp.io/ to give you advise based on the latest documentation.
|
|
158
156
|
|
|
159
157
|
## Security Note
|
|
160
158
|
|
|
@@ -251,12 +249,65 @@ npx aicm init
|
|
|
251
249
|
|
|
252
250
|
### `install`
|
|
253
251
|
|
|
254
|
-
Installs rules
|
|
252
|
+
Installs all rules and MCPs configured in your `aicm.json`.
|
|
255
253
|
|
|
256
254
|
```bash
|
|
257
255
|
npx aicm install
|
|
258
256
|
```
|
|
259
257
|
|
|
258
|
+
## Node.js API
|
|
259
|
+
|
|
260
|
+
In addition to the CLI, aicm can be used programmatically in Node.js applications:
|
|
261
|
+
|
|
262
|
+
```javascript
|
|
263
|
+
const { install, Config } = require("aicm");
|
|
264
|
+
|
|
265
|
+
install().then((result) => {
|
|
266
|
+
if (result.success) {
|
|
267
|
+
console.log(`Successfully installed ${result.installedRuleCount} rules`);
|
|
268
|
+
} else {
|
|
269
|
+
console.error(`Error: ${result.error}`);
|
|
270
|
+
}
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
// Install with custom options
|
|
274
|
+
const customConfig = {
|
|
275
|
+
ides: ["cursor"],
|
|
276
|
+
rules: {
|
|
277
|
+
typescript: "./rules/typescript.mdc",
|
|
278
|
+
react: "@org/rules/react.mdc",
|
|
279
|
+
},
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
install({
|
|
283
|
+
config: customConfig,
|
|
284
|
+
cwd: "/path/to/project",
|
|
285
|
+
silent: true,
|
|
286
|
+
}).then((result) => {
|
|
287
|
+
// Handle result
|
|
288
|
+
});
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
### API Reference
|
|
292
|
+
|
|
293
|
+
#### `install(options?: InstallOptions): Promise<InstallResult>`
|
|
294
|
+
|
|
295
|
+
Installs rules and MCP servers based on configuration.
|
|
296
|
+
|
|
297
|
+
**Options:**
|
|
298
|
+
|
|
299
|
+
- `cwd`: Base directory to use instead of `process.cwd()`
|
|
300
|
+
- `config`: Custom config object to use instead of loading from file
|
|
301
|
+
- `silent`: Whether to suppress console output
|
|
302
|
+
|
|
303
|
+
**Returns:**
|
|
304
|
+
|
|
305
|
+
A Promise that resolves to an object with:
|
|
306
|
+
|
|
307
|
+
- `success`: Whether the operation was successful
|
|
308
|
+
- `error`: Error message if the operation failed
|
|
309
|
+
- `installedRuleCount`: Number of rules installed
|
|
310
|
+
|
|
260
311
|
## Contributing
|
|
261
312
|
|
|
262
313
|
Contributions are welcome! Please feel free to submit a Pull Request.
|
package/dist/api.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { InstallOptions, InstallResult } from "./commands/install";
|
|
2
|
+
/**
|
|
3
|
+
* Install AICM rules based on configuration
|
|
4
|
+
* @param options Install options
|
|
5
|
+
* @returns Result of the install operation
|
|
6
|
+
*/
|
|
7
|
+
export declare function install(options?: InstallOptions): Promise<InstallResult>;
|
|
8
|
+
export { Config, Rule, Rules, RuleMetadata, RuleContent, RuleCollection, } from "./types";
|
package/dist/api.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.install = install;
|
|
4
|
+
const install_1 = require("./commands/install");
|
|
5
|
+
/**
|
|
6
|
+
* Install AICM rules based on configuration
|
|
7
|
+
* @param options Install options
|
|
8
|
+
* @returns Result of the install operation
|
|
9
|
+
*/
|
|
10
|
+
async function install(options = {}) {
|
|
11
|
+
return (0, install_1.install)(options);
|
|
12
|
+
}
|
package/dist/commands/init.js
CHANGED
|
@@ -20,11 +20,10 @@ function initCommand() {
|
|
|
20
20
|
}
|
|
21
21
|
try {
|
|
22
22
|
fs_extra_1.default.writeJsonSync(configPath, defaultConfig, { spaces: 2 });
|
|
23
|
-
console.log(chalk_1.default.green("Configuration file created successfully!"));
|
|
24
23
|
console.log(`Configuration file location: ${chalk_1.default.blue(configPath)}`);
|
|
25
24
|
console.log(`\nNext steps:`);
|
|
26
|
-
console.log(` 1. Edit ${chalk_1.default.blue("aicm.json")} to configure your rules`);
|
|
27
|
-
console.log(` 2. Run ${chalk_1.default.blue("npx aicm install")} to install rules`);
|
|
25
|
+
console.log(` 1. Edit ${chalk_1.default.blue("aicm.json")} to configure your rules & presets`);
|
|
26
|
+
console.log(` 2. Run ${chalk_1.default.blue("npx aicm install")} to install rules & mcps`);
|
|
28
27
|
}
|
|
29
28
|
catch (error) {
|
|
30
29
|
console.error(chalk_1.default.red("Error creating configuration file:"), error);
|
|
@@ -1 +1,42 @@
|
|
|
1
|
+
import { Config } from "../types";
|
|
2
|
+
/**
|
|
3
|
+
* Options for the installCore function
|
|
4
|
+
*/
|
|
5
|
+
export interface InstallOptions {
|
|
6
|
+
/**
|
|
7
|
+
* Base directory to use instead of process.cwd()
|
|
8
|
+
*/
|
|
9
|
+
cwd?: string;
|
|
10
|
+
/**
|
|
11
|
+
* Custom config object to use instead of loading from file
|
|
12
|
+
*/
|
|
13
|
+
config?: Config;
|
|
14
|
+
/**
|
|
15
|
+
* Whether to log progress to console
|
|
16
|
+
*/
|
|
17
|
+
silent?: boolean;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Result of the install operation
|
|
21
|
+
*/
|
|
22
|
+
export interface InstallResult {
|
|
23
|
+
/**
|
|
24
|
+
* Whether the operation was successful
|
|
25
|
+
*/
|
|
26
|
+
success: boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Error message if the operation failed
|
|
29
|
+
*/
|
|
30
|
+
error?: string;
|
|
31
|
+
/**
|
|
32
|
+
* Number of rules installed
|
|
33
|
+
*/
|
|
34
|
+
installedRuleCount: number;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Core implementation of the rule installation logic
|
|
38
|
+
* @param options Install options
|
|
39
|
+
* @returns Result of the install operation
|
|
40
|
+
*/
|
|
41
|
+
export declare function install(options?: InstallOptions): Promise<InstallResult>;
|
|
1
42
|
export declare function installCommand(): Promise<void>;
|
package/dist/commands/install.js
CHANGED
|
@@ -3,6 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.install = install;
|
|
6
7
|
exports.installCommand = installCommand;
|
|
7
8
|
const chalk_1 = __importDefault(require("chalk"));
|
|
8
9
|
const config_1 = require("../utils/config");
|
|
@@ -11,13 +12,19 @@ const rule_collector_1 = require("../utils/rule-collector");
|
|
|
11
12
|
const rule_writer_1 = require("../utils/rule-writer");
|
|
12
13
|
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
13
14
|
const node_path_1 = __importDefault(require("node:path"));
|
|
14
|
-
|
|
15
|
+
/**
|
|
16
|
+
* Write MCP servers configuration to IDE targets
|
|
17
|
+
* @param mcpServers The MCP servers configuration
|
|
18
|
+
* @param ides The IDEs to write to
|
|
19
|
+
* @param cwd The current working directory
|
|
20
|
+
*/
|
|
21
|
+
function writeMcpServersToTargets(mcpServers, ides, cwd) {
|
|
15
22
|
if (!mcpServers)
|
|
16
23
|
return;
|
|
17
24
|
for (const ide of ides) {
|
|
18
25
|
let mcpPath = null;
|
|
19
26
|
if (ide === "cursor") {
|
|
20
|
-
mcpPath = node_path_1.default.join(
|
|
27
|
+
mcpPath = node_path_1.default.join(cwd, ".cursor", "mcp.json");
|
|
21
28
|
fs_extra_1.default.ensureDirSync(node_path_1.default.dirname(mcpPath));
|
|
22
29
|
}
|
|
23
30
|
// Windsurf does not support project mcpServers, so skip
|
|
@@ -26,37 +33,59 @@ function writeMcpServersToTargets(mcpServers, ides) {
|
|
|
26
33
|
}
|
|
27
34
|
}
|
|
28
35
|
}
|
|
29
|
-
|
|
36
|
+
/**
|
|
37
|
+
* Core implementation of the rule installation logic
|
|
38
|
+
* @param options Install options
|
|
39
|
+
* @returns Result of the install operation
|
|
40
|
+
*/
|
|
41
|
+
async function install(options = {}) {
|
|
42
|
+
const cwd = options.cwd || process.cwd();
|
|
43
|
+
const silent = options.silent || false;
|
|
44
|
+
const log = silent ? () => { } : console.log;
|
|
45
|
+
const error = silent ? () => { } : console.error;
|
|
30
46
|
try {
|
|
47
|
+
// Save original process.cwd() and change to the specified cwd
|
|
48
|
+
const originalCwd = process.cwd();
|
|
49
|
+
if (cwd !== originalCwd) {
|
|
50
|
+
process.chdir(cwd);
|
|
51
|
+
}
|
|
31
52
|
// Initialize rule collection
|
|
32
53
|
const ruleCollection = (0, rule_collector_1.initRuleCollection)();
|
|
33
|
-
//
|
|
34
|
-
const config = (0, config_1.getConfig)();
|
|
35
|
-
// If config doesn't exist,
|
|
54
|
+
// Use provided config or load from file
|
|
55
|
+
const config = options.config || (0, config_1.getConfig)();
|
|
56
|
+
// If config doesn't exist, return error
|
|
36
57
|
if (!config) {
|
|
37
|
-
|
|
38
|
-
|
|
58
|
+
error("Configuration file not found!");
|
|
59
|
+
// Restore original cwd
|
|
60
|
+
if (cwd !== originalCwd) {
|
|
61
|
+
process.chdir(originalCwd);
|
|
62
|
+
}
|
|
63
|
+
return {
|
|
64
|
+
success: false,
|
|
65
|
+
error: "Configuration file not found!",
|
|
66
|
+
installedRuleCount: 0,
|
|
67
|
+
};
|
|
39
68
|
}
|
|
40
69
|
// Check if rules are defined (either directly or through presets)
|
|
41
70
|
if (!config.rules || Object.keys(config.rules).length === 0) {
|
|
42
71
|
// If there are no presets defined either, show a message
|
|
43
72
|
if (!config.presets || config.presets.length === 0) {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
console.log(chalk_1.default.yellow("\nNo valid rules found in configuration or presets."));
|
|
55
|
-
return;
|
|
73
|
+
error("No rules defined in configuration.");
|
|
74
|
+
// Restore original cwd
|
|
75
|
+
if (cwd !== originalCwd) {
|
|
76
|
+
process.chdir(originalCwd);
|
|
77
|
+
}
|
|
78
|
+
return {
|
|
79
|
+
success: false,
|
|
80
|
+
error: "No rules defined in configuration.",
|
|
81
|
+
installedRuleCount: 0,
|
|
82
|
+
};
|
|
56
83
|
}
|
|
57
84
|
}
|
|
58
85
|
// Process each rule
|
|
59
86
|
let hasErrors = false;
|
|
87
|
+
const errorMessages = [];
|
|
88
|
+
let installedRuleCount = 0;
|
|
60
89
|
for (const [name, source] of Object.entries(config.rules)) {
|
|
61
90
|
if (source === false)
|
|
62
91
|
continue; // skip canceled rules
|
|
@@ -75,20 +104,32 @@ async function installCommand() {
|
|
|
75
104
|
ruleContent = (0, rule_collector_1.collectLocalRule)(name, source, ruleBasePath);
|
|
76
105
|
break;
|
|
77
106
|
default:
|
|
78
|
-
|
|
107
|
+
error(`Unknown rule type: ${ruleType}`);
|
|
108
|
+
errorMessages.push(`Unknown rule type: ${ruleType}`);
|
|
79
109
|
continue;
|
|
80
110
|
}
|
|
81
111
|
// Add rule to collection
|
|
82
112
|
(0, rule_collector_1.addRuleToCollection)(ruleCollection, ruleContent, config.ides);
|
|
113
|
+
installedRuleCount++;
|
|
83
114
|
}
|
|
84
|
-
catch (
|
|
115
|
+
catch (e) {
|
|
85
116
|
hasErrors = true;
|
|
86
|
-
|
|
117
|
+
const errorMessage = `Error processing rule ${name}: ${e instanceof Error ? e.message : String(e)}`;
|
|
118
|
+
error(errorMessage);
|
|
119
|
+
errorMessages.push(errorMessage);
|
|
87
120
|
}
|
|
88
121
|
}
|
|
89
122
|
// If there were errors, exit with error
|
|
90
123
|
if (hasErrors) {
|
|
91
|
-
|
|
124
|
+
// Restore original cwd
|
|
125
|
+
if (cwd !== originalCwd) {
|
|
126
|
+
process.chdir(originalCwd);
|
|
127
|
+
}
|
|
128
|
+
return {
|
|
129
|
+
success: false,
|
|
130
|
+
error: errorMessages.join("; "),
|
|
131
|
+
installedRuleCount,
|
|
132
|
+
};
|
|
92
133
|
}
|
|
93
134
|
// Write all collected rules to their targets
|
|
94
135
|
(0, rule_writer_1.writeRulesToTargets)(ruleCollection);
|
|
@@ -96,9 +137,40 @@ async function installCommand() {
|
|
|
96
137
|
if (config.mcpServers) {
|
|
97
138
|
// Filter out canceled servers
|
|
98
139
|
const filteredMcpServers = Object.fromEntries(Object.entries(config.mcpServers).filter(([, v]) => v !== false));
|
|
99
|
-
writeMcpServersToTargets(filteredMcpServers, config.ides);
|
|
140
|
+
writeMcpServersToTargets(filteredMcpServers, config.ides, cwd);
|
|
141
|
+
}
|
|
142
|
+
log("Rules installation completed!");
|
|
143
|
+
// Restore original cwd
|
|
144
|
+
if (cwd !== originalCwd) {
|
|
145
|
+
process.chdir(originalCwd);
|
|
146
|
+
}
|
|
147
|
+
return {
|
|
148
|
+
success: true,
|
|
149
|
+
installedRuleCount,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
catch (e) {
|
|
153
|
+
const errorMessage = `Error during rule installation: ${e instanceof Error ? e.message : String(e)}`;
|
|
154
|
+
error(errorMessage);
|
|
155
|
+
// If cwd was changed, restore it
|
|
156
|
+
if (cwd !== process.cwd()) {
|
|
157
|
+
process.chdir(cwd);
|
|
158
|
+
}
|
|
159
|
+
return {
|
|
160
|
+
success: false,
|
|
161
|
+
error: errorMessage,
|
|
162
|
+
installedRuleCount: 0,
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
async function installCommand() {
|
|
167
|
+
try {
|
|
168
|
+
const result = await install({ silent: false });
|
|
169
|
+
if (!result.success) {
|
|
170
|
+
console.error(chalk_1.default.red(result.error));
|
|
171
|
+
process.exit(1);
|
|
100
172
|
}
|
|
101
|
-
console.log(chalk_1.default.green("
|
|
173
|
+
console.log(chalk_1.default.green("Rules installation completed!"));
|
|
102
174
|
}
|
|
103
175
|
catch (error) {
|
|
104
176
|
console.error(chalk_1.default.red(`Error during rule installation: ${error instanceof Error ? error.message : String(error)}`));
|
package/package.json
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aicm",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.1",
|
|
4
4
|
"description": "A TypeScript CLI tool for managing AI IDE rules across different projects and teams",
|
|
5
|
-
"main": "dist/
|
|
5
|
+
"main": "dist/api.js",
|
|
6
|
+
"types": "dist/api.d.ts",
|
|
6
7
|
"bin": {
|
|
7
8
|
"aicm": "./dist/index.js"
|
|
8
9
|
},
|