aicm 0.13.1 → 0.14.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.
@@ -3,203 +3,221 @@ 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.normalizeRules = normalizeRules;
7
- exports.getFullPresetPath = getFullPresetPath;
6
+ exports.SUPPORTED_TARGETS = void 0;
7
+ exports.applyDefaults = applyDefaults;
8
+ exports.validateConfig = validateConfig;
9
+ exports.loadRulesFromDirectory = loadRulesFromDirectory;
10
+ exports.resolvePresetPath = resolvePresetPath;
8
11
  exports.loadPreset = loadPreset;
9
- exports.loadAicmConfigCosmiconfig = loadAicmConfigCosmiconfig;
10
- exports.getConfig = getConfig;
11
- exports.getRuleSource = getRuleSource;
12
- exports.getOriginalPresetPath = getOriginalPresetPath;
12
+ exports.loadAllRules = loadAllRules;
13
+ exports.applyOverrides = applyOverrides;
14
+ exports.loadConfigFile = loadConfigFile;
15
+ exports.loadConfig = loadConfig;
13
16
  exports.saveConfig = saveConfig;
14
17
  const fs_extra_1 = __importDefault(require("fs-extra"));
15
18
  const node_path_1 = __importDefault(require("node:path"));
16
19
  const cosmiconfig_1 = require("cosmiconfig");
17
- const glob_handler_1 = require("./glob-handler");
18
- const CONFIG_FILE = "aicm.json";
19
- function normalizeRules(rules) {
20
- if (!rules)
21
- return {};
22
- if (typeof rules === "string") {
23
- return { "/": rules };
20
+ const fast_glob_1 = __importDefault(require("fast-glob"));
21
+ exports.SUPPORTED_TARGETS = ["cursor", "windsurf", "codex"];
22
+ function detectWorkspacesFromPackageJson(cwd) {
23
+ try {
24
+ const packageJsonPath = node_path_1.default.join(cwd, "package.json");
25
+ if (!fs_extra_1.default.existsSync(packageJsonPath)) {
26
+ return false;
27
+ }
28
+ const packageJson = JSON.parse(fs_extra_1.default.readFileSync(packageJsonPath, "utf8"));
29
+ return Boolean(packageJson.workspaces);
30
+ }
31
+ catch (_a) {
32
+ return false;
24
33
  }
25
- return rules;
26
34
  }
27
- function getFullPresetPath(presetPath, cwd) {
35
+ function applyDefaults(config, cwd) {
28
36
  const workingDir = cwd || process.cwd();
29
- // If it's a local file with .json extension, check relative to the working directory
30
- if (presetPath.endsWith(".json")) {
31
- const absolutePath = node_path_1.default.isAbsolute(presetPath)
32
- ? presetPath
33
- : node_path_1.default.resolve(workingDir, presetPath);
34
- if (fs_extra_1.default.pathExistsSync(absolutePath)) {
35
- return { fullPath: absolutePath, originalPath: presetPath };
37
+ // Auto-detect workspaces if not explicitly set
38
+ const workspaces = config.workspaces !== undefined
39
+ ? config.workspaces
40
+ : detectWorkspacesFromPackageJson(workingDir);
41
+ return {
42
+ rulesDir: config.rulesDir,
43
+ targets: config.targets || ["cursor"],
44
+ presets: config.presets || [],
45
+ overrides: config.overrides || {},
46
+ mcpServers: config.mcpServers || {},
47
+ workspaces,
48
+ };
49
+ }
50
+ function validateConfig(config, configFilePath, cwd) {
51
+ if (typeof config !== "object" || config === null) {
52
+ throw new Error(`Config is not an object at ${configFilePath}`);
53
+ }
54
+ // Validate that either rulesDir or presets is provided
55
+ const hasRulesDir = "rulesDir" in config && typeof config.rulesDir === "string";
56
+ const hasPresets = "presets" in config &&
57
+ Array.isArray(config.presets) &&
58
+ config.presets.length > 0;
59
+ if (!hasRulesDir && !hasPresets) {
60
+ throw new Error(`Either rulesDir or presets must be specified in config at ${configFilePath}`);
61
+ }
62
+ // Validate rulesDir if provided
63
+ if (hasRulesDir) {
64
+ const rulesPath = node_path_1.default.resolve(cwd, config.rulesDir);
65
+ if (!fs_extra_1.default.existsSync(rulesPath)) {
66
+ throw new Error(`Rules directory does not exist: ${rulesPath}`);
67
+ }
68
+ if (!fs_extra_1.default.statSync(rulesPath).isDirectory()) {
69
+ throw new Error(`Rules path is not a directory: ${rulesPath}`);
36
70
  }
37
71
  }
38
- try {
39
- let absolutePresetPath;
40
- // Handle npm package with explicit JSON path
41
- if (presetPath.endsWith(".json")) {
42
- absolutePresetPath = require.resolve(presetPath, {
43
- paths: [__dirname, workingDir],
44
- });
72
+ if ("targets" in config) {
73
+ if (!Array.isArray(config.targets)) {
74
+ throw new Error(`targets must be an array in config at ${configFilePath}`);
45
75
  }
46
- // Handle npm package without explicit JSON path (add aicm.json)
47
- else {
48
- // For npm packages, ensure we properly handle scoped packages (@org/pkg)
49
- const presetPathWithConfig = node_path_1.default.join(presetPath, "aicm.json");
50
- try {
51
- absolutePresetPath = require.resolve(presetPathWithConfig, {
52
- paths: [__dirname, workingDir],
53
- });
54
- }
55
- catch (_a) {
56
- // If direct resolution fails, try as a package name
57
- absolutePresetPath = require.resolve(presetPath, {
58
- paths: [__dirname, workingDir],
59
- });
60
- // If we found the package but not the config file, look for aicm.json
61
- if (fs_extra_1.default.existsSync(absolutePresetPath)) {
62
- const packageDir = node_path_1.default.dirname(absolutePresetPath);
63
- const configPath = node_path_1.default.join(packageDir, "aicm.json");
64
- if (fs_extra_1.default.existsSync(configPath)) {
65
- absolutePresetPath = configPath;
66
- }
67
- }
76
+ if (config.targets.length === 0) {
77
+ throw new Error(`targets must not be empty in config at ${configFilePath}`);
78
+ }
79
+ for (const target of config.targets) {
80
+ if (!exports.SUPPORTED_TARGETS.includes(target)) {
81
+ throw new Error(`Unsupported target: ${target}. Supported targets: ${exports.SUPPORTED_TARGETS.join(", ")}`);
68
82
  }
69
83
  }
70
- return fs_extra_1.default.existsSync(absolutePresetPath)
71
- ? { fullPath: absolutePresetPath, originalPath: presetPath }
72
- : null;
73
84
  }
74
- catch (_b) {
85
+ // Validate override rule names will be checked after rule resolution
86
+ }
87
+ async function loadRulesFromDirectory(rulesDir, source, presetName) {
88
+ const rules = [];
89
+ if (!fs_extra_1.default.existsSync(rulesDir)) {
90
+ return rules;
91
+ }
92
+ const pattern = node_path_1.default.join(rulesDir, "**/*.mdc").replace(/\\/g, "/");
93
+ const filePaths = await (0, fast_glob_1.default)(pattern, {
94
+ onlyFiles: true,
95
+ absolute: true,
96
+ });
97
+ for (const filePath of filePaths) {
98
+ const content = await fs_extra_1.default.readFile(filePath, "utf8");
99
+ // Preserve directory structure by using relative path from rulesDir
100
+ const relativePath = node_path_1.default.relative(rulesDir, filePath);
101
+ const ruleName = relativePath.replace(/\.mdc$/, "").replace(/\\/g, "/");
102
+ rules.push({
103
+ name: ruleName,
104
+ content,
105
+ sourcePath: filePath,
106
+ source,
107
+ presetName,
108
+ });
109
+ }
110
+ return rules;
111
+ }
112
+ function resolvePresetPath(presetPath, cwd) {
113
+ // Support specifying aicm.json directory and load the config from it
114
+ if (!presetPath.endsWith(".json")) {
115
+ presetPath = node_path_1.default.join(presetPath, "aicm.json");
116
+ }
117
+ // Support local or absolute paths
118
+ const absolutePath = node_path_1.default.isAbsolute(presetPath)
119
+ ? presetPath
120
+ : node_path_1.default.resolve(cwd, presetPath);
121
+ if (fs_extra_1.default.existsSync(absolutePath)) {
122
+ return absolutePath;
123
+ }
124
+ try {
125
+ // Support npm packages
126
+ const resolvedPath = require.resolve(presetPath, {
127
+ paths: [cwd, __dirname],
128
+ });
129
+ return fs_extra_1.default.existsSync(resolvedPath) ? resolvedPath : null;
130
+ }
131
+ catch (_a) {
75
132
  return null;
76
133
  }
77
134
  }
78
- /**
79
- * Load a preset file and return its contents
80
- */
81
- function loadPreset(presetPath, cwd) {
82
- const pathInfo = getFullPresetPath(presetPath, cwd);
83
- if (!pathInfo) {
84
- throw new Error(`Error loading preset: "${presetPath}". Make sure the package is installed in your project.`);
135
+ async function loadPreset(presetPath, cwd) {
136
+ const resolvedPresetPath = resolvePresetPath(presetPath, cwd);
137
+ if (!resolvedPresetPath) {
138
+ throw new Error(`Preset not found: "${presetPath}". Make sure the package is installed or the path is correct.`);
85
139
  }
86
- const presetContent = fs_extra_1.default.readFileSync(pathInfo.fullPath, "utf8");
87
- let preset;
140
+ let presetConfig;
88
141
  try {
89
- preset = JSON.parse(presetContent);
142
+ const content = await fs_extra_1.default.readFile(resolvedPresetPath, "utf8");
143
+ presetConfig = JSON.parse(content);
90
144
  }
91
145
  catch (error) {
92
- const parseError = error;
93
- throw new Error(`Error loading preset: Invalid JSON in ${presetPath}: ${parseError.message}`);
146
+ throw new Error(`Failed to load preset "${presetPath}": ${error instanceof Error ? error.message : "Unknown error"}`);
94
147
  }
95
- if (!preset.rules) {
96
- throw new Error(`Error loading preset: Invalid format in ${presetPath} - missing or invalid 'rules' object`);
148
+ // Validate that preset has rulesDir
149
+ if (!presetConfig.rulesDir) {
150
+ throw new Error(`Preset "${presetPath}" must have a rulesDir specified`);
97
151
  }
98
- const normalizedRules = normalizeRules(preset.rules);
152
+ // Resolve preset's rules directory relative to the preset file
153
+ const presetDir = node_path_1.default.dirname(resolvedPresetPath);
154
+ const presetRulesDir = node_path_1.default.resolve(presetDir, presetConfig.rulesDir);
99
155
  return {
100
- rules: normalizedRules,
101
- mcpServers: preset.mcpServers,
102
- presets: preset.presets,
156
+ config: presetConfig,
157
+ rulesDir: presetRulesDir,
103
158
  };
104
159
  }
105
- // Global metadata storage
106
- let currentMetadata = null;
107
- // Track processed presets to avoid circular references
108
- const processedPresets = new Set();
109
- /**
110
- * Process presets and return a new config with merged rules and metadata
111
- */
112
- async function processPresets(config, cwd) {
113
- // Create a deep copy of the config to avoid mutations
114
- const newConfig = JSON.parse(JSON.stringify(config));
115
- const metadata = {
116
- ruleSources: {},
117
- originalPresetPaths: {},
118
- };
119
- // Clear processed presets tracking set when starting from the top level
120
- processedPresets.clear();
121
- return await processPresetsInternal(newConfig, metadata, cwd);
122
- }
123
- /**
124
- * Internal function to process presets recursively
125
- */
126
- async function processPresetsInternal(config, metadata, cwd) {
127
- if (!config.presets || !Array.isArray(config.presets)) {
128
- return { config, metadata };
160
+ async function loadAllRules(config, cwd) {
161
+ const allRules = [];
162
+ let mergedMcpServers = { ...config.mcpServers };
163
+ // Load local rules only if rulesDir is provided
164
+ if (config.rulesDir) {
165
+ const localRulesPath = node_path_1.default.resolve(cwd, config.rulesDir);
166
+ const localRules = await loadRulesFromDirectory(localRulesPath, "local");
167
+ allRules.push(...localRules);
129
168
  }
130
- for (const presetPath of config.presets) {
131
- const pathInfo = getFullPresetPath(presetPath, cwd);
132
- if (!pathInfo) {
133
- throw new Error(`Error loading preset: "${presetPath}". Make sure the package is installed in your project.`);
134
- }
135
- // Skip if we've already processed this preset (prevents circular references)
136
- if (processedPresets.has(pathInfo.fullPath)) {
137
- // Skip duplicates to prevent circular references
138
- continue;
139
- }
140
- // Mark this preset as processed
141
- processedPresets.add(pathInfo.fullPath);
142
- const preset = loadPreset(presetPath, cwd);
143
- if (!preset)
144
- continue;
145
- // Expand glob patterns within the preset using its base directory
146
- const presetDir = node_path_1.default.dirname(pathInfo.fullPath);
147
- const expansion = await (0, glob_handler_1.expandRulesGlobPatterns)(preset.rules, presetDir);
148
- preset.rules = expansion.expandedRules;
149
- // Process nested presets first (depth-first)
150
- if (preset.presets && preset.presets.length > 0) {
151
- // Create a temporary config with just the presets from this preset
152
- const presetConfig = {
153
- rules: {},
154
- presets: preset.presets,
155
- ides: [],
156
- };
157
- // Recursively process the nested presets
158
- const { config: nestedConfig } = await processPresetsInternal(presetConfig, metadata, cwd);
159
- Object.assign(preset.rules, nestedConfig.rules);
160
- }
161
- const { updatedConfig, updatedMetadata } = mergePresetRules(config, preset.rules, pathInfo, metadata);
162
- Object.assign(config.rules, updatedConfig.rules);
163
- Object.assign(metadata.ruleSources, updatedMetadata.ruleSources);
164
- Object.assign(metadata.originalPresetPaths, updatedMetadata.originalPresetPaths);
165
- if (preset.mcpServers) {
166
- config.mcpServers = mergePresetMcpServers(config.mcpServers || {}, preset.mcpServers);
169
+ if (config.presets) {
170
+ for (const presetPath of config.presets) {
171
+ const preset = await loadPreset(presetPath, cwd);
172
+ const presetRules = await loadRulesFromDirectory(preset.rulesDir, "preset", presetPath);
173
+ allRules.push(...presetRules);
174
+ // Merge MCP servers from preset
175
+ if (preset.config.mcpServers) {
176
+ mergedMcpServers = mergePresetMcpServers(mergedMcpServers, preset.config.mcpServers);
177
+ }
167
178
  }
168
179
  }
169
- return { config, metadata };
170
- }
171
- /**
172
- * Merge preset rules into the config without mutation
173
- */
174
- function mergePresetRules(config, presetRules, pathInfo, metadata) {
175
- const updatedRules = { ...config.rules };
176
- const updatedMetadata = {
177
- ruleSources: { ...metadata.ruleSources },
178
- originalPresetPaths: { ...metadata.originalPresetPaths },
180
+ return {
181
+ rules: allRules,
182
+ mcpServers: mergedMcpServers,
179
183
  };
180
- for (const [ruleName, rulePath] of Object.entries(presetRules)) {
181
- // Cancel if set to false in config
182
- if (Object.prototype.hasOwnProperty.call(config.rules, ruleName) &&
183
- config.rules[ruleName] === false) {
184
- delete updatedRules[ruleName];
185
- delete updatedMetadata.ruleSources[ruleName];
186
- delete updatedMetadata.originalPresetPaths[ruleName];
187
- continue;
184
+ }
185
+ function applyOverrides(rules, overrides, cwd) {
186
+ // Validate that all override rule names exist in the resolved rules
187
+ for (const ruleName of Object.keys(overrides)) {
188
+ // TODO: support better error messages with edit distance, helping the user in case of a typo
189
+ // TODO: or shows a list of potential rules to override
190
+ if (!rules.some((rule) => rule.name === ruleName)) {
191
+ throw new Error(`Override rule "${ruleName}" does not exist in resolved rules`);
188
192
  }
189
- // Only add if not already defined in config (override handled by config)
190
- if (!Object.prototype.hasOwnProperty.call(config.rules, ruleName)) {
191
- updatedRules[ruleName] = rulePath;
192
- updatedMetadata.ruleSources[ruleName] = pathInfo.fullPath;
193
- updatedMetadata.originalPresetPaths[ruleName] = pathInfo.originalPath;
193
+ }
194
+ const ruleMap = new Map();
195
+ for (const rule of rules) {
196
+ ruleMap.set(rule.name, rule);
197
+ }
198
+ for (const [ruleName, override] of Object.entries(overrides)) {
199
+ if (override === false) {
200
+ ruleMap.delete(ruleName);
201
+ }
202
+ else if (typeof override === "string") {
203
+ const overridePath = node_path_1.default.resolve(cwd, override);
204
+ if (!fs_extra_1.default.existsSync(overridePath)) {
205
+ throw new Error(`Override rule file not found: ${override} in ${cwd}`);
206
+ }
207
+ const content = fs_extra_1.default.readFileSync(overridePath, "utf8");
208
+ ruleMap.set(ruleName, {
209
+ name: ruleName,
210
+ content,
211
+ sourcePath: overridePath,
212
+ source: "local",
213
+ });
194
214
  }
195
215
  }
196
- return {
197
- updatedConfig: { ...config, rules: updatedRules },
198
- updatedMetadata,
199
- };
216
+ return Array.from(ruleMap.values());
200
217
  }
201
218
  /**
202
- * Merge preset mcpServers without mutation
219
+ * Merge preset MCP servers with local config MCP servers
220
+ * Local config takes precedence over preset config
203
221
  */
204
222
  function mergePresetMcpServers(configMcpServers, presetMcpServers) {
205
223
  const newMcpServers = { ...configMcpServers };
@@ -217,71 +235,45 @@ function mergePresetMcpServers(configMcpServers, presetMcpServers) {
217
235
  }
218
236
  return newMcpServers;
219
237
  }
220
- /**
221
- * Load the aicm config using cosmiconfig, supporting both aicm.json and package.json.
222
- * Returns the config object or null if not found.
223
- */
224
- async function loadAicmConfigCosmiconfig(searchFrom) {
238
+ async function loadConfigFile(searchFrom) {
225
239
  const explorer = (0, cosmiconfig_1.cosmiconfig)("aicm", {
226
- searchPlaces: ["package.json", "aicm.json"],
240
+ searchPlaces: ["aicm.json", "package.json"],
227
241
  });
228
242
  try {
229
243
  const result = await explorer.search(searchFrom);
230
- if (!result || !result.config)
231
- return null;
232
- const rawConfig = result.config;
233
- const normalizedRules = normalizeRules(rawConfig.rules);
234
- const config = {
235
- ...rawConfig,
236
- ides: rawConfig.ides || ["cursor"],
237
- rules: normalizedRules,
238
- };
239
- return config;
244
+ return result;
240
245
  }
241
246
  catch (error) {
242
- throw new Error(`Error loading aicm config: ${error instanceof Error ? error.message : String(error)}`);
247
+ throw new Error(`Failed to load configuration: ${error instanceof Error ? error.message : "Unknown error"}`);
243
248
  }
244
249
  }
245
- /**
246
- * Get the configuration from aicm.json or package.json (using cosmiconfigSync) and merge with any presets
247
- */
248
- async function getConfig(cwd) {
250
+ async function loadConfig(cwd) {
249
251
  const workingDir = cwd || process.cwd();
250
- const config = await loadAicmConfigCosmiconfig(workingDir);
251
- if (!config) {
252
- throw new Error(`No config found in ${workingDir}, create one using "aicm init"`);
252
+ const configResult = await loadConfigFile(workingDir);
253
+ if (!(configResult === null || configResult === void 0 ? void 0 : configResult.config)) {
254
+ return null;
253
255
  }
254
- const { config: processedConfig, metadata } = await processPresets(config, workingDir);
255
- // Store metadata for later access
256
- currentMetadata = metadata;
257
- return processedConfig;
258
- }
259
- /**
260
- * Get the source preset path for a rule if it came from a preset
261
- */
262
- function getRuleSource(config, ruleName) {
263
- var _a;
264
- return (_a = currentMetadata === null || currentMetadata === void 0 ? void 0 : currentMetadata.ruleSources) === null || _a === void 0 ? void 0 : _a[ruleName];
265
- }
266
- /**
267
- * Get the original preset path for a rule if it came from a preset
268
- */
269
- function getOriginalPresetPath(config, ruleName) {
270
- var _a;
271
- return (_a = currentMetadata === null || currentMetadata === void 0 ? void 0 : currentMetadata.originalPresetPaths) === null || _a === void 0 ? void 0 : _a[ruleName];
256
+ validateConfig(configResult.config, configResult.filepath, workingDir);
257
+ const config = applyDefaults(configResult.config, workingDir);
258
+ const { rules, mcpServers } = await loadAllRules(config, workingDir);
259
+ let rulesWithOverrides = rules;
260
+ if (config.overrides) {
261
+ rulesWithOverrides = applyOverrides(rules, config.overrides, workingDir);
262
+ }
263
+ return {
264
+ config,
265
+ rules: rulesWithOverrides,
266
+ mcpServers,
267
+ };
272
268
  }
273
- /**
274
- * Save the configuration to the aicm.json file
275
- */
276
269
  function saveConfig(config, cwd) {
277
270
  const workingDir = cwd || process.cwd();
278
- const configPath = node_path_1.default.join(workingDir, CONFIG_FILE);
271
+ const configPath = node_path_1.default.join(workingDir, "aicm.json");
279
272
  try {
280
- fs_extra_1.default.writeJsonSync(configPath, config, { spaces: 2 });
273
+ fs_extra_1.default.writeFileSync(configPath, JSON.stringify(config, null, 2));
281
274
  return true;
282
275
  }
283
- catch (error) {
284
- console.error("Error writing configuration file:", error);
276
+ catch (_a) {
285
277
  return false;
286
278
  }
287
279
  }
@@ -0,0 +1,64 @@
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;