aicm 0.6.5 → 0.8.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 +11 -8
- package/dist/api.d.ts +1 -1
- package/dist/api.js +1 -1
- package/dist/commands/init.js +1 -0
- package/dist/commands/install.d.ts +3 -3
- package/dist/commands/install.js +33 -21
- package/dist/commands/list.js +2 -2
- package/dist/index.js +3 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/utils/config.js +7 -5
- package/dist/utils/rule-status.d.ts +1 -1
- package/dist/utils/rule-status.js +1 -1
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -30,7 +30,6 @@ In your project's `aicm.json`, reference the package and the specific rule:
|
|
|
30
30
|
|
|
31
31
|
```json
|
|
32
32
|
{
|
|
33
|
-
"ides": ["cursor"],
|
|
34
33
|
"rules": {
|
|
35
34
|
"typescript": "@myteam/ai-tools/rules/typescript.mdc",
|
|
36
35
|
"react": "@myteam/ai-tools/rules/react.mdc"
|
|
@@ -80,7 +79,6 @@ In your project's `aicm.json`, reference the preset by its npm package or direct
|
|
|
80
79
|
|
|
81
80
|
```json
|
|
82
81
|
{
|
|
83
|
-
"ides": ["cursor"],
|
|
84
82
|
"presets": ["@myteam/ai-tools"]
|
|
85
83
|
}
|
|
86
84
|
```
|
|
@@ -132,10 +130,7 @@ npm install --save-dev pirate-coding
|
|
|
132
130
|
2. Create an `aicm.json` file in your project
|
|
133
131
|
|
|
134
132
|
```bash
|
|
135
|
-
echo '{
|
|
136
|
-
"ides": ["cursor"],
|
|
137
|
-
"presets": ["pirate-coding"]
|
|
138
|
-
}' > aicm.json
|
|
133
|
+
echo '{ "presets": ["pirate-coding"] }' > aicm.json
|
|
139
134
|
```
|
|
140
135
|
|
|
141
136
|
3. Install all rules & mcps from your configuration
|
|
@@ -179,6 +174,9 @@ Example `aicm.json`:
|
|
|
179
174
|
- **ides**: Array of IDE names where rules should be installed. Currently supported values:
|
|
180
175
|
|
|
181
176
|
- `"cursor"`: For the Cursor IDE
|
|
177
|
+
- `"windsurf"`: For the Windsurf IDE
|
|
178
|
+
|
|
179
|
+
> **Note:** The 'ides' field is default to `["cursor"]` if not specified.
|
|
182
180
|
|
|
183
181
|
- **rules**: Object containing rule configurations
|
|
184
182
|
|
|
@@ -194,6 +192,8 @@ Example `aicm.json`:
|
|
|
194
192
|
|
|
195
193
|
- Preset files should contain a `rules` and `mcpServers` objects with the same structure as the main configuration.
|
|
196
194
|
|
|
195
|
+
- **installOnCI**: Boolean flag (default: `false`) that controls whether installation should proceed in CI environments. When set to `true`, rules will be installed even in CI environments.
|
|
196
|
+
|
|
197
197
|
### MCP Server Installation
|
|
198
198
|
|
|
199
199
|
- **Cursor**: MCP server configs are written to `.cursor/mcp.json` (see Cursor docs for latest path).
|
|
@@ -249,6 +249,10 @@ Installs all rules and MCPs configured in your `aicm.json`.
|
|
|
249
249
|
npx aicm install
|
|
250
250
|
```
|
|
251
251
|
|
|
252
|
+
Options:
|
|
253
|
+
|
|
254
|
+
- `--ci`: run in CI environments (default: `false`)
|
|
255
|
+
|
|
252
256
|
## Node.js API
|
|
253
257
|
|
|
254
258
|
In addition to the CLI, aicm can be used programmatically in Node.js applications:
|
|
@@ -276,7 +280,6 @@ const customConfig = {
|
|
|
276
280
|
install({
|
|
277
281
|
config: customConfig,
|
|
278
282
|
cwd: "/path/to/project",
|
|
279
|
-
silent: true,
|
|
280
283
|
}).then((result) => {
|
|
281
284
|
// Handle result
|
|
282
285
|
});
|
|
@@ -292,7 +295,7 @@ Installs rules and MCP servers based on configuration.
|
|
|
292
295
|
|
|
293
296
|
- `cwd`: Base directory to use instead of `process.cwd()`
|
|
294
297
|
- `config`: Custom config object to use instead of loading from file
|
|
295
|
-
- `
|
|
298
|
+
- `installOnCI`: Run installation on CI environments (default: `false`)
|
|
296
299
|
|
|
297
300
|
**Returns:**
|
|
298
301
|
|
package/dist/api.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { InstallOptions, InstallResult } from "./commands/install";
|
|
2
2
|
/**
|
|
3
3
|
* Install AICM rules based on configuration
|
|
4
|
-
* @param options
|
|
4
|
+
* @param options Installation options
|
|
5
5
|
* @returns Result of the install operation
|
|
6
6
|
*/
|
|
7
7
|
export declare function install(options?: InstallOptions): Promise<InstallResult>;
|
package/dist/api.js
CHANGED
|
@@ -4,7 +4,7 @@ exports.install = install;
|
|
|
4
4
|
const install_1 = require("./commands/install");
|
|
5
5
|
/**
|
|
6
6
|
* Install AICM rules based on configuration
|
|
7
|
-
* @param options
|
|
7
|
+
* @param options Installation options
|
|
8
8
|
* @returns Result of the install operation
|
|
9
9
|
*/
|
|
10
10
|
async function install(options = {}) {
|
package/dist/commands/init.js
CHANGED
|
@@ -12,9 +12,9 @@ export interface InstallOptions {
|
|
|
12
12
|
*/
|
|
13
13
|
config?: Config;
|
|
14
14
|
/**
|
|
15
|
-
*
|
|
15
|
+
* allow installation on CI environments
|
|
16
16
|
*/
|
|
17
|
-
|
|
17
|
+
installOnCI?: boolean;
|
|
18
18
|
}
|
|
19
19
|
/**
|
|
20
20
|
* Result of the install operation
|
|
@@ -39,4 +39,4 @@ export interface InstallResult {
|
|
|
39
39
|
* @returns Result of the install operation
|
|
40
40
|
*/
|
|
41
41
|
export declare function install(options?: InstallOptions): Promise<InstallResult>;
|
|
42
|
-
export declare function installCommand(): Promise<void>;
|
|
42
|
+
export declare function installCommand(installOnCI?: boolean): Promise<void>;
|
package/dist/commands/install.js
CHANGED
|
@@ -12,6 +12,7 @@ const rule_collector_1 = require("../utils/rule-collector");
|
|
|
12
12
|
const rule_writer_1 = require("../utils/rule-writer");
|
|
13
13
|
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
14
14
|
const node_path_1 = __importDefault(require("node:path"));
|
|
15
|
+
const ci_info_1 = require("ci-info");
|
|
15
16
|
/**
|
|
16
17
|
* Write MCP servers configuration to IDE targets
|
|
17
18
|
* @param mcpServers The MCP servers configuration
|
|
@@ -33,6 +34,19 @@ function writeMcpServersToTargets(mcpServers, ides, cwd) {
|
|
|
33
34
|
}
|
|
34
35
|
}
|
|
35
36
|
}
|
|
37
|
+
/**
|
|
38
|
+
* Checks if the current environment is a CI environment
|
|
39
|
+
* This function respects any explicit settings in process.env.CI
|
|
40
|
+
*/
|
|
41
|
+
function isInCIEnvironment() {
|
|
42
|
+
// Explicit environment variable settings take precedence
|
|
43
|
+
if (process.env.CI === "true")
|
|
44
|
+
return true;
|
|
45
|
+
if (process.env.CI === "false")
|
|
46
|
+
return false;
|
|
47
|
+
// Fall back to ci-info's detection
|
|
48
|
+
return ci_info_1.isCI;
|
|
49
|
+
}
|
|
36
50
|
/**
|
|
37
51
|
* Core implementation of the rule installation logic
|
|
38
52
|
* @param options Install options
|
|
@@ -40,23 +54,15 @@ function writeMcpServersToTargets(mcpServers, ides, cwd) {
|
|
|
40
54
|
*/
|
|
41
55
|
async function install(options = {}) {
|
|
42
56
|
const cwd = options.cwd || process.cwd();
|
|
43
|
-
const
|
|
44
|
-
const log = silent ? () => { } : console.log;
|
|
45
|
-
const error = silent ? () => { } : console.error;
|
|
57
|
+
const installOnCI = options.installOnCI === true; // Default to false if not specified
|
|
46
58
|
try {
|
|
47
|
-
// Save original process.cwd() and change to the specified cwd
|
|
48
59
|
const originalCwd = process.cwd();
|
|
49
60
|
if (cwd !== originalCwd) {
|
|
50
61
|
process.chdir(cwd);
|
|
51
62
|
}
|
|
52
|
-
// Initialize rule collection
|
|
53
63
|
const ruleCollection = (0, rule_collector_1.initRuleCollection)();
|
|
54
|
-
// Use provided config or load from file
|
|
55
64
|
const config = options.config || (0, config_1.getConfig)();
|
|
56
|
-
// If config doesn't exist, return error
|
|
57
65
|
if (!config) {
|
|
58
|
-
error("Configuration file not found!");
|
|
59
|
-
// Restore original cwd
|
|
60
66
|
if (cwd !== originalCwd) {
|
|
61
67
|
process.chdir(originalCwd);
|
|
62
68
|
}
|
|
@@ -66,12 +72,21 @@ async function install(options = {}) {
|
|
|
66
72
|
installedRuleCount: 0,
|
|
67
73
|
};
|
|
68
74
|
}
|
|
75
|
+
const inCI = isInCIEnvironment();
|
|
76
|
+
if (inCI && !installOnCI && !config.installOnCI) {
|
|
77
|
+
if (cwd !== originalCwd) {
|
|
78
|
+
process.chdir(originalCwd);
|
|
79
|
+
}
|
|
80
|
+
console.log(chalk_1.default.yellow("Detected CI environment, skipping install."));
|
|
81
|
+
return {
|
|
82
|
+
success: true,
|
|
83
|
+
installedRuleCount: 0,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
69
86
|
// Check if rules are defined (either directly or through presets)
|
|
70
87
|
if (!config.rules || Object.keys(config.rules).length === 0) {
|
|
71
88
|
// If there are no presets defined either, show a message
|
|
72
89
|
if (!config.presets || config.presets.length === 0) {
|
|
73
|
-
error("No rules defined in configuration.");
|
|
74
|
-
// Restore original cwd
|
|
75
90
|
if (cwd !== originalCwd) {
|
|
76
91
|
process.chdir(originalCwd);
|
|
77
92
|
}
|
|
@@ -104,24 +119,20 @@ async function install(options = {}) {
|
|
|
104
119
|
ruleContent = (0, rule_collector_1.collectLocalRule)(name, source, ruleBasePath);
|
|
105
120
|
break;
|
|
106
121
|
default:
|
|
107
|
-
error(`Unknown rule type: ${ruleType}`);
|
|
108
122
|
errorMessages.push(`Unknown rule type: ${ruleType}`);
|
|
109
123
|
continue;
|
|
110
124
|
}
|
|
111
|
-
// Add rule to collection
|
|
112
125
|
(0, rule_collector_1.addRuleToCollection)(ruleCollection, ruleContent, config.ides);
|
|
113
126
|
installedRuleCount++;
|
|
114
127
|
}
|
|
115
128
|
catch (e) {
|
|
116
129
|
hasErrors = true;
|
|
117
130
|
const errorMessage = `Error processing rule ${name}: ${e instanceof Error ? e.message : String(e)}`;
|
|
118
|
-
error(errorMessage);
|
|
119
131
|
errorMessages.push(errorMessage);
|
|
120
132
|
}
|
|
121
133
|
}
|
|
122
134
|
// If there were errors, exit with error
|
|
123
135
|
if (hasErrors) {
|
|
124
|
-
// Restore original cwd
|
|
125
136
|
if (cwd !== originalCwd) {
|
|
126
137
|
process.chdir(originalCwd);
|
|
127
138
|
}
|
|
@@ -139,7 +150,6 @@ async function install(options = {}) {
|
|
|
139
150
|
const filteredMcpServers = Object.fromEntries(Object.entries(config.mcpServers).filter(([, v]) => v !== false));
|
|
140
151
|
writeMcpServersToTargets(filteredMcpServers, config.ides, cwd);
|
|
141
152
|
}
|
|
142
|
-
log("Rules installation completed");
|
|
143
153
|
// Restore original cwd
|
|
144
154
|
if (cwd !== originalCwd) {
|
|
145
155
|
process.chdir(originalCwd);
|
|
@@ -150,8 +160,7 @@ async function install(options = {}) {
|
|
|
150
160
|
};
|
|
151
161
|
}
|
|
152
162
|
catch (e) {
|
|
153
|
-
const errorMessage =
|
|
154
|
-
error(errorMessage);
|
|
163
|
+
const errorMessage = e instanceof Error ? e.message : String(e);
|
|
155
164
|
// If cwd was changed, restore it
|
|
156
165
|
if (cwd !== process.cwd()) {
|
|
157
166
|
process.chdir(cwd);
|
|
@@ -163,16 +172,19 @@ async function install(options = {}) {
|
|
|
163
172
|
};
|
|
164
173
|
}
|
|
165
174
|
}
|
|
166
|
-
async function installCommand() {
|
|
175
|
+
async function installCommand(installOnCI) {
|
|
167
176
|
try {
|
|
168
|
-
const result = await install({
|
|
177
|
+
const result = await install({ installOnCI });
|
|
169
178
|
if (!result.success) {
|
|
170
179
|
console.error(chalk_1.default.red(result.error));
|
|
171
180
|
process.exit(1);
|
|
172
181
|
}
|
|
182
|
+
else {
|
|
183
|
+
console.log("Rules installation completed");
|
|
184
|
+
}
|
|
173
185
|
}
|
|
174
186
|
catch (error) {
|
|
175
|
-
console.error(chalk_1.default.red(
|
|
187
|
+
console.error(chalk_1.default.red(error instanceof Error ? error.message : String(error)));
|
|
176
188
|
process.exit(1);
|
|
177
189
|
}
|
|
178
190
|
}
|
package/dist/commands/list.js
CHANGED
|
@@ -24,9 +24,9 @@ function listCommand() {
|
|
|
24
24
|
console.log(chalk_1.default.dim("─".repeat(50)));
|
|
25
25
|
for (const [ruleName, source] of Object.entries(config.rules)) {
|
|
26
26
|
if (source === false)
|
|
27
|
-
continue;
|
|
27
|
+
continue;
|
|
28
28
|
const ruleType = (0, rule_detector_1.detectRuleType)(source);
|
|
29
|
-
const status = (0, rule_status_1.checkRuleStatus)(ruleName,
|
|
29
|
+
const status = (0, rule_status_1.checkRuleStatus)(ruleName, config.ides);
|
|
30
30
|
const statusColor = status
|
|
31
31
|
? chalk_1.default.green("Installed")
|
|
32
32
|
: chalk_1.default.yellow("Not installed");
|
package/dist/index.js
CHANGED
|
@@ -16,6 +16,7 @@ const pkg = require("../package.json");
|
|
|
16
16
|
const args = (0, arg_1.default)({
|
|
17
17
|
"--help": Boolean,
|
|
18
18
|
"--version": Boolean,
|
|
19
|
+
"--ci": Boolean,
|
|
19
20
|
"-h": "--help",
|
|
20
21
|
"-v": "--version",
|
|
21
22
|
}, {
|
|
@@ -35,7 +36,7 @@ switch (command) {
|
|
|
35
36
|
(0, init_1.initCommand)();
|
|
36
37
|
break;
|
|
37
38
|
case "install":
|
|
38
|
-
(0, install_1.installCommand)();
|
|
39
|
+
(0, install_1.installCommand)(args["--ci"]);
|
|
39
40
|
break;
|
|
40
41
|
case "list":
|
|
41
42
|
(0, list_1.listCommand)();
|
|
@@ -60,6 +61,7 @@ ${chalk_1.default.bold("COMMANDS")}
|
|
|
60
61
|
${chalk_1.default.bold("OPTIONS")}
|
|
61
62
|
-h, --help Show this help message
|
|
62
63
|
-v, --version Show version number
|
|
64
|
+
--ci Run in CI environments (default: \`false\`)
|
|
63
65
|
|
|
64
66
|
${chalk_1.default.bold("EXAMPLES")}
|
|
65
67
|
$ aicm init
|
package/dist/types/index.d.ts
CHANGED
package/dist/utils/config.js
CHANGED
|
@@ -42,7 +42,7 @@ function getFullPresetPath(presetPath) {
|
|
|
42
42
|
function loadPreset(presetPath) {
|
|
43
43
|
const fullPresetPath = getFullPresetPath(presetPath);
|
|
44
44
|
if (!fullPresetPath) {
|
|
45
|
-
throw new Error(`Error loading preset:
|
|
45
|
+
throw new Error(`Error loading preset: "${presetPath}". Make sure the package is installed in your project.`);
|
|
46
46
|
}
|
|
47
47
|
const presetContent = fs_extra_1.default.readFileSync(fullPresetPath, "utf8");
|
|
48
48
|
let preset;
|
|
@@ -133,11 +133,12 @@ function loadAicmConfigCosmiconfig() {
|
|
|
133
133
|
const config = result.config;
|
|
134
134
|
if (!config.rules)
|
|
135
135
|
config.rules = {};
|
|
136
|
+
if (!config.ides)
|
|
137
|
+
config.ides = ["cursor"];
|
|
136
138
|
return config;
|
|
137
139
|
}
|
|
138
140
|
catch (error) {
|
|
139
|
-
|
|
140
|
-
return null;
|
|
141
|
+
throw new Error(`Error loading aicm config: ${error instanceof Error ? error.message : String(error)}`);
|
|
141
142
|
}
|
|
142
143
|
}
|
|
143
144
|
/**
|
|
@@ -145,8 +146,9 @@ function loadAicmConfigCosmiconfig() {
|
|
|
145
146
|
*/
|
|
146
147
|
function getConfig() {
|
|
147
148
|
const config = loadAicmConfigCosmiconfig();
|
|
148
|
-
if (!config)
|
|
149
|
-
|
|
149
|
+
if (!config) {
|
|
150
|
+
throw new Error(`No config found in ${process.cwd()}, create one using "aicm init"`);
|
|
151
|
+
}
|
|
150
152
|
processPresets(config);
|
|
151
153
|
return config;
|
|
152
154
|
}
|
|
@@ -5,4 +5,4 @@ export declare function getIdePaths(): Record<string, string>;
|
|
|
5
5
|
/**
|
|
6
6
|
* Check if a rule is installed in the specified IDEs
|
|
7
7
|
*/
|
|
8
|
-
export declare function checkRuleStatus(ruleName: string,
|
|
8
|
+
export declare function checkRuleStatus(ruleName: string, ides: string[]): boolean;
|
|
@@ -20,7 +20,7 @@ function getIdePaths() {
|
|
|
20
20
|
/**
|
|
21
21
|
* Check if a rule is installed in the specified IDEs
|
|
22
22
|
*/
|
|
23
|
-
function checkRuleStatus(ruleName,
|
|
23
|
+
function checkRuleStatus(ruleName, ides) {
|
|
24
24
|
const idePaths = getIdePaths();
|
|
25
25
|
return ides.every((ide) => {
|
|
26
26
|
if (!idePaths[ide]) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aicm",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "A TypeScript CLI tool for managing AI IDE rules across different projects and teams",
|
|
5
5
|
"main": "dist/api.js",
|
|
6
6
|
"types": "dist/api.d.ts",
|
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
"arg": "^5.0.2",
|
|
42
42
|
"args": "^5.0.3",
|
|
43
43
|
"chalk": "^4.1.2",
|
|
44
|
+
"ci-info": "^4.2.0",
|
|
44
45
|
"cosmiconfig": "^9.0.0",
|
|
45
46
|
"fs-extra": "^11.1.1"
|
|
46
47
|
},
|