aicm 0.6.0 → 0.6.2
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 +63 -18
- 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 +97 -26
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -121,32 +121,24 @@ 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
|
-
2.
|
|
132
|
+
2. Create an `aicm.json` file in your project
|
|
133
133
|
|
|
134
134
|
```bash
|
|
135
|
-
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
3. Add the rule to your config file: `aicm.json`
|
|
139
|
-
|
|
140
|
-
```json
|
|
141
|
-
{
|
|
135
|
+
echo '{
|
|
142
136
|
"ides": ["cursor"],
|
|
143
|
-
"
|
|
144
|
-
|
|
145
|
-
}
|
|
146
|
-
}
|
|
137
|
+
"presets": ["pirate-coding"]
|
|
138
|
+
}' > aicm.json
|
|
147
139
|
```
|
|
148
140
|
|
|
149
|
-
|
|
141
|
+
3. Install all rules & mcps from your configuration
|
|
150
142
|
|
|
151
143
|
```bash
|
|
152
144
|
npx -y aicm install
|
|
@@ -154,7 +146,7 @@ npx -y aicm install
|
|
|
154
146
|
|
|
155
147
|
This command installs all configured rules and MCPs to their IDE-specific locations.
|
|
156
148
|
|
|
157
|
-
After installation, open Cursor and ask it to do something. Your AI assistant will respond with pirate-themed coding advice.
|
|
149
|
+
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
150
|
|
|
159
151
|
## Security Note
|
|
160
152
|
|
|
@@ -251,12 +243,65 @@ npx aicm init
|
|
|
251
243
|
|
|
252
244
|
### `install`
|
|
253
245
|
|
|
254
|
-
Installs rules
|
|
246
|
+
Installs all rules and MCPs configured in your `aicm.json`.
|
|
255
247
|
|
|
256
248
|
```bash
|
|
257
249
|
npx aicm install
|
|
258
250
|
```
|
|
259
251
|
|
|
252
|
+
## Node.js API
|
|
253
|
+
|
|
254
|
+
In addition to the CLI, aicm can be used programmatically in Node.js applications:
|
|
255
|
+
|
|
256
|
+
```javascript
|
|
257
|
+
const { install, Config } = require("aicm");
|
|
258
|
+
|
|
259
|
+
install().then((result) => {
|
|
260
|
+
if (result.success) {
|
|
261
|
+
console.log(`Successfully installed ${result.installedRuleCount} rules`);
|
|
262
|
+
} else {
|
|
263
|
+
console.error(`Error: ${result.error}`);
|
|
264
|
+
}
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
// Install with custom options
|
|
268
|
+
const customConfig = {
|
|
269
|
+
ides: ["cursor"],
|
|
270
|
+
rules: {
|
|
271
|
+
typescript: "./rules/typescript.mdc",
|
|
272
|
+
react: "@org/rules/react.mdc",
|
|
273
|
+
},
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
install({
|
|
277
|
+
config: customConfig,
|
|
278
|
+
cwd: "/path/to/project",
|
|
279
|
+
silent: true,
|
|
280
|
+
}).then((result) => {
|
|
281
|
+
// Handle result
|
|
282
|
+
});
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
### API Reference
|
|
286
|
+
|
|
287
|
+
#### `install(options?: InstallOptions): Promise<InstallResult>`
|
|
288
|
+
|
|
289
|
+
Installs rules and MCP servers based on configuration.
|
|
290
|
+
|
|
291
|
+
**Options:**
|
|
292
|
+
|
|
293
|
+
- `cwd`: Base directory to use instead of `process.cwd()`
|
|
294
|
+
- `config`: Custom config object to use instead of loading from file
|
|
295
|
+
- `silent`: Whether to suppress console output
|
|
296
|
+
|
|
297
|
+
**Returns:**
|
|
298
|
+
|
|
299
|
+
A Promise that resolves to an object with:
|
|
300
|
+
|
|
301
|
+
- `success`: Whether the operation was successful
|
|
302
|
+
- `error`: Error message if the operation failed
|
|
303
|
+
- `installedRuleCount`: Number of rules installed
|
|
304
|
+
|
|
260
305
|
## Contributing
|
|
261
306
|
|
|
262
307
|
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,39 @@ 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("\nRules installation completed!"));
|
|
102
173
|
}
|
|
103
174
|
catch (error) {
|
|
104
175
|
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.2",
|
|
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
|
},
|