@aiready/cli 0.1.0 → 0.1.3

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,6 +1,6 @@
1
1
 
2
2
  
3
- > @aiready/cli@0.1.0 build /Users/pengcao/projects/aiready/packages/cli
3
+ > @aiready/cli@0.1.3 build /Users/pengcao/projects/aiready/packages/cli
4
4
  > tsup src/index.ts src/cli.ts --format cjs,esm --dts
5
5
 
6
6
  CLI Building entry: src/cli.ts, src/index.ts
@@ -9,15 +9,15 @@
9
9
  CLI Target: es2020
10
10
  CJS Build start
11
11
  ESM Build start
12
- CJS dist/cli.js 8.70 KB
13
12
  CJS dist/index.js 2.51 KB
14
- CJS ⚡️ Build success in 54ms
15
- ESM dist/chunk-S6JWNLN7.mjs 1.40 KB
13
+ CJS dist/cli.js 10.56 KB
14
+ CJS ⚡️ Build success in 60ms
15
+ ESM dist/cli.mjs 7.74 KB
16
16
  ESM dist/index.mjs 138.00 B
17
- ESM dist/cli.mjs 5.95 KB
18
- ESM ⚡️ Build success in 55ms
17
+ ESM dist/chunk-S6JWNLN7.mjs 1.40 KB
18
+ ESM ⚡️ Build success in 60ms
19
19
  DTS Build start
20
- DTS ⚡️ Build success in 560ms
20
+ DTS ⚡️ Build success in 518ms
21
21
  DTS dist/cli.d.ts 20.00 B
22
22
  DTS dist/index.d.ts 731.00 B
23
23
  DTS dist/cli.d.mts 20.00 B
@@ -1,9 +1,27 @@
1
1
 
2
2
  
3
- > @aiready/cli@0.1.0 test /Users/pengcao/projects/aiready/packages/cli
3
+ > @aiready/cli@0.1.1 test /Users/pengcao/projects/aiready/packages/cli
4
4
  > vitest run
5
5
 
6
6
  [?25l
7
7
   RUN  v4.0.16 /Users/pengcao/projects/aiready/packages/cli
8
8
 
9
-  ELIFECYCLE  Test failed. See above for more details.
9
+ [?2026h
10
+  ❯ src/__tests__/cli.test.ts [queued]
11
+
12
+  Test Files 0 passed (1)
13
+  Tests 0 passed (0)
14
+  Start at 03:19:15
15
+  Duration 0ms
16
+ [?2026l ✓ src/__tests__/cli.test.ts (3 tests) 2ms
17
+ ✓ CLI Unified Analysis (3)
18
+ ✓ should run unified analysis with both tools 1ms
19
+ ✓ should run analysis with only patterns tool 0ms
20
+ ✓ should run analysis with only context tool 0ms
21
+
22
+  Test Files  1 passed (1)
23
+  Tests  3 passed (3)
24
+  Start at  03:19:15
25
+  Duration  104ms (transform 27ms, setup 0ms, import 36ms, tests 2ms, environment 0ms)
26
+
27
+ [?25h
package/README.md CHANGED
@@ -96,6 +96,59 @@ aiready scan . --output json --output-file results.json
96
96
  aiready patterns . --similarity 0.6 --min-lines 10
97
97
  ```
98
98
 
99
+ ### Default Exclusions
100
+
101
+ By default, these common build and output directories are excluded from analysis:
102
+
103
+ - Dependencies: `**/node_modules/**`
104
+ - Build outputs: `**/dist/**`, `**/build/**`, `**/out/**`, `**/output/**`, etc.
105
+ - Framework caches: `**/.next/**`, `**/.nuxt/**`, `**/.cache/**`, `**/.turbo/**`
106
+ - Test/coverage: `**/coverage/**`, `**/.nyc_output/**`, `**/.jest/**`
107
+ - Version control/IDE: `**/.git/**`, `**/.vscode/**`, `**/.idea/**`
108
+ - Build artifacts: `**/*.min.js`, `**/*.bundle.js`, `**/*.tsbuildinfo`
109
+
110
+ Use `--include` and `--exclude` options to customize file selection.
111
+
112
+ ### Configuration
113
+
114
+ AIReady supports configuration files to persist your settings. Create one of these files in your project root:
115
+
116
+ - `aiready.json`
117
+ - `aiready.config.json`
118
+ - `.aiready.json`
119
+ - `.aireadyrc.json`
120
+ - `aiready.config.js`
121
+ - `.aireadyrc.js`
122
+
123
+ #### Example Configuration
124
+
125
+ ```json
126
+ {
127
+ "scan": {
128
+ "include": ["**/*.{ts,tsx,js,jsx}"],
129
+ "exclude": ["**/test/**", "**/*.test.*", "**/*.spec.*"]
130
+ },
131
+ "tools": {
132
+ "pattern-detect": {
133
+ "minSimilarity": 0.5,
134
+ "minLines": 8,
135
+ "approx": false
136
+ },
137
+ "context-analyzer": {
138
+ "maxDepth": 4,
139
+ "maxContextBudget": 8000,
140
+ "includeNodeModules": false
141
+ }
142
+ },
143
+ "output": {
144
+ "format": "console",
145
+ "file": "aiready-report.json"
146
+ }
147
+ }
148
+ ```
149
+
150
+ Configuration values are merged with defaults, and CLI options take precedence over config file settings.
151
+
99
152
  ### CI/CD Integration
100
153
 
101
154
  ```bash
package/dist/cli.js CHANGED
@@ -78,21 +78,35 @@ function generateUnifiedSummary(result) {
78
78
  // src/cli.ts
79
79
  var import_chalk = __toESM(require("chalk"));
80
80
  var import_fs = require("fs");
81
+ var import_core = require("@aiready/core");
81
82
  var program = new import_commander.Command();
82
83
  program.name("aiready").description("AIReady - Unified AI-readiness analysis tools").version("0.1.0");
83
84
  program.command("scan").description("Run unified analysis on a codebase").argument("<directory>", "Directory to analyze").option("-t, --tools <tools>", "Tools to run (comma-separated: patterns,context)", "patterns,context").option("--include <patterns>", "File patterns to include (comma-separated)").option("--exclude <patterns>", "File patterns to exclude (comma-separated)").option("-o, --output <format>", "Output format: console, json", "console").option("--output-file <path>", "Output file path (for json)").action(async (directory, options) => {
84
85
  console.log(import_chalk.default.blue("\u{1F680} Starting AIReady unified analysis...\n"));
85
86
  const startTime = Date.now();
86
87
  try {
87
- const tools = options.tools.split(",").map((t) => t.trim());
88
- const results = await analyzeUnified({
88
+ const config = (0, import_core.loadConfig)(directory);
89
+ const defaults = {
90
+ tools: ["patterns", "context"],
91
+ include: void 0,
92
+ exclude: void 0,
93
+ output: {
94
+ format: "console",
95
+ file: void 0
96
+ }
97
+ };
98
+ const mergedConfig = (0, import_core.mergeConfigWithDefaults)(config, defaults);
99
+ const finalOptions = {
89
100
  rootDir: directory,
90
- tools,
91
- include: options.include?.split(","),
92
- exclude: options.exclude?.split(",")
93
- });
101
+ tools: options.tools ? options.tools.split(",").map((t) => t.trim()) : mergedConfig.tools,
102
+ include: options.include?.split(",") || mergedConfig.include,
103
+ exclude: options.exclude?.split(",") || mergedConfig.exclude
104
+ };
105
+ const results = await analyzeUnified(finalOptions);
94
106
  const elapsedTime = ((Date.now() - startTime) / 1e3).toFixed(2);
95
- if (options.output === "json") {
107
+ const outputFormat = options.output || mergedConfig.output?.format || "console";
108
+ const outputFile = options.outputFile || mergedConfig.output?.file;
109
+ if (outputFormat === "json") {
96
110
  const outputData = {
97
111
  ...results,
98
112
  summary: {
@@ -100,9 +114,9 @@ program.command("scan").description("Run unified analysis on a codebase").argume
100
114
  executionTime: parseFloat(elapsedTime)
101
115
  }
102
116
  };
103
- if (options.outputFile) {
104
- (0, import_fs.writeFileSync)(options.outputFile, JSON.stringify(outputData, null, 2));
105
- console.log(import_chalk.default.green(`\u2705 Results saved to ${options.outputFile}`));
117
+ if (outputFile) {
118
+ (0, import_fs.writeFileSync)(outputFile, JSON.stringify(outputData, null, 2));
119
+ console.log(import_chalk.default.green(`\u2705 Results saved to ${outputFile}`));
106
120
  } else {
107
121
  console.log(JSON.stringify(outputData, null, 2));
108
122
  }
@@ -118,24 +132,39 @@ program.command("patterns").description("Run pattern detection analysis").argume
118
132
  console.log(import_chalk.default.blue("\u{1F50D} Analyzing patterns...\n"));
119
133
  const startTime = Date.now();
120
134
  try {
121
- const { analyzePatterns: analyzePatterns2, generateSummary } = await import("@aiready/pattern-detect");
122
- const results = await analyzePatterns2({
135
+ const config = (0, import_core.loadConfig)(directory);
136
+ const defaults = {
137
+ minSimilarity: 0.4,
138
+ minLines: 5,
139
+ include: void 0,
140
+ exclude: void 0,
141
+ output: {
142
+ format: "console",
143
+ file: void 0
144
+ }
145
+ };
146
+ const mergedConfig = (0, import_core.mergeConfigWithDefaults)(config, defaults);
147
+ const finalOptions = {
123
148
  rootDir: directory,
124
- minSimilarity: parseFloat(options.similarity),
125
- minLines: parseInt(options.minLines),
126
- include: options.include?.split(","),
127
- exclude: options.exclude?.split(",")
128
- });
149
+ minSimilarity: options.similarity ? parseFloat(options.similarity) : mergedConfig.minSimilarity,
150
+ minLines: options.minLines ? parseInt(options.minLines) : mergedConfig.minLines,
151
+ include: options.include?.split(",") || mergedConfig.include,
152
+ exclude: options.exclude?.split(",") || mergedConfig.exclude
153
+ };
154
+ const { analyzePatterns: analyzePatterns2, generateSummary } = await import("@aiready/pattern-detect");
155
+ const results = await analyzePatterns2(finalOptions);
129
156
  const elapsedTime = ((Date.now() - startTime) / 1e3).toFixed(2);
130
157
  const summary = generateSummary(results);
131
- if (options.output === "json") {
158
+ const outputFormat = options.output || mergedConfig.output?.format || "console";
159
+ const outputFile = options.outputFile || mergedConfig.output?.file;
160
+ if (outputFormat === "json") {
132
161
  const outputData = {
133
162
  results,
134
163
  summary: { ...summary, executionTime: parseFloat(elapsedTime) }
135
164
  };
136
- if (options.outputFile) {
137
- (0, import_fs.writeFileSync)(options.outputFile, JSON.stringify(outputData, null, 2));
138
- console.log(import_chalk.default.green(`\u2705 Results saved to ${options.outputFile}`));
165
+ if (outputFile) {
166
+ (0, import_fs.writeFileSync)(outputFile, JSON.stringify(outputData, null, 2));
167
+ console.log(import_chalk.default.green(`\u2705 Results saved to ${outputFile}`));
139
168
  } else {
140
169
  console.log(JSON.stringify(outputData, null, 2));
141
170
  }
@@ -153,24 +182,39 @@ program.command("context").description("Run context window cost analysis").argum
153
182
  console.log(import_chalk.default.blue("\u{1F9E0} Analyzing context costs...\n"));
154
183
  const startTime = Date.now();
155
184
  try {
156
- const { analyzeContext: analyzeContext2, generateSummary } = await import("@aiready/context-analyzer");
157
- const results = await analyzeContext2({
185
+ const config = (0, import_core.loadConfig)(directory);
186
+ const defaults = {
187
+ maxDepth: 5,
188
+ maxContextBudget: 1e4,
189
+ include: void 0,
190
+ exclude: void 0,
191
+ output: {
192
+ format: "console",
193
+ file: void 0
194
+ }
195
+ };
196
+ const mergedConfig = (0, import_core.mergeConfigWithDefaults)(config, defaults);
197
+ const finalOptions = {
158
198
  rootDir: directory,
159
- maxDepth: parseInt(options.maxDepth),
160
- maxContextBudget: parseInt(options.maxContext),
161
- include: options.include?.split(","),
162
- exclude: options.exclude?.split(",")
163
- });
199
+ maxDepth: options.maxDepth ? parseInt(options.maxDepth) : mergedConfig.maxDepth,
200
+ maxContextBudget: options.maxContext ? parseInt(options.maxContext) : mergedConfig.maxContextBudget,
201
+ include: options.include?.split(",") || mergedConfig.include,
202
+ exclude: options.exclude?.split(",") || mergedConfig.exclude
203
+ };
204
+ const { analyzeContext: analyzeContext2, generateSummary } = await import("@aiready/context-analyzer");
205
+ const results = await analyzeContext2(finalOptions);
164
206
  const elapsedTime = ((Date.now() - startTime) / 1e3).toFixed(2);
165
207
  const summary = generateSummary(results);
166
- if (options.output === "json") {
208
+ const outputFormat = options.output || mergedConfig.output?.format || "console";
209
+ const outputFile = options.outputFile || mergedConfig.output?.file;
210
+ if (outputFormat === "json") {
167
211
  const outputData = {
168
212
  results,
169
213
  summary: { ...summary, executionTime: parseFloat(elapsedTime) }
170
214
  };
171
- if (options.outputFile) {
172
- (0, import_fs.writeFileSync)(options.outputFile, JSON.stringify(outputData, null, 2));
173
- console.log(import_chalk.default.green(`\u2705 Results saved to ${options.outputFile}`));
215
+ if (outputFile) {
216
+ (0, import_fs.writeFileSync)(outputFile, JSON.stringify(outputData, null, 2));
217
+ console.log(import_chalk.default.green(`\u2705 Results saved to ${outputFile}`));
174
218
  } else {
175
219
  console.log(JSON.stringify(outputData, null, 2));
176
220
  }
package/dist/cli.mjs CHANGED
@@ -8,21 +8,35 @@ import {
8
8
  import { Command } from "commander";
9
9
  import chalk from "chalk";
10
10
  import { writeFileSync } from "fs";
11
+ import { loadConfig, mergeConfigWithDefaults } from "@aiready/core";
11
12
  var program = new Command();
12
13
  program.name("aiready").description("AIReady - Unified AI-readiness analysis tools").version("0.1.0");
13
14
  program.command("scan").description("Run unified analysis on a codebase").argument("<directory>", "Directory to analyze").option("-t, --tools <tools>", "Tools to run (comma-separated: patterns,context)", "patterns,context").option("--include <patterns>", "File patterns to include (comma-separated)").option("--exclude <patterns>", "File patterns to exclude (comma-separated)").option("-o, --output <format>", "Output format: console, json", "console").option("--output-file <path>", "Output file path (for json)").action(async (directory, options) => {
14
15
  console.log(chalk.blue("\u{1F680} Starting AIReady unified analysis...\n"));
15
16
  const startTime = Date.now();
16
17
  try {
17
- const tools = options.tools.split(",").map((t) => t.trim());
18
- const results = await analyzeUnified({
18
+ const config = loadConfig(directory);
19
+ const defaults = {
20
+ tools: ["patterns", "context"],
21
+ include: void 0,
22
+ exclude: void 0,
23
+ output: {
24
+ format: "console",
25
+ file: void 0
26
+ }
27
+ };
28
+ const mergedConfig = mergeConfigWithDefaults(config, defaults);
29
+ const finalOptions = {
19
30
  rootDir: directory,
20
- tools,
21
- include: options.include?.split(","),
22
- exclude: options.exclude?.split(",")
23
- });
31
+ tools: options.tools ? options.tools.split(",").map((t) => t.trim()) : mergedConfig.tools,
32
+ include: options.include?.split(",") || mergedConfig.include,
33
+ exclude: options.exclude?.split(",") || mergedConfig.exclude
34
+ };
35
+ const results = await analyzeUnified(finalOptions);
24
36
  const elapsedTime = ((Date.now() - startTime) / 1e3).toFixed(2);
25
- if (options.output === "json") {
37
+ const outputFormat = options.output || mergedConfig.output?.format || "console";
38
+ const outputFile = options.outputFile || mergedConfig.output?.file;
39
+ if (outputFormat === "json") {
26
40
  const outputData = {
27
41
  ...results,
28
42
  summary: {
@@ -30,9 +44,9 @@ program.command("scan").description("Run unified analysis on a codebase").argume
30
44
  executionTime: parseFloat(elapsedTime)
31
45
  }
32
46
  };
33
- if (options.outputFile) {
34
- writeFileSync(options.outputFile, JSON.stringify(outputData, null, 2));
35
- console.log(chalk.green(`\u2705 Results saved to ${options.outputFile}`));
47
+ if (outputFile) {
48
+ writeFileSync(outputFile, JSON.stringify(outputData, null, 2));
49
+ console.log(chalk.green(`\u2705 Results saved to ${outputFile}`));
36
50
  } else {
37
51
  console.log(JSON.stringify(outputData, null, 2));
38
52
  }
@@ -48,24 +62,39 @@ program.command("patterns").description("Run pattern detection analysis").argume
48
62
  console.log(chalk.blue("\u{1F50D} Analyzing patterns...\n"));
49
63
  const startTime = Date.now();
50
64
  try {
51
- const { analyzePatterns, generateSummary } = await import("@aiready/pattern-detect");
52
- const results = await analyzePatterns({
65
+ const config = loadConfig(directory);
66
+ const defaults = {
67
+ minSimilarity: 0.4,
68
+ minLines: 5,
69
+ include: void 0,
70
+ exclude: void 0,
71
+ output: {
72
+ format: "console",
73
+ file: void 0
74
+ }
75
+ };
76
+ const mergedConfig = mergeConfigWithDefaults(config, defaults);
77
+ const finalOptions = {
53
78
  rootDir: directory,
54
- minSimilarity: parseFloat(options.similarity),
55
- minLines: parseInt(options.minLines),
56
- include: options.include?.split(","),
57
- exclude: options.exclude?.split(",")
58
- });
79
+ minSimilarity: options.similarity ? parseFloat(options.similarity) : mergedConfig.minSimilarity,
80
+ minLines: options.minLines ? parseInt(options.minLines) : mergedConfig.minLines,
81
+ include: options.include?.split(",") || mergedConfig.include,
82
+ exclude: options.exclude?.split(",") || mergedConfig.exclude
83
+ };
84
+ const { analyzePatterns, generateSummary } = await import("@aiready/pattern-detect");
85
+ const results = await analyzePatterns(finalOptions);
59
86
  const elapsedTime = ((Date.now() - startTime) / 1e3).toFixed(2);
60
87
  const summary = generateSummary(results);
61
- if (options.output === "json") {
88
+ const outputFormat = options.output || mergedConfig.output?.format || "console";
89
+ const outputFile = options.outputFile || mergedConfig.output?.file;
90
+ if (outputFormat === "json") {
62
91
  const outputData = {
63
92
  results,
64
93
  summary: { ...summary, executionTime: parseFloat(elapsedTime) }
65
94
  };
66
- if (options.outputFile) {
67
- writeFileSync(options.outputFile, JSON.stringify(outputData, null, 2));
68
- console.log(chalk.green(`\u2705 Results saved to ${options.outputFile}`));
95
+ if (outputFile) {
96
+ writeFileSync(outputFile, JSON.stringify(outputData, null, 2));
97
+ console.log(chalk.green(`\u2705 Results saved to ${outputFile}`));
69
98
  } else {
70
99
  console.log(JSON.stringify(outputData, null, 2));
71
100
  }
@@ -83,24 +112,39 @@ program.command("context").description("Run context window cost analysis").argum
83
112
  console.log(chalk.blue("\u{1F9E0} Analyzing context costs...\n"));
84
113
  const startTime = Date.now();
85
114
  try {
86
- const { analyzeContext, generateSummary } = await import("@aiready/context-analyzer");
87
- const results = await analyzeContext({
115
+ const config = loadConfig(directory);
116
+ const defaults = {
117
+ maxDepth: 5,
118
+ maxContextBudget: 1e4,
119
+ include: void 0,
120
+ exclude: void 0,
121
+ output: {
122
+ format: "console",
123
+ file: void 0
124
+ }
125
+ };
126
+ const mergedConfig = mergeConfigWithDefaults(config, defaults);
127
+ const finalOptions = {
88
128
  rootDir: directory,
89
- maxDepth: parseInt(options.maxDepth),
90
- maxContextBudget: parseInt(options.maxContext),
91
- include: options.include?.split(","),
92
- exclude: options.exclude?.split(",")
93
- });
129
+ maxDepth: options.maxDepth ? parseInt(options.maxDepth) : mergedConfig.maxDepth,
130
+ maxContextBudget: options.maxContext ? parseInt(options.maxContext) : mergedConfig.maxContextBudget,
131
+ include: options.include?.split(",") || mergedConfig.include,
132
+ exclude: options.exclude?.split(",") || mergedConfig.exclude
133
+ };
134
+ const { analyzeContext, generateSummary } = await import("@aiready/context-analyzer");
135
+ const results = await analyzeContext(finalOptions);
94
136
  const elapsedTime = ((Date.now() - startTime) / 1e3).toFixed(2);
95
137
  const summary = generateSummary(results);
96
- if (options.output === "json") {
138
+ const outputFormat = options.output || mergedConfig.output?.format || "console";
139
+ const outputFile = options.outputFile || mergedConfig.output?.file;
140
+ if (outputFormat === "json") {
97
141
  const outputData = {
98
142
  results,
99
143
  summary: { ...summary, executionTime: parseFloat(elapsedTime) }
100
144
  };
101
- if (options.outputFile) {
102
- writeFileSync(options.outputFile, JSON.stringify(outputData, null, 2));
103
- console.log(chalk.green(`\u2705 Results saved to ${options.outputFile}`));
145
+ if (outputFile) {
146
+ writeFileSync(outputFile, JSON.stringify(outputData, null, 2));
147
+ console.log(chalk.green(`\u2705 Results saved to ${outputFile}`));
104
148
  } else {
105
149
  console.log(JSON.stringify(outputData, null, 2));
106
150
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiready/cli",
3
- "version": "0.1.0",
3
+ "version": "0.1.3",
4
4
  "description": "Unified CLI for AIReady analysis tools",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -11,9 +11,9 @@
11
11
  "dependencies": {
12
12
  "commander": "^12.1.0",
13
13
  "chalk": "^5.3.0",
14
- "@aiready/context-analyzer": "0.1.0",
15
- "@aiready/core": "0.2.1",
16
- "@aiready/pattern-detect": "0.5.1"
14
+ "@aiready/core": "0.2.3",
15
+ "@aiready/context-analyzer": "0.1.3",
16
+ "@aiready/pattern-detect": "0.5.3"
17
17
  },
18
18
  "devDependencies": {
19
19
  "tsup": "^8.3.5",
package/src/cli.ts CHANGED
@@ -5,6 +5,7 @@ import { analyzeUnified, generateUnifiedSummary } from './index';
5
5
  import chalk from 'chalk';
6
6
  import { writeFileSync } from 'fs';
7
7
  import { join } from 'path';
8
+ import { loadConfig, mergeConfigWithDefaults } from '@aiready/core';
8
9
 
9
10
  const program = new Command();
10
11
 
@@ -28,18 +29,39 @@ program
28
29
  const startTime = Date.now();
29
30
 
30
31
  try {
31
- const tools = options.tools.split(',').map((t: string) => t.trim()) as ('patterns' | 'context')[];
32
-
33
- const results = await analyzeUnified({
32
+ // Load config file if it exists
33
+ const config = loadConfig(directory);
34
+
35
+ // Define defaults
36
+ const defaults = {
37
+ tools: ['patterns', 'context'],
38
+ include: undefined,
39
+ exclude: undefined,
40
+ output: {
41
+ format: 'console',
42
+ file: undefined,
43
+ },
44
+ };
45
+
46
+ // Merge config with defaults
47
+ const mergedConfig = mergeConfigWithDefaults(config, defaults);
48
+
49
+ // Override with CLI options (CLI takes precedence)
50
+ const finalOptions = {
34
51
  rootDir: directory,
35
- tools,
36
- include: options.include?.split(','),
37
- exclude: options.exclude?.split(','),
38
- });
52
+ tools: options.tools ? options.tools.split(',').map((t: string) => t.trim()) as ('patterns' | 'context')[] : mergedConfig.tools,
53
+ include: options.include?.split(',') || mergedConfig.include,
54
+ exclude: options.exclude?.split(',') || mergedConfig.exclude,
55
+ };
56
+
57
+ const results = await analyzeUnified(finalOptions);
39
58
 
40
59
  const elapsedTime = ((Date.now() - startTime) / 1000).toFixed(2);
41
60
 
42
- if (options.output === 'json') {
61
+ const outputFormat = options.output || mergedConfig.output?.format || 'console';
62
+ const outputFile = options.outputFile || mergedConfig.output?.file;
63
+
64
+ if (outputFormat === 'json') {
43
65
  const outputData = {
44
66
  ...results,
45
67
  summary: {
@@ -48,9 +70,9 @@ program
48
70
  },
49
71
  };
50
72
 
51
- if (options.outputFile) {
52
- writeFileSync(options.outputFile, JSON.stringify(outputData, null, 2));
53
- console.log(chalk.green(`✅ Results saved to ${options.outputFile}`));
73
+ if (outputFile) {
74
+ writeFileSync(outputFile, JSON.stringify(outputData, null, 2));
75
+ console.log(chalk.green(`✅ Results saved to ${outputFile}`));
54
76
  } else {
55
77
  console.log(JSON.stringify(outputData, null, 2));
56
78
  }
@@ -81,28 +103,52 @@ program
81
103
  const startTime = Date.now();
82
104
 
83
105
  try {
106
+ // Load config file if it exists
107
+ const config = loadConfig(directory);
108
+
109
+ // Define defaults
110
+ const defaults = {
111
+ minSimilarity: 0.4,
112
+ minLines: 5,
113
+ include: undefined,
114
+ exclude: undefined,
115
+ output: {
116
+ format: 'console',
117
+ file: undefined,
118
+ },
119
+ };
120
+
121
+ // Merge config with defaults
122
+ const mergedConfig = mergeConfigWithDefaults(config, defaults);
123
+
124
+ // Override with CLI options (CLI takes precedence)
125
+ const finalOptions = {
126
+ rootDir: directory,
127
+ minSimilarity: options.similarity ? parseFloat(options.similarity) : mergedConfig.minSimilarity,
128
+ minLines: options.minLines ? parseInt(options.minLines) : mergedConfig.minLines,
129
+ include: options.include?.split(',') || mergedConfig.include,
130
+ exclude: options.exclude?.split(',') || mergedConfig.exclude,
131
+ };
132
+
84
133
  const { analyzePatterns, generateSummary } = await import('@aiready/pattern-detect');
85
134
 
86
- const results = await analyzePatterns({
87
- rootDir: directory,
88
- minSimilarity: parseFloat(options.similarity),
89
- minLines: parseInt(options.minLines),
90
- include: options.include?.split(','),
91
- exclude: options.exclude?.split(','),
92
- });
135
+ const results = await analyzePatterns(finalOptions);
93
136
 
94
137
  const elapsedTime = ((Date.now() - startTime) / 1000).toFixed(2);
95
138
  const summary = generateSummary(results);
96
139
 
97
- if (options.output === 'json') {
140
+ const outputFormat = options.output || mergedConfig.output?.format || 'console';
141
+ const outputFile = options.outputFile || mergedConfig.output?.file;
142
+
143
+ if (outputFormat === 'json') {
98
144
  const outputData = {
99
145
  results,
100
146
  summary: { ...summary, executionTime: parseFloat(elapsedTime) },
101
147
  };
102
148
 
103
- if (options.outputFile) {
104
- writeFileSync(options.outputFile, JSON.stringify(outputData, null, 2));
105
- console.log(chalk.green(`✅ Results saved to ${options.outputFile}`));
149
+ if (outputFile) {
150
+ writeFileSync(outputFile, JSON.stringify(outputData, null, 2));
151
+ console.log(chalk.green(`✅ Results saved to ${outputFile}`));
106
152
  } else {
107
153
  console.log(JSON.stringify(outputData, null, 2));
108
154
  }
@@ -133,28 +179,52 @@ program
133
179
  const startTime = Date.now();
134
180
 
135
181
  try {
182
+ // Load config file if it exists
183
+ const config = loadConfig(directory);
184
+
185
+ // Define defaults
186
+ const defaults = {
187
+ maxDepth: 5,
188
+ maxContextBudget: 10000,
189
+ include: undefined,
190
+ exclude: undefined,
191
+ output: {
192
+ format: 'console',
193
+ file: undefined,
194
+ },
195
+ };
196
+
197
+ // Merge config with defaults
198
+ const mergedConfig = mergeConfigWithDefaults(config, defaults);
199
+
200
+ // Override with CLI options (CLI takes precedence)
201
+ const finalOptions = {
202
+ rootDir: directory,
203
+ maxDepth: options.maxDepth ? parseInt(options.maxDepth) : mergedConfig.maxDepth,
204
+ maxContextBudget: options.maxContext ? parseInt(options.maxContext) : mergedConfig.maxContextBudget,
205
+ include: options.include?.split(',') || mergedConfig.include,
206
+ exclude: options.exclude?.split(',') || mergedConfig.exclude,
207
+ };
208
+
136
209
  const { analyzeContext, generateSummary } = await import('@aiready/context-analyzer');
137
210
 
138
- const results = await analyzeContext({
139
- rootDir: directory,
140
- maxDepth: parseInt(options.maxDepth),
141
- maxContextBudget: parseInt(options.maxContext),
142
- include: options.include?.split(','),
143
- exclude: options.exclude?.split(','),
144
- });
211
+ const results = await analyzeContext(finalOptions);
145
212
 
146
213
  const elapsedTime = ((Date.now() - startTime) / 1000).toFixed(2);
147
214
  const summary = generateSummary(results);
148
215
 
149
- if (options.output === 'json') {
216
+ const outputFormat = options.output || mergedConfig.output?.format || 'console';
217
+ const outputFile = options.outputFile || mergedConfig.output?.file;
218
+
219
+ if (outputFormat === 'json') {
150
220
  const outputData = {
151
221
  results,
152
222
  summary: { ...summary, executionTime: parseFloat(elapsedTime) },
153
223
  };
154
224
 
155
- if (options.outputFile) {
156
- writeFileSync(options.outputFile, JSON.stringify(outputData, null, 2));
157
- console.log(chalk.green(`✅ Results saved to ${options.outputFile}`));
225
+ if (outputFile) {
226
+ writeFileSync(outputFile, JSON.stringify(outputData, null, 2));
227
+ console.log(chalk.green(`✅ Results saved to ${outputFile}`));
158
228
  } else {
159
229
  console.log(JSON.stringify(outputData, null, 2));
160
230
  }
@@ -1,53 +0,0 @@
1
- // src/index.ts
2
- import { analyzePatterns } from "@aiready/pattern-detect";
3
- import { analyzeContext } from "@aiready/context-analyzer";
4
- async function analyzeUnified(options) {
5
- const startTime = Date.now();
6
- const tools = options.tools || ["patterns", "context"];
7
- const result = {
8
- summary: {
9
- totalIssues: 0,
10
- toolsRun: tools,
11
- executionTime: 0
12
- }
13
- };
14
- if (tools.includes("patterns")) {
15
- result.patterns = await analyzePatterns(options);
16
- result.summary.totalIssues += result.patterns.length;
17
- }
18
- if (tools.includes("context")) {
19
- result.context = await analyzeContext(options);
20
- result.summary.totalIssues += result.context.length;
21
- }
22
- result.summary.executionTime = Date.now() - startTime;
23
- return result;
24
- }
25
- function generateUnifiedSummary(result) {
26
- const { summary } = result;
27
- let output = `\u{1F680} AIReady Analysis Complete
28
-
29
- `;
30
- output += `\u{1F4CA} Summary:
31
- `;
32
- output += ` Tools run: ${summary.toolsRun.join(", ")}
33
- `;
34
- output += ` Total issues found: ${summary.totalIssues}
35
- `;
36
- output += ` Execution time: ${(summary.executionTime / 1e3).toFixed(2)}s
37
-
38
- `;
39
- if (result.patterns?.length) {
40
- output += `\u{1F50D} Pattern Analysis: ${result.patterns.length} issues
41
- `;
42
- }
43
- if (result.context?.length) {
44
- output += `\u{1F9E0} Context Analysis: ${result.context.length} issues
45
- `;
46
- }
47
- return output;
48
- }
49
-
50
- export {
51
- analyzeUnified,
52
- generateUnifiedSummary
53
- };