Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 27 additions & 41 deletions .code-reducer.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,26 @@ model_id: ornith:9b
ollama_base_url: http://localhost:11434
ollama_num_ctx: 20000
docs_dir: wiki

system_prompt: |
You are Code-Reducer, an expert technical writer and code analyzer. Your job is to strictly follow instructions. You do not yap, you do not write filler.
DEFENSIVE RULES: 1. Do NOT use absolute terms ('always', 'never', 'zero') unless explicitly proven. 2. Do NOT guess downstream consequences or invent unhandled paths. If an error is swallowed, just say it is swallowed. 3. Do NOT name standard library packages unless explicitly stated in the source text. 4. Only report facts you are 100% sure about.

module_synthesis_prompt: |-
Task: Write a technical documentation page for a code module based on the provided list of its internal components.
Rule 1: Group related functions and classes under appropriate Markdown headings.
Rule 2: Explain the responsibility of the module and the data flow.
Rule 3: Keep it highly technical and dense.

architecture_prompt: |-
Task: Write a global architecture or quickstart document based on the module summaries.
Rule 1: Explain the system boundaries and how the modules interact.
Rule 2: Provide a dense, developer-friendly overview.

file_fact_consolidation_prompt: |-
You are a specialized code documentation assistant.
Consolidate, deduplicate and merge the following facts extracted from different chunks of the same file into a single, cohesive summary.

extraction_steps:
- name: API_SIGNATURES
prompt: |-
Expand All @@ -19,45 +39,11 @@ extraction_steps:
prompt: |-
Task: Analyze side effects and error handling.
Output: Detail how this code communicates with the outside world (I/O like network, disk, DB) and how it handles/returns errors (wrap, sentinel, panic).

ignore:
- .git
- node_modules
- bower_components
- dist
- build
- cache
- __pycache__
- .pytest_cache
- .mypy_cache
- .tox
- venv
- .venv
- code-reducer
- .gemini
- .code-reducer.yaml
- .code-reducer.lock
- AGENTS.md
- README.md
- go.sum
- .gitignore
ignore_extensions:
- .png
- .jpg
- .jpeg
- .gif
- .pdf
- .exe
- .dll
- .so
- .o
- .a
- .zip
- .gz
- .tar
- .lock
- .pyc
- .pyo
- .pyd
- -lock.json
- .lock.yaml
- pnpm-lock.yaml
- README.md
- .code-reducer.yaml
- go.sum
- go.mod
- screeshots
- examples
12 changes: 9 additions & 3 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,19 @@ jobs:
goarch: "386"
steps:
- name: Checkout Repository
uses: actions/checkout@v7
uses: actions/checkout@v4

- name: Set up Go
uses: actions/setup-go@v6
uses: actions/setup-go@v5
with:
go-version: '1.26'

- name: Run Vet
run: go vet ./...

- name: Run Tests
run: go test -race -v ./...

- name: Build Binary
env:
GOOS: ${{ matrix.goos }}
Expand Down Expand Up @@ -55,7 +61,7 @@ jobs:
fi

- name: Upload to Release
uses: softprops/action-gh-release@v3
uses: softprops/action-gh-release@v2
with:
files: ${{ steps.package.outputs.asset_path }}
env:
Expand Down
16 changes: 15 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,16 @@
.code-reducer.lock
code-reducer
code-reducer

# IDEs and Editors
.idea/
.vscode/
*.suo
*.ntvs*
*.njsproj
*.sln
*.swp

# Build output
dist/
tmp/
*.tmp.*
133 changes: 78 additions & 55 deletions README.md

Large diffs are not rendered by default.

12 changes: 6 additions & 6 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import (
)

var (
modelIdFlag string
modelIDFlag string
numCtxFlag string
)

Expand All @@ -30,7 +30,7 @@ var RootCmd = &cobra.Command{
}

func init() {
RootCmd.PersistentFlags().StringVar(&modelIdFlag, "model-id", "", "Specify LLM model ID")
RootCmd.PersistentFlags().StringVar(&modelIDFlag, "model-id", "", "Specify LLM model ID")
RootCmd.PersistentFlags().StringVar(&numCtxFlag, "num-ctx", "", "Specify Ollama context window size")
}

Expand Down Expand Up @@ -59,7 +59,7 @@ func executeCommand(mode string) error {
}

// Resolve the merged configuration
cfg, err := config.ResolveConfig(repoRoot, modelIdFlag, numCtxFlag)
cfg, err := config.ResolveConfig(repoRoot, modelIDFlag, numCtxFlag)
if err != nil {
return err
}
Expand All @@ -81,10 +81,10 @@ func executeCommand(mode string) error {
defer stop()

runner := engine.NewRunner(cfg)
err = runner.Run(ctx, repoRoot, mode, func(ev engine.Event) {
if ev.Type == "status" {
err = runner.Run(ctx, repoRoot, engine.Mode(mode), func(ev engine.Event) {
if ev.Type == engine.EventStatus {
fmt.Println(ev.Message)
} else if ev.Type == "error" {
} else if ev.Type == engine.EventError {
fmt.Fprintf(os.Stderr, "Error: %s\n", ev.Message)
} else {
fmt.Println(ev.Message)
Expand Down
79 changes: 36 additions & 43 deletions cmd/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,46 +67,28 @@ func RunSetupFlow(repoRoot string) error {
}

var customIgnores []string
var customExtensions []string

if existingCfg != nil {
customIgnores = subtractSlice(existingCfg.Ignore, config.DefaultIgnores)
customExtensions = subtractSlice(existingCfg.IgnoreExtensions, config.DefaultIgnoredExtensions)
customIgnores = existingCfg.Ignore
}

userInputIgnores, ignoresModified := promptStringList(reader, "Enter custom directories/files to ignore (comma-separated)", customIgnores)
userInputIgnores, ignoresModified := promptStringList(reader, "Enter directories, files, or patterns to ignore (comma-separated)", customIgnores)
var ignores []string
if ignoresModified {
if len(userInputIgnores) > 0 {
ignores = config.MergeAndDeduplicate(config.DefaultIgnores, userInputIgnores)
ignores = userInputIgnores
} else {
ignores = []string{}
}
} else {
if existingCfg != nil {
ignores = existingCfg.Ignore
} else {
ignores = config.DefaultIgnores
}
}

userInputExtensions, extensionsModified := promptStringList(reader, "Enter custom file extensions to ignore (comma-separated)", customExtensions)
var ignoreExtensions []string
if extensionsModified {
if len(userInputExtensions) > 0 {
ignoreExtensions = config.MergeAndDeduplicate(config.DefaultIgnoredExtensions, userInputExtensions)
} else {
ignoreExtensions = []string{}
}
} else {
if existingCfg != nil {
ignoreExtensions = existingCfg.IgnoreExtensions
} else {
ignoreExtensions = config.DefaultIgnoredExtensions
ignores = []string{}
}
}

existingDocsDir := "wiki"
existingDocsDir := config.DefaultDocsDir
if existingCfg != nil && existingCfg.DocsDir != "" {
existingDocsDir = existingCfg.DocsDir
}
Expand All @@ -119,14 +101,37 @@ func RunSetupFlow(repoRoot string) error {
extractionSteps = config.DefaultExtractionSteps
}

existingSystemPrompt := config.DefaultSystemPrompt
existingModuleSynthesisPrompt := config.DefaultModuleSynthesisPrompt
existingArchitecturePrompt := config.DefaultArchitecturePrompt
existingFileFactConsolidationPrompt := config.DefaultFileFactConsolidationPrompt

if existingCfg != nil {
if existingCfg.SystemPrompt != "" {
existingSystemPrompt = existingCfg.SystemPrompt
}
if existingCfg.ModuleSynthesisPrompt != "" {
existingModuleSynthesisPrompt = existingCfg.ModuleSynthesisPrompt
}
if existingCfg.ArchitecturePrompt != "" {
existingArchitecturePrompt = existingCfg.ArchitecturePrompt
}
if existingCfg.FileFactConsolidationPrompt != "" {
existingFileFactConsolidationPrompt = existingCfg.FileFactConsolidationPrompt
}
}

newCfg := &config.Config{
ModelID: modelInput,
OllamaBaseURL: urlInput,
OllamaNumCtx: numCtx,
DocsDir: docsDirInput,
ExtractionSteps: extractionSteps,
Ignore: ignores,
IgnoreExtensions: ignoreExtensions,
ModelID: modelInput,
OllamaBaseURL: urlInput,
OllamaNumCtx: numCtx,
DocsDir: docsDirInput,
ExtractionSteps: extractionSteps,
Ignore: ignores,
SystemPrompt: existingSystemPrompt,
ModuleSynthesisPrompt: existingModuleSynthesisPrompt,
ArchitecturePrompt: existingArchitecturePrompt,
FileFactConsolidationPrompt: existingFileFactConsolidationPrompt,
}

err = config.SaveConfig(repoRoot, newCfg)
Expand Down Expand Up @@ -191,16 +196,4 @@ func promptString(reader *bufio.Reader, promptMsg, existingVal string) string {
return input
}

func subtractSlice[T comparable](a, b []T) []T {
bMap := make(map[T]bool)
for _, item := range b {
bMap[item] = true
}
var result []T
for _, item := range a {
if !bMap[item] {
result = append(result, item)
}
}
return result
}

48 changes: 48 additions & 0 deletions examples/go/.code-reducer.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Example .code-reducer.yaml for analyzing Go projects
model_id: "ornith:9b"
ollama_base_url: "http://localhost:11434"
ollama_num_ctx: 8192
docs_dir: "wiki"

# System Prompt defines the AI persona
system_prompt: |
You are Code-Reducer, an expert technical writer and Go code analyzer. Your job is to strictly follow instructions. You do not yap, you do not write filler.
DEFENSIVE RULES:
1. Do NOT use absolute terms ('always', 'never', 'zero') unless explicitly proven.
2. Do NOT guess downstream consequences or invent unhandled paths. If an error is swallowed, just say it is swallowed.
3. Do NOT name standard library packages unless explicitly stated in the source text.
4. Only report facts you are 100% sure about.

# Prompts for synthesized output
module_synthesis_prompt: |
Task: Write a technical documentation page for a code module based on the provided list of its internal components.
Rule 1: Group related functions and classes under appropriate Markdown headings.
Rule 2: Explain the responsibility of the module and the data flow.
Rule 3: Keep it highly technical and dense.

architecture_prompt: |
Task: Write a global architecture or quickstart document based on the module summaries.
Rule 1: Explain the system boundaries and how the modules interact.
Rule 2: Provide a dense, developer-friendly overview.

file_fact_consolidation_prompt: |
You are a specialized code documentation assistant. Consolidate, deduplicate and merge the following facts extracted from different chunks of the same file into a single, cohesive summary.

# Custom extraction steps during map phase
extraction_steps:
- name: "API_SIGNATURES"
prompt: |
Task: Extract the public surface area of the file.
Output: A strict Markdown list of all exported structs, interfaces, and methods. For each, note the actual input and output types. Ignore internal logic.
- name: "BUSINESS_LOGIC"
prompt: |
Task: Analyze the business logic and domain concepts.
Output: Explain what business rules or domain concepts this file solves. Describe the high-level algorithmic flow. Ignore implementation details.
- name: "STATE_AND_CONCURRENCY"
prompt: |
Task: Analyze state mutation and concurrency.
Output: List all mutable state (global variables, changing struct fields) and what concurrency mechanisms (e.g., sync.Mutex, channels) protect them. If none, state 'No mutable state'.
- name: "ERRORS_AND_SIDE_EFFECTS"
prompt: |
Task: Analyze side effects and error handling.
Output: Detail how this code communicates with the outside world (I/O like network, disk, DB) and how it handles/returns errors (wrap, sentinel, panic).
55 changes: 55 additions & 0 deletions examples/terraform/.code-reducer.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Example .code-reducer.yaml for analyzing Terraform infrastructure projects
model_id: "ornith:9b"
ollama_base_url: "http://localhost:11434"
ollama_num_ctx: 8192
docs_dir: "wiki"

# Tell the LLM to behave as a Cloud Architect and IaC analyzer
system_prompt: |
You are Code-Reducer, an expert Cloud Architect and Terraform infrastructure analyzer. Your job is to strictly follow instructions. You do not yap, you do not write filler.
DEFENSIVE RULES:
1. Do NOT assume resources exist unless explicitly declared in the configuration.
2. Do NOT guess downstream resource side effects unless directly linked (e.g., via security group attachments or subnet associations).
3. Only report resource definitions and configurations you are 100% sure about.

# Synthesis prompt for directory modules (which represent infrastructure sub-components)
module_synthesis_prompt: |
Task: Write a technical documentation page for a Terraform module based on the provided list of its internal resources, variables, and sub-modules.
Rule 1: Group related resources (e.g., networking, compute, database, IAM) under appropriate Markdown headings.
Rule 2: Explain the primary responsibility of this module, the resource dependency flow, and security configurations.
Rule 3: Keep it highly technical, listing key resources, inputs, and outputs.

# Synthesis prompt for the global infrastructure overview
architecture_prompt: |
Task: Write a global cloud architecture overview and deployment guide based on the module summaries.
Rule 1: Explain the high-level cloud topology, provider requirements, and how modules connect (e.g., VPC connecting to EKS and RDS).
Rule 2: Provide a dense, developer-friendly infrastructure overview and standard Terraform deployment commands (init, plan, apply).

file_fact_consolidation_prompt: |
You are a specialized infrastructure documentation assistant. Consolidate, deduplicate and merge the following facts extracted from different chunks of the same Terraform file into a single, cohesive summary.

# Custom extraction steps during map phase
extraction_steps:
- name: "PROVISIONED_RESOURCES"
prompt: |
Task: Extract resources and data sources defined in this file.
Output: A strict Markdown list of all resources (`resource "type" "name"`) and data sources (`data "type" "name"`). Note key parameters (e.g. instance type, VPC CIDR, backend configurations).
- name: "VARIABLES_AND_OUTPUTS"
prompt: |
Task: Analyze input variables, outputs, and local variables.
Output: List all input variables (with types and default values) and outputs exported by this file. Mention any complex local variables (`locals`) that define key configurations.
- name: "MODULE_DEPENDENCIES"
prompt: |
Task: Analyze sub-module usage.
Output: Identify any external or internal modules called in this file (`module "name"`), their source paths, and the key inputs passed to them.
- name: "IAM_AND_SECURITY"
prompt: |
Task: Analyze permissions, IAM roles, and security groups.
Output: Detail security groups, firewall rules, IAM roles, policies, and KMS keys defined in this file. Outline what access permissions or network paths they allow.

# Ignore Terraform state, local plugins, and lock files
ignore:
- ".terraform"
- "*.tfstate"
- "*.tfstate.backup"
- ".terraform.lock.hcl"
Loading