aicm 0.20.0 → 0.20.5

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.
@@ -1,49 +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.initCommand = initCommand;
7
- const fs_extra_1 = __importDefault(require("fs-extra"));
8
- const path_1 = __importDefault(require("path"));
9
- const chalk_1 = __importDefault(require("chalk"));
10
- const defaultConfig = {
11
- rootDir: "./",
12
- targets: ["cursor"],
13
- };
14
- function initCommand() {
15
- const configPath = path_1.default.join(process.cwd(), "aicm.json");
16
- if (fs_extra_1.default.existsSync(configPath)) {
17
- console.log(chalk_1.default.yellow("Configuration file already exists!"));
18
- return;
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
- }
34
- fs_extra_1.default.writeJsonSync(configPath, defaultConfig, { spaces: 2 });
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`);
41
- console.log(`\nNext steps:`);
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`);
45
- }
46
- catch (error) {
47
- console.error(chalk_1.default.red("Error creating configuration file:"), error);
48
- }
49
- }
@@ -1,5 +0,0 @@
1
- import { InstallResult } from "./install";
2
- /**
3
- * Install rules across multiple packages in a workspace
4
- */
5
- export declare function installWorkspaces(cwd: string, installOnCI: boolean, verbose?: boolean, dryRun?: boolean): Promise<InstallResult>;
@@ -1,349 +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.installWorkspaces = installWorkspaces;
7
- const chalk_1 = __importDefault(require("chalk"));
8
- const node_path_1 = __importDefault(require("node:path"));
9
- const hooks_1 = require("../utils/hooks");
10
- const working_directory_1 = require("../utils/working-directory");
11
- const workspace_discovery_1 = require("../utils/workspace-discovery");
12
- const install_1 = require("./install");
13
- function mergeWorkspaceCommands(packages) {
14
- var _a;
15
- const commands = [];
16
- const seenPresetCommands = new Set();
17
- for (const pkg of packages) {
18
- const hasCursorTarget = pkg.config.config.targets.includes("cursor");
19
- if (!hasCursorTarget) {
20
- continue;
21
- }
22
- for (const command of (_a = pkg.config.commands) !== null && _a !== void 0 ? _a : []) {
23
- if (command.presetName) {
24
- const presetKey = `${command.presetName}::${command.name}`;
25
- if (seenPresetCommands.has(presetKey)) {
26
- continue;
27
- }
28
- seenPresetCommands.add(presetKey);
29
- }
30
- commands.push(command);
31
- }
32
- }
33
- return commands;
34
- }
35
- function collectWorkspaceCommandTargets(packages) {
36
- const targets = new Set();
37
- for (const pkg of packages) {
38
- if (pkg.config.config.targets.includes("cursor")) {
39
- targets.add("cursor");
40
- }
41
- }
42
- return Array.from(targets);
43
- }
44
- /**
45
- * Merge skills from multiple workspace packages
46
- * Skills are merged flat (not namespaced by preset)
47
- * Dedupes preset skills that appear in multiple packages
48
- */
49
- function mergeWorkspaceSkills(packages) {
50
- var _a;
51
- const skills = [];
52
- const seenPresetSkills = new Set();
53
- for (const pkg of packages) {
54
- // Skills are supported by cursor, claude, and codex targets
55
- const hasSkillsTarget = pkg.config.config.targets.includes("cursor") ||
56
- pkg.config.config.targets.includes("claude") ||
57
- pkg.config.config.targets.includes("codex");
58
- if (!hasSkillsTarget) {
59
- continue;
60
- }
61
- for (const skill of (_a = pkg.config.skills) !== null && _a !== void 0 ? _a : []) {
62
- if (skill.presetName) {
63
- // Dedupe preset skills by preset+name combination
64
- const presetKey = `${skill.presetName}::${skill.name}`;
65
- if (seenPresetSkills.has(presetKey)) {
66
- continue;
67
- }
68
- seenPresetSkills.add(presetKey);
69
- }
70
- skills.push(skill);
71
- }
72
- }
73
- return skills;
74
- }
75
- /**
76
- * Collect all targets that support skills from workspace packages
77
- */
78
- function collectWorkspaceSkillTargets(packages) {
79
- const targets = new Set();
80
- for (const pkg of packages) {
81
- for (const target of pkg.config.config.targets) {
82
- // Skills are supported by cursor, claude, and codex
83
- if (target === "cursor" || target === "claude" || target === "codex") {
84
- targets.add(target);
85
- }
86
- }
87
- }
88
- return Array.from(targets);
89
- }
90
- function mergeWorkspaceMcpServers(packages) {
91
- const merged = {};
92
- const info = {};
93
- for (const pkg of packages) {
94
- for (const [key, value] of Object.entries(pkg.config.mcpServers)) {
95
- if (value === false)
96
- continue;
97
- const json = JSON.stringify(value);
98
- if (!info[key]) {
99
- info[key] = {
100
- configs: new Set([json]),
101
- packages: [pkg.relativePath],
102
- chosen: pkg.relativePath,
103
- };
104
- }
105
- else {
106
- info[key].packages.push(pkg.relativePath);
107
- info[key].configs.add(json);
108
- info[key].chosen = pkg.relativePath;
109
- }
110
- merged[key] = value;
111
- }
112
- }
113
- const conflicts = [];
114
- for (const [key, data] of Object.entries(info)) {
115
- if (data.configs.size > 1) {
116
- conflicts.push({ key, packages: data.packages, chosen: data.chosen });
117
- }
118
- }
119
- return { merged, conflicts };
120
- }
121
- /**
122
- * Merge hooks from multiple workspace packages
123
- */
124
- function mergeWorkspaceHooks(packages) {
125
- const allHooksConfigs = [];
126
- const allHookFiles = [];
127
- for (const pkg of packages) {
128
- // Collect hooks configs
129
- if (pkg.config.hooks) {
130
- allHooksConfigs.push(pkg.config.hooks);
131
- }
132
- // Collect hook files
133
- allHookFiles.push(...pkg.config.hookFiles);
134
- }
135
- // Merge hooks configs
136
- const merged = (0, hooks_1.mergeHooksConfigs)(allHooksConfigs);
137
- // Dedupe hook files by basename with MD5 checking
138
- const dedupedHookFiles = (0, hooks_1.dedupeHookFiles)(allHookFiles);
139
- return { merged, hookFiles: dedupedHookFiles };
140
- }
141
- /**
142
- * Install aicm configurations for all packages in a workspace
143
- */
144
- async function installWorkspacesPackages(packages, options = {}) {
145
- const results = [];
146
- let totalRuleCount = 0;
147
- let totalCommandCount = 0;
148
- let totalAssetCount = 0;
149
- let totalHookCount = 0;
150
- let totalSkillCount = 0;
151
- // Install packages sequentially for now (can be parallelized later)
152
- for (const pkg of packages) {
153
- const packagePath = pkg.absolutePath;
154
- try {
155
- const result = await (0, install_1.installPackage)({
156
- ...options,
157
- cwd: packagePath,
158
- config: pkg.config,
159
- });
160
- totalRuleCount += result.installedRuleCount;
161
- totalCommandCount += result.installedCommandCount;
162
- totalAssetCount += result.installedAssetCount;
163
- totalHookCount += result.installedHookCount;
164
- totalSkillCount += result.installedSkillCount;
165
- results.push({
166
- path: pkg.relativePath,
167
- success: result.success,
168
- error: result.error,
169
- installedRuleCount: result.installedRuleCount,
170
- installedCommandCount: result.installedCommandCount,
171
- installedAssetCount: result.installedAssetCount,
172
- installedHookCount: result.installedHookCount,
173
- installedSkillCount: result.installedSkillCount,
174
- });
175
- }
176
- catch (error) {
177
- results.push({
178
- path: pkg.relativePath,
179
- success: false,
180
- error: error instanceof Error ? error : new Error(String(error)),
181
- installedRuleCount: 0,
182
- installedCommandCount: 0,
183
- installedAssetCount: 0,
184
- installedHookCount: 0,
185
- installedSkillCount: 0,
186
- });
187
- }
188
- }
189
- const failedPackages = results.filter((r) => !r.success);
190
- return {
191
- success: failedPackages.length === 0,
192
- packages: results,
193
- totalRuleCount,
194
- totalCommandCount,
195
- totalAssetCount,
196
- totalHookCount,
197
- totalSkillCount,
198
- };
199
- }
200
- /**
201
- * Install rules across multiple packages in a workspace
202
- */
203
- async function installWorkspaces(cwd, installOnCI, verbose = false, dryRun = false) {
204
- return (0, working_directory_1.withWorkingDirectory)(cwd, async () => {
205
- if (verbose) {
206
- console.log(chalk_1.default.blue("🔍 Discovering packages..."));
207
- }
208
- const allPackages = await (0, workspace_discovery_1.discoverPackagesWithAicm)(cwd);
209
- const packages = allPackages.filter((pkg) => {
210
- if (pkg.config.config.skipInstall === true) {
211
- return false;
212
- }
213
- const isRoot = pkg.relativePath === ".";
214
- if (!isRoot)
215
- return true;
216
- // For root directories, only keep if it has rules, commands, skills, or presets
217
- const hasRules = pkg.config.rules && pkg.config.rules.length > 0;
218
- const hasCommands = pkg.config.commands && pkg.config.commands.length > 0;
219
- const hasSkills = pkg.config.skills && pkg.config.skills.length > 0;
220
- const hasPresets = pkg.config.config.presets && pkg.config.config.presets.length > 0;
221
- return hasRules || hasCommands || hasSkills || hasPresets;
222
- });
223
- if (packages.length === 0) {
224
- return {
225
- success: false,
226
- error: new Error("No packages with aicm configurations found"),
227
- installedRuleCount: 0,
228
- installedCommandCount: 0,
229
- installedAssetCount: 0,
230
- installedHookCount: 0,
231
- installedSkillCount: 0,
232
- packagesCount: 0,
233
- };
234
- }
235
- if (verbose) {
236
- console.log(chalk_1.default.blue(`Found ${packages.length} packages with aicm configurations:`));
237
- packages.forEach((pkg) => {
238
- console.log(chalk_1.default.gray(` - ${pkg.relativePath}`));
239
- });
240
- console.log(chalk_1.default.blue(`📦 Installing configurations...`));
241
- }
242
- const result = await installWorkspacesPackages(packages, {
243
- installOnCI,
244
- verbose,
245
- dryRun,
246
- });
247
- const workspaceCommands = mergeWorkspaceCommands(packages);
248
- const workspaceCommandTargets = collectWorkspaceCommandTargets(packages);
249
- if (workspaceCommands.length > 0) {
250
- (0, install_1.warnPresetCommandCollisions)(workspaceCommands);
251
- }
252
- if (!dryRun &&
253
- workspaceCommands.length > 0 &&
254
- workspaceCommandTargets.length > 0) {
255
- const dedupedWorkspaceCommands = (0, install_1.dedupeCommandsForInstall)(workspaceCommands);
256
- // Collect all assets from packages
257
- const allAssets = packages.flatMap((pkg) => { var _a; return (_a = pkg.config.assets) !== null && _a !== void 0 ? _a : []; });
258
- // Copy assets to root
259
- (0, install_1.writeAssetsToTargets)(allAssets, workspaceCommandTargets);
260
- (0, install_1.writeCommandsToTargets)(dedupedWorkspaceCommands, workspaceCommandTargets);
261
- }
262
- // Merge and write skills for workspace
263
- const workspaceSkills = mergeWorkspaceSkills(packages);
264
- const workspaceSkillTargets = collectWorkspaceSkillTargets(packages);
265
- if (workspaceSkills.length > 0) {
266
- (0, install_1.warnPresetSkillCollisions)(workspaceSkills);
267
- }
268
- if (!dryRun &&
269
- workspaceSkills.length > 0 &&
270
- workspaceSkillTargets.length > 0) {
271
- const dedupedWorkspaceSkills = (0, install_1.dedupeSkillsForInstall)(workspaceSkills);
272
- (0, install_1.writeSkillsToTargets)(dedupedWorkspaceSkills, workspaceSkillTargets);
273
- }
274
- const { merged: rootMcp, conflicts } = mergeWorkspaceMcpServers(packages);
275
- const hasCursorTarget = packages.some((p) => p.config.config.targets.includes("cursor"));
276
- if (!dryRun && hasCursorTarget && Object.keys(rootMcp).length > 0) {
277
- const mcpPath = node_path_1.default.join(cwd, ".cursor", "mcp.json");
278
- (0, install_1.writeMcpServersToFile)(rootMcp, mcpPath);
279
- }
280
- for (const conflict of conflicts) {
281
- console.warn(`Warning: MCP configuration conflict detected\n Key: "${conflict.key}"\n Packages: ${conflict.packages.join(", ")}\n Using configuration from: ${conflict.chosen}`);
282
- }
283
- // Merge and write hooks for workspace
284
- const { merged: rootHooks, hookFiles: rootHookFiles } = mergeWorkspaceHooks(packages);
285
- const hasHooks = rootHooks.hooks && Object.keys(rootHooks.hooks).length > 0;
286
- if (!dryRun && hasCursorTarget && (hasHooks || rootHookFiles.length > 0)) {
287
- (0, hooks_1.writeHooksToCursor)(rootHooks, rootHookFiles, cwd);
288
- }
289
- if (verbose) {
290
- result.packages.forEach((pkg) => {
291
- if (pkg.success) {
292
- const summaryParts = [`${pkg.installedRuleCount} rules`];
293
- if (pkg.installedCommandCount > 0) {
294
- summaryParts.push(`${pkg.installedCommandCount} command${pkg.installedCommandCount === 1 ? "" : "s"}`);
295
- }
296
- if (pkg.installedHookCount > 0) {
297
- summaryParts.push(`${pkg.installedHookCount} hook${pkg.installedHookCount === 1 ? "" : "s"}`);
298
- }
299
- if (pkg.installedSkillCount > 0) {
300
- summaryParts.push(`${pkg.installedSkillCount} skill${pkg.installedSkillCount === 1 ? "" : "s"}`);
301
- }
302
- console.log(chalk_1.default.green(`✅ ${pkg.path} (${summaryParts.join(", ")})`));
303
- }
304
- else {
305
- console.log(chalk_1.default.red(`❌ ${pkg.path}: ${pkg.error}`));
306
- }
307
- });
308
- }
309
- const failedPackages = result.packages.filter((r) => !r.success);
310
- if (failedPackages.length > 0) {
311
- console.log(chalk_1.default.yellow(`Installation completed with errors`));
312
- if (verbose) {
313
- const commandSummary = result.totalCommandCount > 0
314
- ? `, ${result.totalCommandCount} command${result.totalCommandCount === 1 ? "" : "s"} total`
315
- : "";
316
- const hookSummary = result.totalHookCount > 0
317
- ? `, ${result.totalHookCount} hook${result.totalHookCount === 1 ? "" : "s"} total`
318
- : "";
319
- const skillSummary = result.totalSkillCount > 0
320
- ? `, ${result.totalSkillCount} skill${result.totalSkillCount === 1 ? "" : "s"} total`
321
- : "";
322
- console.log(chalk_1.default.green(`Successfully installed: ${result.packages.length - failedPackages.length}/${result.packages.length} packages (${result.totalRuleCount} rule${result.totalRuleCount === 1 ? "" : "s"} total${commandSummary}${hookSummary}${skillSummary})`));
323
- console.log(chalk_1.default.red(`Failed packages: ${failedPackages.map((p) => p.path).join(", ")}`));
324
- }
325
- const errorDetails = failedPackages
326
- .map((p) => `${p.path}: ${p.error}`)
327
- .join("; ");
328
- return {
329
- success: false,
330
- error: new Error(`Package installation failed for ${failedPackages.length} package(s): ${errorDetails}`),
331
- installedRuleCount: result.totalRuleCount,
332
- installedCommandCount: result.totalCommandCount,
333
- installedAssetCount: result.totalAssetCount,
334
- installedHookCount: result.totalHookCount,
335
- installedSkillCount: result.totalSkillCount,
336
- packagesCount: result.packages.length,
337
- };
338
- }
339
- return {
340
- success: true,
341
- installedRuleCount: result.totalRuleCount,
342
- installedCommandCount: result.totalCommandCount,
343
- installedAssetCount: result.totalAssetCount,
344
- installedHookCount: result.totalHookCount,
345
- installedSkillCount: result.totalSkillCount,
346
- packagesCount: result.packages.length,
347
- };
348
- });
349
- }
@@ -1,92 +0,0 @@
1
- import { ResolvedConfig, CommandFile, AssetFile, SkillFile, MCPServers, SupportedTarget } from "../utils/config";
2
- export interface InstallOptions {
3
- /**
4
- * Base directory to use instead of process.cwd()
5
- */
6
- cwd?: string;
7
- /**
8
- * Custom config object to use instead of loading from file
9
- */
10
- config?: ResolvedConfig;
11
- /**
12
- * allow installation on CI environments
13
- */
14
- installOnCI?: boolean;
15
- /**
16
- * Show verbose output during installation
17
- */
18
- verbose?: boolean;
19
- /**
20
- * Perform a dry run without writing any files
21
- */
22
- dryRun?: boolean;
23
- }
24
- /**
25
- * Result of the install operation
26
- */
27
- export interface InstallResult {
28
- /**
29
- * Whether the operation was successful
30
- */
31
- success: boolean;
32
- /**
33
- * Error object if the operation failed
34
- */
35
- error?: Error;
36
- /**
37
- * Number of rules installed
38
- */
39
- installedRuleCount: number;
40
- /**
41
- * Number of commands installed
42
- */
43
- installedCommandCount: number;
44
- /**
45
- * Number of assets installed
46
- */
47
- installedAssetCount: number;
48
- /**
49
- * Number of hooks installed
50
- */
51
- installedHookCount: number;
52
- /**
53
- * Number of skills installed
54
- */
55
- installedSkillCount: number;
56
- /**
57
- * Number of packages installed
58
- */
59
- packagesCount: number;
60
- }
61
- export declare function writeAssetsToTargets(assets: AssetFile[], targets: SupportedTarget[]): void;
62
- export declare function writeCommandsToTargets(commands: CommandFile[], targets: SupportedTarget[]): void;
63
- /**
64
- * Write skills to all supported target directories
65
- */
66
- export declare function writeSkillsToTargets(skills: SkillFile[], targets: SupportedTarget[]): void;
67
- /**
68
- * Warn about skill name collisions from different presets
69
- */
70
- export declare function warnPresetSkillCollisions(skills: SkillFile[]): void;
71
- /**
72
- * Dedupe skills by name (last one wins)
73
- */
74
- export declare function dedupeSkillsForInstall(skills: SkillFile[]): SkillFile[];
75
- export declare function warnPresetCommandCollisions(commands: CommandFile[]): void;
76
- export declare function dedupeCommandsForInstall(commands: CommandFile[]): CommandFile[];
77
- /**
78
- * Write MCP servers configuration to a specific file
79
- */
80
- export declare function writeMcpServersToFile(mcpServers: MCPServers, mcpPath: string): void;
81
- /**
82
- * Install rules for a single package (used within workspaces and standalone installs)
83
- */
84
- export declare function installPackage(options?: InstallOptions): Promise<InstallResult>;
85
- /**
86
- * Core implementation of the rule installation logic
87
- */
88
- export declare function install(options?: InstallOptions): Promise<InstallResult>;
89
- /**
90
- * CLI command wrapper for install
91
- */
92
- export declare function installCommand(installOnCI?: boolean, verbose?: boolean, dryRun?: boolean): Promise<void>;