@parseme/cli 0.0.4 → 0.0.6

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.
package/README.md CHANGED
@@ -46,7 +46,7 @@ PARSEME uses AST analysis to identify:
46
46
  ## **Language Support**
47
47
 
48
48
  - **TypeScript** - Full support including advanced types, decorators, interfaces
49
- - **JavaScript (ES6+)** - Modern JavaScript with all ES features
49
+ - **JavaScript (ES6+)** - Modern JavaScript with ES features
50
50
  - **JSX/TSX** - React and other JSX-based frameworks
51
51
  - **Mixed codebases** - Projects with both JS and TS files
52
52
 
@@ -59,9 +59,6 @@ PARSEME aims to automatically analyse any JavaScript or TypeScript project like:
59
59
  - **NestJS** - Controllers, services, decorators, dependency injection
60
60
  - **Express.js** - Routes, middleware, error handlers
61
61
  - **Fastify** - Route registration, plugins, hooks
62
- - **Koa.js** - Context-based middleware, routing
63
- - **Hapi.js** - Route configuration, server plugins
64
- - **Custom frameworks** - Any HTTP endpoint patterns
65
62
 
66
63
  ### **Frontend Applications**
67
64
 
@@ -70,28 +67,26 @@ PARSEME aims to automatically analyse any JavaScript or TypeScript project like:
70
67
  - **Angular** - Components, services, decorators, modules
71
68
  - **Svelte** - Components, stores, reactive patterns
72
69
  - **Lit** - Web components, custom elements
73
- - **Vanilla JS/TS** - Any component or module patterns
70
+ - **Vanilla JS/TS** - Functions, classes, modules, event handlers
74
71
 
75
- ### **NPM Packages & Libraries**
72
+ ### **Fullstack Frameworks**
76
73
 
77
- - **TypeScript libraries** - Interfaces, types, utility functions
78
- - **JavaScript utilities** - Helper functions, class libraries
79
- - **Node.js modules** - CommonJS and ES modules
80
- - **Monorepo packages** - Lerna, Nx, Rush, Turborepo
74
+ - **Next.js** - Pages, API routes, middleware, components
75
+ - **Nuxt.js** - Pages, server routes, composables, components
81
76
 
82
- ### **Development Tools**
77
+ ### **Packages & Libraries**
83
78
 
84
- - **CLI applications** - Command-line tools and scripts
85
- - **Build tools** - Webpack plugins, Vite configurations
86
- - **Desktop applications** - Electron, Tauri apps
87
- - **Testing utilities** - Jest plugins, test helpers
79
+ - **TypeScript utilities** - Types, interfaces, enums, generic helpers
80
+ - **JavaScript helpers** - Functions, classes, utilities, data manipulation
81
+ - **Node.js modules** - Exports, imports, CommonJS/ESM patterns
82
+ - **Monorepo packages** - Shared utilities, cross-package dependencies
88
83
 
89
- ### **Fullstack Frameworks**
84
+ ### **Development Tools**
90
85
 
91
- - **Next.js** - Pages, API routes, middleware, components
92
- - **Nuxt.js** - Vue-based fullstack applications
93
- - **SvelteKit** - Svelte-based fullstack applications
94
- - **Remix** - React-based fullstack applications
86
+ - **CLI tools** - Commands, options, argument parsing
87
+ - **Build plugins** - Plugin functions, configuration handlers
88
+ - **Desktop apps** - Main processes, renderers, IPC handlers
89
+ - **Testing utilities** - Test functions, mocks, utilities, custom matchers
95
90
 
96
91
  ## Installation
97
92
 
@@ -105,11 +100,13 @@ npm install --save-dev parseme
105
100
 
106
101
  ```bash
107
102
  npx parseme init
103
+ # or use the alias
104
+ npx parseme i
108
105
  ```
109
106
 
110
107
  You'll be prompted for:
111
108
  - Context directory path (default: `parseme-context`)
112
- - Exclude patterns (default: `node_modules/**`, `.git/**` - patterns from `.gitignore` will be ignored by default as well)
109
+ - Exclude patterns (default: `node_modules/**`, `dist/**`, `.git/**` - in git repositories, additional patterns on top of git-tracked files)
113
110
 
114
111
  A minimal config file will be created with only your custom settings.
115
112
 
@@ -123,7 +120,7 @@ npm install --save-dev parseme
123
120
  ```json
124
121
  {
125
122
  "scripts": {
126
- "parseme": "parseme"
123
+ "parseme": "parseme generate"
127
124
  }
128
125
  }
129
126
  ```
@@ -132,7 +129,9 @@ npm install --save-dev parseme
132
129
  ```bash
133
130
  npm run parseme
134
131
  # or
135
- npx parseme
132
+ npx parseme generate
133
+ # or use the alias
134
+ npx parseme g
136
135
  ```
137
136
 
138
137
  This creates:
@@ -174,14 +173,12 @@ const config = {
174
173
  maxDepth: 10,
175
174
 
176
175
  // Git integration
177
- includeGitInfo: true,
176
+ includeGitInfo: true, // Include git repository information in context
177
+ useGitForFiles: true, // Use git to discover files (respects .gitignore)
178
178
 
179
- // AI-friendly size limits
179
+ // Size limits
180
180
  limits: {
181
- maxLinesPerFile: 1000,
182
- maxCharsPerFile: 50000,
183
- maxFilesPerContext: 20,
184
- truncateStrategy: 'truncate', // 'truncate' | 'split' | 'summarize'
181
+ maxFilesPerContext: 5000,
185
182
  },
186
183
 
187
184
  // Content sections (all default to true)
@@ -271,12 +268,13 @@ Configuration values are resolved in the following order (highest to lowest prio
271
268
 
272
269
  - `rootDir` - Project root directory (default: `process.cwd()`)
273
270
  - `analyzeFileTypes` - File extensions to analyze (default and supported: `['ts', 'tsx', 'js', 'jsx']`)
274
- - `excludePatterns` - Additional glob patterns to exclude on top of `.gitignore` patterns. Patterns from `.gitignore` are always included in exclusions, and `excludePatterns` adds to them.
271
+ - `excludePatterns` - Additional glob patterns to exclude files. In git repositories, only git-tracked files are analyzed (respecting all `.gitignore` files automatically). Use `excludePatterns` to exclude additional files beyond what git ignores.
275
272
  - `maxDepth` - Maximum directory depth to traverse (default: `10`)
276
273
 
277
274
  #### Git Integration
278
275
 
279
- - `includeGitInfo` - Include git repository information (default: `true`)
276
+ - `includeGitInfo` - Include git repository information in context files (default: `true`)
277
+ - `useGitForFiles` - Use git to discover files, respecting .gitignore (default: `true`)
280
278
 
281
279
  #### Content Sections
282
280
 
@@ -298,12 +296,7 @@ Toggle which sections to include in the output (all default to `true`):
298
296
 
299
297
  #### Size Limits
300
298
 
301
- AI-friendly size limits to prevent token overflow:
302
-
303
- - `limits.maxLinesPerFile` - Maximum lines per file (default: `1000`)
304
- - `limits.maxCharsPerFile` - Maximum characters per file (default: `50000`)
305
- - `limits.maxFilesPerContext` - Maximum files per context (default: `20`)
306
- - `limits.truncateStrategy` - Strategy: `"truncate"`, `"split"`, or `"summarize"` (default: `"truncate"`)
299
+ - `limits.maxFilesPerContext` - Maximum number of files to analyze (default: `5000`)
307
300
 
308
301
  ## Output Format
309
302
 
@@ -324,10 +317,12 @@ The context directory location can be customized via the `contextDir` configurat
324
317
 
325
318
  ```bash
326
319
  # Generate context (auto-detects config file)
327
- npx parseme
320
+ npx parseme generate
321
+ npx parseme g # alias
328
322
 
329
323
  # Initialize configuration (JSON by default)
330
324
  npx parseme init
325
+ npx parseme i # alias
331
326
 
332
327
  # Initialize with TypeScript format
333
328
  npx parseme init --format ts
@@ -336,7 +331,7 @@ npx parseme init --format ts
336
331
  npx parseme init --format js
337
332
 
338
333
  # Use custom config file
339
- npx parseme --config custom.config.js
334
+ npx parseme generate --config custom.config.js
340
335
 
341
336
  # If added to package.json scripts, use npm run
342
337
  npm run parseme
@@ -345,26 +340,36 @@ npm run parseme
345
340
  # Runs automatically after each commit
346
341
 
347
342
  # Override config with CLI flags
348
- npx parseme --output custom.md --context-dir docs/context --root ./src --no-git
343
+ npx parseme generate --output custom.md --context-dir docs/context --root ./src
344
+
345
+ # Disable git info generation (keeps git for file discovery)
346
+ npx parseme generate --no-git-info
347
+
348
+ # Disable git for file discovery (keeps git info generation)
349
+ npx parseme generate --no-git-files
350
+
351
+ # Disable both git info and git file discovery
352
+ npx parseme generate --no-git-info --no-git-files
349
353
 
350
354
  # Specify file types and exclude patterns
351
- npx parseme --file-types ts js --exclude "**/*.test.ts"
355
+ npx parseme generate --file-types ts js --exclude "**/*.test.ts"
352
356
  ```
353
357
 
354
358
  ### CLI Options
355
359
 
356
- #### Main Command (`parseme`)
360
+ #### Generate Command (`parseme generate` or `parseme g`)
357
361
 
358
362
  - `-c, --config <path>` - Config file path
359
363
  - `-o, --output <path>` - Output file path
360
364
  - `-r, --root <path>` - Root directory to analyze
361
365
  - `--context-dir <path>` - Context directory path (default: parseme-context)
362
366
  - `--file-types <types...>` - File types to analyze (e.g., ts tsx js jsx)
363
- - `--exclude <patterns...>` - Exclude patterns (glob)
364
- - `--no-git` - Disable git information
367
+ - `--exclude <patterns...>` - Additional exclude patterns (glob, in git repositories on top of git-tracked files)
368
+ - `--no-git-info` - Disable git info generation (keeps git for file discovery)
369
+ - `--no-git-files` - Disable git for file discovery (uses filesystem crawling instead)
365
370
  - `--max-depth <number>` - Maximum directory depth
366
371
 
367
- #### Init Command (`parseme init`)
372
+ #### Init Command (`parseme init` or `parseme i`)
368
373
 
369
374
  - `-f, --force` - Overwrite existing config
370
375
  - `--format <format>` - Config format: json, ts, or js (default: json)
@@ -374,7 +379,7 @@ npx parseme --file-types ts js --exclude "**/*.test.ts"
374
379
  When running `parseme init` interactively (TTY, not CI), you'll be prompted to configure:
375
380
 
376
381
  - **Context directory** - Where to store context files (default: `parseme-context`)
377
- - **Exclude patterns** - Comma-separated glob patterns (default: `node_modules/**`, `.git/**` - patterns from `.gitignore` will be ignored by default as well)
382
+ - **Exclude patterns** - Comma-separated glob patterns (default: `node_modules/**`, `dist/**`, `.git/**` - in git repositories, additional patterns on top of git-tracked files)
378
383
 
379
384
  After initialization, setup tips are displayed:
380
385
 
@@ -404,11 +409,6 @@ PARSEME automatically detects and provides specialized analysis for:
404
409
  - Plugin identification
405
410
  - Hook analysis
406
411
 
407
- ### Koa & Hapi
408
-
409
- - Route and middleware detection
410
- - Framework-specific patterns
411
-
412
412
  ## Programmatic API
413
413
 
414
414
  You can also use PARSEME programmatically:
@@ -425,16 +425,48 @@ await generator.generateToFile('./output/PARSEME.md');
425
425
 
426
426
  ## Git Hook Integration
427
427
 
428
- Keep your AI context automatically updated by adding parseme as a post-commit hook:
428
+ Keep your AI context automatically updated by integrating parseme with git hooks. The recommended setup uses three hooks to ensure context files always have git info locally but stay clean on remote:
429
+
430
+ ### Recommended Hook Setup
429
431
 
430
- ### Manual Setup
432
+ #### Manual Setup
431
433
 
432
434
  ```bash
433
- # Create and make executable
434
- echo '#!/bin/sh\npx parseme' > .git/hooks/post-commit
435
- chmod +x .git/hooks/post-commit
435
+ # 1. Post-commit: Generate context with git info after each commit
436
+ cat > .git/hooks/post-commit << 'EOF'
437
+ #!/bin/sh
438
+
439
+ npx parseme generate
440
+ EOF
441
+
442
+ # 2. Pre-push: Regenerate without git info and amend before pushing
443
+ cat > .git/hooks/pre-push << 'EOF'
444
+ #!/bin/sh
445
+
446
+ # Regenerate without git info for clean remote state
447
+ npx parseme generate --no-git-info
448
+
449
+ # Stage parseme files (parseme-context/ may be different if configured)
450
+ git add parseme-context/ PARSEME.md
451
+
452
+ # Amend the commit with updated parseme files
453
+ git commit --amend --no-edit --no-verify
454
+ EOF
455
+
456
+ # 3. Post-push: Restore git info locally after push completes
457
+ cat > .git/hooks/post-push << 'EOF'
458
+ #!/bin/sh
459
+
460
+ # Regenerate with git info for local development
461
+ npx parseme generate
462
+ EOF
463
+
464
+ # Make hooks executable
465
+ chmod +x .git/hooks/post-commit .git/hooks/pre-push .git/hooks/post-push
436
466
  ```
437
467
 
468
+ **Note:** If you've configured a custom `contextDir` (either in your config file or via the `--context-dir` CLI flag), update the `git add` path in the pre-push hook accordingly (e.g., `git add docs/context/ PARSEME.md`).
469
+
438
470
  ### Using Husky
439
471
 
440
472
  ```json
@@ -442,13 +474,25 @@ chmod +x .git/hooks/post-commit
442
474
  {
443
475
  "husky": {
444
476
  "hooks": {
445
- "post-commit": "npx parseme"
477
+ "post-commit": "npx parseme generate",
478
+ "pre-push": "npx parseme generate --no-git-info && git add parseme-context/ PARSEME.md && git commit --amend --no-edit --no-verify",
479
+ "post-push": "npx parseme generate"
446
480
  }
447
481
  }
448
482
  }
449
483
  ```
450
484
 
451
- This automatically regenerates your AI context files after every commit, ensuring they're always up-to-date!
485
+ **Note:** If using a custom `contextDir`, update the `git add` path to match your configuration.
486
+
487
+ ### How It Works
488
+
489
+ 1. **post-commit**: After you commit, parseme generates context files with git info (current branch, recent commits, git diff) for local development
490
+ 2. **pre-push**: Before pushing, parseme regenerates without git info (`--no-git-info` flag) and amends the commit to keep remote clean
491
+ 3. **post-push**: After push completes, parseme regenerates with git info again so your local working copy maintains full context
492
+
493
+ The `--no-verify` flag in pre-push prevents an infinite loop by skipping hook execution on the amend.
494
+
495
+ This automatically keeps your AI context files synchronized with your code while maintaining clean context on remote and detailed context locally!
452
496
 
453
497
  ## Requirements
454
498
 
package/dist/cli/cli.js CHANGED
@@ -1,16 +1,18 @@
1
1
  #!/usr/bin/env node
2
2
  import { join } from 'path';
3
3
  import { Command } from 'commander';
4
- import { prompt } from './prompt.js';
5
4
  import { ParsemeConfig } from '../core/config.js';
6
5
  import { ParsemeGenerator } from '../core/generator.js';
6
+ import { prompt } from '../utils/prompt.js';
7
7
  const program = new Command();
8
8
  async function promptForMissingConfig(config) {
9
9
  return { ...config };
10
10
  }
11
11
  program.name('parseme').description('AI Project Context Generator').version('0.1.0');
12
- // Main command - just run parseme
12
+ // Generate command
13
13
  program
14
+ .command('generate')
15
+ .alias('g')
14
16
  .description('Generate project context using config file')
15
17
  .option('-c, --config <path>', 'Config file path')
16
18
  .option('-o, --output <path>', 'Output file path')
@@ -18,7 +20,8 @@ program
18
20
  .option('--context-dir <path>', 'Context directory path (default: parseme-context)')
19
21
  .option('--file-types <types...>', 'File types to analyze (e.g., ts tsx js jsx)')
20
22
  .option('--exclude <patterns...>', 'Exclude patterns (glob)')
21
- .option('--no-git', 'Disable git information')
23
+ .option('--no-git-files', 'Disable git for file discovery')
24
+ .option('--no-git-info', 'Disable git info generation')
22
25
  .option('--max-depth <number>', 'Maximum directory depth', parseInt)
23
26
  .action(async (options) => {
24
27
  try {
@@ -29,7 +32,8 @@ program
29
32
  ...(options.contextDir && { contextDir: options.contextDir }),
30
33
  ...(options.fileTypes && { analyzeFileTypes: options.fileTypes }),
31
34
  ...(options.exclude && { excludePatterns: options.exclude }),
32
- ...(options.git === false && { includeGitInfo: false }),
35
+ ...(options.gitFiles === false && { useGitForFiles: false }),
36
+ ...(options.gitInfo === false && { includeGitInfo: false }),
33
37
  ...(options.maxDepth && { maxDepth: options.maxDepth }),
34
38
  };
35
39
  const configFromFile = await ParsemeConfig.fromFile(options.config, {
@@ -56,8 +60,10 @@ program
56
60
  process.exit(1);
57
61
  }
58
62
  });
63
+ // Init command
59
64
  program
60
65
  .command('init')
66
+ .alias('i')
61
67
  .description('Initialize parseme configuration')
62
68
  .option('-f, --force', 'Overwrite existing config')
63
69
  .option('--format <format>', 'Config format: json, ts, or js', 'json')
@@ -83,6 +89,10 @@ program
83
89
  }
84
90
  // Build config with only user-specified values
85
91
  const userConfig = {};
92
+ // Set defaults that would normally be prompted for
93
+ const defaultExcludePatterns = ['node_modules/**', 'dist/**', '.git/**'];
94
+ userConfig.contextDir = 'parseme-context';
95
+ userConfig.excludePatterns = defaultExcludePatterns;
86
96
  // Only prompt if interactive (TTY) and not in CI
87
97
  if (process.stdin.isTTY && !process.env.CI) {
88
98
  // Ask about context directory path
@@ -92,9 +102,8 @@ program
92
102
  defaultValue: 'parseme-context',
93
103
  });
94
104
  // Ask about exclude patterns
95
- const defaultExcludePatterns = ['node_modules/**', 'dist/**', '.git/**'];
96
105
  const excludePatternsAnswer = await prompt({
97
- message: 'Exclude patterns (comma-separated glob patterns, patterns from .gitignore will be ignored by default as well)',
106
+ message: 'Exclude patterns (comma-separated glob patterns - in git repositories, additional to git-tracked files)',
98
107
  defaultValue: defaultExcludePatterns.join(', '),
99
108
  });
100
109
  // Always set exclude patterns to what user entered (or defaults if they pressed enter)
@@ -109,8 +118,8 @@ program
109
118
  if (options.format === 'ts') {
110
119
  console.log('For TypeScript configs, ensure tsx or ts-node is available to load .ts files');
111
120
  }
112
- console.log('Tip: Add "parseme": "parseme" to your package.json scripts for easier manual execution or hook integration');
113
- console.log('Tip: Add parseme as a git hook to keep context auto-updated! See README for setup instructions.');
121
+ console.log('Tip: Add "parseme": "parseme generate" to your package.json scripts for easier manual execution or hook integration');
122
+ console.log('Tip: Add parseme as git hooks to keep context auto-updated! See README for recommended hook setup (post-commit, pre-push, post-push).');
114
123
  console.log('');
115
124
  console.log('Tip: Add this section to your README.md to help AI agents find the context:');
116
125
  console.log('');
@@ -125,31 +134,13 @@ program
125
134
  process.exit(1);
126
135
  }
127
136
  });
128
- // If no command and no args, run main action
137
+ // If no command provided, show error and available commands
129
138
  if (process.argv.length <= 2) {
130
- // Run the default action
131
- (async () => {
132
- try {
133
- const configFromFile = await ParsemeConfig.fromFile(undefined, {
134
- showWarnings: true,
135
- throwOnNotFound: true,
136
- });
137
- const interactiveConfig = await promptForMissingConfig(configFromFile.get());
138
- const config = new ParsemeConfig(interactiveConfig);
139
- const generator = new ParsemeGenerator(config.get());
140
- await generator.generateToFile();
141
- console.log('Context generated successfully');
142
- }
143
- catch (error) {
144
- if (error instanceof Error && error.message.includes('No configuration file found')) {
145
- console.error(error.message);
146
- process.exit(1);
147
- }
148
- console.error('Failed to generate context:', error);
149
- process.exit(1);
150
- }
151
- })();
152
- }
153
- else {
154
- program.parse();
139
+ console.error('No command specified.\n');
140
+ console.error('Available commands:');
141
+ console.error(' parseme generate (or parseme g) - Generate project context');
142
+ console.error(' parseme init (or parseme i) - Initialize parseme configuration');
143
+ console.error('\nUse "parseme --help" for more information');
144
+ process.exit(1);
155
145
  }
146
+ program.parse();
@@ -2,7 +2,7 @@ import type { ParsemeConfig } from '../config.js';
2
2
  import type { FileAnalysis } from '../types.js';
3
3
  export declare class ASTAnalyzer {
4
4
  private readonly config;
5
- private readonly ig;
5
+ private readonly fileCollector;
6
6
  private readonly patternDetector;
7
7
  constructor(config: ParsemeConfig);
8
8
  analyzeProject(rootDir: string): Promise<FileAnalysis[]>;
@@ -1,46 +1,32 @@
1
1
  import { readFile } from 'fs/promises';
2
- import { relative, extname } from 'path';
2
+ import { join, extname } from 'path';
3
3
  import { parse } from '@babel/parser';
4
4
  import traverse from '@babel/traverse';
5
5
  import * as t from '@babel/types';
6
- import { glob } from 'glob';
7
- import ignore from 'ignore';
8
6
  import { PatternDetector } from './pattern-detector.js';
7
+ import { FileCollector } from '../../utils/file-collector.js';
9
8
  export class ASTAnalyzer {
10
9
  config;
11
- ig;
10
+ fileCollector;
12
11
  patternDetector;
13
12
  constructor(config) {
14
13
  this.config = config;
15
- this.ig = ignore();
16
- const configData = this.config.get();
17
- this.ig.add(configData.excludePatterns || []);
14
+ this.fileCollector = new FileCollector(config);
18
15
  this.patternDetector = new PatternDetector();
19
16
  }
20
17
  async analyzeProject(rootDir) {
21
- const configData = this.config.get();
22
- const fileTypes = configData.analyzeFileTypes || ['ts', 'tsx', 'js', 'jsx'];
23
- const patterns = fileTypes.map((type) => `**/*.${type}`);
24
- const files = await glob(patterns, {
25
- cwd: rootDir,
26
- absolute: true,
27
- ignore: configData.excludePatterns,
28
- });
18
+ const result = await this.fileCollector.getCodeFiles(rootDir);
29
19
  const analyses = [];
30
- for (const file of files) {
31
- const relativePath = relative(rootDir, file);
32
- // Skip if ignored
33
- if (this.ig.ignores(relativePath)) {
34
- continue;
35
- }
20
+ for (const file of result.files) {
21
+ const filePath = join(rootDir, file);
36
22
  try {
37
- const analysis = await this.analyzeFile(file, relativePath);
23
+ const analysis = await this.analyzeFile(filePath, file);
38
24
  if (analysis) {
39
25
  analyses.push(analysis);
40
26
  }
41
27
  }
42
28
  catch (error) {
43
- console.warn(`Failed to analyze ${relativePath}:`, error);
29
+ console.warn(`Failed to analyze ${file}:`, error);
44
30
  // Continue with other files
45
31
  }
46
32
  }
@@ -1,9 +1,7 @@
1
1
  import type { ProjectInfo, FrameworkInfo } from '../types.js';
2
2
  export declare class FrameworkDetector {
3
- detect(projectInfo: ProjectInfo): Promise<FrameworkInfo>;
4
- private detectExpress;
5
- private detectFastify;
6
- private detectNestJS;
7
- private detectKoa;
8
- private detectHapi;
3
+ private readonly frameworks;
4
+ detect(projectInfo: ProjectInfo): Promise<FrameworkInfo[]>;
5
+ private shouldDetect;
6
+ private buildFrameworkInfo;
9
7
  }