@anhnguyen02/catlas 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/README.md +59 -0
  2. package/dist/assembler/context-assembler.d.ts +17 -0
  3. package/dist/assembler/context-assembler.d.ts.map +1 -0
  4. package/dist/assembler/context-assembler.js +18 -0
  5. package/dist/assembler/context-assembler.js.map +1 -0
  6. package/dist/cli.d.ts +3 -0
  7. package/dist/cli.d.ts.map +1 -0
  8. package/dist/cli.js +113 -0
  9. package/dist/cli.js.map +1 -0
  10. package/dist/detector/project-detector.d.ts +10 -0
  11. package/dist/detector/project-detector.d.ts.map +1 -0
  12. package/dist/detector/project-detector.js +171 -0
  13. package/dist/detector/project-detector.js.map +1 -0
  14. package/dist/exporter/markdown.d.ts +5 -0
  15. package/dist/exporter/markdown.d.ts.map +1 -0
  16. package/dist/exporter/markdown.js +106 -0
  17. package/dist/exporter/markdown.js.map +1 -0
  18. package/dist/extractor/ctags-runner.d.ts +8 -0
  19. package/dist/extractor/ctags-runner.d.ts.map +1 -0
  20. package/dist/extractor/ctags-runner.js +99 -0
  21. package/dist/extractor/ctags-runner.js.map +1 -0
  22. package/dist/extractor/import-graph.d.ts +6 -0
  23. package/dist/extractor/import-graph.d.ts.map +1 -0
  24. package/dist/extractor/import-graph.js +127 -0
  25. package/dist/extractor/import-graph.js.map +1 -0
  26. package/dist/extractor/module-graph.d.ts +16 -0
  27. package/dist/extractor/module-graph.d.ts.map +1 -0
  28. package/dist/extractor/module-graph.js +108 -0
  29. package/dist/extractor/module-graph.js.map +1 -0
  30. package/dist/ranker/priority-ranker.d.ts +15 -0
  31. package/dist/ranker/priority-ranker.d.ts.map +1 -0
  32. package/dist/ranker/priority-ranker.js +49 -0
  33. package/dist/ranker/priority-ranker.js.map +1 -0
  34. package/dist/scanner/file-classifier.d.ts +9 -0
  35. package/dist/scanner/file-classifier.d.ts.map +1 -0
  36. package/dist/scanner/file-classifier.js +21 -0
  37. package/dist/scanner/file-classifier.js.map +1 -0
  38. package/dist/scanner/role-detector.d.ts +9 -0
  39. package/dist/scanner/role-detector.d.ts.map +1 -0
  40. package/dist/scanner/role-detector.js +39 -0
  41. package/dist/scanner/role-detector.js.map +1 -0
  42. package/dist/scanner/tree-builder.d.ts +8 -0
  43. package/dist/scanner/tree-builder.d.ts.map +1 -0
  44. package/dist/scanner/tree-builder.js +13 -0
  45. package/dist/scanner/tree-builder.js.map +1 -0
  46. package/dist/scanner/tree-walker.d.ts +7 -0
  47. package/dist/scanner/tree-walker.d.ts.map +1 -0
  48. package/dist/scanner/tree-walker.js +43 -0
  49. package/dist/scanner/tree-walker.js.map +1 -0
  50. package/dist/types.d.ts +34 -0
  51. package/dist/types.d.ts.map +1 -0
  52. package/dist/types.js +2 -0
  53. package/dist/types.js.map +1 -0
  54. package/dist/utils/cache.d.ts +18 -0
  55. package/dist/utils/cache.d.ts.map +1 -0
  56. package/dist/utils/cache.js +50 -0
  57. package/dist/utils/cache.js.map +1 -0
  58. package/dist/utils/diff.d.ts +10 -0
  59. package/dist/utils/diff.d.ts.map +1 -0
  60. package/dist/utils/diff.js +43 -0
  61. package/dist/utils/diff.js.map +1 -0
  62. package/dist/utils/gitignore.d.ts +9 -0
  63. package/dist/utils/gitignore.d.ts.map +1 -0
  64. package/dist/utils/gitignore.js +35 -0
  65. package/dist/utils/gitignore.js.map +1 -0
  66. package/dist/utils/logger.d.ts +7 -0
  67. package/dist/utils/logger.d.ts.map +1 -0
  68. package/dist/utils/logger.js +33 -0
  69. package/dist/utils/logger.js.map +1 -0
  70. package/package.json +51 -0
package/README.md ADDED
@@ -0,0 +1,59 @@
1
+ # πŸ—ΊοΈ Catlas
2
+
3
+ [![npm version](https://badge.fury.io/js/%40anhnguyen02%2Fcatlas.svg)](https://www.npmjs.com/package/@anhnguyen02/catlas)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+
6
+ > **AI-First Codebase Context Generator.**
7
+ > Instantly build a deterministic, token-optimized `ATLAS.md` mapped for AI Agents like Claude, Cursor, and Aider.
8
+
9
+ **Catlas** is a blazing-fast CLI tool that bridges the gap between your massive codebase and AI coding assistants. Instead of relying on LLMs to guess your project's structure, Catlas uses strictly deterministic **Static Analysis** to generate a highly compressed (`<700 tokens`) knowledge graph of your project.
10
+
11
+ ## ✨ Features
12
+
13
+ - ⚑️ **Zero LLM Dependency:** Runs locally, instantly, and deterministically without arbitrary API calls or hallucinations.
14
+ - 🎯 **AI-Optimized Output:** Strict token budgeting. Delivers a perfectly dense knowledge file without wasting your LLM context window.
15
+ - βš™οΈ **Deterministic Detection:** Automatically recognizes your stack (e.g., Nuxt, Next.js, FastAPI, Golang) and maps your application architecture precisely without hallucinating framework rules.
16
+ - 🧠 **Smart Ctags Extraction:** Interrogates your project with Universal Ctags to pull out core signatures, interfaces, and module boundaries.
17
+ - πŸ“‰ **Impact-Based Filtering:** Cuts through the noise. Catlas identifies and retains only the Top-20 most impactful entry points and core services using internal graph ranking.
18
+
19
+ ---
20
+
21
+ ## πŸ“¦ Installation
22
+
23
+ Install globally via npm to use `catlas` across all your projects:
24
+
25
+ ```bash
26
+ npm install -g @anhnguyen02/catlas
27
+ ```
28
+
29
+ ### System Requirements
30
+ You must have `universal-ctags` installed on your machine for the symbol extractor to work.
31
+ - **macOS:** `brew install universal-ctags`
32
+ - **Linux:** `sudo apt-get install universal-ctags`
33
+ - **Windows:** Install via [ctags.io](https://ctags.io/) or use WSL.
34
+
35
+ ---
36
+
37
+ ## πŸš€ Usage
38
+
39
+ Navigate to any project directory and run the scanner to map your codebase:
40
+
41
+ ```bash
42
+ cd /path/to/your/project
43
+ catlas scan -d .
44
+ ```
45
+
46
+ ### Run via npx (No Installation)
47
+ If you prefer not to install globally, you can execute it directly:
48
+
49
+ ```bash
50
+ npx @anhnguyen02/catlas scan -d .
51
+ ```
52
+
53
+ ### What Happens Next?
54
+ Catlas will output a highly structured `ATLAS.md` file in the root of your directory. Whenever you start a new AI coding session (e.g., in Cursor or with Claude), simply point the AI to this file, and it will instantly understand the context, architecture, and core dependencies of your project!
55
+
56
+ ---
57
+
58
+ ## πŸ“„ License
59
+ MIT
@@ -0,0 +1,17 @@
1
+ import type { FileData, ExtractedSymbol, ModuleNode, ProjectProfile } from '../types.js';
2
+ export interface ProjectMap {
3
+ projectName: string;
4
+ description?: string;
5
+ entryPoints: string[];
6
+ dependencies: Record<string, string>;
7
+ scripts: Record<string, string>;
8
+ stack: string;
9
+ fileTree: string;
10
+ moduleGraph: ModuleNode[];
11
+ hotFiles: FileData[];
12
+ coreSignatures: ExtractedSymbol[];
13
+ }
14
+ export declare class ContextAssembler {
15
+ assemble(rootDir: string, profile: ProjectProfile, stack: string, fileTree: string, moduleGraph: ModuleNode[], hotFiles: FileData[], coreSignatures: ExtractedSymbol[]): ProjectMap;
16
+ }
17
+ //# sourceMappingURL=context-assembler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-assembler.d.ts","sourceRoot":"","sources":["../../src/assembler/context-assembler.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAExF,MAAM,WAAW,UAAU;IACzB,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,WAAW,EAAE,MAAM,EAAE,CAAA;IACrB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACpC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC/B,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,EAAE,UAAU,EAAE,CAAA;IACzB,QAAQ,EAAE,QAAQ,EAAE,CAAA;IACpB,cAAc,EAAE,eAAe,EAAE,CAAA;CAClC;AAED,qBAAa,gBAAgB;IACpB,QAAQ,CACb,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,cAAc,EACvB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,UAAU,EAAE,EACzB,QAAQ,EAAE,QAAQ,EAAE,EACpB,cAAc,EAAE,eAAe,EAAE,GAChC,UAAU;CAcd"}
@@ -0,0 +1,18 @@
1
+ import path from 'node:path';
2
+ export class ContextAssembler {
3
+ assemble(rootDir, profile, stack, fileTree, moduleGraph, hotFiles, coreSignatures) {
4
+ return {
5
+ projectName: profile.projectName || path.basename(rootDir),
6
+ description: profile.description,
7
+ entryPoints: profile.entryPoints || [],
8
+ dependencies: profile.dependencies || {},
9
+ scripts: profile.scripts || {},
10
+ stack,
11
+ fileTree,
12
+ moduleGraph,
13
+ hotFiles,
14
+ coreSignatures,
15
+ };
16
+ }
17
+ }
18
+ //# sourceMappingURL=context-assembler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-assembler.js","sourceRoot":"","sources":["../../src/assembler/context-assembler.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAA;AAgB5B,MAAM,OAAO,gBAAgB;IACpB,QAAQ,CACb,OAAe,EACf,OAAuB,EACvB,KAAa,EACb,QAAgB,EAChB,WAAyB,EACzB,QAAoB,EACpB,cAAiC;QAEjC,OAAO;YACL,WAAW,EAAE,OAAO,CAAC,WAAW,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC;YAC1D,WAAW,EAAE,OAAO,CAAC,WAAW;YAChC,WAAW,EAAE,OAAO,CAAC,WAAW,IAAI,EAAE;YACtC,YAAY,EAAE,OAAO,CAAC,YAAY,IAAI,EAAE;YACxC,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,EAAE;YAC9B,KAAK;YACL,QAAQ;YACR,WAAW;YACX,QAAQ;YACR,cAAc;SACf,CAAA;IACH,CAAC;CACF"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js ADDED
@@ -0,0 +1,113 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from 'commander';
3
+ import fs from 'node:fs';
4
+ import path from 'node:path';
5
+ import { log, logStep, logDivider, setVerbose } from './utils/logger.js';
6
+ import { ProjectDetector } from './detector/project-detector.js';
7
+ import { TreeWalker } from './scanner/tree-walker.js';
8
+ import { RoleDetector } from './scanner/role-detector.js';
9
+ const program = new Command();
10
+ const TOTAL_STEPS = 9;
11
+ // Read version from package.json dynamically
12
+ const pkgMeta = JSON.parse(fs.readFileSync(new URL('../package.json', import.meta.url), 'utf-8'));
13
+ program
14
+ .name('catlas')
15
+ .description('AI-First static codebase mapper')
16
+ .version(pkgMeta.version);
17
+ program
18
+ .command('scan')
19
+ .description('Static analysis scan to generate ATLAS.md')
20
+ .option('-d, --dir <path>', 'Project root directory', '.')
21
+ .option('-v, --verbose', 'Enable verbose debug logging', false)
22
+ .action(async (options) => {
23
+ if (options.verbose)
24
+ setVerbose(true);
25
+ const rootDir = path.resolve(options.dir);
26
+ try {
27
+ await scan(rootDir);
28
+ }
29
+ catch (error) {
30
+ const message = error instanceof Error ? error.message : String(error);
31
+ log('error', `Scan failed: ${message}`);
32
+ process.exit(1);
33
+ }
34
+ });
35
+ async function scan(rootDir) {
36
+ const projectName = path.basename(rootDir);
37
+ logDivider();
38
+ log('info', `Catlas β€” Scanning "${projectName}"`);
39
+ logDivider();
40
+ // 1. Project Detector
41
+ logStep(1, TOTAL_STEPS, 'Detecting language & framework...');
42
+ const detector = new ProjectDetector();
43
+ const profile = detector.detect(rootDir);
44
+ log('success', `Detected: ${profile.language} / ${profile.framework}`);
45
+ const stack = `${profile.language.toUpperCase()} | ${profile.framework.toUpperCase()}`;
46
+ // 2. Tree Walker
47
+ logStep(2, TOTAL_STEPS, 'Walking directory tree...');
48
+ const walker = new TreeWalker(rootDir);
49
+ const files = walker.walk();
50
+ log('success', `Found ${files.length} code files`);
51
+ // 3. Role Detector (generic, path-based)
52
+ logStep(3, TOTAL_STEPS, 'Classifying file roles...');
53
+ const roleDetector = new RoleDetector();
54
+ const fileData = files.map(filePath => {
55
+ const role = roleDetector.classify(filePath);
56
+ return {
57
+ path: filePath,
58
+ role,
59
+ symbols: [],
60
+ imports: [],
61
+ inDegree: 0
62
+ };
63
+ });
64
+ // Group by role for logging
65
+ const roleCounts = {};
66
+ fileData.forEach(fd => {
67
+ roleCounts[fd.role] = (roleCounts[fd.role] || 0) + 1;
68
+ });
69
+ log('success', `Classified roles:`);
70
+ for (const [role, count] of Object.entries(roleCounts)) {
71
+ log('info', ` - ${role}: ${count}`, undefined);
72
+ }
73
+ logDivider();
74
+ // 4. File Tree Builder
75
+ logStep(4, TOTAL_STEPS, 'Building compact file tree...');
76
+ const { TreeBuilder } = await import('./scanner/tree-builder.js');
77
+ const treeBuilder = new TreeBuilder();
78
+ const fileTree = treeBuilder.build(files);
79
+ // 5. Ctags Runner
80
+ logStep(5, TOTAL_STEPS, 'Extracting symbols with Universal Ctags...');
81
+ const { CtagsRunner } = await import('./extractor/ctags-runner.js');
82
+ const ctags = new CtagsRunner();
83
+ ctags.extract(fileData, rootDir);
84
+ // 6. Import Graph
85
+ logStep(6, TOTAL_STEPS, 'Building import graph...');
86
+ const { ImportGraph } = await import('./extractor/import-graph.js');
87
+ const graph = new ImportGraph();
88
+ graph.build(fileData, profile.language, rootDir);
89
+ // 7. Module Graph
90
+ logStep(7, TOTAL_STEPS, 'Building module dependency graph...');
91
+ const { ModuleGraph } = await import('./extractor/module-graph.js');
92
+ const moduleGraph = new ModuleGraph();
93
+ const moduleNodes = moduleGraph.build(fileData);
94
+ // 8. Priority Ranker
95
+ logStep(8, TOTAL_STEPS, 'Ranking files and symbols...');
96
+ const { PriorityRanker } = await import('./ranker/priority-ranker.js');
97
+ const ranker = new PriorityRanker();
98
+ const hotFiles = ranker.rankFiles(fileData);
99
+ const coreSignatures = ranker.rankSymbols(fileData);
100
+ // 9. Assemble & Export
101
+ logStep(9, TOTAL_STEPS, 'Generating ATLAS.md...');
102
+ const { ContextAssembler } = await import('./assembler/context-assembler.js');
103
+ const assembler = new ContextAssembler();
104
+ const projectMap = assembler.assemble(rootDir, profile, stack, fileTree, moduleNodes, hotFiles, coreSignatures);
105
+ const { MarkdownExporter } = await import('./exporter/markdown.js');
106
+ const exporter = new MarkdownExporter();
107
+ const outputPath = path.join(rootDir, 'ATLAS.md');
108
+ exporter.export(projectMap, outputPath);
109
+ logDivider();
110
+ log('success', `ATLAS.md generated: ${outputPath}`);
111
+ }
112
+ program.parse();
113
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { ProjectProfile } from '../types.js';
2
+ export declare class ProjectDetector {
3
+ /**
4
+ * Detects the project language and framework.
5
+ * Returns only { language, framework } β€” no convention loading.
6
+ * AI agents already know framework conventions, so we only need the name.
7
+ */
8
+ detect(rootDir: string): ProjectProfile;
9
+ }
10
+ //# sourceMappingURL=project-detector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-detector.d.ts","sourceRoot":"","sources":["../../src/detector/project-detector.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAGjD,qBAAa,eAAe;IAC1B;;;;OAIG;IACI,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc;CA2I/C"}
@@ -0,0 +1,171 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { log } from '../utils/logger.js';
4
+ export class ProjectDetector {
5
+ /**
6
+ * Detects the project language and framework.
7
+ * Returns only { language, framework } β€” no convention loading.
8
+ * AI agents already know framework conventions, so we only need the name.
9
+ */
10
+ detect(rootDir) {
11
+ let framework = 'unknown';
12
+ let language = 'unknown';
13
+ let projectName;
14
+ let description;
15
+ let entryPoints = [];
16
+ let dependencies = {};
17
+ let scripts = {};
18
+ // 1. Check Node.js (package.json)
19
+ const pkgPath = path.join(rootDir, 'package.json');
20
+ if (fs.existsSync(pkgPath)) {
21
+ language = 'typescript';
22
+ try {
23
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8') || '{}');
24
+ const deps = { ...(pkg.dependencies || {}), ...(pkg.devDependencies || {}) };
25
+ if (pkg.name)
26
+ projectName = pkg.name;
27
+ if (pkg.description)
28
+ description = pkg.description;
29
+ if (pkg.dependencies)
30
+ dependencies = pkg.dependencies;
31
+ if (pkg.scripts)
32
+ scripts = pkg.scripts;
33
+ if (pkg.bin) {
34
+ if (typeof pkg.bin === 'string')
35
+ entryPoints.push(pkg.bin);
36
+ else
37
+ Object.values(pkg.bin).forEach(v => entryPoints.push(String(v)));
38
+ }
39
+ if (pkg.main)
40
+ entryPoints.push(pkg.main);
41
+ if (pkg.exports) {
42
+ if (typeof pkg.exports === 'string')
43
+ entryPoints.push(pkg.exports);
44
+ else if (pkg.exports['.']) {
45
+ const e = pkg.exports['.'];
46
+ if (typeof e === 'string')
47
+ entryPoints.push(e);
48
+ else if (e.import)
49
+ entryPoints.push(e.import);
50
+ else if (e.require)
51
+ entryPoints.push(e.require);
52
+ else if (e.default)
53
+ entryPoints.push(e.default);
54
+ }
55
+ }
56
+ if (deps['nuxt'])
57
+ framework = 'nuxt';
58
+ else if (deps['next'])
59
+ framework = 'next';
60
+ else if (deps['@nestjs/core'])
61
+ framework = 'nestjs';
62
+ else if (deps['express'])
63
+ framework = 'express';
64
+ else if (deps['@angular/core'])
65
+ framework = 'angular';
66
+ else if (deps['react'])
67
+ framework = 'react';
68
+ else if (deps['vue'])
69
+ framework = 'vue';
70
+ else if (deps['svelte'])
71
+ framework = 'svelte';
72
+ else
73
+ framework = 'node';
74
+ }
75
+ catch (e) {
76
+ log('warn', `Failed to parse package.json (${e?.message || 'Invalid Format'}), falling back generic analysis`);
77
+ framework = 'generic';
78
+ language = 'typescript';
79
+ }
80
+ }
81
+ // 2. Check Python (requirements.txt or pyproject.toml)
82
+ else {
83
+ const reqPath = path.join(rootDir, 'requirements.txt');
84
+ const pyprojectPath = path.join(rootDir, 'pyproject.toml');
85
+ if (fs.existsSync(reqPath) || fs.existsSync(pyprojectPath)) {
86
+ language = 'python';
87
+ const content = fs.existsSync(reqPath)
88
+ ? fs.readFileSync(reqPath, 'utf-8')
89
+ : fs.readFileSync(pyprojectPath, 'utf-8');
90
+ const lowerContent = content.toLowerCase();
91
+ if (lowerContent.includes('fastapi'))
92
+ framework = 'fastapi';
93
+ else if (lowerContent.includes('django'))
94
+ framework = 'django';
95
+ else if (lowerContent.includes('flask'))
96
+ framework = 'flask';
97
+ else
98
+ framework = 'python';
99
+ }
100
+ // 3. Check Go (go.mod)
101
+ else {
102
+ const goModPath = path.join(rootDir, 'go.mod');
103
+ if (fs.existsSync(goModPath)) {
104
+ language = 'go';
105
+ const content = fs.readFileSync(goModPath, 'utf-8');
106
+ const moduleMatch = content.match(/^module\s+(.+)$/m);
107
+ if (moduleMatch)
108
+ projectName = moduleMatch[1].trim().split('/').pop() || projectName;
109
+ if (content.includes('github.com/gin-gonic/gin'))
110
+ framework = 'gin';
111
+ else if (content.includes('github.com/gofiber/fiber'))
112
+ framework = 'fiber';
113
+ else if (content.includes('github.com/labstack/echo'))
114
+ framework = 'echo';
115
+ else
116
+ framework = 'go';
117
+ }
118
+ // 4. Check Rust (Cargo.toml)
119
+ else {
120
+ const cargoPath = path.join(rootDir, 'Cargo.toml');
121
+ if (fs.existsSync(cargoPath)) {
122
+ language = 'rust';
123
+ const content = fs.readFileSync(cargoPath, 'utf-8').toLowerCase();
124
+ if (content.includes('actix'))
125
+ framework = 'actix';
126
+ else if (content.includes('axum'))
127
+ framework = 'axum';
128
+ else
129
+ framework = 'rust';
130
+ }
131
+ // 5. Check Java/Kotlin (pom.xml or build.gradle)
132
+ else {
133
+ const pomPath = path.join(rootDir, 'pom.xml');
134
+ const gradlePath = path.join(rootDir, 'build.gradle');
135
+ const gradleKtsPath = path.join(rootDir, 'build.gradle.kts');
136
+ if (fs.existsSync(pomPath) || fs.existsSync(gradlePath) || fs.existsSync(gradleKtsPath)) {
137
+ const hasPom = fs.existsSync(pomPath);
138
+ const content = hasPom
139
+ ? fs.readFileSync(pomPath, 'utf-8')
140
+ : fs.readFileSync(fs.existsSync(gradleKtsPath) ? gradleKtsPath : gradlePath, 'utf-8');
141
+ language = fs.existsSync(gradleKtsPath) ? 'kotlin' : 'java';
142
+ const lowerContent = content.toLowerCase();
143
+ if (lowerContent.includes('spring'))
144
+ framework = 'spring';
145
+ else
146
+ framework = language;
147
+ }
148
+ }
149
+ }
150
+ }
151
+ }
152
+ if (framework === 'unknown') {
153
+ log('warn', 'Could not detect project framework. Output will use generic analysis.');
154
+ framework = 'generic';
155
+ language = 'generic';
156
+ }
157
+ if (!projectName) {
158
+ projectName = path.basename(rootDir);
159
+ }
160
+ return {
161
+ language,
162
+ framework,
163
+ projectName,
164
+ description,
165
+ entryPoints,
166
+ dependencies,
167
+ scripts
168
+ };
169
+ }
170
+ }
171
+ //# sourceMappingURL=project-detector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-detector.js","sourceRoot":"","sources":["../../src/detector/project-detector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { ProjectMap } from '../assembler/context-assembler.js';
2
+ export declare class MarkdownExporter {
3
+ export(projectMap: ProjectMap, exportPath: string): void;
4
+ }
5
+ //# sourceMappingURL=markdown.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/exporter/markdown.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mCAAmC,CAAA;AAEnE,qBAAa,gBAAgB;IACpB,MAAM,CAAC,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI;CAgHhE"}
@@ -0,0 +1,106 @@
1
+ import fs from 'node:fs';
2
+ export class MarkdownExporter {
3
+ export(projectMap, exportPath) {
4
+ const lines = [];
5
+ // 1. Header
6
+ lines.push(`# ${projectMap.projectName}`);
7
+ if (projectMap.description) {
8
+ lines.push(`> ${projectMap.description}`);
9
+ }
10
+ lines.push(`> Stack: ${projectMap.stack}`);
11
+ lines.push('');
12
+ // 1.1 Entry Points
13
+ if (projectMap.entryPoints && projectMap.entryPoints.length > 0) {
14
+ lines.push('## ENTRY POINTS');
15
+ const uniqueEntries = Array.from(new Set(projectMap.entryPoints));
16
+ for (const entry of uniqueEntries) {
17
+ lines.push(`- \`${entry}\``);
18
+ }
19
+ lines.push('');
20
+ }
21
+ // 1.2 Core Dependencies
22
+ const depKeys = Object.keys(projectMap.dependencies || {});
23
+ if (depKeys.length > 0) {
24
+ lines.push('## CORE DEPENDENCIES');
25
+ for (const dep of depKeys.slice(0, 10)) {
26
+ lines.push(`- \`${dep}\`: ${projectMap.dependencies[dep]}`);
27
+ }
28
+ if (depKeys.length > 10)
29
+ lines.push(`- ...and ${depKeys.length - 10} more`);
30
+ lines.push('');
31
+ }
32
+ // 1.3 Scripts
33
+ const scriptKeys = Object.keys(projectMap.scripts || {});
34
+ if (scriptKeys.length > 0) {
35
+ const importantScripts = ['dev', 'build', 'test', 'start'];
36
+ const matchedScripts = importantScripts.filter(s => projectMap.scripts[s]);
37
+ if (matchedScripts.length > 0) {
38
+ lines.push('## SCRIPTS');
39
+ for (const req of matchedScripts) {
40
+ lines.push(`- \`${req}\`: ${projectMap.scripts[req]}`);
41
+ }
42
+ lines.push('');
43
+ }
44
+ }
45
+ // 2. File Tree
46
+ lines.push('## FILE TREE');
47
+ lines.push('```');
48
+ lines.push(projectMap.fileTree);
49
+ lines.push('```');
50
+ lines.push('');
51
+ // 3. Module Graph
52
+ if (projectMap.moduleGraph.length > 0) {
53
+ lines.push('## MODULE GRAPH');
54
+ for (const node of projectMap.moduleGraph) {
55
+ if (node.dependsOn.length > 0) {
56
+ lines.push(`${node.path}/ β†’ ${node.dependsOn.map(d => d + '/').join(', ')}`);
57
+ }
58
+ }
59
+ lines.push('');
60
+ }
61
+ // 4. Core Architecture (X-Ray of most-imported files with their symbols)
62
+ lines.push('## CORE ARCHITECTURE (X-RAY)');
63
+ if (projectMap.hotFiles.length === 0 && projectMap.coreSignatures.length === 0) {
64
+ lines.push('> No high-impact files detected.');
65
+ }
66
+ else {
67
+ // Build a set of files to render (hot files + any file having core signatures)
68
+ const filesToRender = new Map();
69
+ for (const fd of projectMap.hotFiles) {
70
+ filesToRender.set(fd.path, fd);
71
+ }
72
+ // Group signatures by file for clean display
73
+ const sigsByFile = new Map();
74
+ for (const sig of projectMap.coreSignatures) {
75
+ if (!sigsByFile.has(sig.path))
76
+ sigsByFile.set(sig.path, []);
77
+ sigsByFile.get(sig.path).push(sig);
78
+ // Ensure file is in filesToRender even if not in hotFiles
79
+ if (!filesToRender.has(sig.path)) {
80
+ filesToRender.set(sig.path, {
81
+ path: sig.path,
82
+ role: sig.fileRole,
83
+ symbols: [],
84
+ imports: [],
85
+ inDegree: sig.inDegree
86
+ });
87
+ }
88
+ }
89
+ // Sort files by inDegree descending
90
+ const sortedFiles = Array.from(filesToRender.values()).sort((a, b) => b.inDegree - a.inDegree);
91
+ for (const fd of sortedFiles) {
92
+ const label = fd.inDegree > 0 ? ` (${fd.inDegree} importers)` : '';
93
+ lines.push(`πŸ”₯ ${fd.path}${label}`);
94
+ const sigs = sigsByFile.get(fd.path) || [];
95
+ for (const sig of sigs) {
96
+ const kindLabel = `[${sig.kind}]`;
97
+ const display = sig.signature ? `${kindLabel} ${sig.name}${sig.signature}` : `${kindLabel} ${sig.name}`;
98
+ lines.push(` β†’ ${display}`);
99
+ }
100
+ }
101
+ }
102
+ lines.push('');
103
+ fs.writeFileSync(exportPath, lines.join('\n'), 'utf-8');
104
+ }
105
+ }
106
+ //# sourceMappingURL=markdown.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdown.js","sourceRoot":"","sources":["../../src/exporter/markdown.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { FileData } from '../types.js';
2
+ export declare class CtagsRunner {
3
+ private ctagsPath;
4
+ constructor();
5
+ private findCtags;
6
+ extract(fileDataList: FileData[], rootDir: string): void;
7
+ }
8
+ //# sourceMappingURL=ctags-runner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ctags-runner.d.ts","sourceRoot":"","sources":["../../src/extractor/ctags-runner.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAA6B,QAAQ,EAAE,MAAM,aAAa,CAAA;AAGtE,qBAAa,WAAW;IACtB,OAAO,CAAC,SAAS,CAAQ;;IAMzB,OAAO,CAAC,SAAS;IAWV,OAAO,CAAC,YAAY,EAAE,QAAQ,EAAE,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;CAsFhE"}