Skip to content

feat: add LLM-friendly commands (env info, project doctor, project explain, project scaffold) #39

@rios0rios0

Description

@rios0rios0

Summary

DevForge currently manages repositories, project lifecycle, and Docker — but lacks capabilities that help LLMs and developers quickly understand, diagnose, and bootstrap projects. This issue proposes four new commands that make DevForge a tool LLMs can invoke to reason about codebases.

This was identified by comparing DevForge with Lino, a .NET-specific scaffolding CLI. While Lino's code generation features are too framework-specific to port, the gap in project introspection and structured output for machine consumption is clear. All four commands support a --json flag for LLM-consumable structured output.


Motivation

  • LLM-friendliness: An LLM working on a codebase can run dev project explain . --json to instantly understand architecture, entry points, dependencies, and patterns — without reading dozens of files.
  • Developer onboarding: dev project doctor and dev project explain reduce the time to understand a new project from minutes to seconds.
  • Project bootstrapping: dev project scaffold brings the existing Claude Code scaffolding skills into the CLI, making them available to any LLM or automation.
  • Environment debugging: dev env info --json gives an LLM (or developer) a complete picture of installed tools and auth status in one command.

Implementation Order and Dependencies

Feature 1: dev env info          (simplest, introduces --json output pattern)
    │
    v
Feature 2: dev project doctor    (reuses JSON pattern, introduces ProjectChecker interface)
    │
    v
Feature 3: dev project explain   (reuses ProjectChecker, adds architecture analysis)
    │
    v
Feature 4: dev project scaffold  (most complex, uses embedded templates)

Features 1 and 2 are mostly independent and could be implemented in parallel. Feature 3 reuses ProjectChecker from Feature 2. Feature 4 is fully independent but benefits from patterns established by the first three.


Feature 1: dev env info

Purpose: Dump all installed tooling versions, Git provider auth status, and shell info in one structured output. An LLM debugging "why won't this build" can run this first.

Usage

dev env info          # human-readable output
dev env info --json   # structured JSON for LLM consumption

Example JSON Output

{
  "devforge_version": "0.5.0",
  "tools": [
    {"name": "go", "version": "1.23.0", "installed": true},
    {"name": "node", "version": "20.11.0", "installed": true},
    {"name": "python3", "version": "3.12.1", "installed": true},
    {"name": "java", "version": "", "installed": false},
    {"name": "docker", "version": "24.0.7", "installed": true},
    {"name": "git", "version": "2.43.0", "installed": true},
    {"name": "make", "version": "4.4.1", "installed": true},
    {"name": "terraform", "version": "", "installed": false}
  ],
  "auth": [
    {"provider": "github", "env_var": "GH_TOKEN", "set": true},
    {"provider": "azuredevops", "env_var": "AZURE_DEVOPS_EXT_PAT", "set": false},
    {"provider": "gitlab", "env_var": "GITLAB_TOKEN", "set": false}
  ],
  "shell": "/bin/zsh"
}

New Files

File Purpose
internal/env/runner.go ToolRunner interface + DefaultToolRunner (wraps exec.Command for version checks)
internal/env/info.go RunInfo function, InfoConfig, EnvReport, ToolStatus, AuthStatus types
internal/env/info_test.go BDD parallel tests
internal/testutil/doubles/tool_runner_stub.go Test double for ToolRunner

Key Interfaces

// ToolRunner abstracts external tool version detection for testability.
type ToolRunner interface {
    Version(tool string, args ...string) (string, error)
    EnvVar(name string) string
}

Design Details

  • Mapper from tool name to version-check arguments (no switch/case):
    var toolVersionArgs = map[string][]string{
        "go": {"version"}, "node": {"--version"}, "python3": {"--version"},
        "java": {"-version"}, "docker": {"--version"}, "git": {"--version"},
        "make": {"--version"}, "terraform": {"version"},
    }
  • Auth token check uses env vars: GH_TOKEN, AZURE_DEVOPS_EXT_PAT, GITLAB_TOKEN
  • CLI wiring: new envCmd command group in main.go with newEnvInfoCmd() factory

Feature 2: dev project doctor [path]

Purpose: Run project health diagnostics with structured pass/warn/fail results. An LLM can parse the output to identify and fix issues automatically.

Usage

dev project doctor .          # human-readable with status symbols
dev project doctor . --json   # structured JSON

Example JSON Output

{
  "language": "go",
  "checks": [
    {"category": "sdk", "name": "SDK installed", "status": "pass", "detail": "go 1.23.0"},
    {"category": "tools", "name": "make", "status": "pass"},
    {"category": "tools", "name": "docker", "status": "pass"},
    {"category": "tools", "name": "git", "status": "pass"},
    {"category": "makefile", "name": "target: lint", "status": "pass"},
    {"category": "makefile", "name": "target: test", "status": "pass"},
    {"category": "makefile", "name": "target: sast", "status": "warn", "detail": "target not found in Makefile"},
    {"category": "docs", "name": "README.md", "status": "pass"},
    {"category": "docs", "name": "CHANGELOG.md", "status": "pass"},
    {"category": "docs", "name": "CONTRIBUTING.md", "status": "fail", "detail": "file not found"},
    {"category": "ci", "name": "CI/CD config", "status": "pass", "detail": ".github/workflows/"}
  ],
  "summary": {"pass": 9, "warn": 1, "fail": 1}
}

New Files

File Purpose
internal/project/checker.go ProjectChecker interface + DefaultProjectChecker
internal/project/doctor.go RunDoctor function, DoctorConfig, CheckResult, DoctorReport types
internal/project/doctor_test.go BDD parallel tests
internal/testutil/doubles/project_checker_stub.go Test double for ProjectChecker

Key Interfaces

// ProjectChecker abstracts filesystem checks for testability.
type ProjectChecker interface {
    FileExists(path string) bool
    ReadFile(path string) (string, error)
    ToolExists(name string) bool
}

Health Checks (mapper pattern — slice of check functions, no switch/case)

Check Category Logic
SDK installed sdk info.CurrentVersion != ""
Required tools tools checker.ToolExists("make"), "docker", "git"
Makefile targets makefile Read Makefile, regex for lint:, test:, sast:, build:
Documentation docs checker.FileExists("README.md"), CHANGELOG.md, CONTRIBUTING.md
CI/CD config ci Check .github/workflows/ or .gitlab-ci.yml or azure-pipelines.yml

Feature 3: dev project explain [path]

Purpose: Machine-readable project analysis. This is the highest-value LLM feature — an LLM runs this to instantly understand a codebase's architecture, entry points, dependencies, and patterns before making changes.

Usage

dev project explain .          # human-readable sections
dev project explain . --json   # structured JSON for LLM consumption

Example JSON Output

{
  "language": "go",
  "sdk_version": "1.23.0",
  "required_version": "1.23",
  "dependencies": [
    {"name": "github.com/spf13/cobra", "version": "v1.8.0", "source_file": "go.mod"},
    {"name": "github.com/sirupsen/logrus", "version": "v1.9.3", "source_file": "go.mod"},
    {"name": "github.com/rios0rios0/langforge", "version": "v0.3.0", "source_file": "go.mod"},
    {"name": "github.com/rios0rios0/gitforge", "version": "v0.2.0", "source_file": "go.mod"}
  ],
  "structure": {
    "layers": [
      {"name": "cmd", "path": "cmd/devforge", "type": "cmd"},
      {"name": "repo", "path": "internal/repo", "type": "internal"},
      {"name": "project", "path": "internal/project", "type": "internal"},
      {"name": "docker", "path": "internal/docker", "type": "internal"},
      {"name": "testutil", "path": "internal/testutil", "type": "test"}
    ],
    "entry_points": ["cmd/devforge/main.go"],
    "patterns": ["Clean Architecture", "Dependency Injection", "Mapper Pattern"],
    "file_tree": [
      {"path": "cmd/devforge", "is_dir": true, "layer": "cmd"},
      {"path": "internal/repo", "is_dir": true, "layer": "internal"},
      {"path": "internal/project", "is_dir": true, "layer": "internal"},
      {"path": "internal/docker", "is_dir": true, "layer": "internal"},
      {"path": "internal/testutil/doubles", "is_dir": true, "layer": "test"},
      {"path": "internal/testutil/builders", "is_dir": true, "layer": "test"}
    ]
  }
}

New Files

File Purpose
internal/project/analyzer.go ProjectAnalyzer interface + DefaultProjectAnalyzer
internal/project/explain.go RunExplain function, ExplainConfig, ExplainReport, DependencyInfo types
internal/project/explain_test.go BDD parallel tests
internal/project/analyzer_test.go Tests for analysis logic
internal/testutil/doubles/project_analyzer_stub.go Test double for ProjectAnalyzer

Key Interfaces

// ProjectAnalyzer abstracts project structure analysis for testability.
type ProjectAnalyzer interface {
    Analyze(repoPath string) (*ProjectStructure, error)
}

Analysis Logic

  • Layer detection (mapper): {"domain": "domain", "infrastructure": "infrastructure", "cmd": "cmd", "internal": "internal", "test": "test", "pkg": "pkg", "src": "src", "lib": "lib"}
  • Pattern detection: Clean Architecture = domain/ + infrastructure/ present; DDD = entities/ + commands/ inside domain; CQRS = separate command/query directories
  • Entry points (mapper per language): {"go": ["main.go"], "node": ["index.ts", "index.js"], "python": ["main.py", "__main__.py", "app.py"]}
  • Dependencies: parse go.mod require block, package.json dependencies, pyproject.toml dependencies
  • File tree: walk directory (max depth 3), annotate each dir with its detected layer

Feature 4: dev project scaffold [language] [path]

Purpose: Language-agnostic project scaffolding following Clean Architecture. Brings the existing Claude Code scaffolding skills into the CLI so any LLM or automation can bootstrap projects.

Usage

dev project scaffold go ./my-project --name my-project --module github.com/org/my-project
dev project scaffold python ./my-api --name my-api
dev project scaffold node ./my-app --name my-app

Supported Languages

Language Aliases Generated Structure
Go go cmd/<name>/main.go, internal/domain/{entities,commands,repositories}/, internal/infrastructure/{controllers,repositories}/, Makefile, go.mod
Python python src/<name>/domain/{entities,commands,repositories}/, src/<name>/infrastructure/{controllers,repositories}/, tests/, pyproject.toml, Makefile
Node/TS node, ts, typescript src/domain/{entities,commands,repositories}/, src/infrastructure/{controllers,repositories}/, tests/, package.json, tsconfig.json, Makefile

All languages also get: README.md, CHANGELOG.md, CONTRIBUTING.md, .gitignore, .editorconfig

New Files

File Purpose
internal/project/scaffold.go RunScaffold function, ScaffoldConfig type
internal/project/templates.go TemplateRenderer interface + DefaultTemplateRenderer using embed.FS
internal/project/templates/go/** Go project template files
internal/project/templates/python/** Python project template files
internal/project/templates/node/** Node/TypeScript project template files
internal/project/templates/common/** Shared templates (README, CHANGELOG, etc.)
internal/project/scaffold_test.go BDD parallel tests
internal/testutil/doubles/template_renderer_stub.go Test double for TemplateRenderer

Key Interfaces

type TemplateRenderer interface {
    Render(templatePath string, data TemplateData) (string, error)
    ListTemplates(language string) ([]string, error)
}

Design Details

  • Language dispatch via mapper (no switch/case): {"go": "go", "python": "python", "node": "node", "ts": "node", "typescript": "node"}
  • Embedded templates via //go:embed templates/* + Go text/template
  • Generates Clean Architecture structure (domain/infrastructure split)
  • Target dir must be empty or non-existent; --force flag to override
  • CLI flags: --name (project name), --module (module path, e.g., Go module or npm scope)

Files Modified

File Change
cmd/devforge/main.go Add envCmd group + 4 new command factory functions (newEnvInfoCmd, newProjectDoctorCmd, newProjectExplainCmd, newProjectScaffoldCmd)
CHANGELOG.md Add 4 entries under [Unreleased] > Added
CLAUDE.md Update Usage and Architecture sections
README.md Add new commands to usage section

Design Constraints

These constraints come from the existing codebase patterns:

  1. Interface-driven testability: all external operations behind interfaces, stubs in internal/testutil/doubles/ using the fluent builder pattern (NewStub().WithError(err))
  2. No switch/case: all dispatch uses mapper pattern (maps of string → value/function)
  3. BDD tests: // given, // when, // then blocks, parallel via t.Parallel() + t.Run()
  4. Output convention: status/log to cfg.Output (stderr) via logf(), machine output to stdout
  5. Config structs: each operation gets a config struct with injected dependencies (see project.Config pattern)

Verification Checklist

After each feature:

  • make build — binary compiles
  • make test — all tests pass (new + existing)
  • make lint — no lint errors
  • Manual smoke test of the new command
  • --json output is valid JSON (parseable by jq)

Final integration:

  • dev env info --json | jq . works
  • dev project doctor . --json | jq . works
  • dev project explain . --json | jq . works
  • dev project scaffold go /tmp/test-project --name test-project --module github.com/test/test-project creates expected files
  • All documentation updated (CHANGELOG, CLAUDE.md, README)

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions