Skip to content

feat(cli): add --verbose flag for clean default init output#22

Merged
dean0x merged 2 commits intomainfrom
feature/improve-cli-init-output
Dec 1, 2025
Merged

feat(cli): add --verbose flag for clean default init output#22
dean0x merged 2 commits intomainfrom
feature/improve-cli-init-output

Conversation

@dean0x
Copy link
Copy Markdown
Owner

@dean0x dean0x commented Dec 1, 2025

Summary

Refactors devflow init to show clean, command-focused output by default. Users who want detailed installation progress can use the --verbose flag. This improves the first-run experience by reducing noise and highlighting what matters most: the available commands.

Changes

Features

  • Add --verbose flag to devflow init command
  • Clean default output shows only essential info: version, available commands with descriptions, and docs link
  • Verbose mode preserves all current detailed output (installation paths, scope info, manual merge instructions, skills list)

Refactoring

  • Extract command list into DEVFLOW_COMMANDS constant with user-friendly descriptions
  • Extract skills list into DEVFLOW_SKILLS constant for verbose output
  • Create renderCleanOutput() function for minimal default mode
  • Create renderVerboseOutput() function preserving current detailed behavior
  • Wrap all progress/status logging in verbose checks
  • Improve command description alignment in output

Documentation

  • Update CLI help text with --verbose example
  • Reorder and align help examples for better readability

Breaking Changes

None. Default behavior changes from verbose to clean output, but --verbose flag restores previous behavior. This is a UX improvement, not a breaking API change.

Testing

Manual Testing Recommendations

  1. Run devflow init without flags - verify clean output with command list
  2. Run devflow init --verbose - verify full detailed output matches previous behavior
  3. Run devflow init --scope local - verify scope prompt still works in clean mode
  4. Run devflow init in non-TTY environment - verify default scope selection works silently

Related Issues

Closes #21


🤖 Generated with Claude Code

Refactor `devflow init` to show clean, command-focused output by default.
Users who want detailed installation progress can use `--verbose` flag.

Changes:
- Add DEVFLOW_COMMANDS constant with user-friendly descriptions
- Add DEVFLOW_SKILLS constant for verbose output
- Create renderCleanOutput() for minimal default mode
- Create renderVerboseOutput() preserving current detailed behavior
- Wrap all progress/status logging in verbose checks
- Update CLI help text with --verbose example

Closes #21

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@dean0x
Copy link
Copy Markdown
Owner Author

dean0x commented Dec 1, 2025

[BLOCKING] Documentation: Missing CHANGELOG.md Entry

The CHANGELOG.md file has no entry for the --verbose flag feature. The file still shows 0.8.0 as the latest version with no mention of:

  • New --verbose flag
  • Changed default output behavior (clean by default)
  • New render functions

Suggested Fix:

Add an entry to CHANGELOG.md:

## [Unreleased] or [0.9.0] - 2025-12-XX

### Changed
- **CLI init output** - Clean, minimal output by default
  - Default mode shows condensed installation summary
  - `--verbose` flag restores detailed step-by-step output
  - Improved command list alignment and readability

Why: Changelogs are essential for users and contributors to understand what changed between versions. Missing entries make it difficult to track feature additions and breaking changes.


From: documentation audit | Severity: CRITICAL


Generated by Claude Code via /code-review

@dean0x
Copy link
Copy Markdown
Owner Author

dean0x commented Dec 1, 2025

[BLOCKING] Documentation: README.md CLI Commands Table Outdated

The CLI commands table in README.md (line 262) does not document the new --verbose option.

Current Documentation:

| `npx devflow-kit init` | Initialize DevFlow for Claude Code | `--scope <user\|local>` ... `--skip-docs` ... |

Suggested Fix:

Update the table to include the --verbose option:

| `npx devflow-kit init` | Initialize DevFlow for Claude Code | `--scope <user\|local>` - Installation scope<br>`--verbose` - Show detailed installation output<br>`--skip-docs` - Skip creating `.docs/` structure |

Why: Users rely on README documentation to discover available CLI options. Missing documentation for the --verbose flag means users will not know this option exists.


From: documentation audit | Severity: CRITICAL


Generated by Claude Code via /code-review

@dean0x
Copy link
Copy Markdown
Owner Author

dean0x commented Dec 1, 2025

[SHOULD-FIX] Documentation: Incomplete JSDoc for Render Functions

The new render functions (renderCleanOutput and renderVerboseOutput) have minimal JSDoc documentation without @param or @returns annotations.

File: src/cli/commands/init.ts (lines 77-94, 96-138)

Current:

/**
 * Render clean output for default mode
 */
function renderCleanOutput(version: string): void {

Suggested Fix:

/**
 * Render clean, minimal output for default mode
 * Shows installation confirmation and available commands only
 * @param version - DevFlow version being installed
 */
function renderCleanOutput(version: string): void {

/**
 * Render detailed output with step-by-step progress
 * Preserves the original verbose installation behavior
 * @param version - DevFlow version being installed
 * @param scope - Installation scope (user or local)
 * @param claudeDir - Path to Claude directory
 * @param devflowDir - Path to DevFlow directory
 * @param settingsExists - Whether existing settings.json was found
 * @param claudeMdExists - Whether existing CLAUDE.md was found
 */
function renderVerboseOutput(
  version: string,
  scope: 'user' | 'local',
  claudeDir: string,
  devflowDir: string,
  settingsExists: boolean,
  claudeMdExists: boolean
): void {

Why: Proper JSDoc improves IDE IntelliSense, enables documentation generation, and helps future maintainers understand the purpose of each parameter.


From: documentation audit | Severity: HIGH


Generated by Claude Code via /code-review

@dean0x
Copy link
Copy Markdown
Owner Author

dean0x commented Dec 1, 2025

[SHOULD-FIX] Architecture: Hardcoded Command Registry

The command and skill definitions (DEVFLOW_COMMANDS and DEVFLOW_SKILLS) are hardcoded within the init command module, creating a maintenance burden and potential drift from the actual filesystem.

File: src/cli/commands/init.ts (lines 48-75)

Problems:

  • Duplication risk: If command list appears elsewhere, it will be duplicated
  • Single Responsibility Violation: init module owns both installation logic AND command registry data
  • Maintenance burden: Adding a new command requires editing init.ts
  • Source of truth conflict: Commands exist in src/claude/commands/devflow/ but are manually listed here

Option 1: Extract to Shared Module

// src/cli/registry.ts
export interface DevFlowItem {
  readonly name: string;
  readonly description: string;
}

export const DEVFLOW_COMMANDS: readonly DevFlowItem[] = [
  { name: '/catch-up', description: 'Get up to speed on project state' },
  // ...
];

export const DEVFLOW_SKILLS: readonly DevFlowItem[] = [
  { name: 'pattern-check', description: 'Architectural pattern validation' },
  // ...
];

Option 2: Derive from Filesystem (Dynamic)

// src/cli/registry.ts
export async function discoverCommands(): Promise<DevFlowItem[]> {
  const commandsDir = path.join(claudeSourceDir, 'commands/devflow');
  const files = await fs.readdir(commandsDir);
  // Parse command metadata from files
}

Comparison

Approach Pros Cons
Extract to module Simple, type-safe, fast Still manual, can drift
Derive from filesystem Always accurate, DRY I/O overhead, parsing complexity

Recommended: Option 1 for this PR (minimal change), Option 2 as future improvement.


From: architecture audit | Severity: MEDIUM


Generated by Claude Code via /code-review

@dean0x
Copy link
Copy Markdown
Owner Author

dean0x commented Dec 1, 2025

[SHOULD-FIX] Architecture: Verbose Flag Scattered Throughout Handler

The verbose flag is checked approximately 20 times throughout a 500+ line action handler, creating high cognitive load and tight coupling between logging and installation logic.

File: src/cli/commands/init.ts (lines 156-682)

Current Pattern:

// Repeated throughout the file:
if (verbose) { console.log(`...`); }
if (verbose) { console.log('...'); }
if (verbose) { console.log('...'); }
// ~17 more occurrences

Option 1: Logger Abstraction (Strategy Pattern)

interface Logger {
  log(message: string): void;
  warn(message: string): void;
}

const silentLogger: Logger = {
  log: () => {},
  warn: () => {}
};

const consoleLogger: Logger = {
  log: console.log,
  warn: console.warn
};

// In action handler:
const logger = verbose ? consoleLogger : silentLogger;

// Then throughout code:
logger.log('Installing components...');
logger.log('Claude Code detected');

Option 2: Conditional Wrapper Function

const log = verbose ? console.log.bind(console) : () => {};

// Then throughout code:
log('Installing components...');

Comparison

Approach Pros Cons
Logger abstraction Extensible, testable, clear intent More code, interface overhead
Wrapper function Minimal change, simple Less extensible, no warn/error levels

Recommended: Option 1 if you plan to add more output modes later; Option 2 for quick fix.


From: architecture audit | Severity: MEDIUM


Generated by Claude Code via /code-review

@dean0x
Copy link
Copy Markdown
Owner Author

dean0x commented Dec 1, 2025

[SHOULD-FIX] TypeScript: Missing Explicit Interface for Options Parameter

The options parameter in the action handler has an implicit type inferred from Commander.js, which provides weak type safety for accessing properties.

File: src/cli/commands/init.ts (line 145)

Current:

.action(async (options) => {
  // options.verbose, options.scope, options.skipDocs - loosely typed

Suggested Fix:

Define an explicit options interface:

interface InitOptions {
  skipDocs?: boolean;
  scope?: string;
  verbose?: boolean;
}

// Then in the command chain:
.action(async (options: InitOptions) => {

Why: This provides:

  • Better IDE autocomplete
  • Compile-time verification of property names
  • Self-documenting code
  • Protection against typos in property access

From: typescript audit | Severity: WARNING


Generated by Claude Code via /code-review

@dean0x
Copy link
Copy Markdown
Owner Author

dean0x commented Dec 1, 2025

[SHOULD-FIX] TypeScript: Type Assertion Without Runtime Validation

The scope type assertion bypasses TypeScript's type checking, relying solely on the regex pattern for validation.

File: src/cli/commands/init.ts (line 166)

Current:

scope = options.scope.toLowerCase() as 'user' | 'local';

While the regex validation on line 143 (/^(user|local)$/i) provides runtime safety, the type assertion itself is unsafe if the regex were changed or removed.

Suggested Fix (Defense in Depth):

const normalizedScope = options.scope.toLowerCase();
if (normalizedScope !== 'user' && normalizedScope !== 'local') {
  console.error('Invalid scope value');
  process.exit(1);
}
scope = normalizedScope;  // Type narrowed by the check

Alternative: If keeping the assertion, add a comment explaining the coupling:

// SAFETY: Regex on line 143 validates this is 'user' | 'local'
scope = options.scope.toLowerCase() as 'user' | 'local';

Why: Type assertions can hide bugs when upstream code changes. Explicit runtime validation ensures type safety even if the regex is modified.


From: typescript audit | Severity: WARNING


Generated by Claude Code via /code-review

@dean0x
Copy link
Copy Markdown
Owner Author

dean0x commented Dec 1, 2025

[SHOULD-FIX] Complexity: Large Action Handler Function

The main action handler in initCommand spans approximately 543 lines (lines 143-686), making it difficult to maintain, test, and reason about.

File: src/cli/commands/init.ts

Current structure:

  • Version reading: ~10 lines
  • Verbose flag setup: ~6 lines
  • Scope determination: ~65 lines (TTY check, readline prompt, validation)
  • Path configuration: ~25 lines
  • Claude Code detection: ~25 lines
  • Directory setup: ~45 lines
  • Skills cleanup: ~30 lines (nested loops)
  • Component installation: ~20 lines
  • Settings installation: ~35 lines
  • CLAUDE.md installation: ~30 lines
  • .claudeignore creation: ~130 lines (embedded template)
  • .gitignore update: ~30 lines
  • .docs structure creation: ~15 lines
  • Output rendering: ~8 lines

Suggested Refactoring:

interface InstallContext {
  version: string;
  scope: 'user' | 'local';
  verbose: boolean;
  paths: InstallationPaths;
  flags: { settingsExists: boolean; claudeMdExists: boolean };
}

async function runInit(options: InitOptions): Promise<void> {
  const context = await initializeContext(options);
  await validateEnvironment(context);
  await cleanPreviousInstallation(context);
  await installComponents(context);
  await configureSettings(context);
  await createProjectFiles(context);
  renderOutput(context);
}

Why: This decomposition enables:

  • Easier unit testing of individual steps
  • Clear single responsibility per function
  • Better error handling boundaries
  • Improved readability and maintainability

Note: This is pre-existing technical debt made more visible by the PR's additions. Consider addressing in a follow-up PR.


From: complexity audit | Severity: WARNING


Generated by Claude Code via /code-review

@dean0x
Copy link
Copy Markdown
Owner Author

dean0x commented Dec 1, 2025

[SHOULD-FIX] Tests: No Test Coverage for New Functionality

This branch introduces significant changes to CLI output behavior (new --verbose flag, new render functions) with zero test coverage.

Files: src/cli/commands/init.ts (lines 80-94, 99-138, 144, 156-682)

Untested Code Paths:

  • renderCleanOutput() function
  • renderVerboseOutput() function (with 8 boolean combinations)
  • --verbose flag parsing and propagation
  • Default (non-verbose) mode output
  • DEVFLOW_COMMANDS and DEVFLOW_SKILLS constants

Note: The project currently has no testing infrastructure ("test": "echo \"No tests yet\" && exit 0"), so this is pre-existing technical debt. However, new functionality without tests increases the risk of silent regressions.

Suggested Approach for Future Testing:

// src/cli/commands/init.test.ts
import { describe, it, expect, vi } from 'vitest';

describe('renderCleanOutput', () => {
  it('should display version and commands', () => {
    const consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => {});
    renderCleanOutput('1.0.0');
    expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining('1.0.0'));
    consoleSpy.mockRestore();
  });
});

Recommended Follow-up Actions:

  1. Add testing framework (Vitest recommended for TypeScript ESM)
  2. Create tests for new render functions
  3. Add integration tests for --verbose flag behavior

From: tests audit | Severity: HIGH (informational - pre-existing debt)


Generated by Claude Code via /code-review

- Add [Unreleased] section to CHANGELOG.md for --verbose flag
- Update README.md CLI commands table with --verbose option
- Add JSDoc documentation for renderCleanOutput/renderVerboseOutput
- Add InitOptions and CommandDefinition interfaces for type safety
- Add runtime validation for scope parameter
- Use nullish coalescing for verbose flag

Addresses code review feedback from PR #22

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@dean0x dean0x merged commit 945abc9 into main Dec 1, 2025
@dean0x dean0x deleted the feature/improve-cli-init-output branch December 1, 2025 23:15
dean0x pushed a commit that referenced this pull request Apr 16, 2026
Review walkthrough across 4 sessions resolved all 31 issues from the
2026-04-15_1022 code review (19 fixed, 5 rejected, 1 deferred, 6
pre-resolved).

Blocking fixes (sessions 1-2):
- CHANGELOG contradiction rewritten (#1)
- Worktree placeholder unified on "{worktree}" across 11 sites (#3)
- /debug migrated to index pattern (#4)
- KNOWLEDGE_CONTEXT quoting standardized, no inline fallback (#6)
- apply-knowledge skill defers to footer for paths (#7)
- Simplifier dropped from knowledge consumers; 4 agents canonicalized (#8)
- lstat+isFile guard on legacy-knowledge-purge unlink (#9)

Architecture + consistency fixes (session 2):
- Bare-form CLI removed, dispatch simplified to index-only (#10)
- code-review-teams template+table extraction (#12)
- Designer Apply Knowledge H2 added (#13)
- Teams phase numbering aligned (#14)
- loadKnowledgeContext + full subcommand removed entirely (#16)

Complexity + performance + testing + docs fixes (sessions 3-4):
- D-A filter extracted to isDeprecatedOrSuperseded predicate (#18)
- formatAdrLine/formatPfLine merged into formatEntryLine (#19)
- Shared test fixtures extracted to tests/knowledge/fixtures.ts (#21)
- Token claim "~250 tokens" dropped from 12 sites (#22)
- tmpdir cleanup added to test fixtures (#25)
- self-learning.md example and footer paths corrected (#28, #29)

28 files changed, 333 insertions, 524 deletions. 1021/1021 tests passing.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Improve CLI init output - professional formatting with command focus

1 participant