feat(cli): add --verbose flag for clean default init output#22
Conversation
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>
|
[BLOCKING] Documentation: Missing CHANGELOG.md Entry The CHANGELOG.md file has no entry for the
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 readabilityWhy: 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 |
|
[BLOCKING] Documentation: README.md CLI Commands Table Outdated The CLI commands table in README.md (line 262) does not document the new Current Documentation: | `npx devflow-kit init` | Initialize DevFlow for Claude Code | `--scope <user\|local>` ... `--skip-docs` ... |Suggested Fix: Update the table to include the | `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 From: documentation audit | Severity: CRITICAL Generated by Claude Code via |
|
[SHOULD-FIX] Documentation: Incomplete JSDoc for Render Functions The new render functions ( File: 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 |
|
[SHOULD-FIX] Architecture: Hardcoded Command Registry The command and skill definitions ( File: Problems:
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
Recommended: Option 1 for this PR (minimal change), Option 2 as future improvement. From: architecture audit | Severity: MEDIUM Generated by Claude Code via |
|
[SHOULD-FIX] Architecture: Verbose Flag Scattered Throughout Handler The File: Current Pattern: // Repeated throughout the file:
if (verbose) { console.log(`...`); }
if (verbose) { console.log('...'); }
if (verbose) { console.log('...'); }
// ~17 more occurrencesOption 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
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 |
|
[SHOULD-FIX] TypeScript: Missing Explicit Interface for Options Parameter The File: Current: .action(async (options) => {
// options.verbose, options.scope, options.skipDocs - loosely typedSuggested 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:
From: typescript audit | Severity: WARNING Generated by Claude Code via |
|
[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: Current: scope = options.scope.toLowerCase() as 'user' | 'local';While the regex validation on line 143 ( 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 checkAlternative: 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 |
|
[SHOULD-FIX] Complexity: Large Action Handler Function The main action handler in File: Current structure:
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:
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 |
|
[SHOULD-FIX] Tests: No Test Coverage for New Functionality This branch introduces significant changes to CLI output behavior (new Files: Untested Code Paths:
Note: The project currently has no testing infrastructure ( 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:
From: tests audit | Severity: HIGH (informational - pre-existing debt) Generated by Claude Code via |
- 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>
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.
Summary
Refactors
devflow initto show clean, command-focused output by default. Users who want detailed installation progress can use the--verboseflag. This improves the first-run experience by reducing noise and highlighting what matters most: the available commands.Changes
Features
--verboseflag todevflow initcommandRefactoring
DEVFLOW_COMMANDSconstant with user-friendly descriptionsDEVFLOW_SKILLSconstant for verbose outputrenderCleanOutput()function for minimal default moderenderVerboseOutput()function preserving current detailed behaviorDocumentation
--verboseexampleBreaking Changes
None. Default behavior changes from verbose to clean output, but
--verboseflag restores previous behavior. This is a UX improvement, not a breaking API change.Testing
Manual Testing Recommendations
devflow initwithout flags - verify clean output with command listdevflow init --verbose- verify full detailed output matches previous behaviordevflow init --scope local- verify scope prompt still works in clean modedevflow initin non-TTY environment - verify default scope selection works silentlyRelated Issues
Closes #21
🤖 Generated with Claude Code