@aiready/cli 0.1.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.
@@ -0,0 +1,24 @@
1
+
2
+ 
3
+ > @aiready/cli@0.1.0 build /Users/pengcao/projects/aiready/packages/cli
4
+ > tsup src/index.ts src/cli.ts --format cjs,esm --dts
5
+
6
+ CLI Building entry: src/cli.ts, src/index.ts
7
+ CLI Using tsconfig: tsconfig.json
8
+ CLI tsup v8.5.1
9
+ CLI Target: es2020
10
+ CJS Build start
11
+ ESM Build start
12
+ CJS dist/cli.js 8.70 KB
13
+ CJS dist/index.js 2.51 KB
14
+ CJS ⚡️ Build success in 54ms
15
+ ESM dist/chunk-S6JWNLN7.mjs 1.40 KB
16
+ ESM dist/index.mjs 138.00 B
17
+ ESM dist/cli.mjs 5.95 KB
18
+ ESM ⚡️ Build success in 55ms
19
+ DTS Build start
20
+ DTS ⚡️ Build success in 560ms
21
+ DTS dist/cli.d.ts 20.00 B
22
+ DTS dist/index.d.ts 731.00 B
23
+ DTS dist/cli.d.mts 20.00 B
24
+ DTS dist/index.d.mts 731.00 B
@@ -0,0 +1,9 @@
1
+
2
+ 
3
+ > @aiready/cli@0.1.0 test /Users/pengcao/projects/aiready/packages/cli
4
+ > vitest run
5
+
6
+ [?25l
7
+  RUN  v4.0.16 /Users/pengcao/projects/aiready/packages/cli
8
+
9
+  ELIFECYCLE  Test failed. See above for more details.
package/README.md ADDED
@@ -0,0 +1,138 @@
1
+ # @aiready/cli
2
+
3
+ Unified CLI for AIReady analysis tools. Provides both unified analysis and individual tool access.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install -g @aiready/cli
9
+ # or
10
+ pnpm add -g @aiready/cli
11
+ # or
12
+ yarn global add @aiready/cli
13
+ ```
14
+
15
+ ## Usage
16
+
17
+ ### Unified Analysis
18
+
19
+ Run both pattern detection and context analysis:
20
+
21
+ ```bash
22
+ aiready scan <directory>
23
+ ```
24
+
25
+ ### Individual Tools
26
+
27
+ #### Pattern Detection
28
+
29
+ ```bash
30
+ aiready patterns <directory> [options]
31
+ ```
32
+
33
+ Options:
34
+ - `-s, --similarity <number>`: Minimum similarity score (0-1) (default: 0.40)
35
+ - `-l, --min-lines <number>`: Minimum lines to consider (default: 5)
36
+ - `--include <patterns>`: File patterns to include (comma-separated)
37
+ - `--exclude <patterns>`: File patterns to exclude (comma-separated)
38
+ - `-o, --output <format>`: Output format: console, json (default: console)
39
+ - `--output-file <path>`: Output file path (for json)
40
+
41
+ #### Context Analysis
42
+
43
+ ```bash
44
+ aiready context <directory> [options]
45
+ ```
46
+
47
+ Options:
48
+ - `--max-depth <number>`: Maximum acceptable import depth (default: 5)
49
+ - `--max-context <number>`: Maximum acceptable context budget (tokens) (default: 10000)
50
+ - `--include <patterns>`: File patterns to include (comma-separated)
51
+ - `--exclude <patterns>`: File patterns to exclude (comma-separated)
52
+ - `-o, --output <format>`: Output format: console, json (default: console)
53
+ - `--output-file <path>`: Output file path (for json)
54
+
55
+ ### Unified Scan Options
56
+
57
+ ```bash
58
+ aiready scan <directory> [options]
59
+ ```
60
+
61
+ Options:
62
+ - `-t, --tools <tools>`: Tools to run (comma-separated: patterns,context) (default: patterns,context)
63
+ - `--include <patterns>`: File patterns to include (comma-separated)
64
+ - `--exclude <patterns>`: File patterns to exclude (comma-separated)
65
+ - `-o, --output <format>`: Output format: console, json (default: console)
66
+ - `--output-file <path>`: Output file path (for json)
67
+
68
+ ## Examples
69
+
70
+ ### Quick Analysis
71
+
72
+ ```bash
73
+ # Analyze current directory with both tools
74
+ aiready scan .
75
+
76
+ # Analyze only patterns
77
+ aiready patterns .
78
+
79
+ # Analyze only context costs
80
+ aiready context .
81
+ ```
82
+
83
+ ### Advanced Usage
84
+
85
+ ```bash
86
+ # Analyze specific file types
87
+ aiready scan ./src --include "**/*.ts,**/*.js"
88
+
89
+ # Exclude test files
90
+ aiready scan . --exclude "**/*.test.*,**/*.spec.*"
91
+
92
+ # Save results to JSON file
93
+ aiready scan . --output json --output-file results.json
94
+
95
+ # Run only pattern analysis with custom similarity threshold
96
+ aiready patterns . --similarity 0.6 --min-lines 10
97
+ ```
98
+
99
+ ### CI/CD Integration
100
+
101
+ ```bash
102
+ # JSON output for automated processing
103
+ aiready scan . --output json --output-file aiready-results.json
104
+
105
+ # Exit with error code if issues found
106
+ aiready scan . && echo "No issues found" || echo "Issues detected"
107
+ ```
108
+
109
+ ## Output Formats
110
+
111
+ ### Console Output
112
+
113
+ Human-readable summary with key metrics and issue counts.
114
+
115
+ ### JSON Output
116
+
117
+ Structured data including:
118
+ - Full analysis results
119
+ - Detailed metrics
120
+ - Issue breakdowns
121
+ - Execution timing
122
+
123
+ ## Exit Codes
124
+
125
+ - `0`: Success, no critical issues
126
+ - `1`: Analysis failed or critical issues found
127
+
128
+ ## Integration
129
+
130
+ The CLI is designed to integrate with:
131
+ - CI/CD pipelines
132
+ - Pre-commit hooks
133
+ - IDE extensions
134
+ - Automated workflows
135
+
136
+ For programmatic usage, see the individual packages:
137
+ - [@aiready/pattern-detect](../pattern-detect)
138
+ - [@aiready/context-analyzer](../context-analyzer)
@@ -0,0 +1,53 @@
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
+ };
@@ -0,0 +1,53 @@
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 || 0;
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
+ };
package/dist/cli.d.mts ADDED
@@ -0,0 +1 @@
1
+ #!/usr/bin/env node
package/dist/cli.d.ts ADDED
@@ -0,0 +1 @@
1
+ #!/usr/bin/env node
package/dist/cli.js ADDED
@@ -0,0 +1,189 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
18
+ // If the importer is in node compatibility mode or this is not an ESM
19
+ // file that has been converted to a CommonJS file using a Babel-
20
+ // compatible transform (i.e. "__esModule" has not been set), then set
21
+ // "default" to the CommonJS "module.exports" for node compatibility.
22
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
23
+ mod
24
+ ));
25
+
26
+ // src/cli.ts
27
+ var import_commander = require("commander");
28
+
29
+ // src/index.ts
30
+ var import_pattern_detect = require("@aiready/pattern-detect");
31
+ var import_context_analyzer = require("@aiready/context-analyzer");
32
+ async function analyzeUnified(options) {
33
+ const startTime = Date.now();
34
+ const tools = options.tools || ["patterns", "context"];
35
+ const result = {
36
+ summary: {
37
+ totalIssues: 0,
38
+ toolsRun: tools,
39
+ executionTime: 0
40
+ }
41
+ };
42
+ if (tools.includes("patterns")) {
43
+ result.patterns = await (0, import_pattern_detect.analyzePatterns)(options);
44
+ result.summary.totalIssues += result.patterns.length;
45
+ }
46
+ if (tools.includes("context")) {
47
+ result.context = await (0, import_context_analyzer.analyzeContext)(options);
48
+ result.summary.totalIssues += result.context?.length || 0;
49
+ }
50
+ result.summary.executionTime = Date.now() - startTime;
51
+ return result;
52
+ }
53
+ function generateUnifiedSummary(result) {
54
+ const { summary } = result;
55
+ let output = `\u{1F680} AIReady Analysis Complete
56
+
57
+ `;
58
+ output += `\u{1F4CA} Summary:
59
+ `;
60
+ output += ` Tools run: ${summary.toolsRun.join(", ")}
61
+ `;
62
+ output += ` Total issues found: ${summary.totalIssues}
63
+ `;
64
+ output += ` Execution time: ${(summary.executionTime / 1e3).toFixed(2)}s
65
+
66
+ `;
67
+ if (result.patterns?.length) {
68
+ output += `\u{1F50D} Pattern Analysis: ${result.patterns.length} issues
69
+ `;
70
+ }
71
+ if (result.context?.length) {
72
+ output += `\u{1F9E0} Context Analysis: ${result.context.length} issues
73
+ `;
74
+ }
75
+ return output;
76
+ }
77
+
78
+ // src/cli.ts
79
+ var import_chalk = __toESM(require("chalk"));
80
+ var import_fs = require("fs");
81
+ var program = new import_commander.Command();
82
+ program.name("aiready").description("AIReady - Unified AI-readiness analysis tools").version("0.1.0");
83
+ 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
+ console.log(import_chalk.default.blue("\u{1F680} Starting AIReady unified analysis...\n"));
85
+ const startTime = Date.now();
86
+ try {
87
+ const tools = options.tools.split(",").map((t) => t.trim());
88
+ const results = await analyzeUnified({
89
+ rootDir: directory,
90
+ tools,
91
+ include: options.include?.split(","),
92
+ exclude: options.exclude?.split(",")
93
+ });
94
+ const elapsedTime = ((Date.now() - startTime) / 1e3).toFixed(2);
95
+ if (options.output === "json") {
96
+ const outputData = {
97
+ ...results,
98
+ summary: {
99
+ ...results.summary,
100
+ executionTime: parseFloat(elapsedTime)
101
+ }
102
+ };
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}`));
106
+ } else {
107
+ console.log(JSON.stringify(outputData, null, 2));
108
+ }
109
+ } else {
110
+ console.log(generateUnifiedSummary(results));
111
+ }
112
+ } catch (error) {
113
+ console.error(import_chalk.default.red("\u274C Analysis failed:"), error);
114
+ process.exit(1);
115
+ }
116
+ });
117
+ program.command("patterns").description("Run pattern detection analysis").argument("<directory>", "Directory to analyze").option("-s, --similarity <number>", "Minimum similarity score (0-1)", "0.40").option("-l, --min-lines <number>", "Minimum lines to consider", "5").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) => {
118
+ console.log(import_chalk.default.blue("\u{1F50D} Analyzing patterns...\n"));
119
+ const startTime = Date.now();
120
+ try {
121
+ const { analyzePatterns: analyzePatterns2, generateSummary } = await import("@aiready/pattern-detect");
122
+ const results = await analyzePatterns2({
123
+ rootDir: directory,
124
+ minSimilarity: parseFloat(options.similarity),
125
+ minLines: parseInt(options.minLines),
126
+ include: options.include?.split(","),
127
+ exclude: options.exclude?.split(",")
128
+ });
129
+ const elapsedTime = ((Date.now() - startTime) / 1e3).toFixed(2);
130
+ const summary = generateSummary(results);
131
+ if (options.output === "json") {
132
+ const outputData = {
133
+ results,
134
+ summary: { ...summary, executionTime: parseFloat(elapsedTime) }
135
+ };
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}`));
139
+ } else {
140
+ console.log(JSON.stringify(outputData, null, 2));
141
+ }
142
+ } else {
143
+ console.log(`Pattern Analysis Complete (${elapsedTime}s)`);
144
+ console.log(`Found ${summary.totalPatterns} duplicate patterns`);
145
+ console.log(`Total token cost: ${summary.totalTokenCost} tokens`);
146
+ }
147
+ } catch (error) {
148
+ console.error(import_chalk.default.red("\u274C Pattern analysis failed:"), error);
149
+ process.exit(1);
150
+ }
151
+ });
152
+ program.command("context").description("Run context window cost analysis").argument("<directory>", "Directory to analyze").option("--max-depth <number>", "Maximum acceptable import depth", "5").option("--max-context <number>", "Maximum acceptable context budget (tokens)", "10000").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) => {
153
+ console.log(import_chalk.default.blue("\u{1F9E0} Analyzing context costs...\n"));
154
+ const startTime = Date.now();
155
+ try {
156
+ const { analyzeContext: analyzeContext2, generateSummary } = await import("@aiready/context-analyzer");
157
+ const results = await analyzeContext2({
158
+ rootDir: directory,
159
+ maxDepth: parseInt(options.maxDepth),
160
+ maxContextBudget: parseInt(options.maxContext),
161
+ include: options.include?.split(","),
162
+ exclude: options.exclude?.split(",")
163
+ });
164
+ const elapsedTime = ((Date.now() - startTime) / 1e3).toFixed(2);
165
+ const summary = generateSummary(results);
166
+ if (options.output === "json") {
167
+ const outputData = {
168
+ results,
169
+ summary: { ...summary, executionTime: parseFloat(elapsedTime) }
170
+ };
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}`));
174
+ } else {
175
+ console.log(JSON.stringify(outputData, null, 2));
176
+ }
177
+ } else {
178
+ console.log(`Context Analysis Complete (${elapsedTime}s)`);
179
+ console.log(`Files analyzed: ${summary.totalFiles}`);
180
+ console.log(`Issues found: ${results.length}`);
181
+ console.log(`Average cohesion: ${(summary.avgCohesion * 100).toFixed(1)}%`);
182
+ console.log(`Average fragmentation: ${(summary.avgFragmentation * 100).toFixed(1)}%`);
183
+ }
184
+ } catch (error) {
185
+ console.error(import_chalk.default.red("\u274C Context analysis failed:"), error);
186
+ process.exit(1);
187
+ }
188
+ });
189
+ program.parse();
package/dist/cli.mjs ADDED
@@ -0,0 +1,119 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ analyzeUnified,
4
+ generateUnifiedSummary
5
+ } from "./chunk-S6JWNLN7.mjs";
6
+
7
+ // src/cli.ts
8
+ import { Command } from "commander";
9
+ import chalk from "chalk";
10
+ import { writeFileSync } from "fs";
11
+ var program = new Command();
12
+ program.name("aiready").description("AIReady - Unified AI-readiness analysis tools").version("0.1.0");
13
+ 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
+ console.log(chalk.blue("\u{1F680} Starting AIReady unified analysis...\n"));
15
+ const startTime = Date.now();
16
+ try {
17
+ const tools = options.tools.split(",").map((t) => t.trim());
18
+ const results = await analyzeUnified({
19
+ rootDir: directory,
20
+ tools,
21
+ include: options.include?.split(","),
22
+ exclude: options.exclude?.split(",")
23
+ });
24
+ const elapsedTime = ((Date.now() - startTime) / 1e3).toFixed(2);
25
+ if (options.output === "json") {
26
+ const outputData = {
27
+ ...results,
28
+ summary: {
29
+ ...results.summary,
30
+ executionTime: parseFloat(elapsedTime)
31
+ }
32
+ };
33
+ if (options.outputFile) {
34
+ writeFileSync(options.outputFile, JSON.stringify(outputData, null, 2));
35
+ console.log(chalk.green(`\u2705 Results saved to ${options.outputFile}`));
36
+ } else {
37
+ console.log(JSON.stringify(outputData, null, 2));
38
+ }
39
+ } else {
40
+ console.log(generateUnifiedSummary(results));
41
+ }
42
+ } catch (error) {
43
+ console.error(chalk.red("\u274C Analysis failed:"), error);
44
+ process.exit(1);
45
+ }
46
+ });
47
+ program.command("patterns").description("Run pattern detection analysis").argument("<directory>", "Directory to analyze").option("-s, --similarity <number>", "Minimum similarity score (0-1)", "0.40").option("-l, --min-lines <number>", "Minimum lines to consider", "5").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) => {
48
+ console.log(chalk.blue("\u{1F50D} Analyzing patterns...\n"));
49
+ const startTime = Date.now();
50
+ try {
51
+ const { analyzePatterns, generateSummary } = await import("@aiready/pattern-detect");
52
+ const results = await analyzePatterns({
53
+ rootDir: directory,
54
+ minSimilarity: parseFloat(options.similarity),
55
+ minLines: parseInt(options.minLines),
56
+ include: options.include?.split(","),
57
+ exclude: options.exclude?.split(",")
58
+ });
59
+ const elapsedTime = ((Date.now() - startTime) / 1e3).toFixed(2);
60
+ const summary = generateSummary(results);
61
+ if (options.output === "json") {
62
+ const outputData = {
63
+ results,
64
+ summary: { ...summary, executionTime: parseFloat(elapsedTime) }
65
+ };
66
+ if (options.outputFile) {
67
+ writeFileSync(options.outputFile, JSON.stringify(outputData, null, 2));
68
+ console.log(chalk.green(`\u2705 Results saved to ${options.outputFile}`));
69
+ } else {
70
+ console.log(JSON.stringify(outputData, null, 2));
71
+ }
72
+ } else {
73
+ console.log(`Pattern Analysis Complete (${elapsedTime}s)`);
74
+ console.log(`Found ${summary.totalPatterns} duplicate patterns`);
75
+ console.log(`Total token cost: ${summary.totalTokenCost} tokens`);
76
+ }
77
+ } catch (error) {
78
+ console.error(chalk.red("\u274C Pattern analysis failed:"), error);
79
+ process.exit(1);
80
+ }
81
+ });
82
+ program.command("context").description("Run context window cost analysis").argument("<directory>", "Directory to analyze").option("--max-depth <number>", "Maximum acceptable import depth", "5").option("--max-context <number>", "Maximum acceptable context budget (tokens)", "10000").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) => {
83
+ console.log(chalk.blue("\u{1F9E0} Analyzing context costs...\n"));
84
+ const startTime = Date.now();
85
+ try {
86
+ const { analyzeContext, generateSummary } = await import("@aiready/context-analyzer");
87
+ const results = await analyzeContext({
88
+ rootDir: directory,
89
+ maxDepth: parseInt(options.maxDepth),
90
+ maxContextBudget: parseInt(options.maxContext),
91
+ include: options.include?.split(","),
92
+ exclude: options.exclude?.split(",")
93
+ });
94
+ const elapsedTime = ((Date.now() - startTime) / 1e3).toFixed(2);
95
+ const summary = generateSummary(results);
96
+ if (options.output === "json") {
97
+ const outputData = {
98
+ results,
99
+ summary: { ...summary, executionTime: parseFloat(elapsedTime) }
100
+ };
101
+ if (options.outputFile) {
102
+ writeFileSync(options.outputFile, JSON.stringify(outputData, null, 2));
103
+ console.log(chalk.green(`\u2705 Results saved to ${options.outputFile}`));
104
+ } else {
105
+ console.log(JSON.stringify(outputData, null, 2));
106
+ }
107
+ } else {
108
+ console.log(`Context Analysis Complete (${elapsedTime}s)`);
109
+ console.log(`Files analyzed: ${summary.totalFiles}`);
110
+ console.log(`Issues found: ${results.length}`);
111
+ console.log(`Average cohesion: ${(summary.avgCohesion * 100).toFixed(1)}%`);
112
+ console.log(`Average fragmentation: ${(summary.avgFragmentation * 100).toFixed(1)}%`);
113
+ }
114
+ } catch (error) {
115
+ console.error(chalk.red("\u274C Context analysis failed:"), error);
116
+ process.exit(1);
117
+ }
118
+ });
119
+ program.parse();
@@ -0,0 +1,19 @@
1
+ import { ScanOptions, AnalysisResult } from '@aiready/core';
2
+ import { ContextAnalysisResult } from '@aiready/context-analyzer';
3
+
4
+ interface UnifiedAnalysisOptions extends ScanOptions {
5
+ tools?: ('patterns' | 'context')[];
6
+ }
7
+ interface UnifiedAnalysisResult {
8
+ patterns?: AnalysisResult[];
9
+ context?: ContextAnalysisResult[];
10
+ summary: {
11
+ totalIssues: number;
12
+ toolsRun: string[];
13
+ executionTime: number;
14
+ };
15
+ }
16
+ declare function analyzeUnified(options: UnifiedAnalysisOptions): Promise<UnifiedAnalysisResult>;
17
+ declare function generateUnifiedSummary(result: UnifiedAnalysisResult): string;
18
+
19
+ export { type UnifiedAnalysisOptions, type UnifiedAnalysisResult, analyzeUnified, generateUnifiedSummary };
@@ -0,0 +1,19 @@
1
+ import { ScanOptions, AnalysisResult } from '@aiready/core';
2
+ import { ContextAnalysisResult } from '@aiready/context-analyzer';
3
+
4
+ interface UnifiedAnalysisOptions extends ScanOptions {
5
+ tools?: ('patterns' | 'context')[];
6
+ }
7
+ interface UnifiedAnalysisResult {
8
+ patterns?: AnalysisResult[];
9
+ context?: ContextAnalysisResult[];
10
+ summary: {
11
+ totalIssues: number;
12
+ toolsRun: string[];
13
+ executionTime: number;
14
+ };
15
+ }
16
+ declare function analyzeUnified(options: UnifiedAnalysisOptions): Promise<UnifiedAnalysisResult>;
17
+ declare function generateUnifiedSummary(result: UnifiedAnalysisResult): string;
18
+
19
+ export { type UnifiedAnalysisOptions, type UnifiedAnalysisResult, analyzeUnified, generateUnifiedSummary };
package/dist/index.js ADDED
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ analyzeUnified: () => analyzeUnified,
24
+ generateUnifiedSummary: () => generateUnifiedSummary
25
+ });
26
+ module.exports = __toCommonJS(index_exports);
27
+ var import_pattern_detect = require("@aiready/pattern-detect");
28
+ var import_context_analyzer = require("@aiready/context-analyzer");
29
+ async function analyzeUnified(options) {
30
+ const startTime = Date.now();
31
+ const tools = options.tools || ["patterns", "context"];
32
+ const result = {
33
+ summary: {
34
+ totalIssues: 0,
35
+ toolsRun: tools,
36
+ executionTime: 0
37
+ }
38
+ };
39
+ if (tools.includes("patterns")) {
40
+ result.patterns = await (0, import_pattern_detect.analyzePatterns)(options);
41
+ result.summary.totalIssues += result.patterns.length;
42
+ }
43
+ if (tools.includes("context")) {
44
+ result.context = await (0, import_context_analyzer.analyzeContext)(options);
45
+ result.summary.totalIssues += result.context?.length || 0;
46
+ }
47
+ result.summary.executionTime = Date.now() - startTime;
48
+ return result;
49
+ }
50
+ function generateUnifiedSummary(result) {
51
+ const { summary } = result;
52
+ let output = `\u{1F680} AIReady Analysis Complete
53
+
54
+ `;
55
+ output += `\u{1F4CA} Summary:
56
+ `;
57
+ output += ` Tools run: ${summary.toolsRun.join(", ")}
58
+ `;
59
+ output += ` Total issues found: ${summary.totalIssues}
60
+ `;
61
+ output += ` Execution time: ${(summary.executionTime / 1e3).toFixed(2)}s
62
+
63
+ `;
64
+ if (result.patterns?.length) {
65
+ output += `\u{1F50D} Pattern Analysis: ${result.patterns.length} issues
66
+ `;
67
+ }
68
+ if (result.context?.length) {
69
+ output += `\u{1F9E0} Context Analysis: ${result.context.length} issues
70
+ `;
71
+ }
72
+ return output;
73
+ }
74
+ // Annotate the CommonJS export names for ESM import in node:
75
+ 0 && (module.exports = {
76
+ analyzeUnified,
77
+ generateUnifiedSummary
78
+ });
package/dist/index.mjs ADDED
@@ -0,0 +1,8 @@
1
+ import {
2
+ analyzeUnified,
3
+ generateUnifiedSummary
4
+ } from "./chunk-S6JWNLN7.mjs";
5
+ export {
6
+ analyzeUnified,
7
+ generateUnifiedSummary
8
+ };
package/package.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "@aiready/cli",
3
+ "version": "0.1.0",
4
+ "description": "Unified CLI for AIReady analysis tools",
5
+ "main": "./dist/index.js",
6
+ "module": "./dist/index.mjs",
7
+ "types": "./dist/index.d.ts",
8
+ "bin": {
9
+ "aiready": "./dist/cli.js"
10
+ },
11
+ "dependencies": {
12
+ "commander": "^12.1.0",
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"
17
+ },
18
+ "devDependencies": {
19
+ "tsup": "^8.3.5",
20
+ "@types/node": "^20.0.0"
21
+ },
22
+ "keywords": [
23
+ "aiready",
24
+ "cli",
25
+ "ai-readiness",
26
+ "code-analysis"
27
+ ],
28
+ "license": "MIT",
29
+ "scripts": {
30
+ "build": "tsup src/index.ts src/cli.ts --format cjs,esm --dts",
31
+ "dev": "tsup src/index.ts src/cli.ts --format cjs,esm --dts --watch",
32
+ "test": "vitest run",
33
+ "lint": "eslint src",
34
+ "clean": "rm -rf dist"
35
+ }
36
+ }
@@ -0,0 +1,55 @@
1
+ import { describe, it, expect, vi } from 'vitest';
2
+ import { analyzeUnified } from '../index';
3
+
4
+ // Mock the individual tools
5
+ vi.mock('@aiready/pattern-detect', () => ({
6
+ analyzePatterns: vi.fn().mockResolvedValue([]),
7
+ generateSummary: vi.fn().mockReturnValue({
8
+ totalDuplicateLines: 0,
9
+ potentialSavings: 0,
10
+ }),
11
+ }));
12
+
13
+ vi.mock('@aiready/context-analyzer', () => ({
14
+ analyzeContext: vi.fn().mockResolvedValue([]),
15
+ generateSummary: vi.fn().mockReturnValue({
16
+ totalFiles: 0,
17
+ averageCohesion: 0,
18
+ averageFragmentation: 0,
19
+ }),
20
+ }));
21
+
22
+ describe('CLI Unified Analysis', () => {
23
+ it('should run unified analysis with both tools', async () => {
24
+ const results = await analyzeUnified({
25
+ rootDir: '/test',
26
+ tools: ['patterns', 'context'],
27
+ });
28
+
29
+ expect(results).toHaveProperty('patterns');
30
+ expect(results).toHaveProperty('context');
31
+ expect(results).toHaveProperty('summary');
32
+ });
33
+
34
+ it('should run analysis with only patterns tool', async () => {
35
+ const results = await analyzeUnified({
36
+ rootDir: '/test',
37
+ tools: ['patterns'],
38
+ });
39
+
40
+ expect(results).toHaveProperty('patterns');
41
+ expect(results).not.toHaveProperty('context');
42
+ expect(results).toHaveProperty('summary');
43
+ });
44
+
45
+ it('should run analysis with only context tool', async () => {
46
+ const results = await analyzeUnified({
47
+ rootDir: '/test',
48
+ tools: ['context'],
49
+ });
50
+
51
+ expect(results).not.toHaveProperty('patterns');
52
+ expect(results).toHaveProperty('context');
53
+ expect(results).toHaveProperty('summary');
54
+ });
55
+ });
package/src/cli.ts ADDED
@@ -0,0 +1,174 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { Command } from 'commander';
4
+ import { analyzeUnified, generateUnifiedSummary } from './index';
5
+ import chalk from 'chalk';
6
+ import { writeFileSync } from 'fs';
7
+ import { join } from 'path';
8
+
9
+ const program = new Command();
10
+
11
+ program
12
+ .name('aiready')
13
+ .description('AIReady - Unified AI-readiness analysis tools')
14
+ .version('0.1.0');
15
+
16
+ program
17
+ .command('scan')
18
+ .description('Run unified analysis on a codebase')
19
+ .argument('<directory>', 'Directory to analyze')
20
+ .option('-t, --tools <tools>', 'Tools to run (comma-separated: patterns,context)', 'patterns,context')
21
+ .option('--include <patterns>', 'File patterns to include (comma-separated)')
22
+ .option('--exclude <patterns>', 'File patterns to exclude (comma-separated)')
23
+ .option('-o, --output <format>', 'Output format: console, json', 'console')
24
+ .option('--output-file <path>', 'Output file path (for json)')
25
+ .action(async (directory, options) => {
26
+ console.log(chalk.blue('🚀 Starting AIReady unified analysis...\n'));
27
+
28
+ const startTime = Date.now();
29
+
30
+ try {
31
+ const tools = options.tools.split(',').map((t: string) => t.trim()) as ('patterns' | 'context')[];
32
+
33
+ const results = await analyzeUnified({
34
+ rootDir: directory,
35
+ tools,
36
+ include: options.include?.split(','),
37
+ exclude: options.exclude?.split(','),
38
+ });
39
+
40
+ const elapsedTime = ((Date.now() - startTime) / 1000).toFixed(2);
41
+
42
+ if (options.output === 'json') {
43
+ const outputData = {
44
+ ...results,
45
+ summary: {
46
+ ...results.summary,
47
+ executionTime: parseFloat(elapsedTime),
48
+ },
49
+ };
50
+
51
+ if (options.outputFile) {
52
+ writeFileSync(options.outputFile, JSON.stringify(outputData, null, 2));
53
+ console.log(chalk.green(`✅ Results saved to ${options.outputFile}`));
54
+ } else {
55
+ console.log(JSON.stringify(outputData, null, 2));
56
+ }
57
+ } else {
58
+ // Console output
59
+ console.log(generateUnifiedSummary(results));
60
+ }
61
+ } catch (error) {
62
+ console.error(chalk.red('❌ Analysis failed:'), error);
63
+ process.exit(1);
64
+ }
65
+ });
66
+
67
+ // Individual tool commands for convenience
68
+ program
69
+ .command('patterns')
70
+ .description('Run pattern detection analysis')
71
+ .argument('<directory>', 'Directory to analyze')
72
+ .option('-s, --similarity <number>', 'Minimum similarity score (0-1)', '0.40')
73
+ .option('-l, --min-lines <number>', 'Minimum lines to consider', '5')
74
+ .option('--include <patterns>', 'File patterns to include (comma-separated)')
75
+ .option('--exclude <patterns>', 'File patterns to exclude (comma-separated)')
76
+ .option('-o, --output <format>', 'Output format: console, json', 'console')
77
+ .option('--output-file <path>', 'Output file path (for json)')
78
+ .action(async (directory, options) => {
79
+ console.log(chalk.blue('🔍 Analyzing patterns...\n'));
80
+
81
+ const startTime = Date.now();
82
+
83
+ try {
84
+ const { analyzePatterns, generateSummary } = await import('@aiready/pattern-detect');
85
+
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
+ });
93
+
94
+ const elapsedTime = ((Date.now() - startTime) / 1000).toFixed(2);
95
+ const summary = generateSummary(results);
96
+
97
+ if (options.output === 'json') {
98
+ const outputData = {
99
+ results,
100
+ summary: { ...summary, executionTime: parseFloat(elapsedTime) },
101
+ };
102
+
103
+ if (options.outputFile) {
104
+ writeFileSync(options.outputFile, JSON.stringify(outputData, null, 2));
105
+ console.log(chalk.green(`✅ Results saved to ${options.outputFile}`));
106
+ } else {
107
+ console.log(JSON.stringify(outputData, null, 2));
108
+ }
109
+ } else {
110
+ console.log(`Pattern Analysis Complete (${elapsedTime}s)`);
111
+ console.log(`Found ${summary.totalPatterns} duplicate patterns`);
112
+ console.log(`Total token cost: ${summary.totalTokenCost} tokens`);
113
+ }
114
+ } catch (error) {
115
+ console.error(chalk.red('❌ Pattern analysis failed:'), error);
116
+ process.exit(1);
117
+ }
118
+ });
119
+
120
+ program
121
+ .command('context')
122
+ .description('Run context window cost analysis')
123
+ .argument('<directory>', 'Directory to analyze')
124
+ .option('--max-depth <number>', 'Maximum acceptable import depth', '5')
125
+ .option('--max-context <number>', 'Maximum acceptable context budget (tokens)', '10000')
126
+ .option('--include <patterns>', 'File patterns to include (comma-separated)')
127
+ .option('--exclude <patterns>', 'File patterns to exclude (comma-separated)')
128
+ .option('-o, --output <format>', 'Output format: console, json', 'console')
129
+ .option('--output-file <path>', 'Output file path (for json)')
130
+ .action(async (directory, options) => {
131
+ console.log(chalk.blue('🧠 Analyzing context costs...\n'));
132
+
133
+ const startTime = Date.now();
134
+
135
+ try {
136
+ const { analyzeContext, generateSummary } = await import('@aiready/context-analyzer');
137
+
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
+ });
145
+
146
+ const elapsedTime = ((Date.now() - startTime) / 1000).toFixed(2);
147
+ const summary = generateSummary(results);
148
+
149
+ if (options.output === 'json') {
150
+ const outputData = {
151
+ results,
152
+ summary: { ...summary, executionTime: parseFloat(elapsedTime) },
153
+ };
154
+
155
+ if (options.outputFile) {
156
+ writeFileSync(options.outputFile, JSON.stringify(outputData, null, 2));
157
+ console.log(chalk.green(`✅ Results saved to ${options.outputFile}`));
158
+ } else {
159
+ console.log(JSON.stringify(outputData, null, 2));
160
+ }
161
+ } else {
162
+ console.log(`Context Analysis Complete (${elapsedTime}s)`);
163
+ console.log(`Files analyzed: ${summary.totalFiles}`);
164
+ console.log(`Issues found: ${results.length}`);
165
+ console.log(`Average cohesion: ${(summary.avgCohesion * 100).toFixed(1)}%`);
166
+ console.log(`Average fragmentation: ${(summary.avgFragmentation * 100).toFixed(1)}%`);
167
+ }
168
+ } catch (error) {
169
+ console.error(chalk.red('❌ Context analysis failed:'), error);
170
+ process.exit(1);
171
+ }
172
+ });
173
+
174
+ program.parse();
package/src/index.ts ADDED
@@ -0,0 +1,66 @@
1
+ import { analyzePatterns } from '@aiready/pattern-detect';
2
+ import { analyzeContext } from '@aiready/context-analyzer';
3
+ import type { AnalysisResult, ScanOptions } from '@aiready/core';
4
+ import type { ContextAnalysisResult } from '@aiready/context-analyzer';
5
+
6
+ export interface UnifiedAnalysisOptions extends ScanOptions {
7
+ tools?: ('patterns' | 'context')[];
8
+ }
9
+
10
+ export interface UnifiedAnalysisResult {
11
+ patterns?: AnalysisResult[];
12
+ context?: ContextAnalysisResult[];
13
+ summary: {
14
+ totalIssues: number;
15
+ toolsRun: string[];
16
+ executionTime: number;
17
+ };
18
+ }
19
+
20
+ export async function analyzeUnified(
21
+ options: UnifiedAnalysisOptions
22
+ ): Promise<UnifiedAnalysisResult> {
23
+ const startTime = Date.now();
24
+ const tools = options.tools || ['patterns', 'context'];
25
+ const result: UnifiedAnalysisResult = {
26
+ summary: {
27
+ totalIssues: 0,
28
+ toolsRun: tools,
29
+ executionTime: 0,
30
+ },
31
+ };
32
+
33
+ // Run pattern detection
34
+ if (tools.includes('patterns')) {
35
+ result.patterns = await analyzePatterns(options);
36
+ result.summary.totalIssues += result.patterns.length;
37
+ }
38
+
39
+ // Run context analysis
40
+ if (tools.includes('context')) {
41
+ result.context = await analyzeContext(options);
42
+ result.summary.totalIssues += result.context?.length || 0;
43
+ }
44
+
45
+ result.summary.executionTime = Date.now() - startTime;
46
+ return result;
47
+ }
48
+
49
+ export function generateUnifiedSummary(result: UnifiedAnalysisResult): string {
50
+ const { summary } = result;
51
+ let output = `🚀 AIReady Analysis Complete\n\n`;
52
+ output += `📊 Summary:\n`;
53
+ output += ` Tools run: ${summary.toolsRun.join(', ')}\n`;
54
+ output += ` Total issues found: ${summary.totalIssues}\n`;
55
+ output += ` Execution time: ${(summary.executionTime / 1000).toFixed(2)}s\n\n`;
56
+
57
+ if (result.patterns?.length) {
58
+ output += `🔍 Pattern Analysis: ${result.patterns.length} issues\n`;
59
+ }
60
+
61
+ if (result.context?.length) {
62
+ output += `🧠 Context Analysis: ${result.context.length} issues\n`;
63
+ }
64
+
65
+ return output;
66
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,8 @@
1
+ {
2
+ "extends": "../core/tsconfig.json",
3
+ "compilerOptions": {
4
+ "outDir": "./dist",
5
+ "rootDir": "./src"
6
+ },
7
+ "include": ["src/**/*"]
8
+ }