spec-gen-cli 1.0.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.
- package/LICENSE +21 -0
- package/README.md +1078 -0
- package/dist/api/analyze.d.ts +17 -0
- package/dist/api/analyze.d.ts.map +1 -0
- package/dist/api/analyze.js +109 -0
- package/dist/api/analyze.js.map +1 -0
- package/dist/api/drift.d.ts +21 -0
- package/dist/api/drift.d.ts.map +1 -0
- package/dist/api/drift.js +145 -0
- package/dist/api/drift.js.map +1 -0
- package/dist/api/generate.d.ts +18 -0
- package/dist/api/generate.d.ts.map +1 -0
- package/dist/api/generate.js +251 -0
- package/dist/api/generate.js.map +1 -0
- package/dist/api/index.d.ts +39 -0
- package/dist/api/index.d.ts.map +1 -0
- package/dist/api/index.js +32 -0
- package/dist/api/index.js.map +1 -0
- package/dist/api/init.d.ts +18 -0
- package/dist/api/init.d.ts.map +1 -0
- package/dist/api/init.js +82 -0
- package/dist/api/init.js.map +1 -0
- package/dist/api/run.d.ts +19 -0
- package/dist/api/run.d.ts.map +1 -0
- package/dist/api/run.js +291 -0
- package/dist/api/run.js.map +1 -0
- package/dist/api/specs.d.ts +49 -0
- package/dist/api/specs.d.ts.map +1 -0
- package/dist/api/specs.js +136 -0
- package/dist/api/specs.js.map +1 -0
- package/dist/api/types.d.ts +176 -0
- package/dist/api/types.d.ts.map +1 -0
- package/dist/api/types.js +9 -0
- package/dist/api/types.js.map +1 -0
- package/dist/api/verify.d.ts +20 -0
- package/dist/api/verify.d.ts.map +1 -0
- package/dist/api/verify.js +117 -0
- package/dist/api/verify.js.map +1 -0
- package/dist/cli/commands/analyze.d.ts +27 -0
- package/dist/cli/commands/analyze.d.ts.map +1 -0
- package/dist/cli/commands/analyze.js +485 -0
- package/dist/cli/commands/analyze.js.map +1 -0
- package/dist/cli/commands/drift.d.ts +9 -0
- package/dist/cli/commands/drift.d.ts.map +1 -0
- package/dist/cli/commands/drift.js +540 -0
- package/dist/cli/commands/drift.js.map +1 -0
- package/dist/cli/commands/generate.d.ts +9 -0
- package/dist/cli/commands/generate.d.ts.map +1 -0
- package/dist/cli/commands/generate.js +633 -0
- package/dist/cli/commands/generate.js.map +1 -0
- package/dist/cli/commands/init.d.ts +9 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +171 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/mcp.d.ts +638 -0
- package/dist/cli/commands/mcp.d.ts.map +1 -0
- package/dist/cli/commands/mcp.js +574 -0
- package/dist/cli/commands/mcp.js.map +1 -0
- package/dist/cli/commands/run.d.ts +24 -0
- package/dist/cli/commands/run.d.ts.map +1 -0
- package/dist/cli/commands/run.js +546 -0
- package/dist/cli/commands/run.js.map +1 -0
- package/dist/cli/commands/verify.d.ts +9 -0
- package/dist/cli/commands/verify.d.ts.map +1 -0
- package/dist/cli/commands/verify.js +417 -0
- package/dist/cli/commands/verify.js.map +1 -0
- package/dist/cli/commands/view.d.ts +9 -0
- package/dist/cli/commands/view.d.ts.map +1 -0
- package/dist/cli/commands/view.js +511 -0
- package/dist/cli/commands/view.js.map +1 -0
- package/dist/cli/index.d.ts +9 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +83 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/core/analyzer/architecture-writer.d.ts +67 -0
- package/dist/core/analyzer/architecture-writer.d.ts.map +1 -0
- package/dist/core/analyzer/architecture-writer.js +209 -0
- package/dist/core/analyzer/architecture-writer.js.map +1 -0
- package/dist/core/analyzer/artifact-generator.d.ts +222 -0
- package/dist/core/analyzer/artifact-generator.d.ts.map +1 -0
- package/dist/core/analyzer/artifact-generator.js +726 -0
- package/dist/core/analyzer/artifact-generator.js.map +1 -0
- package/dist/core/analyzer/call-graph.d.ts +83 -0
- package/dist/core/analyzer/call-graph.d.ts.map +1 -0
- package/dist/core/analyzer/call-graph.js +827 -0
- package/dist/core/analyzer/call-graph.js.map +1 -0
- package/dist/core/analyzer/code-shaper.d.ts +33 -0
- package/dist/core/analyzer/code-shaper.d.ts.map +1 -0
- package/dist/core/analyzer/code-shaper.js +149 -0
- package/dist/core/analyzer/code-shaper.js.map +1 -0
- package/dist/core/analyzer/dependency-graph.d.ts +179 -0
- package/dist/core/analyzer/dependency-graph.d.ts.map +1 -0
- package/dist/core/analyzer/dependency-graph.js +574 -0
- package/dist/core/analyzer/dependency-graph.js.map +1 -0
- package/dist/core/analyzer/duplicate-detector.d.ts +52 -0
- package/dist/core/analyzer/duplicate-detector.d.ts.map +1 -0
- package/dist/core/analyzer/duplicate-detector.js +279 -0
- package/dist/core/analyzer/duplicate-detector.js.map +1 -0
- package/dist/core/analyzer/embedding-service.d.ts +50 -0
- package/dist/core/analyzer/embedding-service.d.ts.map +1 -0
- package/dist/core/analyzer/embedding-service.js +104 -0
- package/dist/core/analyzer/embedding-service.js.map +1 -0
- package/dist/core/analyzer/file-walker.d.ts +78 -0
- package/dist/core/analyzer/file-walker.d.ts.map +1 -0
- package/dist/core/analyzer/file-walker.js +531 -0
- package/dist/core/analyzer/file-walker.js.map +1 -0
- package/dist/core/analyzer/import-parser.d.ts +91 -0
- package/dist/core/analyzer/import-parser.d.ts.map +1 -0
- package/dist/core/analyzer/import-parser.js +720 -0
- package/dist/core/analyzer/import-parser.js.map +1 -0
- package/dist/core/analyzer/index.d.ts +10 -0
- package/dist/core/analyzer/index.d.ts.map +1 -0
- package/dist/core/analyzer/index.js +10 -0
- package/dist/core/analyzer/index.js.map +1 -0
- package/dist/core/analyzer/refactor-analyzer.d.ts +80 -0
- package/dist/core/analyzer/refactor-analyzer.d.ts.map +1 -0
- package/dist/core/analyzer/refactor-analyzer.js +339 -0
- package/dist/core/analyzer/refactor-analyzer.js.map +1 -0
- package/dist/core/analyzer/repository-mapper.d.ts +150 -0
- package/dist/core/analyzer/repository-mapper.d.ts.map +1 -0
- package/dist/core/analyzer/repository-mapper.js +731 -0
- package/dist/core/analyzer/repository-mapper.js.map +1 -0
- package/dist/core/analyzer/signature-extractor.d.ts +31 -0
- package/dist/core/analyzer/signature-extractor.d.ts.map +1 -0
- package/dist/core/analyzer/signature-extractor.js +387 -0
- package/dist/core/analyzer/signature-extractor.js.map +1 -0
- package/dist/core/analyzer/significance-scorer.d.ts +79 -0
- package/dist/core/analyzer/significance-scorer.d.ts.map +1 -0
- package/dist/core/analyzer/significance-scorer.js +407 -0
- package/dist/core/analyzer/significance-scorer.js.map +1 -0
- package/dist/core/analyzer/subgraph-extractor.d.ts +43 -0
- package/dist/core/analyzer/subgraph-extractor.d.ts.map +1 -0
- package/dist/core/analyzer/subgraph-extractor.js +129 -0
- package/dist/core/analyzer/subgraph-extractor.js.map +1 -0
- package/dist/core/analyzer/vector-index.d.ts +63 -0
- package/dist/core/analyzer/vector-index.d.ts.map +1 -0
- package/dist/core/analyzer/vector-index.js +169 -0
- package/dist/core/analyzer/vector-index.js.map +1 -0
- package/dist/core/drift/drift-detector.d.ts +102 -0
- package/dist/core/drift/drift-detector.d.ts.map +1 -0
- package/dist/core/drift/drift-detector.js +597 -0
- package/dist/core/drift/drift-detector.js.map +1 -0
- package/dist/core/drift/git-diff.d.ts +55 -0
- package/dist/core/drift/git-diff.d.ts.map +1 -0
- package/dist/core/drift/git-diff.js +356 -0
- package/dist/core/drift/git-diff.js.map +1 -0
- package/dist/core/drift/index.d.ts +12 -0
- package/dist/core/drift/index.d.ts.map +1 -0
- package/dist/core/drift/index.js +9 -0
- package/dist/core/drift/index.js.map +1 -0
- package/dist/core/drift/spec-mapper.d.ts +73 -0
- package/dist/core/drift/spec-mapper.d.ts.map +1 -0
- package/dist/core/drift/spec-mapper.js +353 -0
- package/dist/core/drift/spec-mapper.js.map +1 -0
- package/dist/core/generator/adr-generator.d.ts +32 -0
- package/dist/core/generator/adr-generator.d.ts.map +1 -0
- package/dist/core/generator/adr-generator.js +192 -0
- package/dist/core/generator/adr-generator.js.map +1 -0
- package/dist/core/generator/index.d.ts +9 -0
- package/dist/core/generator/index.d.ts.map +1 -0
- package/dist/core/generator/index.js +12 -0
- package/dist/core/generator/index.js.map +1 -0
- package/dist/core/generator/mapping-generator.d.ts +54 -0
- package/dist/core/generator/mapping-generator.d.ts.map +1 -0
- package/dist/core/generator/mapping-generator.js +239 -0
- package/dist/core/generator/mapping-generator.js.map +1 -0
- package/dist/core/generator/openspec-compat.d.ts +160 -0
- package/dist/core/generator/openspec-compat.d.ts.map +1 -0
- package/dist/core/generator/openspec-compat.js +523 -0
- package/dist/core/generator/openspec-compat.js.map +1 -0
- package/dist/core/generator/openspec-format-generator.d.ts +111 -0
- package/dist/core/generator/openspec-format-generator.d.ts.map +1 -0
- package/dist/core/generator/openspec-format-generator.js +817 -0
- package/dist/core/generator/openspec-format-generator.js.map +1 -0
- package/dist/core/generator/openspec-writer.d.ts +131 -0
- package/dist/core/generator/openspec-writer.d.ts.map +1 -0
- package/dist/core/generator/openspec-writer.js +379 -0
- package/dist/core/generator/openspec-writer.js.map +1 -0
- package/dist/core/generator/prompts.d.ts +35 -0
- package/dist/core/generator/prompts.d.ts.map +1 -0
- package/dist/core/generator/prompts.js +212 -0
- package/dist/core/generator/prompts.js.map +1 -0
- package/dist/core/generator/spec-pipeline.d.ts +94 -0
- package/dist/core/generator/spec-pipeline.d.ts.map +1 -0
- package/dist/core/generator/spec-pipeline.js +474 -0
- package/dist/core/generator/spec-pipeline.js.map +1 -0
- package/dist/core/generator/stages/stage1-survey.d.ts +19 -0
- package/dist/core/generator/stages/stage1-survey.d.ts.map +1 -0
- package/dist/core/generator/stages/stage1-survey.js +105 -0
- package/dist/core/generator/stages/stage1-survey.js.map +1 -0
- package/dist/core/generator/stages/stage2-entities.d.ts +11 -0
- package/dist/core/generator/stages/stage2-entities.d.ts.map +1 -0
- package/dist/core/generator/stages/stage2-entities.js +67 -0
- package/dist/core/generator/stages/stage2-entities.js.map +1 -0
- package/dist/core/generator/stages/stage3-services.d.ts +11 -0
- package/dist/core/generator/stages/stage3-services.d.ts.map +1 -0
- package/dist/core/generator/stages/stage3-services.js +75 -0
- package/dist/core/generator/stages/stage3-services.js.map +1 -0
- package/dist/core/generator/stages/stage4-api.d.ts +11 -0
- package/dist/core/generator/stages/stage4-api.d.ts.map +1 -0
- package/dist/core/generator/stages/stage4-api.js +65 -0
- package/dist/core/generator/stages/stage4-api.js.map +1 -0
- package/dist/core/generator/stages/stage5-architecture.d.ts +10 -0
- package/dist/core/generator/stages/stage5-architecture.d.ts.map +1 -0
- package/dist/core/generator/stages/stage5-architecture.js +62 -0
- package/dist/core/generator/stages/stage5-architecture.js.map +1 -0
- package/dist/core/generator/stages/stage6-adr.d.ts +8 -0
- package/dist/core/generator/stages/stage6-adr.d.ts.map +1 -0
- package/dist/core/generator/stages/stage6-adr.js +41 -0
- package/dist/core/generator/stages/stage6-adr.js.map +1 -0
- package/dist/core/services/chat-agent.d.ts +45 -0
- package/dist/core/services/chat-agent.d.ts.map +1 -0
- package/dist/core/services/chat-agent.js +310 -0
- package/dist/core/services/chat-agent.js.map +1 -0
- package/dist/core/services/chat-tools.d.ts +32 -0
- package/dist/core/services/chat-tools.d.ts.map +1 -0
- package/dist/core/services/chat-tools.js +270 -0
- package/dist/core/services/chat-tools.js.map +1 -0
- package/dist/core/services/config-manager.d.ts +61 -0
- package/dist/core/services/config-manager.d.ts.map +1 -0
- package/dist/core/services/config-manager.js +143 -0
- package/dist/core/services/config-manager.js.map +1 -0
- package/dist/core/services/gitignore-manager.d.ts +29 -0
- package/dist/core/services/gitignore-manager.d.ts.map +1 -0
- package/dist/core/services/gitignore-manager.js +106 -0
- package/dist/core/services/gitignore-manager.js.map +1 -0
- package/dist/core/services/index.d.ts +8 -0
- package/dist/core/services/index.d.ts.map +1 -0
- package/dist/core/services/index.js +8 -0
- package/dist/core/services/index.js.map +1 -0
- package/dist/core/services/llm-service.d.ts +336 -0
- package/dist/core/services/llm-service.d.ts.map +1 -0
- package/dist/core/services/llm-service.js +1155 -0
- package/dist/core/services/llm-service.js.map +1 -0
- package/dist/core/services/mcp-handlers/analysis.d.ts +42 -0
- package/dist/core/services/mcp-handlers/analysis.d.ts.map +1 -0
- package/dist/core/services/mcp-handlers/analysis.js +300 -0
- package/dist/core/services/mcp-handlers/analysis.js.map +1 -0
- package/dist/core/services/mcp-handlers/graph.d.ts +65 -0
- package/dist/core/services/mcp-handlers/graph.d.ts.map +1 -0
- package/dist/core/services/mcp-handlers/graph.js +509 -0
- package/dist/core/services/mcp-handlers/graph.js.map +1 -0
- package/dist/core/services/mcp-handlers/semantic.d.ts +38 -0
- package/dist/core/services/mcp-handlers/semantic.d.ts.map +1 -0
- package/dist/core/services/mcp-handlers/semantic.js +172 -0
- package/dist/core/services/mcp-handlers/semantic.js.map +1 -0
- package/dist/core/services/mcp-handlers/utils.d.ts +21 -0
- package/dist/core/services/mcp-handlers/utils.d.ts.map +1 -0
- package/dist/core/services/mcp-handlers/utils.js +62 -0
- package/dist/core/services/mcp-handlers/utils.js.map +1 -0
- package/dist/core/services/project-detector.d.ts +32 -0
- package/dist/core/services/project-detector.d.ts.map +1 -0
- package/dist/core/services/project-detector.js +111 -0
- package/dist/core/services/project-detector.js.map +1 -0
- package/dist/core/verifier/index.d.ts +5 -0
- package/dist/core/verifier/index.d.ts.map +1 -0
- package/dist/core/verifier/index.js +5 -0
- package/dist/core/verifier/index.js.map +1 -0
- package/dist/core/verifier/verification-engine.d.ts +226 -0
- package/dist/core/verifier/verification-engine.d.ts.map +1 -0
- package/dist/core/verifier/verification-engine.js +681 -0
- package/dist/core/verifier/verification-engine.js.map +1 -0
- package/dist/types/index.d.ts +252 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +5 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/pipeline.d.ts +148 -0
- package/dist/types/pipeline.d.ts.map +1 -0
- package/dist/types/pipeline.js +5 -0
- package/dist/types/pipeline.js.map +1 -0
- package/dist/utils/errors.d.ts +51 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +128 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/logger.d.ts +149 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +331 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/progress.d.ts +142 -0
- package/dist/utils/progress.d.ts.map +1 -0
- package/dist/utils/progress.js +280 -0
- package/dist/utils/progress.js.map +1 -0
- package/dist/utils/prompts.d.ts +53 -0
- package/dist/utils/prompts.d.ts.map +1 -0
- package/dist/utils/prompts.js +199 -0
- package/dist/utils/prompts.js.map +1 -0
- package/dist/utils/shutdown.d.ts +89 -0
- package/dist/utils/shutdown.d.ts.map +1 -0
- package/dist/utils/shutdown.js +237 -0
- package/dist/utils/shutdown.js.map +1 -0
- package/package.json +114 -0
- package/src/viewer/InteractiveGraphViewer.jsx +1486 -0
- package/src/viewer/app/index.html +17 -0
- package/src/viewer/app/main.jsx +13 -0
- package/src/viewer/components/ArchitectureView.jsx +177 -0
- package/src/viewer/components/ChatPanel.jsx +448 -0
- package/src/viewer/components/ClusterGraph.jsx +441 -0
- package/src/viewer/components/FilterBar.jsx +179 -0
- package/src/viewer/components/FlatGraph.jsx +275 -0
- package/src/viewer/components/MicroComponents.jsx +83 -0
- package/src/viewer/hooks/usePanZoom.js +79 -0
- package/src/viewer/utils/constants.js +47 -0
- package/src/viewer/utils/graph-helpers.js +291 -0
package/README.md
ADDED
|
@@ -0,0 +1,1078 @@
|
|
|
1
|
+
# spec-gen
|
|
2
|
+
|
|
3
|
+
Reverse-engineer [OpenSpec](https://github.com/Fission-AI/OpenSpec) specifications from existing codebases, then keep them in sync as code evolves.
|
|
4
|
+
|
|
5
|
+
## The Problem
|
|
6
|
+
|
|
7
|
+
Most software has no specification. The code is the spec, scattered across thousands of files, tribal knowledge, and stale documentation. Tools like `openspec init` create empty scaffolding, but someone still has to write everything. By the time specs are written manually, the code has already changed.
|
|
8
|
+
|
|
9
|
+
spec-gen automates this. It analyzes your codebase through static analysis, generates structured specifications using an LLM, and continuously detects when code and specs fall out of sync.
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
# Install from npm
|
|
15
|
+
npm install -g spec-gen-cli
|
|
16
|
+
|
|
17
|
+
# Navigate to your project
|
|
18
|
+
cd /path/to/your-project
|
|
19
|
+
|
|
20
|
+
# Run the pipeline
|
|
21
|
+
spec-gen init # Detect project type, create config
|
|
22
|
+
spec-gen analyze # Static analysis (no API key needed)
|
|
23
|
+
spec-gen generate # Generate specs (requires API key)
|
|
24
|
+
spec-gen drift # Check for spec drift
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
<details>
|
|
28
|
+
<summary>Install from source</summary>
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
git clone https://github.com/clay-good/spec-gen
|
|
32
|
+
cd spec-gen
|
|
33
|
+
npm install && npm run build && npm link
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
</details>
|
|
37
|
+
|
|
38
|
+
<details>
|
|
39
|
+
<summary>Nix/NixOS</summary>
|
|
40
|
+
|
|
41
|
+
**Run directly:**
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
nix run github:clay-good/spec-gen -- init
|
|
45
|
+
nix run github:clay-good/spec-gen -- analyze
|
|
46
|
+
nix run github:clay-good/spec-gen -- generate
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
**Temporary shell:**
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
nix shell github:clay-good/spec-gen
|
|
53
|
+
spec-gen --version
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
**System flake integration:**
|
|
57
|
+
|
|
58
|
+
```nix
|
|
59
|
+
{
|
|
60
|
+
inputs.spec-gen.url = "github:clay-good/spec-gen";
|
|
61
|
+
|
|
62
|
+
outputs = { self, nixpkgs, spec-gen }: {
|
|
63
|
+
nixosConfigurations.myhost = nixpkgs.lib.nixosSystem {
|
|
64
|
+
modules = [{
|
|
65
|
+
environment.systemPackages = [ spec-gen.packages.x86_64-linux.default ];
|
|
66
|
+
}];
|
|
67
|
+
};
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
**Development:**
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
git clone https://github.com/clay-good/spec-gen
|
|
76
|
+
cd spec-gen
|
|
77
|
+
nix develop
|
|
78
|
+
npm run dev
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
</details>
|
|
82
|
+
|
|
83
|
+
## What It Does
|
|
84
|
+
|
|
85
|
+
**1. Analyze** (no API key needed)
|
|
86
|
+
|
|
87
|
+
Scans your codebase using pure static analysis:
|
|
88
|
+
- Walks the directory tree, respects .gitignore, scores files by significance
|
|
89
|
+
- Parses imports and exports to build a dependency graph
|
|
90
|
+
- Clusters related files into business domains automatically
|
|
91
|
+
- Produces structured context that makes LLM generation more accurate
|
|
92
|
+
|
|
93
|
+
**2. Generate** (API key required)
|
|
94
|
+
|
|
95
|
+
Sends the analysis context to an LLM to produce specifications:
|
|
96
|
+
- Stage 1: Project survey and categorization
|
|
97
|
+
- Stage 2: Entity extraction (core data models)
|
|
98
|
+
- Stage 3: Service analysis (business logic)
|
|
99
|
+
- Stage 4: API extraction (HTTP endpoints)
|
|
100
|
+
- Stage 5: Architecture synthesis (overall structure)
|
|
101
|
+
- Stage 6: ADR enrichment (Architecture Decision Records, with `--adr`)
|
|
102
|
+
|
|
103
|
+
**3. Verify** (API key required)
|
|
104
|
+
|
|
105
|
+
Tests generated specs by predicting file contents from specs alone, then comparing predictions to actual code. Reports an accuracy score and identifies gaps.
|
|
106
|
+
|
|
107
|
+
**4. Drift Detection** (no API key needed)
|
|
108
|
+
|
|
109
|
+
Compares git changes against spec file mappings to find divergence:
|
|
110
|
+
- **Gap**: Code changed but its spec was not updated
|
|
111
|
+
- **Stale**: Spec references deleted or renamed files
|
|
112
|
+
- **Uncovered**: New files with no matching spec domain
|
|
113
|
+
- **Orphaned**: Spec declares files that no longer exist
|
|
114
|
+
- **ADR gap**: Code changed in a domain referenced by an ADR
|
|
115
|
+
- **ADR orphaned**: ADR references domains that no longer exist in specs
|
|
116
|
+
|
|
117
|
+
## Architecture
|
|
118
|
+
|
|
119
|
+
```mermaid
|
|
120
|
+
graph TD
|
|
121
|
+
subgraph CLI["CLI Layer"]
|
|
122
|
+
CMD[spec-gen commands]
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
subgraph API["Programmatic API"]
|
|
126
|
+
API_INIT[specGenInit]
|
|
127
|
+
API_ANALYZE[specGenAnalyze]
|
|
128
|
+
API_GENERATE[specGenGenerate]
|
|
129
|
+
API_VERIFY[specGenVerify]
|
|
130
|
+
API_DRIFT[specGenDrift]
|
|
131
|
+
API_RUN[specGenRun]
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
subgraph Core["Core Layer"]
|
|
135
|
+
direction TB
|
|
136
|
+
|
|
137
|
+
subgraph Init["Init"]
|
|
138
|
+
PD[Project Detector]
|
|
139
|
+
CM[Config Manager]
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
subgraph Analyze["Analyze -- no API key"]
|
|
143
|
+
FW[File Walker] --> SS[Significance Scorer]
|
|
144
|
+
SS --> IP[Import Parser]
|
|
145
|
+
IP --> DG[Dependency Graph]
|
|
146
|
+
DG --> RM[Repository Mapper]
|
|
147
|
+
RM --> AG[Artifact Generator]
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
subgraph Generate["Generate -- API key required"]
|
|
151
|
+
SP[Spec Pipeline] --> FF[OpenSpec Formatter]
|
|
152
|
+
FF --> OW[OpenSpec Writer]
|
|
153
|
+
SP --> ADR[ADR Generator]
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
subgraph Verify["Verify -- API key required"]
|
|
157
|
+
VE[Verification Engine]
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
subgraph Drift["Drift -- no API key"]
|
|
161
|
+
GA[Git Analyzer] --> SM[Spec Mapper]
|
|
162
|
+
SM --> DD[Drift Detector]
|
|
163
|
+
DD -.->|optional| LE[LLM Enhancer]
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
LLM[LLM Service -- Anthropic / OpenAI / Compatible]
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
CMD --> API_INIT & API_ANALYZE & API_GENERATE & API_VERIFY & API_DRIFT
|
|
170
|
+
API_RUN --> API_INIT & API_ANALYZE & API_GENERATE
|
|
171
|
+
|
|
172
|
+
API_INIT --> Init
|
|
173
|
+
API_ANALYZE --> Analyze
|
|
174
|
+
API_GENERATE --> Generate
|
|
175
|
+
API_VERIFY --> Verify
|
|
176
|
+
API_DRIFT --> Drift
|
|
177
|
+
|
|
178
|
+
Generate --> LLM
|
|
179
|
+
Verify --> LLM
|
|
180
|
+
LE -.-> LLM
|
|
181
|
+
|
|
182
|
+
AG -->|analysis artifacts| SP
|
|
183
|
+
AG -->|analysis artifacts| VE
|
|
184
|
+
|
|
185
|
+
subgraph Output["Output"]
|
|
186
|
+
SPECS[openspec/specs/*.md]
|
|
187
|
+
ADRS[openspec/decisions/*.md]
|
|
188
|
+
ANALYSIS[.spec-gen/analysis/]
|
|
189
|
+
REPORT[Drift Report]
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
OW --> SPECS
|
|
193
|
+
ADR --> ADRS
|
|
194
|
+
AG --> ANALYSIS
|
|
195
|
+
DD --> REPORT
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
## Drift Detection
|
|
199
|
+
|
|
200
|
+
Drift detection is the core of ongoing spec maintenance. It runs in milliseconds, needs no API key, and works entirely from git diffs and spec file mappings.
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
$ spec-gen drift
|
|
204
|
+
|
|
205
|
+
Spec Drift Detection
|
|
206
|
+
|
|
207
|
+
Analyzing git changes...
|
|
208
|
+
Base ref: main
|
|
209
|
+
Branch: feature/add-notifications
|
|
210
|
+
Changed files: 12
|
|
211
|
+
|
|
212
|
+
Loading spec mappings...
|
|
213
|
+
Spec domains: 6
|
|
214
|
+
Mapped source files: 34
|
|
215
|
+
|
|
216
|
+
Detecting drift...
|
|
217
|
+
|
|
218
|
+
Issues Found: 3
|
|
219
|
+
|
|
220
|
+
[ERROR] gap: src/services/user-service.ts
|
|
221
|
+
Spec: openspec/specs/user/spec.md
|
|
222
|
+
File changed (+45/-12 lines) but spec was not updated
|
|
223
|
+
|
|
224
|
+
[WARNING] uncovered: src/services/email-queue.ts
|
|
225
|
+
New file has no matching spec domain
|
|
226
|
+
|
|
227
|
+
[INFO] adr-gap: openspec/decisions/adr-0001-jwt-auth.md
|
|
228
|
+
Code changed in domain(s) auth referenced by ADR-001
|
|
229
|
+
|
|
230
|
+
Summary:
|
|
231
|
+
Gaps: 2
|
|
232
|
+
Uncovered: 1
|
|
233
|
+
ADR gaps: 1
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### ADR Drift Detection
|
|
237
|
+
|
|
238
|
+
When `openspec/decisions/` contains Architecture Decision Records, drift detection automatically checks whether code changes affect domains referenced by ADRs. ADR issues are reported at `info` severity since code changes rarely invalidate architectural decisions. Superseded and deprecated ADRs are excluded.
|
|
239
|
+
|
|
240
|
+
### LLM-Enhanced Mode
|
|
241
|
+
|
|
242
|
+
Static drift detection catches structural changes but cannot tell whether a change actually affects spec-documented behavior. A variable rename triggers the same alert as a genuine behavior change.
|
|
243
|
+
|
|
244
|
+
`--use-llm` post-processes gap issues by sending each file's diff and its matching spec to the LLM. The LLM classifies each gap as relevant (keeps the alert) or not relevant (downgrades to info). This reduces false positives.
|
|
245
|
+
|
|
246
|
+
```bash
|
|
247
|
+
spec-gen drift # Static mode: fast, deterministic
|
|
248
|
+
spec-gen drift --use-llm # LLM-enhanced: fewer false positives
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
## CI/CD Integration
|
|
252
|
+
|
|
253
|
+
spec-gen is designed to run in automated pipelines. The deterministic commands (`init`, `analyze`, `drift`) need no API key and produce consistent results.
|
|
254
|
+
|
|
255
|
+
### Pre-Commit Hook
|
|
256
|
+
|
|
257
|
+
```bash
|
|
258
|
+
spec-gen drift --install-hook # Install
|
|
259
|
+
spec-gen drift --uninstall-hook # Remove
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
The hook runs in static mode (fast, no API key needed) and blocks commits when drift is detected at warning level or above.
|
|
263
|
+
|
|
264
|
+
### GitHub Actions / CI Pipelines
|
|
265
|
+
|
|
266
|
+
```yaml
|
|
267
|
+
# .github/workflows/spec-drift.yml
|
|
268
|
+
name: Spec Drift Check
|
|
269
|
+
on: [pull_request]
|
|
270
|
+
jobs:
|
|
271
|
+
drift:
|
|
272
|
+
runs-on: ubuntu-latest
|
|
273
|
+
steps:
|
|
274
|
+
- uses: actions/checkout@v4
|
|
275
|
+
with:
|
|
276
|
+
fetch-depth: 0 # Full history needed for git diff
|
|
277
|
+
- uses: actions/setup-node@v4
|
|
278
|
+
with:
|
|
279
|
+
node-version: '20'
|
|
280
|
+
- run: npm install -g spec-gen-cli
|
|
281
|
+
- run: spec-gen drift --fail-on error --json
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
```bash
|
|
285
|
+
# Or in any CI script
|
|
286
|
+
spec-gen drift --fail-on error --json # JSON output, fail on errors only
|
|
287
|
+
spec-gen drift --fail-on warning # Fail on warnings too
|
|
288
|
+
spec-gen drift --domains auth,user # Check specific domains
|
|
289
|
+
spec-gen drift --no-color # Plain output for CI logs
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
### Deterministic vs. LLM-Enhanced
|
|
293
|
+
|
|
294
|
+
| | Deterministic (Default) | LLM-Enhanced |
|
|
295
|
+
|---|---|---|
|
|
296
|
+
| **API key** | No | Yes |
|
|
297
|
+
| **Speed** | Milliseconds | Seconds per LLM call |
|
|
298
|
+
| **Commands** | `analyze`, `drift`, `init` | `generate`, `verify`, `drift --use-llm` |
|
|
299
|
+
| **Reproducibility** | Identical every run | May vary |
|
|
300
|
+
| **Best for** | CI, pre-commit hooks, quick checks | Initial generation, reducing false positives |
|
|
301
|
+
|
|
302
|
+
## LLM Providers
|
|
303
|
+
|
|
304
|
+
spec-gen supports four providers. The default is Anthropic Claude.
|
|
305
|
+
|
|
306
|
+
| Provider | `provider` value | API key env var | Default model |
|
|
307
|
+
|----------|-----------------|-----------------|---------------|
|
|
308
|
+
| Anthropic Claude | `anthropic` *(default)* | `ANTHROPIC_API_KEY` | `claude-sonnet-4-20250514` |
|
|
309
|
+
| OpenAI | `openai` | `OPENAI_API_KEY` | `gpt-4o` |
|
|
310
|
+
| OpenAI-compatible *(Mistral, Groq, Ollama...)* | `openai-compat` | `OPENAI_COMPAT_API_KEY` | `mistral-large-latest` |
|
|
311
|
+
| Google Gemini | `gemini` | `GEMINI_API_KEY` | `gemini-2.0-flash` |
|
|
312
|
+
|
|
313
|
+
### Selecting a provider
|
|
314
|
+
|
|
315
|
+
Set `provider` (and optionally `model`) in the `generation` block of `.spec-gen/config.json`:
|
|
316
|
+
|
|
317
|
+
```json
|
|
318
|
+
{
|
|
319
|
+
"generation": {
|
|
320
|
+
"provider": "openai",
|
|
321
|
+
"model": "gpt-4o-mini",
|
|
322
|
+
"domains": "auto"
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
Override the model for a single run:
|
|
328
|
+
```bash
|
|
329
|
+
spec-gen generate --model claude-opus-4-20250514
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
### OpenAI-compatible servers (Ollama, Mistral, Groq, LM Studio, vLLM...)
|
|
333
|
+
|
|
334
|
+
Use `provider: "openai-compat"` with a base URL and API key:
|
|
335
|
+
|
|
336
|
+
**Environment variables:**
|
|
337
|
+
```bash
|
|
338
|
+
export OPENAI_COMPAT_BASE_URL=http://localhost:11434/v1 # Ollama, LM Studio, local servers
|
|
339
|
+
export OPENAI_COMPAT_API_KEY=ollama # any non-empty value for local servers
|
|
340
|
+
# use your real API key for cloud providers (Mistral, Groq...)
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
**Config file** (per-project):
|
|
344
|
+
```json
|
|
345
|
+
{
|
|
346
|
+
"generation": {
|
|
347
|
+
"provider": "openai-compat",
|
|
348
|
+
"model": "llama3.2",
|
|
349
|
+
"openaiCompatBaseUrl": "http://localhost:11434/v1",
|
|
350
|
+
"domains": "auto"
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
**Self-signed certificates** (internal servers, VPN endpoints):
|
|
356
|
+
```bash
|
|
357
|
+
spec-gen generate --insecure
|
|
358
|
+
```
|
|
359
|
+
Or in `config.json`:
|
|
360
|
+
```json
|
|
361
|
+
{
|
|
362
|
+
"generation": {
|
|
363
|
+
"provider": "openai-compat",
|
|
364
|
+
"openaiCompatBaseUrl": "https://internal-llm.corp.net/v1",
|
|
365
|
+
"skipSslVerify": true,
|
|
366
|
+
"domains": "auto"
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
Works with: Ollama, LM Studio, Mistral AI, Groq, Together AI, LiteLLM, vLLM,
|
|
372
|
+
text-generation-inference, LocalAI, Azure OpenAI, and any `/v1/chat/completions` server.
|
|
373
|
+
|
|
374
|
+
### Custom base URL for Anthropic or OpenAI
|
|
375
|
+
|
|
376
|
+
To redirect the built-in Anthropic or OpenAI provider to a proxy or self-hosted endpoint:
|
|
377
|
+
|
|
378
|
+
```bash
|
|
379
|
+
# CLI (one-off)
|
|
380
|
+
spec-gen generate --api-base https://my-proxy.corp.net/v1
|
|
381
|
+
|
|
382
|
+
# Environment variable
|
|
383
|
+
export ANTHROPIC_API_BASE=https://my-proxy.corp.net/v1
|
|
384
|
+
export OPENAI_API_BASE=https://my-proxy.corp.net/v1
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
Or in `config.json` under the `llm` block:
|
|
388
|
+
```json
|
|
389
|
+
{
|
|
390
|
+
"llm": {
|
|
391
|
+
"apiBase": "https://my-proxy.corp.net/v1",
|
|
392
|
+
"sslVerify": false
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
`sslVerify: false` disables TLS certificate validation -- use only for internal servers with self-signed certificates.
|
|
398
|
+
|
|
399
|
+
Priority: CLI flags > environment variables > config file > provider defaults.
|
|
400
|
+
|
|
401
|
+
## Commands
|
|
402
|
+
|
|
403
|
+
| Command | Description | API Key |
|
|
404
|
+
|---------|-------------|---------|
|
|
405
|
+
| `spec-gen init` | Initialize configuration | No |
|
|
406
|
+
| `spec-gen analyze` | Run static analysis | No |
|
|
407
|
+
| `spec-gen generate` | Generate specs from analysis | Yes |
|
|
408
|
+
| `spec-gen generate --adr` | Also generate Architecture Decision Records | Yes |
|
|
409
|
+
| `spec-gen verify` | Verify spec accuracy | Yes |
|
|
410
|
+
| `spec-gen drift` | Detect spec drift (static) | No |
|
|
411
|
+
| `spec-gen drift --use-llm` | Detect spec drift (LLM-enhanced) | Yes |
|
|
412
|
+
| `spec-gen run` | Full pipeline: init, analyze, generate | Yes |
|
|
413
|
+
| `spec-gen view` | Launch interactive graph & spec viewer in the browser | No |
|
|
414
|
+
| `spec-gen mcp` | Start MCP server (stdio, for Cline / Claude Code) | No |
|
|
415
|
+
|
|
416
|
+
### Global Options
|
|
417
|
+
|
|
418
|
+
```bash
|
|
419
|
+
--api-base <url> # Custom LLM API base URL (proxy / self-hosted)
|
|
420
|
+
--insecure # Disable SSL certificate verification
|
|
421
|
+
--config <path> # Config file path (default: .spec-gen/config.json)
|
|
422
|
+
-q, --quiet # Errors only
|
|
423
|
+
-v, --verbose # Debug output
|
|
424
|
+
--no-color # Plain text output (enables timestamps)
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
Generate-specific options:
|
|
428
|
+
```bash
|
|
429
|
+
--model <name> # Override LLM model (e.g. gpt-4o-mini, llama3.2)
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
### Drift Options
|
|
433
|
+
|
|
434
|
+
```bash
|
|
435
|
+
spec-gen drift [options]
|
|
436
|
+
--base <ref> # Git ref to compare against (default: auto-detect)
|
|
437
|
+
--files <paths> # Specific files to check (comma-separated)
|
|
438
|
+
--domains <list> # Only check specific domains
|
|
439
|
+
--use-llm # LLM semantic analysis
|
|
440
|
+
--json # JSON output
|
|
441
|
+
--fail-on <severity> # Exit non-zero threshold: error, warning, info
|
|
442
|
+
--max-files <n> # Max changed files to analyze (default: 100)
|
|
443
|
+
--install-hook # Install pre-commit hook
|
|
444
|
+
--uninstall-hook # Remove pre-commit hook
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
### Generate Options
|
|
448
|
+
|
|
449
|
+
```bash
|
|
450
|
+
spec-gen generate [options]
|
|
451
|
+
--model <name> # LLM model to use
|
|
452
|
+
--dry-run # Preview without writing
|
|
453
|
+
--domains <list> # Only generate specific domains
|
|
454
|
+
--merge # Merge with existing specs
|
|
455
|
+
--no-overwrite # Skip existing files
|
|
456
|
+
--adr # Also generate ADRs
|
|
457
|
+
--adr-only # Generate only ADRs
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
### Analyze Options
|
|
461
|
+
|
|
462
|
+
```bash
|
|
463
|
+
spec-gen analyze [options]
|
|
464
|
+
--output <path> # Output directory (default: .spec-gen/analysis/)
|
|
465
|
+
--max-files <n> # Max files (default: 500)
|
|
466
|
+
--include <glob> # Additional include patterns
|
|
467
|
+
--exclude <glob> # Additional exclude patterns
|
|
468
|
+
--force # Force re-analysis (bypass 1-hour cache)
|
|
469
|
+
--embed # Build semantic vector index after analysis (requires embedding config)
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
### Verify Options
|
|
473
|
+
|
|
474
|
+
```bash
|
|
475
|
+
spec-gen verify [options]
|
|
476
|
+
--samples <n> # Files to verify (default: 5)
|
|
477
|
+
--threshold <0-1> # Minimum score to pass (default: 0.7)
|
|
478
|
+
--files <paths> # Specific files to verify
|
|
479
|
+
--domains <list> # Only verify specific domains
|
|
480
|
+
--json # JSON output
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
## MCP Server
|
|
484
|
+
|
|
485
|
+
`spec-gen mcp` starts spec-gen as a [Model Context Protocol](https://modelcontextprotocol.io/) server over stdio, exposing static analysis as tools that any MCP-compatible AI agent (Cline, Roo Code, Kilocode, Claude Code, Cursor...) can call directly -- no API key required.
|
|
486
|
+
|
|
487
|
+
### Setup
|
|
488
|
+
|
|
489
|
+
**Claude Code** -- add a `.mcp.json` at your project root (the repo ships one):
|
|
490
|
+
|
|
491
|
+
```json
|
|
492
|
+
{
|
|
493
|
+
"mcpServers": {
|
|
494
|
+
"spec-gen": {
|
|
495
|
+
"command": "node",
|
|
496
|
+
"args": ["/absolute/path/to/spec-gen/dist/cli/index.js", "mcp"]
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
**Cline / Roo Code / Kilocode** -- add the same block under `mcpServers` in the MCP settings JSON of your editor.
|
|
503
|
+
|
|
504
|
+
### Quick Start
|
|
505
|
+
|
|
506
|
+
**1. Build spec-gen**
|
|
507
|
+
|
|
508
|
+
```bash
|
|
509
|
+
git clone https://github.com/clay-good/spec-gen
|
|
510
|
+
cd spec-gen && npm install && npm run build
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
**2. Generate specs once** (required for drift detection and naming alignment)
|
|
514
|
+
|
|
515
|
+
```bash
|
|
516
|
+
cd /path/to/your-project
|
|
517
|
+
spec-gen init # detect project type, create config
|
|
518
|
+
spec-gen generate # generate OpenSpec specs (requires LLM API key)
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
**3. Connect your editor**
|
|
522
|
+
|
|
523
|
+
#### Claude Code
|
|
524
|
+
|
|
525
|
+
The repo ships a `.mcp.json` -- edit the path and you are done:
|
|
526
|
+
|
|
527
|
+
```json
|
|
528
|
+
{
|
|
529
|
+
"mcpServers": {
|
|
530
|
+
"spec-gen": {
|
|
531
|
+
"command": "node",
|
|
532
|
+
"args": ["/absolute/path/to/spec-gen/dist/cli/index.js", "mcp"]
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
```
|
|
537
|
+
|
|
538
|
+
The tools are available directly in any Claude Code conversation. Just ask naturally -- Claude calls the right tools automatically:
|
|
539
|
+
|
|
540
|
+
```
|
|
541
|
+
You: Analyse my codebase and tell me what needs refactoring most urgently
|
|
542
|
+
Claude: [analyze_codebase -> get_refactor_report -> analyze_impact on top result]
|
|
543
|
+
-> Project summary, top issues ranked by priority, risk score and recommended
|
|
544
|
+
strategy for the highest-impact function
|
|
545
|
+
|
|
546
|
+
You: Are there any duplicate functions I should consolidate?
|
|
547
|
+
Claude: [get_duplicate_report]
|
|
548
|
+
-> Clone groups sorted by impact (exact / structural / near), file paths, line ranges
|
|
549
|
+
|
|
550
|
+
You: Show me everything that calls parseConfig and draw a diagram
|
|
551
|
+
Claude: [get_subgraph with direction: "upstream", format: "mermaid"]
|
|
552
|
+
-> Mermaid flowchart of the upstream call chain
|
|
553
|
+
```
|
|
554
|
+
|
|
555
|
+
#### Cline / Roo Code / Kilocode
|
|
556
|
+
|
|
557
|
+
Add the same `mcpServers` block in the editor's MCP settings JSON, then install the pre-built slash command workflows:
|
|
558
|
+
|
|
559
|
+
```bash
|
|
560
|
+
cd /path/to/your-project
|
|
561
|
+
mkdir -p .clinerules/workflows
|
|
562
|
+
cp /path/to/spec-gen/examples/cline-workflows/*.md .clinerules/workflows/
|
|
563
|
+
```
|
|
564
|
+
|
|
565
|
+
Type one of the following commands in a conversation:
|
|
566
|
+
|
|
567
|
+
| Command | Needs API key | What it does |
|
|
568
|
+
|---------|:---:|-------------|
|
|
569
|
+
| `/spec-gen-analyze-codebase` | No | Architecture overview, call graph highlights, top refactor issues |
|
|
570
|
+
| `/spec-gen-check-spec-drift` | No | Detect code changes not reflected in specs; per-kind remediation guidance |
|
|
571
|
+
| `/spec-gen-plan-refactor` | No | Static analysis -> impact assessment -> written plan saved to `.spec-gen/refactor-plan.md` (no code changes) |
|
|
572
|
+
| `/spec-gen-execute-refactor` | No | Read the plan and apply changes incrementally, with tests and diff verification after each step |
|
|
573
|
+
|
|
574
|
+
`analyze_codebase`, `check_spec_drift`, and all refactoring tools run on **pure static analysis** -- no LLM quota consumed. Only `spec-gen generate` (the one-time spec generation step) requires an API key.
|
|
575
|
+
|
|
576
|
+
### Cline Slash Commands
|
|
577
|
+
|
|
578
|
+
`examples/cline-workflows/` contains four executable workflow files. Copy them to your project's `.clinerules/workflows/` to activate them as slash commands:
|
|
579
|
+
|
|
580
|
+
```bash
|
|
581
|
+
mkdir -p .clinerules/workflows
|
|
582
|
+
cp /path/to/spec-gen/examples/cline-workflows/*.md .clinerules/workflows/
|
|
583
|
+
```
|
|
584
|
+
|
|
585
|
+
| Command | What it does |
|
|
586
|
+
|---------|-------------|
|
|
587
|
+
| `/spec-gen-analyze-codebase` | Runs `analyze_codebase`, summarises the results (project type, file count, top 3 refactor issues, detected domains), shows the call graph highlights, and suggests next steps. |
|
|
588
|
+
| `/spec-gen-check-spec-drift` | Runs `check_spec_drift`, presents issues by severity (gap / stale / uncovered / orphaned-spec), shows per-kind remediation commands, and optionally drills into affected file signatures. |
|
|
589
|
+
| `/spec-gen-plan-refactor` | Runs static analysis, picks the highest-priority target with coverage gate, assesses impact and call graph, then writes a detailed plan to `.spec-gen/refactor-plan.md`. No code changes. |
|
|
590
|
+
| `/spec-gen-execute-refactor` | Reads `.spec-gen/refactor-plan.md`, establishes a green baseline, and applies each planned change one at a time -- with diff verification and test run after every step. Optional final step covers dead-code detection and naming alignment (requires `spec-gen generate`). |
|
|
591
|
+
|
|
592
|
+
All four commands ask which directory to use, call the MCP tools directly, and guide you through the results without leaving the editor. They work in Cline, Roo Code, Kilocode, and any editor that supports the `.clinerules/workflows/` convention.
|
|
593
|
+
|
|
594
|
+
### Tools
|
|
595
|
+
|
|
596
|
+
All tools run on **pure static analysis** -- no LLM quota consumed.
|
|
597
|
+
|
|
598
|
+
**Analysis**
|
|
599
|
+
|
|
600
|
+
| Tool | Description | Requires prior analysis |
|
|
601
|
+
|------|-------------|:---:|
|
|
602
|
+
| `analyze_codebase` | Run full static analysis: repo structure, dependency graph, call graph (hub functions, entry points, layer violations), and top refactoring priorities. Results cached for 1 hour (`force: true` to bypass). | No |
|
|
603
|
+
| `get_call_graph` | Hub functions (high fan-in), entry points (no internal callers), and architectural layer violations. Supports TypeScript, JavaScript, Python, Go, Rust, Ruby, Java. | Yes |
|
|
604
|
+
| `get_signatures` | Compact function/class signatures per file. Filter by path substring with `filePattern`. Useful for understanding a module's public API without reading full source. | Yes |
|
|
605
|
+
| `get_duplicate_report` | Detect duplicate code: Type 1 (exact clones), Type 2 (structural -- renamed variables), Type 3 (near-clones with Jaccard similarity >= 0.7). Groups sorted by impact. | Yes |
|
|
606
|
+
|
|
607
|
+
**Refactoring**
|
|
608
|
+
|
|
609
|
+
| Tool | Description | Requires prior analysis |
|
|
610
|
+
|------|-------------|:---:|
|
|
611
|
+
| `get_refactor_report` | Prioritized list of functions with structural issues: unreachable code, hub overload (high fan-in), god functions (high fan-out), SRP violations, cyclic dependencies. | Yes |
|
|
612
|
+
| `analyze_impact` | Deep impact analysis for a specific function: fan-in/fan-out, upstream call chain, downstream critical path, risk score (0-100), blast radius, and recommended strategy. | Yes |
|
|
613
|
+
| `get_low_risk_refactor_candidates` | Safest functions to refactor first: low fan-in, low fan-out, not a hub, no cyclic involvement. Best starting point for incremental, low-risk sessions. | Yes |
|
|
614
|
+
| `get_leaf_functions` | Functions that make no internal calls (leaves of the call graph). Zero downstream blast radius. Sorted by fan-in by default -- most-called leaves have the best unit-test ROI. | Yes |
|
|
615
|
+
| `get_critical_hubs` | Highest-impact hub functions ranked by criticality. Each hub gets a stability score (0-100) and a recommended approach: extract, split, facade, or delegate. | Yes |
|
|
616
|
+
|
|
617
|
+
**Navigation**
|
|
618
|
+
|
|
619
|
+
| Tool | Description | Requires prior analysis |
|
|
620
|
+
|------|-------------|:---:|
|
|
621
|
+
| `get_subgraph` | Depth-limited subgraph centred on a function. Direction: `downstream` (what it calls), `upstream` (who calls it), or `both`. Output as JSON or Mermaid diagram. | Yes |
|
|
622
|
+
| `get_architecture_overview` | High-level cluster map: roles (entry layer, orchestrator, core utilities, API layer, internal), inter-cluster dependencies, global entry points, and critical hubs. No LLM required. | Yes |
|
|
623
|
+
| `get_function_skeleton` | Noise-stripped view of a source file: logs, inline comments, and non-JSDoc block comments removed. Signatures, control flow, return/throw, and call expressions preserved. Returns reduction %. | No |
|
|
624
|
+
| `suggest_insertion_points` | Semantic search over the vector index to find the best existing functions to extend or hook into when implementing a new feature. Returns ranked candidates with role and strategy. | Yes (+ `--embed`) |
|
|
625
|
+
| `search_code` | Natural-language semantic search over indexed functions. Returns the closest matches by meaning with similarity score. Useful for navigating unfamiliar codebases. | Yes (+ `--embed`) |
|
|
626
|
+
|
|
627
|
+
**Specs**
|
|
628
|
+
|
|
629
|
+
| Tool | Description | Requires prior analysis |
|
|
630
|
+
|------|-------------|:---:|
|
|
631
|
+
| `get_mapping` | Requirement->function mapping produced by `spec-gen generate`. Shows which functions implement which spec requirements, confidence level, and orphan functions with no spec coverage. | Yes (generate) |
|
|
632
|
+
| `check_spec_drift` | Detect code changes not reflected in OpenSpec specs. Compares git-changed files against spec coverage maps. Issues: gap / stale / uncovered / orphaned-spec / adr-gap. | Yes (generate) |
|
|
633
|
+
|
|
634
|
+
### Parameters
|
|
635
|
+
|
|
636
|
+
**`analyze_codebase`**
|
|
637
|
+
```
|
|
638
|
+
directory string Absolute path to the project directory
|
|
639
|
+
force boolean Force re-analysis even if cache is fresh (default: false)
|
|
640
|
+
```
|
|
641
|
+
|
|
642
|
+
**`get_refactor_report`**, **`get_call_graph`**
|
|
643
|
+
```
|
|
644
|
+
directory string Absolute path to the project directory
|
|
645
|
+
```
|
|
646
|
+
|
|
647
|
+
**`get_signatures`**
|
|
648
|
+
```
|
|
649
|
+
directory string Absolute path to the project directory
|
|
650
|
+
filePattern string Optional path substring filter (e.g. "services", ".py")
|
|
651
|
+
```
|
|
652
|
+
|
|
653
|
+
**`get_subgraph`**
|
|
654
|
+
```
|
|
655
|
+
directory string Absolute path to the project directory
|
|
656
|
+
functionName string Function name to centre on (case-insensitive partial match)
|
|
657
|
+
direction string "downstream" | "upstream" | "both" (default: "downstream")
|
|
658
|
+
maxDepth number BFS traversal depth limit (default: 3)
|
|
659
|
+
format string "json" | "mermaid" (default: "json")
|
|
660
|
+
```
|
|
661
|
+
|
|
662
|
+
*Note: If no exact name match is found, `get_subgraph` falls back to semantic search (when a vector index is available) to find the most similar function.*
|
|
663
|
+
|
|
664
|
+
**`get_mapping`**
|
|
665
|
+
```
|
|
666
|
+
directory string Absolute path to the project directory
|
|
667
|
+
domain string Optional domain filter (e.g. "auth", "crawler")
|
|
668
|
+
orphansOnly boolean Return only orphan functions (default: false)
|
|
669
|
+
```
|
|
670
|
+
|
|
671
|
+
**`get_duplicate_report`**
|
|
672
|
+
```
|
|
673
|
+
directory string Absolute path to the project directory
|
|
674
|
+
```
|
|
675
|
+
|
|
676
|
+
**`check_spec_drift`**
|
|
677
|
+
```
|
|
678
|
+
directory string Absolute path to the project directory
|
|
679
|
+
base string Git ref to compare against (default: auto-detect main/master)
|
|
680
|
+
files string[] Specific files to check (default: all changed files)
|
|
681
|
+
domains string[] Only check these spec domains (default: all)
|
|
682
|
+
failOn string Minimum severity to report: "error" | "warning" | "info" (default: "warning")
|
|
683
|
+
maxFiles number Max changed files to analyze (default: 100)
|
|
684
|
+
```
|
|
685
|
+
|
|
686
|
+
**`analyze_impact`**
|
|
687
|
+
```
|
|
688
|
+
directory string Absolute path to the project directory
|
|
689
|
+
symbol string Function or method name (exact or partial match)
|
|
690
|
+
depth number Traversal depth for upstream/downstream chains (default: 2)
|
|
691
|
+
```
|
|
692
|
+
|
|
693
|
+
*Note: If no exact name match is found, `analyze_impact` falls back to semantic search (when a vector index is available) to find the most similar function.*
|
|
694
|
+
|
|
695
|
+
**`get_low_risk_refactor_candidates`**
|
|
696
|
+
```
|
|
697
|
+
directory string Absolute path to the project directory
|
|
698
|
+
limit number Max candidates to return (default: 5)
|
|
699
|
+
filePattern string Optional path substring filter (e.g. "services", ".py")
|
|
700
|
+
```
|
|
701
|
+
|
|
702
|
+
**`get_leaf_functions`**
|
|
703
|
+
```
|
|
704
|
+
directory string Absolute path to the project directory
|
|
705
|
+
limit number Max results to return (default: 20)
|
|
706
|
+
filePattern string Optional path substring filter
|
|
707
|
+
sortBy string "fanIn" (default) | "name" | "file"
|
|
708
|
+
```
|
|
709
|
+
|
|
710
|
+
**`get_critical_hubs`**
|
|
711
|
+
```
|
|
712
|
+
directory string Absolute path to the project directory
|
|
713
|
+
limit number Max hubs to return (default: 10)
|
|
714
|
+
minFanIn number Minimum fan-in threshold to be considered a hub (default: 3)
|
|
715
|
+
```
|
|
716
|
+
|
|
717
|
+
**`get_architecture_overview`**
|
|
718
|
+
```
|
|
719
|
+
directory string Absolute path to the project directory
|
|
720
|
+
```
|
|
721
|
+
|
|
722
|
+
**`get_function_skeleton`**
|
|
723
|
+
```
|
|
724
|
+
directory string Absolute path to the project directory
|
|
725
|
+
filePath string Path to the file, relative to the project directory
|
|
726
|
+
```
|
|
727
|
+
|
|
728
|
+
**`suggest_insertion_points`**
|
|
729
|
+
```
|
|
730
|
+
directory string Absolute path to the project directory
|
|
731
|
+
query string Natural-language description of the feature to implement
|
|
732
|
+
limit number Max candidates to return (default: 5)
|
|
733
|
+
```
|
|
734
|
+
|
|
735
|
+
**`search_code`**
|
|
736
|
+
```
|
|
737
|
+
directory string Absolute path to the project directory
|
|
738
|
+
query string Natural-language query, e.g. "authenticate user with JWT"
|
|
739
|
+
limit number Max results (default: 10)
|
|
740
|
+
language string Filter by language: "TypeScript" | "Python" | "Go" | ...
|
|
741
|
+
minFanIn number Only return functions with at least this many callers
|
|
742
|
+
```
|
|
743
|
+
|
|
744
|
+
### Typical workflow
|
|
745
|
+
|
|
746
|
+
**Scenario A -- Initial exploration**
|
|
747
|
+
```
|
|
748
|
+
1. analyze_codebase({ directory }) # repo structure + call graph + top issues
|
|
749
|
+
2. get_call_graph({ directory }) # hub functions + layer violations
|
|
750
|
+
3. get_duplicate_report({ directory }) # clone groups to consolidate
|
|
751
|
+
4. get_refactor_report({ directory }) # prioritized refactoring candidates
|
|
752
|
+
```
|
|
753
|
+
|
|
754
|
+
**Scenario B -- Targeted refactoring**
|
|
755
|
+
```
|
|
756
|
+
1. analyze_impact({ directory, symbol: "myFunction" }) # risk score + blast radius + strategy
|
|
757
|
+
2. get_subgraph({ directory, functionName: "myFunction", # Mermaid call neighbourhood
|
|
758
|
+
direction: "both", format: "mermaid" })
|
|
759
|
+
3. get_low_risk_refactor_candidates({ directory, # safe entry points to extract first
|
|
760
|
+
filePattern: "myFile" })
|
|
761
|
+
4. get_leaf_functions({ directory, filePattern: "myFile" }) # zero-risk extraction targets
|
|
762
|
+
```
|
|
763
|
+
|
|
764
|
+
**Scenario C -- Spec maintenance**
|
|
765
|
+
```
|
|
766
|
+
1. check_spec_drift({ directory }) # code changes not reflected in specs
|
|
767
|
+
2. get_mapping({ directory, orphansOnly: true }) # functions with no spec coverage
|
|
768
|
+
```
|
|
769
|
+
|
|
770
|
+
## Interactive Graph Viewer
|
|
771
|
+
|
|
772
|
+
`spec-gen view` launches a local React app that visualises your codebase analysis and lets you explore spec requirements side-by-side with the dependency graph.
|
|
773
|
+
|
|
774
|
+
```bash
|
|
775
|
+
# Run analysis first (if not already done)
|
|
776
|
+
spec-gen analyze
|
|
777
|
+
|
|
778
|
+
# Launch the viewer (opens browser automatically)
|
|
779
|
+
spec-gen view
|
|
780
|
+
|
|
781
|
+
# Options
|
|
782
|
+
spec-gen view --port 4000 # custom port (default: 5173)
|
|
783
|
+
spec-gen view --host 0.0.0.0 # expose on LAN
|
|
784
|
+
spec-gen view --no-open # don't open browser automatically
|
|
785
|
+
spec-gen view --analysis <path> # custom analysis dir (default: .spec-gen/analysis/)
|
|
786
|
+
spec-gen view --spec <path> # custom spec dir (default: ./openspec/specs/)
|
|
787
|
+
```
|
|
788
|
+
|
|
789
|
+
### Views
|
|
790
|
+
|
|
791
|
+
| View | Description |
|
|
792
|
+
|------|-------------|
|
|
793
|
+
| **Clusters** | Colour-coded architectural clusters with expandable member nodes |
|
|
794
|
+
| **Flat** | Force-directed dependency graph (all nodes) |
|
|
795
|
+
| **Architecture** | High-level cluster map: role-coloured boxes, inter-cluster dependency arrows |
|
|
796
|
+
|
|
797
|
+
### Diagram Chat
|
|
798
|
+
|
|
799
|
+
The right sidebar includes a **Diagram Chat** panel powered by an LLM agent. The chat can access all analysis tools and interact with the graph:
|
|
800
|
+
|
|
801
|
+
- Ask questions about your codebase in natural language
|
|
802
|
+
- Graph functions and requirements mentioned in answers are automatically highlighted
|
|
803
|
+
- Clusters containing highlighted nodes auto-expand to reveal the nodes
|
|
804
|
+
- Select a node in the chat to view its details tab
|
|
805
|
+
|
|
806
|
+
Example queries:
|
|
807
|
+
- "What are the most critical functions?"
|
|
808
|
+
- "Where would I add a new API endpoint?"
|
|
809
|
+
- "Show me the impact of changing the authentication service"
|
|
810
|
+
|
|
811
|
+
The chat requires an LLM API key (same provider configuration as `spec-gen generate`). Viewer-only operations like graph browsing, skeleton view, and search do not require an API key.
|
|
812
|
+
|
|
813
|
+
### Right panel tabs (select a node to activate)
|
|
814
|
+
|
|
815
|
+
| Tab | Content |
|
|
816
|
+
|-----|---------|
|
|
817
|
+
| **Node** | File metadata: exports, language, score |
|
|
818
|
+
| **Links** | Direct callers and callees |
|
|
819
|
+
| **Blast** | Downstream impact radius |
|
|
820
|
+
| **Spec** | Requirements linked to the selected file -- body, domain, confidence |
|
|
821
|
+
| **Skeleton** | Noise-stripped source: logs and comments removed, structure preserved |
|
|
822
|
+
| **Info** | Global stats and top-ranked files |
|
|
823
|
+
|
|
824
|
+
### Search
|
|
825
|
+
|
|
826
|
+
The search bar filters all three views simultaneously (text match on name, path, exports, tags). If a vector index was built with `--embed`, typing >= 3 characters also queries the semantic index and shows the top 5 function matches in a dropdown.
|
|
827
|
+
|
|
828
|
+
### Automatic data loading
|
|
829
|
+
|
|
830
|
+
The viewer auto-loads all available data on startup:
|
|
831
|
+
|
|
832
|
+
| Endpoint | Source | Required? |
|
|
833
|
+
|----------|--------|-----------|
|
|
834
|
+
| `/api/dependency-graph` | `.spec-gen/analysis/dependency-graph.json` | Yes |
|
|
835
|
+
| `/api/llm-context` | `.spec-gen/analysis/llm-context.json` | No |
|
|
836
|
+
| `/api/refactor-priorities` | `.spec-gen/analysis/refactor-priorities.json` | No |
|
|
837
|
+
| `/api/mapping` | `.spec-gen/analysis/mapping.json` | No |
|
|
838
|
+
| `/api/spec-requirements` | `openspec/specs/**/*.md` + `mapping.json` | No |
|
|
839
|
+
| `/api/skeleton?file=` | Source file on disk | No |
|
|
840
|
+
| `/api/search?q=` | `.spec-gen/analysis/vector-index/` | No (`--embed`) |
|
|
841
|
+
|
|
842
|
+
Run `spec-gen generate` to produce `mapping.json` and the spec files. Once present, the **Spec** tab shows the full requirement body for each selected file.
|
|
843
|
+
|
|
844
|
+
### View Options
|
|
845
|
+
|
|
846
|
+
```bash
|
|
847
|
+
spec-gen view [options]
|
|
848
|
+
--analysis <path> Analysis directory (default: .spec-gen/analysis/)
|
|
849
|
+
--spec <path> Spec files directory (default: ./openspec/specs/)
|
|
850
|
+
--port <n> Port (default: 5173)
|
|
851
|
+
--host <host> Bind host (default: 127.0.0.1; use 0.0.0.0 for LAN)
|
|
852
|
+
--no-open Skip automatic browser open
|
|
853
|
+
```
|
|
854
|
+
|
|
855
|
+
## Output
|
|
856
|
+
|
|
857
|
+
spec-gen writes to the OpenSpec directory structure:
|
|
858
|
+
|
|
859
|
+
```
|
|
860
|
+
openspec/
|
|
861
|
+
config.yaml # Project metadata
|
|
862
|
+
specs/
|
|
863
|
+
overview/spec.md # System overview
|
|
864
|
+
architecture/spec.md # Architecture
|
|
865
|
+
auth/spec.md # Domain: Authentication
|
|
866
|
+
user/spec.md # Domain: User management
|
|
867
|
+
api/spec.md # API specification
|
|
868
|
+
decisions/ # With --adr flag
|
|
869
|
+
index.md # ADR index
|
|
870
|
+
adr-0001-*.md # Individual decisions
|
|
871
|
+
```
|
|
872
|
+
|
|
873
|
+
Each spec uses RFC 2119 keywords (SHALL, MUST, SHOULD), Given/When/Then scenarios, and technical notes linking to implementation files.
|
|
874
|
+
|
|
875
|
+
### Analysis Artifacts
|
|
876
|
+
|
|
877
|
+
Static analysis output is stored in `.spec-gen/analysis/`:
|
|
878
|
+
|
|
879
|
+
| File | Description |
|
|
880
|
+
|------|-------------|
|
|
881
|
+
| `repo-structure.json` | Project structure and metadata |
|
|
882
|
+
| `dependency-graph.json` | Import/export relationships |
|
|
883
|
+
| `llm-context.json` | Context prepared for LLM (signatures, call graph) |
|
|
884
|
+
| `dependencies.mermaid` | Visual dependency graph |
|
|
885
|
+
| `SUMMARY.md` | Human-readable analysis summary |
|
|
886
|
+
| `call-graph.json` | Function-level call graph (7 languages) |
|
|
887
|
+
| `refactor-priorities.json` | Refactoring issues by file and function |
|
|
888
|
+
| `mapping.json` | Requirement->function mapping (produced by `generate`) |
|
|
889
|
+
| `vector-index/` | LanceDB semantic index (produced by `--embed`) |
|
|
890
|
+
|
|
891
|
+
`spec-gen analyze` also writes **`ARCHITECTURE.md`** to your project root -- a Markdown overview of module clusters, entry points, and critical hubs, refreshed on every run.
|
|
892
|
+
|
|
893
|
+
## Semantic Search
|
|
894
|
+
|
|
895
|
+
`spec-gen analyze --embed` builds a vector index over all functions in the call graph, enabling natural-language search via the `search_code` and `suggest_insertion_points` MCP tools, and the search bar in the viewer.
|
|
896
|
+
|
|
897
|
+
### Embedding configuration
|
|
898
|
+
|
|
899
|
+
Provide an OpenAI-compatible embedding endpoint (Ollama, OpenAI, Mistral, etc.) via environment variables or `.spec-gen/config.json`:
|
|
900
|
+
|
|
901
|
+
**Environment variables:**
|
|
902
|
+
```bash
|
|
903
|
+
EMBED_BASE_URL=https://api.openai.com/v1
|
|
904
|
+
EMBED_MODEL=text-embedding-3-small
|
|
905
|
+
EMBED_API_KEY=sk-... # optional for local servers
|
|
906
|
+
|
|
907
|
+
# Then run:
|
|
908
|
+
spec-gen analyze --embed
|
|
909
|
+
```
|
|
910
|
+
|
|
911
|
+
**Config file (`.spec-gen/config.json`):**
|
|
912
|
+
```json
|
|
913
|
+
{
|
|
914
|
+
"embedding": {
|
|
915
|
+
"baseUrl": "http://localhost:11434/v1",
|
|
916
|
+
"model": "nomic-embed-text"
|
|
917
|
+
}
|
|
918
|
+
}
|
|
919
|
+
```
|
|
920
|
+
|
|
921
|
+
The index is stored in `.spec-gen/analysis/vector-index/` and is automatically used by the viewer's search bar and the `search_code` / `suggest_insertion_points` MCP tools.
|
|
922
|
+
|
|
923
|
+
## Configuration
|
|
924
|
+
|
|
925
|
+
`spec-gen init` creates `.spec-gen/config.json`:
|
|
926
|
+
|
|
927
|
+
```json
|
|
928
|
+
{
|
|
929
|
+
"version": "1.0.0",
|
|
930
|
+
"projectType": "nodejs",
|
|
931
|
+
"openspecPath": "./openspec",
|
|
932
|
+
"analysis": {
|
|
933
|
+
"maxFiles": 500,
|
|
934
|
+
"includePatterns": [],
|
|
935
|
+
"excludePatterns": []
|
|
936
|
+
},
|
|
937
|
+
"generation": {
|
|
938
|
+
"model": "claude-sonnet-4-20250514",
|
|
939
|
+
"domains": "auto"
|
|
940
|
+
}
|
|
941
|
+
}
|
|
942
|
+
```
|
|
943
|
+
|
|
944
|
+
### Environment Variables
|
|
945
|
+
|
|
946
|
+
| Variable | Provider | Description |
|
|
947
|
+
|----------|----------|-------------|
|
|
948
|
+
| `ANTHROPIC_API_KEY` | `anthropic` | Anthropic API key |
|
|
949
|
+
| `ANTHROPIC_API_BASE` | `anthropic` | Custom base URL (proxy / self-hosted) |
|
|
950
|
+
| `OPENAI_API_KEY` | `openai` | OpenAI API key |
|
|
951
|
+
| `OPENAI_API_BASE` | `openai` | Custom base URL (Azure, proxy...) |
|
|
952
|
+
| `OPENAI_COMPAT_API_KEY` | `openai-compat` | API key for OpenAI-compatible server |
|
|
953
|
+
| `OPENAI_COMPAT_BASE_URL` | `openai-compat` | Base URL, e.g. `https://api.mistral.ai/v1` |
|
|
954
|
+
| `GEMINI_API_KEY` | `gemini` | Google Gemini API key |
|
|
955
|
+
| `DEBUG` | -- | Enable stack traces on errors |
|
|
956
|
+
| `CI` | -- | Auto-detected; enables timestamps in output |
|
|
957
|
+
|
|
958
|
+
## Requirements
|
|
959
|
+
|
|
960
|
+
- Node.js 20+
|
|
961
|
+
- API key for `generate`, `verify`, and `drift --use-llm` -- set the env var for your chosen provider:
|
|
962
|
+
```bash
|
|
963
|
+
export ANTHROPIC_API_KEY=sk-ant-... # Anthropic (default)
|
|
964
|
+
export OPENAI_API_KEY=sk-... # OpenAI
|
|
965
|
+
export OPENAI_COMPAT_API_KEY=ollama # OpenAI-compatible local server
|
|
966
|
+
export GEMINI_API_KEY=... # Google Gemini
|
|
967
|
+
```
|
|
968
|
+
- `analyze`, `drift`, and `init` require no API key
|
|
969
|
+
|
|
970
|
+
## Supported Languages
|
|
971
|
+
|
|
972
|
+
| Language | Signatures | Call Graph |
|
|
973
|
+
|----------|-----------|------------|
|
|
974
|
+
| TypeScript / JavaScript | Full | Full |
|
|
975
|
+
| Python | Full | Full |
|
|
976
|
+
| Go | Full | Full |
|
|
977
|
+
| Rust | Full | Full |
|
|
978
|
+
| Ruby | Full | Full |
|
|
979
|
+
| Java | Full | Full |
|
|
980
|
+
|
|
981
|
+
TypeScript projects get the best results due to richer type information.
|
|
982
|
+
|
|
983
|
+
## Usage Options
|
|
984
|
+
|
|
985
|
+
**CLI Tool** (recommended):
|
|
986
|
+
```bash
|
|
987
|
+
spec-gen init && spec-gen analyze && spec-gen generate && spec-gen drift --install-hook
|
|
988
|
+
```
|
|
989
|
+
|
|
990
|
+
**Claude Code Skill**: Copy `skills/claude-spec-gen.md` to `.claude/skills/` in your project.
|
|
991
|
+
|
|
992
|
+
**OpenSpec Skill**: Copy `skills/openspec-skill.md` to your OpenSpec skills directory.
|
|
993
|
+
|
|
994
|
+
**Direct LLM Prompting**: Use `AGENTS.md` as a system prompt for any LLM.
|
|
995
|
+
|
|
996
|
+
**Programmatic API**: Import spec-gen as a library in your own tools.
|
|
997
|
+
|
|
998
|
+
## Programmatic API
|
|
999
|
+
|
|
1000
|
+
spec-gen exposes a typed Node.js API for integration into other tools (like [OpenSpec CLI](https://github.com/Fission-AI/OpenSpec)). Every CLI command has a corresponding API function that returns structured results instead of printing to the console.
|
|
1001
|
+
|
|
1002
|
+
```bash
|
|
1003
|
+
npm install spec-gen
|
|
1004
|
+
```
|
|
1005
|
+
|
|
1006
|
+
```typescript
|
|
1007
|
+
import { specGenAnalyze, specGenDrift, specGenRun } from 'spec-gen';
|
|
1008
|
+
|
|
1009
|
+
// Run the full pipeline
|
|
1010
|
+
const result = await specGenRun({
|
|
1011
|
+
rootPath: '/path/to/project',
|
|
1012
|
+
adr: true,
|
|
1013
|
+
onProgress: (event) => console.log(`[${event.phase}] ${event.step}`),
|
|
1014
|
+
});
|
|
1015
|
+
console.log(`Generated ${result.generation.report.filesWritten.length} specs`);
|
|
1016
|
+
|
|
1017
|
+
// Check for drift
|
|
1018
|
+
const drift = await specGenDrift({
|
|
1019
|
+
rootPath: '/path/to/project',
|
|
1020
|
+
failOn: 'warning',
|
|
1021
|
+
});
|
|
1022
|
+
if (drift.hasDrift) {
|
|
1023
|
+
console.warn(`${drift.summary.total} drift issues found`);
|
|
1024
|
+
}
|
|
1025
|
+
|
|
1026
|
+
// Static analysis only (no API key needed)
|
|
1027
|
+
const analysis = await specGenAnalyze({
|
|
1028
|
+
rootPath: '/path/to/project',
|
|
1029
|
+
maxFiles: 1000,
|
|
1030
|
+
});
|
|
1031
|
+
console.log(`Analyzed ${analysis.repoMap.summary.analyzedFiles} files`);
|
|
1032
|
+
```
|
|
1033
|
+
|
|
1034
|
+
### API Functions
|
|
1035
|
+
|
|
1036
|
+
| Function | Description | API Key |
|
|
1037
|
+
|----------|-------------|---------|
|
|
1038
|
+
| `specGenInit(options?)` | Initialize config and openspec directory | No |
|
|
1039
|
+
| `specGenAnalyze(options?)` | Run static analysis | No |
|
|
1040
|
+
| `specGenGenerate(options?)` | Generate specs from analysis | Yes |
|
|
1041
|
+
| `specGenVerify(options?)` | Verify spec accuracy | Yes |
|
|
1042
|
+
| `specGenDrift(options?)` | Detect spec-to-code drift | No* |
|
|
1043
|
+
| `specGenRun(options?)` | Full pipeline: init + analyze + generate | Yes |
|
|
1044
|
+
|
|
1045
|
+
\* `specGenDrift` requires an API key only when `llmEnhanced: true`.
|
|
1046
|
+
|
|
1047
|
+
All functions accept an optional `onProgress` callback for status updates and throw errors instead of calling `process.exit`. See [src/api/types.ts](src/api/types.ts) for full option and result type definitions.
|
|
1048
|
+
|
|
1049
|
+
## Examples
|
|
1050
|
+
|
|
1051
|
+
| Example | Description |
|
|
1052
|
+
|---------|-------------|
|
|
1053
|
+
| [examples/openspec-analysis/](examples/openspec-analysis/) | Static analysis output from `spec-gen analyze` |
|
|
1054
|
+
| [examples/openspec-cli/](examples/openspec-cli/) | Specifications generated with `spec-gen generate` |
|
|
1055
|
+
| [examples/drift-demo/](examples/drift-demo/) | Sample project configured for drift detection |
|
|
1056
|
+
|
|
1057
|
+
## Development
|
|
1058
|
+
|
|
1059
|
+
```bash
|
|
1060
|
+
npm install # Install dependencies
|
|
1061
|
+
npm run dev # Development mode (watch)
|
|
1062
|
+
npm run build # Build
|
|
1063
|
+
npm run test:run # Run tests (1052 unit tests)
|
|
1064
|
+
npm run typecheck # Type check
|
|
1065
|
+
```
|
|
1066
|
+
|
|
1067
|
+
1052 unit tests covering static analysis, call graph, refactor analysis, spec mapping, drift detection, LLM enhancement, ADR generation, and the full CLI.
|
|
1068
|
+
|
|
1069
|
+
## Links
|
|
1070
|
+
|
|
1071
|
+
- [OpenSpec](https://github.com/Fission-AI/OpenSpec) - Spec-driven development framework
|
|
1072
|
+
- [Architecture](docs/ARCHITECTURE.md) - Internal design and module organization
|
|
1073
|
+
- [Algorithms](docs/ALGORITHMS.md) - Analysis algorithms
|
|
1074
|
+
- [OpenSpec Integration](docs/OPENSPEC-INTEGRATION.md) - How spec-gen integrates with OpenSpec
|
|
1075
|
+
- [OpenSpec Format](docs/OPENSPEC-FORMAT.md) - Spec format reference
|
|
1076
|
+
- [Philosophy](docs/PHILOSOPHY.md) - "Archaeology over Creativity"
|
|
1077
|
+
- [Troubleshooting](docs/TROUBLESHOOTING.md) - Common issues and solutions
|
|
1078
|
+
- [AGENTS.md](AGENTS.md) - LLM system prompt for direct prompting
|