@grafema/cli 0.3.17 → 0.3.20

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 +1 @@
1
- {"version":3,"file":"wtf.js","sourceRoot":"","sources":["../../src/commands/wtf.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"wtf.js","sourceRoot":"","sources":["../../src/commands/wtf.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Shared utilities for project initialization and quickstart.
3
+ *
4
+ * Used by both `grafema init` and `grafema analyze --quickstart`.
5
+ */
6
+ /** All file extensions supported by Grafema's analyzers. */
7
+ export declare const SUPPORTED_EXTENSIONS: string[];
8
+ /**
9
+ * Scan a project directory for supported file extensions.
10
+ * Returns a Map of extension → file count for detected extensions.
11
+ */
12
+ export declare function scanExtensions(projectPath: string): Map<string, number>;
13
+ /**
14
+ * Generate config YAML content.
15
+ *
16
+ * If `detectedExtensions` is provided and non-empty, only includes those extensions.
17
+ * Otherwise falls back to all supported extensions (same as `grafema init`).
18
+ */
19
+ export declare function generateSmartConfig(detectedExtensions?: Map<string, number>): string;
20
+ /**
21
+ * Write config file to .grafema/config.yaml, creating the directory if needed.
22
+ */
23
+ export declare function writeConfig(projectPath: string, configContent: string): void;
24
+ /**
25
+ * Add Grafema entries to .gitignore if it exists and doesn't already have them.
26
+ */
27
+ export declare function updateGitignore(projectPath: string): boolean;
28
+ /**
29
+ * Format detected extensions as a human-readable string.
30
+ * Groups by language and shows total file count per language.
31
+ *
32
+ * Example: "TypeScript (342 files), JavaScript (18 files), Python (5 files)"
33
+ */
34
+ export declare function formatDetected(detected: Map<string, number>): string;
35
+ //# sourceMappingURL=quickstart.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quickstart.d.ts","sourceRoot":"","sources":["../../src/utils/quickstart.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,4DAA4D;AAC5D,eAAO,MAAM,oBAAoB,UAmBhC,CAAC;AAaF;;;GAGG;AACH,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAoCvE;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,kBAAkB,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAoCpF;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,IAAI,CAM5E;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAa5D;AAiBD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAWpE"}
@@ -0,0 +1,175 @@
1
+ /**
2
+ * Shared utilities for project initialization and quickstart.
3
+ *
4
+ * Used by both `grafema init` and `grafema analyze --quickstart`.
5
+ */
6
+ import { join } from 'path';
7
+ import { existsSync, mkdirSync, writeFileSync, readFileSync, readdirSync } from 'fs';
8
+ import { stringify as stringifyYAML } from 'yaml';
9
+ import { GRAFEMA_VERSION, getSchemaVersion } from '@grafema/util';
10
+ /** All file extensions supported by Grafema's analyzers. */
11
+ export const SUPPORTED_EXTENSIONS = [
12
+ // JavaScript / TypeScript
13
+ 'js', 'jsx', 'mjs', 'cjs', 'ts', 'tsx',
14
+ // Rust
15
+ 'rs',
16
+ // Java / Kotlin
17
+ 'java', 'kt', 'kts',
18
+ // Python
19
+ 'py', 'pyi',
20
+ // Go
21
+ 'go',
22
+ // Haskell
23
+ 'hs',
24
+ // C / C++
25
+ 'c', 'h', 'cpp', 'hpp', 'cc', 'cxx', 'hxx', 'hh', 'inl', 'ipp', 'tpp', 'txx',
26
+ // Swift / Objective-C
27
+ 'swift', 'm', 'mm',
28
+ // BEAM (Elixir / Erlang)
29
+ 'ex', 'exs', 'erl', 'hrl',
30
+ ];
31
+ /** Directories to skip during project scanning. */
32
+ const SKIP_DIRS = new Set([
33
+ 'node_modules', 'dist', 'build', 'target', 'vendor',
34
+ '.git', '.grafema', 'coverage', '.next', '.nuxt',
35
+ '__pycache__', '.tox', '.venv',
36
+ ]);
37
+ const SUPPORTED_SET = new Set(SUPPORTED_EXTENSIONS);
38
+ const MAX_DEPTH = 10;
39
+ const MAX_FILES = 50_000;
40
+ /**
41
+ * Scan a project directory for supported file extensions.
42
+ * Returns a Map of extension → file count for detected extensions.
43
+ */
44
+ export function scanExtensions(projectPath) {
45
+ const counts = new Map();
46
+ let filesScanned = 0;
47
+ function walk(dir, depth) {
48
+ if (depth > MAX_DEPTH || filesScanned >= MAX_FILES)
49
+ return;
50
+ let entries;
51
+ try {
52
+ entries = readdirSync(dir, { withFileTypes: true });
53
+ }
54
+ catch {
55
+ return; // Permission denied or similar — skip
56
+ }
57
+ for (const entry of entries) {
58
+ if (filesScanned >= MAX_FILES)
59
+ return;
60
+ if (entry.isDirectory()) {
61
+ if (!SKIP_DIRS.has(entry.name) && !entry.name.startsWith('.')) {
62
+ walk(join(dir, entry.name), depth + 1);
63
+ }
64
+ }
65
+ else if (entry.isFile()) {
66
+ filesScanned++;
67
+ const dot = entry.name.lastIndexOf('.');
68
+ if (dot !== -1) {
69
+ const ext = entry.name.slice(dot + 1);
70
+ if (SUPPORTED_SET.has(ext)) {
71
+ counts.set(ext, (counts.get(ext) ?? 0) + 1);
72
+ }
73
+ }
74
+ }
75
+ }
76
+ }
77
+ walk(projectPath, 0);
78
+ return counts;
79
+ }
80
+ /**
81
+ * Generate config YAML content.
82
+ *
83
+ * If `detectedExtensions` is provided and non-empty, only includes those extensions.
84
+ * Otherwise falls back to all supported extensions (same as `grafema init`).
85
+ */
86
+ export function generateSmartConfig(detectedExtensions) {
87
+ const exts = (detectedExtensions && detectedExtensions.size > 0)
88
+ ? [...detectedExtensions.keys()]
89
+ : SUPPORTED_EXTENSIONS;
90
+ const extensions = `*.{${exts.join(',')}}`;
91
+ const config = {
92
+ version: getSchemaVersion(GRAFEMA_VERSION),
93
+ root: '..',
94
+ include: [`**/${extensions}`],
95
+ exclude: [
96
+ '**/*.test.*',
97
+ '**/__tests__/**',
98
+ '**/node_modules/**',
99
+ '**/dist/**',
100
+ '**/build/**',
101
+ '**/target/**',
102
+ '**/vendor/**',
103
+ '**/.git/**',
104
+ ],
105
+ };
106
+ const yaml = stringifyYAML(config, {
107
+ lineWidth: 0,
108
+ });
109
+ return `# Grafema Configuration
110
+ # Documentation: https://github.com/grafema/grafema#configuration
111
+ # Supported: JS/TS, Rust, Java, Kotlin, Python, Go, Haskell, C/C++, Swift, Elixir/Erlang
112
+
113
+ ${yaml}
114
+ # services: # Explicit service definitions (overrides auto-discovery)
115
+ # - name: "api"
116
+ # path: "."
117
+ # entryPoint: "src/index.ts"
118
+ `;
119
+ }
120
+ /**
121
+ * Write config file to .grafema/config.yaml, creating the directory if needed.
122
+ */
123
+ export function writeConfig(projectPath, configContent) {
124
+ const grafemaDir = join(projectPath, '.grafema');
125
+ if (!existsSync(grafemaDir)) {
126
+ mkdirSync(grafemaDir, { recursive: true });
127
+ }
128
+ writeFileSync(join(grafemaDir, 'config.yaml'), configContent);
129
+ }
130
+ /**
131
+ * Add Grafema entries to .gitignore if it exists and doesn't already have them.
132
+ */
133
+ export function updateGitignore(projectPath) {
134
+ const gitignorePath = join(projectPath, '.gitignore');
135
+ if (existsSync(gitignorePath)) {
136
+ const gitignore = readFileSync(gitignorePath, 'utf-8');
137
+ if (!gitignore.includes('.grafema/graph.rfdb')) {
138
+ writeFileSync(gitignorePath, gitignore + '\n# Grafema\n.grafema/graph.rfdb\n.grafema/rfdb.sock\n');
139
+ return true;
140
+ }
141
+ }
142
+ return false;
143
+ }
144
+ /** Map of extension to human-readable language name. */
145
+ const EXT_LANGUAGE = {
146
+ js: 'JavaScript', jsx: 'JavaScript', mjs: 'JavaScript', cjs: 'JavaScript',
147
+ ts: 'TypeScript', tsx: 'TypeScript',
148
+ rs: 'Rust',
149
+ java: 'Java', kt: 'Kotlin', kts: 'Kotlin',
150
+ py: 'Python', pyi: 'Python',
151
+ go: 'Go',
152
+ hs: 'Haskell',
153
+ c: 'C', h: 'C/C++', cpp: 'C++', hpp: 'C++', cc: 'C++', cxx: 'C++', hxx: 'C++', hh: 'C++',
154
+ inl: 'C++', ipp: 'C++', tpp: 'C++', txx: 'C++',
155
+ swift: 'Swift', m: 'Objective-C', mm: 'Objective-C++',
156
+ ex: 'Elixir', exs: 'Elixir', erl: 'Erlang', hrl: 'Erlang',
157
+ };
158
+ /**
159
+ * Format detected extensions as a human-readable string.
160
+ * Groups by language and shows total file count per language.
161
+ *
162
+ * Example: "TypeScript (342 files), JavaScript (18 files), Python (5 files)"
163
+ */
164
+ export function formatDetected(detected) {
165
+ // Group counts by language
166
+ const langCounts = new Map();
167
+ for (const [ext, count] of detected) {
168
+ const lang = EXT_LANGUAGE[ext] ?? ext;
169
+ langCounts.set(lang, (langCounts.get(lang) ?? 0) + count);
170
+ }
171
+ // Sort by count descending
172
+ const sorted = [...langCounts.entries()].sort((a, b) => b[1] - a[1]);
173
+ return sorted.map(([lang, count]) => `${lang} (${count} files)`).join(', ');
174
+ }
175
+ //# sourceMappingURL=quickstart.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quickstart.js","sourceRoot":"","sources":["../../src/utils/quickstart.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@grafema/cli",
3
- "version": "0.3.17",
3
+ "version": "0.3.20",
4
4
  "description": "CLI for Grafema code analysis toolkit",
5
5
  "type": "module",
6
6
  "main": "./dist/cli.js",
@@ -35,9 +35,9 @@
35
35
  "dependencies": {
36
36
  "commander": "^13.0.0",
37
37
  "yaml": "^2.8.2",
38
- "@grafema/api": "0.3.17",
39
- "@grafema/util": "0.3.17",
40
- "@grafema/types": "0.3.17"
38
+ "@grafema/api": "0.3.20",
39
+ "@grafema/util": "0.3.20",
40
+ "@grafema/types": "0.3.20"
41
41
  },
42
42
  "optionalDependencies": {
43
43
  "@grafema/grafema-darwin-arm64": "0.3.16",
package/src/cli.ts CHANGED
@@ -33,6 +33,7 @@ import { explainCommand } from './commands/explain.js';
33
33
  import { fileCommand } from './commands/file.js';
34
34
  import { setupSkillCommand } from './commands/setup-skill.js';
35
35
  import { gitIngestCommand } from './commands/git-ingest.js';
36
+ import { registryCommand } from './commands/registry.js';
36
37
 
37
38
  // Read version from package.json
38
39
  const __dirname = dirname(fileURLToPath(import.meta.url));
@@ -74,5 +75,6 @@ program.addCommand(explainCommand);
74
75
  program.addCommand(fileCommand);
75
76
  program.addCommand(setupSkillCommand);
76
77
  program.addCommand(gitIngestCommand);
78
+ program.addCommand(registryCommand);
77
79
 
78
80
  program.parse();
@@ -21,6 +21,7 @@ export const analyzeCommand = new Command('analyze')
21
21
  .option('--log-file <path>', 'Write all log output to a file')
22
22
  .option('--strict', 'Enable strict mode (fail on unresolved references)')
23
23
  .option('--no-auto-start', 'Do not auto-start RFDB server (require manual start)')
24
+ .option('--quickstart', 'Auto-initialize if no config exists (scan project, generate config)')
24
25
  .addHelpText('after', `
25
26
  Examples:
26
27
  grafema analyze Analyze current project
@@ -32,5 +33,6 @@ Examples:
32
33
  grafema analyze --log-file out.log Write all logs to a file
33
34
  grafema analyze --strict Fail on unresolved references (debugging)
34
35
  grafema analyze --no-auto-start Require manual server start
36
+ grafema analyze --quickstart Auto-init and analyze (no grafema init needed)
35
37
  `)
36
38
  .action(analyzeAction);
@@ -19,8 +19,10 @@ import {
19
19
  findAnalyzerBinary,
20
20
  ensureBinary,
21
21
  ManifestGenerator,
22
+ ManifestResolver,
22
23
  } from '@grafema/util';
23
24
  import type { LogLevel } from '@grafema/util';
25
+ import { scanExtensions, generateSmartConfig, writeConfig, updateGitignore, formatDetected } from '../utils/quickstart.js';
24
26
 
25
27
  export interface NodeEdgeCountBackend {
26
28
  nodeCount: () => Promise<number>;
@@ -148,7 +150,7 @@ async function ensureLanguageBinaries(configPath: string, log: (...args: unknown
148
150
  }
149
151
  }
150
152
 
151
- export async function analyzeAction(path: string, options: { service?: string; entrypoint?: string; clear?: boolean; quiet?: boolean; verbose?: boolean; debug?: boolean; logLevel?: string; logFile?: string; strict?: boolean; autoStart?: boolean }): Promise<void> {
153
+ export async function analyzeAction(path: string, options: { service?: string; entrypoint?: string; clear?: boolean; quiet?: boolean; verbose?: boolean; debug?: boolean; logLevel?: string; logFile?: string; strict?: boolean; autoStart?: boolean; quickstart?: boolean }): Promise<void> {
152
154
  const projectPath = resolve(path);
153
155
  const grafemaDir = join(projectPath, '.grafema');
154
156
  const dbPath = join(grafemaDir, 'graph.rfdb');
@@ -191,7 +193,24 @@ export async function analyzeAction(path: string, options: { service?: string; e
191
193
  debug(`Using orchestrator: ${orchestratorBinary}`);
192
194
 
193
195
  // Find config file for the orchestrator
194
- const configPath = findConfigFile(projectPath);
196
+ let configPath = findConfigFile(projectPath);
197
+ if (!configPath && options.quickstart) {
198
+ // Quickstart: auto-generate config by scanning the project
199
+ const detected = scanExtensions(projectPath);
200
+ const configContent = generateSmartConfig(detected);
201
+ writeConfig(projectPath, configContent);
202
+ updateGitignore(projectPath);
203
+
204
+ if (detected.size > 0) {
205
+ info(`Quickstart: detected ${formatDetected(detected)}`);
206
+ } else {
207
+ info('Quickstart: no supported files detected, using all extensions');
208
+ }
209
+ info('Created .grafema/config.yaml');
210
+ info('');
211
+
212
+ configPath = findConfigFile(projectPath);
213
+ }
195
214
  if (!configPath) {
196
215
  console.error('');
197
216
  console.error('No grafema config file found.');
@@ -200,7 +219,7 @@ export async function analyzeAction(path: string, options: { service?: string; e
200
219
  console.error(` ${join(projectPath, 'grafema.config.yaml')}`);
201
220
  console.error(` ${join(projectPath, '.grafema', 'config.yaml')}`);
202
221
  console.error('');
203
- console.error('Create a config file with at least:');
222
+ console.error('Run with --quickstart to auto-generate, or create manually:');
204
223
  console.error(' root: "."');
205
224
  console.error(' include:');
206
225
  console.error(' - "**/*.js"');
@@ -300,6 +319,20 @@ export async function analyzeAction(path: string, options: { service?: string; e
300
319
  } catch (err) {
301
320
  debug(`Manifest generation skipped: ${err instanceof Error ? err.message : String(err)}`);
302
321
  }
322
+
323
+ // Auto-load registry manifests for cross-package resolution
324
+ const registryDir = join(projectPath, 'registry');
325
+ if (existsSync(registryDir)) {
326
+ try {
327
+ const resolver = new ManifestResolver();
328
+ const loaded = resolver.loadFromRegistry(registryDir);
329
+ if (loaded > 0) {
330
+ info(` Registry: ${loaded} package manifests loaded`);
331
+ }
332
+ } catch (err) {
333
+ debug(`Registry loading skipped: ${err instanceof Error ? err.message : String(err)}`);
334
+ }
335
+ }
303
336
  } else {
304
337
  console.error('');
305
338
  console.error(`Analysis failed with exit code ${exitCode}`);
@@ -4,77 +4,15 @@
4
4
 
5
5
  import { Command } from 'commander';
6
6
  import { resolve, join } from 'path';
7
- import { existsSync, mkdirSync, writeFileSync, readFileSync } from 'fs';
7
+ import { existsSync } from 'fs';
8
8
  import { spawn } from 'child_process';
9
9
  import { createInterface } from 'readline';
10
10
  import { fileURLToPath } from 'url';
11
- import { stringify as stringifyYAML } from 'yaml';
12
- import { GRAFEMA_VERSION, getSchemaVersion } from '@grafema/util';
13
11
  import { installSkill } from './setup-skill.js';
12
+ import { generateSmartConfig, writeConfig, updateGitignore } from '../utils/quickstart.js';
14
13
 
15
14
  const __dirname = fileURLToPath(new URL('.', import.meta.url));
16
15
 
17
- /** All file extensions supported by Grafema's analyzers. */
18
- const SUPPORTED_EXTENSIONS = [
19
- // JavaScript / TypeScript
20
- 'js', 'jsx', 'mjs', 'cjs', 'ts', 'tsx',
21
- // Rust
22
- 'rs',
23
- // Java / Kotlin
24
- 'java', 'kt', 'kts',
25
- // Python
26
- 'py', 'pyi',
27
- // Go
28
- 'go',
29
- // Haskell
30
- 'hs',
31
- // C / C++
32
- 'c', 'h', 'cpp', 'hpp', 'cc', 'cxx', 'hxx', 'hh', 'inl', 'ipp', 'tpp', 'txx',
33
- // Swift / Objective-C
34
- 'swift', 'm', 'mm',
35
- // BEAM (Elixir / Erlang)
36
- 'ex', 'exs', 'erl', 'hrl',
37
- ];
38
-
39
- /**
40
- * Generate config.yaml content.
41
- * Minimal config — the Rust orchestrator has its own built-in analysis pipeline.
42
- * Includes all supported extensions; orchestrator skips languages with no matching files.
43
- */
44
- function generateConfigYAML(): string {
45
- const extensions = `*.{${SUPPORTED_EXTENSIONS.join(',')}}`;
46
- const config = {
47
- version: getSchemaVersion(GRAFEMA_VERSION),
48
- root: '..',
49
- include: [`**/${extensions}`],
50
- exclude: [
51
- '**/*.test.*',
52
- '**/__tests__/**',
53
- '**/node_modules/**',
54
- '**/dist/**',
55
- '**/build/**',
56
- '**/target/**',
57
- '**/vendor/**',
58
- '**/.git/**',
59
- ],
60
- };
61
-
62
- const yaml = stringifyYAML(config, {
63
- lineWidth: 0,
64
- });
65
-
66
- return `# Grafema Configuration
67
- # Documentation: https://github.com/grafema/grafema#configuration
68
- # Supported: JS/TS, Rust, Java, Kotlin, Python, Go, Haskell, C/C++, Swift, Elixir/Erlang
69
-
70
- ${yaml}
71
- # services: # Explicit service definitions (overrides auto-discovery)
72
- # - name: "api"
73
- # path: "."
74
- # entryPoint: "src/index.ts"
75
- `;
76
- }
77
-
78
16
  /**
79
17
  * Ask user a yes/no question. Returns true for yes (default), false for no.
80
18
  */
@@ -187,27 +125,14 @@ Examples:
187
125
  return;
188
126
  }
189
127
 
190
- // Create .grafema directory
191
- if (!existsSync(grafemaDir)) {
192
- mkdirSync(grafemaDir, { recursive: true });
193
- }
194
-
195
- // Write config
196
- const configContent = generateConfigYAML();
197
- writeFileSync(configPath, configContent);
128
+ // Write config (generateSmartConfig with no args = all extensions, same as before)
129
+ const configContent = generateSmartConfig();
130
+ writeConfig(projectPath, configContent);
198
131
  console.log('✓ Created .grafema/config.yaml');
199
132
 
200
133
  // Add to .gitignore if exists
201
- const gitignorePath = join(projectPath, '.gitignore');
202
- if (existsSync(gitignorePath)) {
203
- const gitignore = readFileSync(gitignorePath, 'utf-8');
204
- if (!gitignore.includes('.grafema/graph.rfdb')) {
205
- writeFileSync(
206
- gitignorePath,
207
- gitignore + '\n# Grafema\n.grafema/graph.rfdb\n.grafema/rfdb.sock\n'
208
- );
209
- console.log('✓ Updated .gitignore');
210
- }
134
+ if (updateGitignore(projectPath)) {
135
+ console.log('✓ Updated .gitignore');
211
136
  }
212
137
 
213
138
  // Auto-install Agent Skill for AI-assisted development
@@ -0,0 +1,138 @@
1
+ /**
2
+ * Registry command — build and manage the local manifest registry.
3
+ *
4
+ * grafema registry build [--packages <names>] [--all] [--force] [--verbose]
5
+ * grafema registry list
6
+ * grafema registry status
7
+ */
8
+
9
+ import { Command } from 'commander';
10
+ import { resolve, join } from 'path';
11
+ import { existsSync, readFileSync } from 'fs';
12
+ import { parse as parseYaml } from 'yaml';
13
+ import { RegistryBuilder } from '@grafema/util';
14
+ import type { RegistryIndex } from '@grafema/util';
15
+
16
+ function getRegistryDir(path: string): string {
17
+ return join(resolve(path), 'registry');
18
+ }
19
+
20
+ const buildCommand = new Command('build')
21
+ .description('Build manifest registry for npm dependencies')
22
+ .argument('[path]', 'Project path', '.')
23
+ .option('-p, --packages <names>', 'Comma-separated package names to build')
24
+ .option('-a, --all', 'Build all discovered dependencies')
25
+ .option('-f, --force', 'Rebuild even if manifest exists')
26
+ .option('-v, --verbose', 'Show detailed output')
27
+ .option('--skip <names>', 'Comma-separated package names to skip')
28
+ .option('--timeout <ms>', 'Max per-package timeout in ms (adaptive by default)', '600000')
29
+ .option('--max-files <count>', 'Skip packages exceeding this file count', '5000')
30
+ .action(async (path: string, options: {
31
+ packages?: string;
32
+ all?: boolean;
33
+ force?: boolean;
34
+ verbose?: boolean;
35
+ skip?: string;
36
+ timeout?: string;
37
+ maxFiles?: string;
38
+ }) => {
39
+ const projectPath = resolve(path);
40
+ const registryDir = getRegistryDir(path);
41
+
42
+ const builder = new RegistryBuilder({
43
+ projectPath,
44
+ registryDir,
45
+ force: options.force,
46
+ verbose: options.verbose,
47
+ skip: options.skip?.split(',').map(s => s.trim()) ?? [],
48
+ timeout: parseInt(options.timeout ?? '120000', 10),
49
+ maxFiles: parseInt(options.maxFiles ?? '5000', 10),
50
+ });
51
+
52
+ if (options.packages) {
53
+ const names = options.packages.split(',').map(s => s.trim());
54
+ await builder.buildPackages(names);
55
+ } else if (options.all) {
56
+ await builder.buildAll();
57
+ } else {
58
+ console.error('Specify --packages <names> or --all');
59
+ process.exit(1);
60
+ }
61
+
62
+ // Write index and print summary
63
+ const indexPath = builder.writeIndex();
64
+ builder.printSummary();
65
+ console.log(`\nIndex: ${indexPath}`);
66
+ });
67
+
68
+ const listCommand = new Command('list')
69
+ .description('List packages in the local registry')
70
+ .argument('[path]', 'Project path', '.')
71
+ .action((path: string) => {
72
+ const registryDir = getRegistryDir(path);
73
+ const indexPath = join(registryDir, 'index.yaml');
74
+
75
+ if (!existsSync(indexPath)) {
76
+ console.log('No registry found. Run `grafema registry build --all` first.');
77
+ return;
78
+ }
79
+
80
+ const index = parseYaml(readFileSync(indexPath, 'utf-8')) as RegistryIndex;
81
+ if (!index?.entries?.length) {
82
+ console.log('Registry is empty.');
83
+ return;
84
+ }
85
+
86
+ console.log(`Registry: ${index.entries.length} packages (analyzer ${index.analyzer_version})\n`);
87
+
88
+ const nameWidth = Math.max(...index.entries.map(e => e.name.length), 7);
89
+ console.log(`${'Package'.padEnd(nameWidth)} Version Exports Confidence Source`);
90
+ console.log(`${'─'.repeat(nameWidth)} ────────── ─────── ────────── ──────`);
91
+
92
+ for (const entry of index.entries) {
93
+ console.log(
94
+ `${entry.name.padEnd(nameWidth)} ${entry.version.padEnd(10)} ${String(entry.total_exports).padStart(7)} ${entry.confidence.toFixed(2).padStart(10)} ${entry.source_type}`,
95
+ );
96
+ }
97
+ });
98
+
99
+ const statusCommand = new Command('status')
100
+ .description('Show registry build status vs installed dependencies')
101
+ .argument('[path]', 'Project path', '.')
102
+ .action((path: string) => {
103
+ const projectPath = resolve(path);
104
+ const registryDir = getRegistryDir(path);
105
+
106
+ const builder = new RegistryBuilder({ projectPath, registryDir });
107
+ const deps = builder.discoverDependencies();
108
+
109
+ const indexPath = join(registryDir, 'index.yaml');
110
+ const builtNames = new Set<string>();
111
+ if (existsSync(indexPath)) {
112
+ const index = parseYaml(readFileSync(indexPath, 'utf-8')) as RegistryIndex;
113
+ if (index?.entries) {
114
+ for (const e of index.entries) builtNames.add(e.name);
115
+ }
116
+ }
117
+
118
+ const built = deps.filter(d => builtNames.has(d));
119
+ const missing = deps.filter(d => !builtNames.has(d));
120
+
121
+ console.log(`Dependencies: ${deps.length} total, ${built.length} in registry, ${missing.length} missing\n`);
122
+
123
+ if (missing.length > 0) {
124
+ console.log('Missing from registry:');
125
+ for (const name of missing) {
126
+ console.log(` ${name}`);
127
+ }
128
+ console.log(`\nRun: grafema registry build --packages ${missing.join(',')}`);
129
+ } else {
130
+ console.log('All dependencies have manifests in the registry.');
131
+ }
132
+ });
133
+
134
+ export const registryCommand = new Command('registry')
135
+ .description('Manage local manifest registry for npm dependencies')
136
+ .addCommand(buildCommand)
137
+ .addCommand(listCommand)
138
+ .addCommand(statusCommand);
@@ -156,6 +156,7 @@ Examples:
156
156
 
157
157
  const narrative = renderTraceNarrative(results, variable.name || variable.id, {
158
158
  detail: options.detail || 'normal',
159
+ hintStyle: 'cli',
159
160
  });
160
161
  console.log(narrative);
161
162
 
@@ -23,6 +23,7 @@ import { Spinner } from '../utils/spinner.js';
23
23
  interface WtfCommandOptions {
24
24
  project: string;
25
25
  depth: string;
26
+ detail: 'summary' | 'normal' | 'full';
26
27
  json?: boolean;
27
28
  }
28
29
 
@@ -31,12 +32,14 @@ export const wtfCommand = new Command('wtf')
31
32
  .argument('<symbol>', 'Variable, constant, or parameter name to trace')
32
33
  .option('-p, --project <path>', 'Project path', '.')
33
34
  .option('-d, --depth <n>', 'Max trace depth', '10')
35
+ .option('--detail <level>', 'Level of detail: summary, normal (default), full', 'normal')
34
36
  .option('-j, --json', 'Output as JSON')
35
37
  .addHelpText('after', `
36
38
  Examples:
37
39
  grafema wtf req.user Trace where req.user comes from
38
40
  grafema wtf config.apiKey Where does this value originate?
39
41
  grafema wtf userId --depth 5 Limit trace depth
42
+ grafema wtf token --detail full Show complete chain (no compression)
40
43
  grafema wtf token --json Output as JSON
41
44
  `)
42
45
  .action(async (symbol: string, options: WtfCommandOptions) => {
@@ -130,7 +133,7 @@ Examples:
130
133
  } else {
131
134
  console.log(`${found.name} (${found.type}) — ${found.file}${found.line ? ':' + found.line : ''}`);
132
135
  console.log('');
133
- const narrative = renderTraceNarrative(results, found.name, { detail: 'normal' });
136
+ const narrative = renderTraceNarrative(results, found.name, { detail: options.detail || 'normal', hintStyle: 'cli' });
134
137
  console.log(narrative);
135
138
  }
136
139
  } finally {