Adr 007 Merge Generate Into Build Command
Status: Accepted
Date: 2026-01-03
Implementation Date: 2026-01-03
Decision Makers: DocBuilder Core Team
Technical Story: Simplify command-line interface by consolidating redundant commands
Context and Problem Statement
DocBuilder currently has two commands for building documentation sites:
build- Full-featured build with Git integration, multi-repo support, config filesgenerate- Simplified CI/CD generator for single local directories
Analysis reveals that these commands have significant functional overlap:
Shared functionality:
- Both discover documentation files from local directories
- Both generate Hugo sites with themes
- Both support custom output directories, titles, and base URLs
- Both create minimal in-memory configs when needed
Current differences:
generatehas--renderboolean flag (skip Hugo execution)generateuses temporary directory workflow with public/ copybuildsupports--incremental,--render-mode,--relocatable,--keep-workspacebuildhas local fallback mode that mirrorsgeneratefunctionality
Key insight: When build runs without a config file, it already implements the same workflow as generate:
The existence of two commands creates:
- Confusion: Users must choose between
buildandgeneratefor simple use cases - Maintenance burden: ~170 lines of duplicate code to maintain
- API inconsistency: Similar operations with different flag names (
--rendervs--render-mode) - Split documentation: Two commands to document and support
Decision
We will merge the generate command into build by:
- Removing the
generatecommand entirely (project is greenfield, no backward compatibility needed) - Using existing
--render-mode=neverflag for--render=falseuse case (already supported) - Simplifying mental model:
buildhandles all build scenarios
Rationale
Why Merge into build (not the reverse)?
buildis more feature-complete: Supports incremental mode, versioning, multi-repobuildis the primary command: Used in production, has richer config support- Natural hierarchy:
buildencompasses all building scenarios (local, remote, multi-repo) - Less breaking: Most users likely use
build;generatewas designed for CI/CD niche
Why Not Keep Both?
- Semantic distinction is weak: Both “build” and “generate” mean the same thing (create documentation site)
- Implementation proves redundancy: Local mode in
buildalready duplicatesgenerate - User confusion: No clear rule for when to use which command
- Maintenance cost: Every feature must be implemented twice or users get inconsistent experience
Implementation Plan
Since the project is still greenfield, we can remove generate immediately:
- Delete
cmd/docbuilder/commands/generate.go - Remove
generatefrom command registration inmain.go - Update all documentation and examples
- Update README with clear build command usage
- Verify CI/CD examples use
buildcommand
Command Usage Guide
Users who might have used generate should use build instead:
Flag mapping:
generate flag |
build equivalent |
|---|---|
-d, --docs-dir |
-d, --docs-dir (same) |
-o, --output |
-o, --output (same) |
--title |
--title (same) |
--base-url |
--base-url (same) |
--render=false |
--render-mode=never |
--render=true |
(default behavior) |
Consequences
Benefits
- Simpler CLI: One command for all build scenarios
- Reduced code: Remove ~170 lines of duplicate code
- Consistent UX: Unified flag names and behavior across all build modes
- Easier maintenance: Single code path to test, document, and enhance
- Clearer mental model: “Build from local? Use
build. Build from remote? Usebuild.” - Better discoverability: New users find one obvious command instead of choosing between two
Risks and Mitigation
-
Breaking change for early adopters
- Risk: Minimal - project is greenfield with limited users
- Mitigation: Update all documentation and examples immediately
- Mitigation: Clear release notes explaining the consolidation
-
Lost semantic clarity
- Risk: Some users might prefer “generate” name for CI/CD
- Mitigation: Documentation shows clear “build for CI/CD” examples
- Mitigation:
buildcommand is intuitive and self-explanatory
Testing Strategy
- Add integration tests verifying
buildlocal mode produces expected output - Verify all CI/CD examples in docs work with
buildcommand - Update any existing tests that referenced
generatecommand - Ensure help text and documentation reflect removal
Alternatives Considered
Alternative 1: Merge build into generate
Rejected because:
generateis less feature-complete (no incremental, no versioning)buildis the primary, more widely-used command- Would require renaming “build” to “generate” in all documentation
- Name “build” is more intuitive than “generate” for the main command
Alternative 2: Keep both, but make generate call build internally
Rejected because:
- Still maintains two commands in user-facing API
- Doesn’t reduce maintenance burden (two sets of docs, two help texts)
- Users still confused about which to use
- Unnecessary complexity for a greenfield project
Alternative 3: Make generate a subcommand of build
Example: build generate or build local
Rejected because:
- Adds unnecessary nesting (no other subcommands exist)
build -d ./docsis simpler thanbuild local -d ./docs- Flags already disambiguate behavior (presence of
-cvs-d)
Alternative 4: Keep both, clearly document use cases
Rejected because:
- Doesn’t solve code duplication
- Relies on users reading documentation (many won’t)
- Semantic distinction is too subtle to enforce
- Creates unnecessary decision point for users
Related Decisions
- ADR-006: Drop local namespace for single-repo builds - This ADR’s single-repo detection aligns with unified build command
- ADR-001: Golden Testing Strategy - Consolidation reduces test surface area
References
- Kong CLI framework - Used for command-line parsing
[adr-007-merge-generate-into-build-command](https://docs.home.luguber.info/_uid/52e0a4c1-9281-4086-b0e5-d6ff690eee53/)