aicm 0.14.4 → 0.15.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.
Files changed (51) hide show
  1. package/README.md +18 -1
  2. package/dist/commands/install.js +61 -93
  3. package/dist/utils/config.d.ts +3 -1
  4. package/dist/utils/config.js +2 -0
  5. package/dist/utils/rules-file-writer.d.ts +5 -0
  6. package/dist/utils/rules-file-writer.js +46 -1
  7. package/package.json +1 -1
  8. package/dist/api_v2.d.ts +0 -9
  9. package/dist/api_v2.js +0 -12
  10. package/dist/bin/aicm_v2.d.ts +0 -2
  11. package/dist/bin/aicm_v2.js +0 -8
  12. package/dist/cli_v2.d.ts +0 -2
  13. package/dist/cli_v2.js +0 -94
  14. package/dist/commands/install/install-package.d.ts +0 -53
  15. package/dist/commands/install/install-package.js +0 -122
  16. package/dist/commands/install/install-single-package.d.ts +0 -53
  17. package/dist/commands/install/install-single-package.js +0 -139
  18. package/dist/commands/install/install-workspaces.d.ts +0 -9
  19. package/dist/commands/install/install-workspaces.js +0 -172
  20. package/dist/commands/install_new.d.ts +0 -17
  21. package/dist/commands/install_new.js +0 -457
  22. package/dist/commands/install_v2.d.ts +0 -52
  23. package/dist/commands/install_v2.js +0 -505
  24. package/dist/commands/install_/327/2242.d.ts +0 -59
  25. package/dist/commands/install_/327/2242.js +0 -546
  26. package/dist/commands/workspaces/discovery.d.ts +0 -7
  27. package/dist/commands/workspaces/discovery.js +0 -50
  28. package/dist/commands/workspaces/workspaces-install.d.ts +0 -9
  29. package/dist/commands/workspaces/workspaces-install.js +0 -48
  30. package/dist/index.d.ts +0 -2
  31. package/dist/index.js +0 -76
  32. package/dist/types/index.d.ts +0 -64
  33. package/dist/types/index.js +0 -2
  34. package/dist/utils/config_new.d.ts +0 -64
  35. package/dist/utils/config_new.js +0 -228
  36. package/dist/utils/config_v2.d.ts +0 -64
  37. package/dist/utils/config_v2.js +0 -250
  38. package/dist/utils/glob-handler.d.ts +0 -35
  39. package/dist/utils/glob-handler.js +0 -125
  40. package/dist/utils/mcp-writer.d.ts +0 -14
  41. package/dist/utils/mcp-writer.js +0 -69
  42. package/dist/utils/mdc-parser.d.ts +0 -9
  43. package/dist/utils/mdc-parser.js +0 -59
  44. package/dist/utils/rule-collector.d.ts +0 -33
  45. package/dist/utils/rule-collector.js +0 -169
  46. package/dist/utils/rule-detector.d.ts +0 -4
  47. package/dist/utils/rule-detector.js +0 -31
  48. package/dist/utils/rule-status.d.ts +0 -8
  49. package/dist/utils/rule-status.js +0 -53
  50. package/dist/utils/rule-writer.d.ts +0 -6
  51. package/dist/utils/rule-writer.js +0 -118
package/dist/index.js DELETED
@@ -1,76 +0,0 @@
1
- #!/usr/bin/env node
2
- "use strict";
3
- var __importDefault = (this && this.__importDefault) || function (mod) {
4
- return (mod && mod.__esModule) ? mod : { "default": mod };
5
- };
6
- Object.defineProperty(exports, "__esModule", { value: true });
7
- const arg_1 = __importDefault(require("arg"));
8
- const chalk_1 = __importDefault(require("chalk"));
9
- const init_1 = require("./commands/init");
10
- const install_1 = require("./commands/install");
11
- const list_1 = require("./commands/list");
12
- // Define version from package.json
13
- // eslint-disable-next-line @typescript-eslint/no-require-imports
14
- const pkg = require("../package.json");
15
- // Parse arguments
16
- const args = (0, arg_1.default)({
17
- "--help": Boolean,
18
- "--version": Boolean,
19
- "--ci": Boolean,
20
- "--workspaces": Boolean,
21
- "--verbose": Boolean,
22
- "-h": "--help",
23
- "-v": "--version",
24
- }, {
25
- permissive: true,
26
- argv: process.argv.slice(2),
27
- });
28
- // Show version
29
- if (args["--version"]) {
30
- console.log(pkg.version);
31
- process.exit(0);
32
- }
33
- // Get the command (first non-flag argument)
34
- const command = args._.length > 0 ? args._[0] : null;
35
- // Execute the appropriate command
36
- switch (command) {
37
- case "init":
38
- (0, init_1.initCommand)();
39
- break;
40
- case "install":
41
- (0, install_1.installCommand)(args["--ci"], args["--workspaces"], args["--verbose"]);
42
- break;
43
- case "list":
44
- (0, list_1.listCommand)();
45
- break;
46
- default:
47
- // Show help
48
- showHelp();
49
- break;
50
- }
51
- function showHelp() {
52
- console.log(`
53
- ${chalk_1.default.bold("aicm")} - A CLI tool for managing AI IDE configurations
54
-
55
- ${chalk_1.default.bold("USAGE")}
56
- $ aicm [command] [options]
57
-
58
- ${chalk_1.default.bold("COMMANDS")}
59
- init Initialize a new aicm configuration file
60
- install Install rules from configured sources
61
- list List all configured rules and their status
62
-
63
- ${chalk_1.default.bold("OPTIONS")}
64
- -h, --help Show this help message
65
- -v, --version Show version number
66
- --ci Run in CI environments (default: \`false\`)
67
- --workspaces Install rules across all workspaces
68
- --verbose Show detailed output during installation
69
-
70
- ${chalk_1.default.bold("EXAMPLES")}
71
- $ aicm init
72
- $ aicm install
73
- $ aicm install --workspaces
74
- $ aicm list
75
- `);
76
- }
@@ -1,64 +0,0 @@
1
- export type Rule = string | false;
2
- export interface Rules {
3
- [ruleName: string]: Rule;
4
- }
5
- export type MCPServer = {
6
- command: string;
7
- args?: string[];
8
- env?: Record<string, string>;
9
- url?: never;
10
- } | {
11
- url: string;
12
- env?: Record<string, string>;
13
- command?: never;
14
- args?: never;
15
- } | false;
16
- export interface MCPServers {
17
- [serverName: string]: MCPServer;
18
- }
19
- export interface Config {
20
- ides?: string[];
21
- rules?: Rules | string;
22
- presets?: string[];
23
- mcpServers?: MCPServers;
24
- workspaces?: boolean;
25
- }
26
- export interface NormalizedConfig extends Omit<Config, "rules"> {
27
- ides: string[];
28
- rules: Rules;
29
- }
30
- export interface RuleMetadata {
31
- type?: string;
32
- alwaysApply?: boolean | string;
33
- globs?: string[] | string;
34
- description?: string;
35
- [key: string]: any;
36
- }
37
- export interface RuleContent {
38
- name: string;
39
- content: string;
40
- metadata: RuleMetadata;
41
- sourcePath: string;
42
- presetPath?: string;
43
- }
44
- export interface RuleCollection {
45
- cursor: RuleContent[];
46
- windsurf: RuleContent[];
47
- codex: RuleContent[];
48
- }
49
- export interface PackageInfo {
50
- relativePath: string;
51
- absolutePath: string;
52
- config: NormalizedConfig;
53
- }
54
- export interface WorkspacesInstallResult {
55
- success: boolean;
56
- packages: Array<{
57
- path: string;
58
- success: boolean;
59
- error?: string;
60
- errorStack?: string;
61
- installedRuleCount: number;
62
- }>;
63
- totalRuleCount: number;
64
- }
@@ -1,2 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,64 +0,0 @@
1
- import { CosmiconfigResult } from "cosmiconfig";
2
- export interface RawConfig {
3
- rulesDir: string;
4
- targets?: string[];
5
- presets?: string[];
6
- overrides?: Record<string, string | false>;
7
- mcpServers?: MCPServers;
8
- workspaces?: boolean;
9
- }
10
- export interface Config {
11
- rulesDir: string;
12
- targets: string[];
13
- presets?: string[];
14
- overrides?: Record<string, string | false>;
15
- mcpServers?: MCPServers;
16
- workspaces?: boolean;
17
- }
18
- export type MCPServer = {
19
- command: string;
20
- args?: string[];
21
- env?: Record<string, string>;
22
- url?: never;
23
- } | {
24
- url: string;
25
- env?: Record<string, string>;
26
- command?: never;
27
- args?: never;
28
- } | false;
29
- export interface MCPServers {
30
- [serverName: string]: MCPServer;
31
- }
32
- export interface RuleFile {
33
- name: string;
34
- content: string;
35
- sourcePath: string;
36
- source: "local" | "preset";
37
- presetName?: string;
38
- }
39
- export interface RuleCollection {
40
- [target: string]: RuleFile[];
41
- }
42
- export interface ResolvedConfig {
43
- config: Config;
44
- rules: RuleFile[];
45
- mcpServers: MCPServers;
46
- }
47
- export declare const SUPPORTED_TARGETS: readonly ["cursor", "windsurf", "codex"];
48
- export type SupportedTarget = (typeof SUPPORTED_TARGETS)[number];
49
- export declare function applyDefaults(config: RawConfig): Config;
50
- export declare function validateConfig(config: unknown, configFilePath: string, cwd: string): asserts config is Config;
51
- export declare function loadRulesFromDirectory(rulesDir: string, source: "local" | "preset", presetName?: string): Promise<RuleFile[]>;
52
- export declare function resolvePresetPath(presetPath: string, cwd: string): string | null;
53
- export declare function loadPreset(presetPath: string, cwd: string): Promise<{
54
- config: Config;
55
- rulesDir: string;
56
- }>;
57
- export declare function loadAllRules(config: Config, cwd: string): Promise<{
58
- rules: RuleFile[];
59
- mcpServers: MCPServers;
60
- }>;
61
- export declare function applyOverrides(rules: RuleFile[], overrides: Record<string, string | false>, cwd: string): RuleFile[];
62
- export declare function loadConfigFile(searchFrom?: string): Promise<CosmiconfigResult>;
63
- export declare function loadConfig(cwd?: string): Promise<ResolvedConfig | null>;
64
- export declare function saveConfig(config: Config, cwd?: string): boolean;
@@ -1,228 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.SUPPORTED_TARGETS = void 0;
7
- exports.applyDefaults = applyDefaults;
8
- exports.validateConfig = validateConfig;
9
- exports.loadRulesFromDirectory = loadRulesFromDirectory;
10
- exports.resolvePresetPath = resolvePresetPath;
11
- exports.loadPreset = loadPreset;
12
- exports.loadAllRules = loadAllRules;
13
- exports.applyOverrides = applyOverrides;
14
- exports.loadConfigFile = loadConfigFile;
15
- exports.loadConfig = loadConfig;
16
- exports.saveConfig = saveConfig;
17
- const fs_extra_1 = __importDefault(require("fs-extra"));
18
- const node_path_1 = __importDefault(require("node:path"));
19
- const cosmiconfig_1 = require("cosmiconfig");
20
- const fast_glob_1 = __importDefault(require("fast-glob"));
21
- exports.SUPPORTED_TARGETS = ["cursor", "windsurf", "codex"];
22
- function applyDefaults(config) {
23
- return {
24
- rulesDir: config.rulesDir,
25
- targets: config.targets || ["cursor"],
26
- presets: config.presets || [],
27
- overrides: config.overrides || {},
28
- mcpServers: config.mcpServers || {},
29
- workspaces: config.workspaces || false,
30
- };
31
- }
32
- function validateConfig(config, configFilePath, cwd) {
33
- if (typeof config !== "object" || config === null) {
34
- throw new Error(`Config is not an object at ${configFilePath}`);
35
- }
36
- if (!("rulesDir" in config)) {
37
- throw new Error(`rulesDir is not specified in config at ${configFilePath}`);
38
- }
39
- if (typeof config.rulesDir !== "string") {
40
- throw new Error(`rulesDir is not a string in config at ${configFilePath}`);
41
- }
42
- const rulesPath = node_path_1.default.resolve(cwd, config.rulesDir);
43
- if (!fs_extra_1.default.existsSync(rulesPath)) {
44
- throw new Error(`Rules directory does not exist: ${rulesPath}`);
45
- }
46
- if (!fs_extra_1.default.statSync(rulesPath).isDirectory()) {
47
- throw new Error(`Rules path is not a directory: ${rulesPath}`);
48
- }
49
- if ("targets" in config) {
50
- if (!Array.isArray(config.targets)) {
51
- throw new Error(`targets must be an array in config at ${configFilePath}`);
52
- }
53
- if (config.targets.length === 0) {
54
- throw new Error(`targets must not be empty in config at ${configFilePath}`);
55
- }
56
- for (const target of config.targets) {
57
- if (!exports.SUPPORTED_TARGETS.includes(target)) {
58
- throw new Error(`Unsupported target: ${target}. Supported targets: ${exports.SUPPORTED_TARGETS.join(", ")}`);
59
- }
60
- }
61
- }
62
- // Validate override rule names will be checked after rule resolution
63
- }
64
- async function loadRulesFromDirectory(rulesDir, source, presetName) {
65
- const rules = [];
66
- if (!fs_extra_1.default.existsSync(rulesDir)) {
67
- return rules;
68
- }
69
- const pattern = node_path_1.default.join(rulesDir, "**/*.mdc").replace(/\\/g, "/");
70
- const filePaths = await (0, fast_glob_1.default)(pattern, {
71
- onlyFiles: true,
72
- absolute: true,
73
- });
74
- for (const filePath of filePaths) {
75
- const content = await fs_extra_1.default.readFile(filePath, "utf8");
76
- const ruleName = node_path_1.default.basename(filePath, ".mdc");
77
- rules.push({
78
- name: ruleName,
79
- content,
80
- sourcePath: filePath,
81
- source,
82
- presetName,
83
- });
84
- }
85
- return rules;
86
- }
87
- function resolvePresetPath(presetPath, cwd) {
88
- // Support specifying aicm.json directory and load the config from it
89
- if (!presetPath.endsWith(".json")) {
90
- presetPath = node_path_1.default.join(presetPath, "aicm.json");
91
- }
92
- // Support local or absolute paths
93
- const absolutePath = node_path_1.default.isAbsolute(presetPath)
94
- ? presetPath
95
- : node_path_1.default.resolve(cwd, presetPath);
96
- if (fs_extra_1.default.existsSync(absolutePath)) {
97
- return absolutePath;
98
- }
99
- try {
100
- // Support npm packages
101
- const resolvedPath = require.resolve(presetPath, {
102
- paths: [cwd, __dirname],
103
- });
104
- return fs_extra_1.default.existsSync(resolvedPath) ? resolvedPath : null;
105
- }
106
- catch (_a) {
107
- return null;
108
- }
109
- }
110
- async function loadPreset(presetPath, cwd) {
111
- const resolvedPresetPath = resolvePresetPath(presetPath, cwd);
112
- if (!resolvedPresetPath) {
113
- throw new Error(`Preset not found: "${presetPath}". Make sure the package is installed or the path is correct.`);
114
- }
115
- let presetConfig;
116
- try {
117
- const content = await fs_extra_1.default.readFile(resolvedPresetPath, "utf8");
118
- presetConfig = JSON.parse(content);
119
- }
120
- catch (error) {
121
- throw new Error(`Failed to load preset "${presetPath}": ${error instanceof Error ? error.message : "Unknown error"}`);
122
- }
123
- // Resolve preset's rules directory relative to the preset file
124
- const presetDir = node_path_1.default.dirname(resolvedPresetPath);
125
- const presetRulesDir = node_path_1.default.resolve(presetDir, presetConfig.rulesDir);
126
- return {
127
- config: presetConfig,
128
- rulesDir: presetRulesDir,
129
- };
130
- }
131
- async function loadAllRules(config, cwd) {
132
- const allRules = [];
133
- let mergedMcpServers = { ...config.mcpServers };
134
- // Load local rules
135
- const localRulesPath = node_path_1.default.resolve(cwd, config.rulesDir);
136
- const localRules = await loadRulesFromDirectory(localRulesPath, "local");
137
- allRules.push(...localRules);
138
- if (config.presets) {
139
- for (const presetPath of config.presets) {
140
- const preset = await loadPreset(presetPath, cwd);
141
- const presetRules = await loadRulesFromDirectory(preset.rulesDir, "preset", presetPath);
142
- allRules.push(...presetRules);
143
- // Merge MCP servers from preset
144
- if (preset.config.mcpServers) {
145
- mergedMcpServers = { ...mergedMcpServers, ...preset.config.mcpServers };
146
- }
147
- }
148
- }
149
- return {
150
- rules: allRules,
151
- mcpServers: mergedMcpServers,
152
- };
153
- }
154
- function applyOverrides(rules, overrides, cwd) {
155
- // Validate that all override rule names exist in the resolved rules
156
- for (const ruleName of Object.keys(overrides)) {
157
- // TODO: support better error messages with edit distance, helping the user in case of a typo
158
- // TODO: or shows a list of potential rules to override
159
- if (!rules.some((rule) => rule.name === ruleName)) {
160
- throw new Error(`Override rule "${ruleName}" does not exist in resolved rules`);
161
- }
162
- }
163
- const ruleMap = new Map();
164
- for (const rule of rules) {
165
- ruleMap.set(rule.name, rule);
166
- }
167
- for (const [ruleName, override] of Object.entries(overrides)) {
168
- if (override === false) {
169
- ruleMap.delete(ruleName);
170
- }
171
- else if (typeof override === "string") {
172
- const overridePath = node_path_1.default.resolve(cwd, override);
173
- if (!fs_extra_1.default.existsSync(overridePath)) {
174
- throw new Error(`Override rule file not found: ${override} in ${cwd}`);
175
- }
176
- const content = fs_extra_1.default.readFileSync(overridePath, "utf8");
177
- ruleMap.set(ruleName, {
178
- name: ruleName,
179
- content,
180
- sourcePath: overridePath,
181
- source: "local",
182
- });
183
- }
184
- }
185
- return Array.from(ruleMap.values());
186
- }
187
- async function loadConfigFile(searchFrom) {
188
- const explorer = (0, cosmiconfig_1.cosmiconfig)("aicm", {
189
- searchPlaces: ["aicm.json", "package.json"],
190
- });
191
- try {
192
- const result = await explorer.search(searchFrom);
193
- return result;
194
- }
195
- catch (error) {
196
- throw new Error(`Failed to load configuration: ${error instanceof Error ? error.message : "Unknown error"}`);
197
- }
198
- }
199
- async function loadConfig(cwd) {
200
- const workingDir = cwd || process.cwd();
201
- const configResult = await loadConfigFile(workingDir);
202
- if (!(configResult === null || configResult === void 0 ? void 0 : configResult.config)) {
203
- return null;
204
- }
205
- validateConfig(configResult.config, configResult.filepath, workingDir);
206
- const config = applyDefaults(configResult.config);
207
- const { rules, mcpServers } = await loadAllRules(config, workingDir);
208
- let rulesWithOverrides = rules;
209
- if (config.overrides) {
210
- rulesWithOverrides = applyOverrides(rules, config.overrides, workingDir);
211
- }
212
- return {
213
- config,
214
- rules: rulesWithOverrides,
215
- mcpServers,
216
- };
217
- }
218
- function saveConfig(config, cwd) {
219
- const workingDir = cwd || process.cwd();
220
- const configPath = node_path_1.default.join(workingDir, "aicm.json");
221
- try {
222
- fs_extra_1.default.writeFileSync(configPath, JSON.stringify(config, null, 2));
223
- return true;
224
- }
225
- catch (_a) {
226
- return false;
227
- }
228
- }
@@ -1,64 +0,0 @@
1
- import { CosmiconfigResult } from "cosmiconfig";
2
- export interface RawConfig {
3
- rulesDir: string;
4
- targets?: string[];
5
- presets?: string[];
6
- overrides?: Record<string, string | false>;
7
- mcpServers?: MCPServers;
8
- workspaces?: boolean;
9
- }
10
- export interface Config {
11
- rulesDir: string;
12
- targets: string[];
13
- presets?: string[];
14
- overrides?: Record<string, string | false>;
15
- mcpServers?: MCPServers;
16
- workspaces?: boolean;
17
- }
18
- export type MCPServer = {
19
- command: string;
20
- args?: string[];
21
- env?: Record<string, string>;
22
- url?: never;
23
- } | {
24
- url: string;
25
- env?: Record<string, string>;
26
- command?: never;
27
- args?: never;
28
- } | false;
29
- export interface MCPServers {
30
- [serverName: string]: MCPServer;
31
- }
32
- export interface RuleFile {
33
- name: string;
34
- content: string;
35
- sourcePath: string;
36
- source: "local" | "preset";
37
- presetName?: string;
38
- }
39
- export interface RuleCollection {
40
- [target: string]: RuleFile[];
41
- }
42
- export interface ResolvedConfig {
43
- config: Config;
44
- rules: RuleFile[];
45
- mcpServers: MCPServers;
46
- }
47
- export declare const SUPPORTED_TARGETS: readonly ["cursor", "windsurf", "codex"];
48
- export type SupportedTarget = (typeof SUPPORTED_TARGETS)[number];
49
- export declare function applyDefaults(config: RawConfig): Config;
50
- export declare function validateConfig(config: unknown, configFilePath: string, cwd: string): asserts config is Config;
51
- export declare function loadRulesFromDirectory(rulesDir: string, source: "local" | "preset", presetName?: string): Promise<RuleFile[]>;
52
- export declare function resolvePresetPath(presetPath: string, cwd: string): string | null;
53
- export declare function loadPreset(presetPath: string, cwd: string): Promise<{
54
- config: Config;
55
- rulesDir: string;
56
- }>;
57
- export declare function loadAllRules(config: Config, cwd: string): Promise<{
58
- rules: RuleFile[];
59
- mcpServers: MCPServers;
60
- }>;
61
- export declare function applyOverrides(rules: RuleFile[], overrides: Record<string, string | false>, cwd: string): RuleFile[];
62
- export declare function loadConfigFile(searchFrom?: string): Promise<CosmiconfigResult>;
63
- export declare function loadConfig(cwd?: string): Promise<ResolvedConfig | null>;
64
- export declare function saveConfig(config: Config, cwd?: string): boolean;