#!/usr/bin/env node /** * GSD Tools — CLI utility for GSD workflow operations * * Replaces repetitive inline bash patterns across ~50 GSD command/workflow/agent files. * Centralizes: config parsing, model resolution, phase lookup, git commits, summary verification. * * Usage: node gsd-tools.cjs [args] [--raw] * * Atomic Commands: * state load Load project config + state * state json Output STATE.md frontmatter as JSON * state update Update a STATE.md field * state get [section] Get STATE.md content or section * state patch --field val ... Batch update STATE.md fields * state begin-phase --phase N --name S --plans C Update STATE.md for new phase start * state signal-waiting --type T --question Q --options "A|B" --phase P Write WAITING.json signal * state signal-resume Remove WAITING.json signal * resolve-model Get model for agent based on profile * find-phase Find phase directory by number * commit [--files f1 f2] Commit planning docs * verify-summary Verify a SUMMARY.md file * generate-slug Convert text to URL-safe slug * current-timestamp [format] Get timestamp (full|date|filename) * list-todos [area] Count and enumerate pending todos * verify-path-exists Check file/directory existence * config-ensure-section Initialize .planning/config.json * history-digest Aggregate all SUMMARY.md data * summary-extract [--fields] Extract structured data from SUMMARY.md * state-snapshot Structured parse of STATE.md * phase-plan-index Index plans with waves and status * websearch Search web via Brave API (if configured) * [--limit N] [--freshness day|week|month] * * Phase Operations: * phase next-decimal Calculate next decimal phase number * phase add Append new phase to roadmap + create dir * phase insert Insert decimal phase after existing * phase remove [--force] Remove phase, renumber all subsequent * phase complete Mark phase done, update state + roadmap * * Roadmap Operations: * roadmap get-phase Extract phase section from ROADMAP.md * roadmap analyze Full roadmap parse with disk status * roadmap update-plan-progress Update progress table row from disk (PLAN vs SUMMARY counts) * * Requirements Operations: * requirements mark-complete Mark requirement IDs as complete in REQUIREMENTS.md * Accepts: REQ-01,REQ-02 or REQ-01 REQ-02 or [REQ-01, REQ-02] * * Milestone Operations: * milestone complete Archive milestone, create MILESTONES.md * [--name ] * [--archive-phases] Move phase dirs to milestones/vX.Y-phases/ * * Validation: * validate consistency Check phase numbering, disk/roadmap sync * validate health [--repair] Check .planning/ integrity, optionally repair * * Progress: * progress [json|table|bar] Render progress in various formats * * Todos: * todo complete Move todo from pending to completed * * Scaffolding: * scaffold context --phase Create CONTEXT.md template * scaffold uat --phase Create UAT.md template * scaffold verification --phase Create VERIFICATION.md template * scaffold phase-dir --phase Create phase directory * --name * * Frontmatter CRUD: * frontmatter get [--field k] Extract frontmatter as JSON * frontmatter set --field k Update single frontmatter field * --value jsonVal * frontmatter merge Merge JSON into frontmatter * --data '{json}' * frontmatter validate Validate required fields * --schema plan|summary|verification * * Verification Suite: * verify plan-structure Check PLAN.md structure + tasks * verify phase-completeness Check all plans have summaries * verify references Check @-refs + paths resolve * verify commits

[h2] ... Batch verify commit hashes * verify artifacts Check must_haves.artifacts * verify key-links Check must_haves.key_links * * Template Fill: * template fill summary --phase N Create pre-filled SUMMARY.md * [--plan M] [--name "..."] * [--fields '{json}'] * template fill plan --phase N Create pre-filled PLAN.md * [--plan M] [--type execute|tdd] * [--wave N] [--fields '{json}'] * template fill verification Create pre-filled VERIFICATION.md * --phase N [--fields '{json}'] * * State Progression: * state advance-plan Increment plan counter * state record-metric --phase N Record execution metrics * --plan M --duration Xmin * [--tasks N] [--files N] * state update-progress Recalculate progress bar * state add-decision --summary "..." Add decision to STATE.md * [--phase N] [--rationale "..."] * [--summary-file path] [--rationale-file path] * state add-blocker --text "..." Add blocker * [--text-file path] * state resolve-blocker --text "..." Remove blocker * state record-session Update session continuity * --stopped-at "..." * [--resume-file path] * * Compound Commands (workflow-specific initialization): * init execute-phase All context for execute-phase workflow * init plan-phase All context for plan-phase workflow * init new-project All context for new-project workflow * init new-milestone All context for new-milestone workflow * init quick All context for quick workflow * init resume All context for resume-project workflow * init verify-work All context for verify-work workflow * init phase-op Generic phase operation context * init todos [area] All context for todo workflows * init milestone-op All context for milestone operations * init map-codebase All context for map-codebase workflow * init progress All context for progress workflow */ const fs = require('fs'); const path = require('path'); const { error } = require('./lib/core.cjs'); const state = require('./lib/state.cjs'); const phase = require('./lib/phase.cjs'); const roadmap = require('./lib/roadmap.cjs'); const verify = require('./lib/verify.cjs'); const config = require('./lib/config.cjs'); const template = require('./lib/template.cjs'); const milestone = require('./lib/milestone.cjs'); const commands = require('./lib/commands.cjs'); const init = require('./lib/init.cjs'); const frontmatter = require('./lib/frontmatter.cjs'); const profilePipeline = require('./lib/profile-pipeline.cjs'); const profileOutput = require('./lib/profile-output.cjs'); // ─── CLI Router ─────────────────────────────────────────────────────────────── async function main() { const args = process.argv.slice(2); // Optional cwd override for sandboxed subagents running outside project root. let cwd = process.cwd(); const cwdEqArg = args.find(arg => arg.startsWith('--cwd=')); const cwdIdx = args.indexOf('--cwd'); if (cwdEqArg) { const value = cwdEqArg.slice('--cwd='.length).trim(); if (!value) error('Missing value for --cwd'); args.splice(args.indexOf(cwdEqArg), 1); cwd = path.resolve(value); } else if (cwdIdx !== -1) { const value = args[cwdIdx + 1]; if (!value || value.startsWith('--')) error('Missing value for --cwd'); args.splice(cwdIdx, 2); cwd = path.resolve(value); } if (!fs.existsSync(cwd) || !fs.statSync(cwd).isDirectory()) { error(`Invalid --cwd: ${cwd}`); } const rawIndex = args.indexOf('--raw'); const raw = rawIndex !== -1; if (rawIndex !== -1) args.splice(rawIndex, 1); const command = args[0]; if (!command) { error('Usage: gsd-tools [args] [--raw] [--cwd ]\nCommands: state, resolve-model, find-phase, commit, verify-summary, verify, frontmatter, template, generate-slug, current-timestamp, list-todos, verify-path-exists, config-ensure-section, init'); } switch (command) { case 'state': { const subcommand = args[1]; if (subcommand === 'json') { state.cmdStateJson(cwd, raw); } else if (subcommand === 'update') { state.cmdStateUpdate(cwd, args[2], args[3]); } else if (subcommand === 'get') { state.cmdStateGet(cwd, args[2], raw); } else if (subcommand === 'patch') { const patches = {}; for (let i = 2; i < args.length; i += 2) { const key = args[i].replace(/^--/, ''); const value = args[i + 1]; if (key && value !== undefined) { patches[key] = value; } } state.cmdStatePatch(cwd, patches, raw); } else if (subcommand === 'advance-plan') { state.cmdStateAdvancePlan(cwd, raw); } else if (subcommand === 'record-metric') { const phaseIdx = args.indexOf('--phase'); const planIdx = args.indexOf('--plan'); const durationIdx = args.indexOf('--duration'); const tasksIdx = args.indexOf('--tasks'); const filesIdx = args.indexOf('--files'); state.cmdStateRecordMetric(cwd, { phase: phaseIdx !== -1 ? args[phaseIdx + 1] : null, plan: planIdx !== -1 ? args[planIdx + 1] : null, duration: durationIdx !== -1 ? args[durationIdx + 1] : null, tasks: tasksIdx !== -1 ? args[tasksIdx + 1] : null, files: filesIdx !== -1 ? args[filesIdx + 1] : null, }, raw); } else if (subcommand === 'update-progress') { state.cmdStateUpdateProgress(cwd, raw); } else if (subcommand === 'add-decision') { const phaseIdx = args.indexOf('--phase'); const summaryIdx = args.indexOf('--summary'); const summaryFileIdx = args.indexOf('--summary-file'); const rationaleIdx = args.indexOf('--rationale'); const rationaleFileIdx = args.indexOf('--rationale-file'); state.cmdStateAddDecision(cwd, { phase: phaseIdx !== -1 ? args[phaseIdx + 1] : null, summary: summaryIdx !== -1 ? args[summaryIdx + 1] : null, summary_file: summaryFileIdx !== -1 ? args[summaryFileIdx + 1] : null, rationale: rationaleIdx !== -1 ? args[rationaleIdx + 1] : '', rationale_file: rationaleFileIdx !== -1 ? args[rationaleFileIdx + 1] : null, }, raw); } else if (subcommand === 'add-blocker') { const textIdx = args.indexOf('--text'); const textFileIdx = args.indexOf('--text-file'); state.cmdStateAddBlocker(cwd, { text: textIdx !== -1 ? args[textIdx + 1] : null, text_file: textFileIdx !== -1 ? args[textFileIdx + 1] : null, }, raw); } else if (subcommand === 'resolve-blocker') { const textIdx = args.indexOf('--text'); state.cmdStateResolveBlocker(cwd, textIdx !== -1 ? args[textIdx + 1] : null, raw); } else if (subcommand === 'record-session') { const stoppedIdx = args.indexOf('--stopped-at'); const resumeIdx = args.indexOf('--resume-file'); state.cmdStateRecordSession(cwd, { stopped_at: stoppedIdx !== -1 ? args[stoppedIdx + 1] : null, resume_file: resumeIdx !== -1 ? args[resumeIdx + 1] : 'None', }, raw); } else if (subcommand === 'begin-phase') { const phaseIdx = args.indexOf('--phase'); const nameIdx = args.indexOf('--name'); const plansIdx = args.indexOf('--plans'); state.cmdStateBeginPhase( cwd, phaseIdx !== -1 ? args[phaseIdx + 1] : null, nameIdx !== -1 ? args[nameIdx + 1] : null, plansIdx !== -1 ? parseInt(args[plansIdx + 1], 10) : null, raw ); } else if (subcommand === 'signal-waiting') { const typeIdx = args.indexOf('--type'); const qIdx = args.indexOf('--question'); const optIdx = args.indexOf('--options'); const phaseIdx = args.indexOf('--phase'); state.cmdSignalWaiting( cwd, typeIdx !== -1 ? args[typeIdx + 1] : null, qIdx !== -1 ? args[qIdx + 1] : null, optIdx !== -1 ? args[optIdx + 1] : null, phaseIdx !== -1 ? args[phaseIdx + 1] : null, raw ); } else if (subcommand === 'signal-resume') { state.cmdSignalResume(cwd, raw); } else { state.cmdStateLoad(cwd, raw); } break; } case 'resolve-model': { commands.cmdResolveModel(cwd, args[1], raw); break; } case 'find-phase': { phase.cmdFindPhase(cwd, args[1], raw); break; } case 'commit': { const amend = args.includes('--amend'); const filesIndex = args.indexOf('--files'); // Collect all positional args between command name and first flag, // then join them — handles both quoted ("multi word msg") and // unquoted (multi word msg) invocations from different shells const endIndex = filesIndex !== -1 ? filesIndex : args.length; const messageArgs = args.slice(1, endIndex).filter(a => !a.startsWith('--')); const message = messageArgs.join(' ') || undefined; const files = filesIndex !== -1 ? args.slice(filesIndex + 1).filter(a => !a.startsWith('--')) : []; commands.cmdCommit(cwd, message, files, raw, amend); break; } case 'verify-summary': { const summaryPath = args[1]; const countIndex = args.indexOf('--check-count'); const checkCount = countIndex !== -1 ? parseInt(args[countIndex + 1], 10) : 2; verify.cmdVerifySummary(cwd, summaryPath, checkCount, raw); break; } case 'template': { const subcommand = args[1]; if (subcommand === 'select') { template.cmdTemplateSelect(cwd, args[2], raw); } else if (subcommand === 'fill') { const templateType = args[2]; const phaseIdx = args.indexOf('--phase'); const planIdx = args.indexOf('--plan'); const nameIdx = args.indexOf('--name'); const typeIdx = args.indexOf('--type'); const waveIdx = args.indexOf('--wave'); const fieldsIdx = args.indexOf('--fields'); template.cmdTemplateFill(cwd, templateType, { phase: phaseIdx !== -1 ? args[phaseIdx + 1] : null, plan: planIdx !== -1 ? args[planIdx + 1] : null, name: nameIdx !== -1 ? args[nameIdx + 1] : null, type: typeIdx !== -1 ? args[typeIdx + 1] : 'execute', wave: waveIdx !== -1 ? args[waveIdx + 1] : '1', fields: fieldsIdx !== -1 ? JSON.parse(args[fieldsIdx + 1]) : {}, }, raw); } else { error('Unknown template subcommand. Available: select, fill'); } break; } case 'frontmatter': { const subcommand = args[1]; const file = args[2]; if (subcommand === 'get') { const fieldIdx = args.indexOf('--field'); frontmatter.cmdFrontmatterGet(cwd, file, fieldIdx !== -1 ? args[fieldIdx + 1] : null, raw); } else if (subcommand === 'set') { const fieldIdx = args.indexOf('--field'); const valueIdx = args.indexOf('--value'); frontmatter.cmdFrontmatterSet(cwd, file, fieldIdx !== -1 ? args[fieldIdx + 1] : null, valueIdx !== -1 ? args[valueIdx + 1] : undefined, raw); } else if (subcommand === 'merge') { const dataIdx = args.indexOf('--data'); frontmatter.cmdFrontmatterMerge(cwd, file, dataIdx !== -1 ? args[dataIdx + 1] : null, raw); } else if (subcommand === 'validate') { const schemaIdx = args.indexOf('--schema'); frontmatter.cmdFrontmatterValidate(cwd, file, schemaIdx !== -1 ? args[schemaIdx + 1] : null, raw); } else { error('Unknown frontmatter subcommand. Available: get, set, merge, validate'); } break; } case 'verify': { const subcommand = args[1]; if (subcommand === 'plan-structure') { verify.cmdVerifyPlanStructure(cwd, args[2], raw); } else if (subcommand === 'phase-completeness') { verify.cmdVerifyPhaseCompleteness(cwd, args[2], raw); } else if (subcommand === 'references') { verify.cmdVerifyReferences(cwd, args[2], raw); } else if (subcommand === 'commits') { verify.cmdVerifyCommits(cwd, args.slice(2), raw); } else if (subcommand === 'artifacts') { verify.cmdVerifyArtifacts(cwd, args[2], raw); } else if (subcommand === 'key-links') { verify.cmdVerifyKeyLinks(cwd, args[2], raw); } else { error('Unknown verify subcommand. Available: plan-structure, phase-completeness, references, commits, artifacts, key-links'); } break; } case 'generate-slug': { commands.cmdGenerateSlug(args[1], raw); break; } case 'current-timestamp': { commands.cmdCurrentTimestamp(args[1] || 'full', raw); break; } case 'list-todos': { commands.cmdListTodos(cwd, args[1], raw); break; } case 'verify-path-exists': { commands.cmdVerifyPathExists(cwd, args[1], raw); break; } case 'config-ensure-section': { config.cmdConfigEnsureSection(cwd, raw); break; } case 'config-set': { config.cmdConfigSet(cwd, args[1], args[2], raw); break; } case "config-set-model-profile": { config.cmdConfigSetModelProfile(cwd, args[1], raw); break; } case 'config-get': { config.cmdConfigGet(cwd, args[1], raw); break; } case 'history-digest': { commands.cmdHistoryDigest(cwd, raw); break; } case 'phases': { const subcommand = args[1]; if (subcommand === 'list') { const typeIndex = args.indexOf('--type'); const phaseIndex = args.indexOf('--phase'); const options = { type: typeIndex !== -1 ? args[typeIndex + 1] : null, phase: phaseIndex !== -1 ? args[phaseIndex + 1] : null, includeArchived: args.includes('--include-archived'), }; phase.cmdPhasesList(cwd, options, raw); } else { error('Unknown phases subcommand. Available: list'); } break; } case 'roadmap': { const subcommand = args[1]; if (subcommand === 'get-phase') { roadmap.cmdRoadmapGetPhase(cwd, args[2], raw); } else if (subcommand === 'analyze') { roadmap.cmdRoadmapAnalyze(cwd, raw); } else if (subcommand === 'update-plan-progress') { roadmap.cmdRoadmapUpdatePlanProgress(cwd, args[2], raw); } else { error('Unknown roadmap subcommand. Available: get-phase, analyze, update-plan-progress'); } break; } case 'requirements': { const subcommand = args[1]; if (subcommand === 'mark-complete') { milestone.cmdRequirementsMarkComplete(cwd, args.slice(2), raw); } else { error('Unknown requirements subcommand. Available: mark-complete'); } break; } case 'phase': { const subcommand = args[1]; if (subcommand === 'next-decimal') { phase.cmdPhaseNextDecimal(cwd, args[2], raw); } else if (subcommand === 'add') { phase.cmdPhaseAdd(cwd, args.slice(2).join(' '), raw); } else if (subcommand === 'insert') { phase.cmdPhaseInsert(cwd, args[2], args.slice(3).join(' '), raw); } else if (subcommand === 'remove') { const forceFlag = args.includes('--force'); phase.cmdPhaseRemove(cwd, args[2], { force: forceFlag }, raw); } else if (subcommand === 'complete') { phase.cmdPhaseComplete(cwd, args[2], raw); } else { error('Unknown phase subcommand. Available: next-decimal, add, insert, remove, complete'); } break; } case 'milestone': { const subcommand = args[1]; if (subcommand === 'complete') { const nameIndex = args.indexOf('--name'); const archivePhases = args.includes('--archive-phases'); // Collect --name value (everything after --name until next flag or end) let milestoneName = null; if (nameIndex !== -1) { const nameArgs = []; for (let i = nameIndex + 1; i < args.length; i++) { if (args[i].startsWith('--')) break; nameArgs.push(args[i]); } milestoneName = nameArgs.join(' ') || null; } milestone.cmdMilestoneComplete(cwd, args[2], { name: milestoneName, archivePhases }, raw); } else { error('Unknown milestone subcommand. Available: complete'); } break; } case 'validate': { const subcommand = args[1]; if (subcommand === 'consistency') { verify.cmdValidateConsistency(cwd, raw); } else if (subcommand === 'health') { const repairFlag = args.includes('--repair'); verify.cmdValidateHealth(cwd, { repair: repairFlag }, raw); } else { error('Unknown validate subcommand. Available: consistency, health'); } break; } case 'progress': { const subcommand = args[1] || 'json'; commands.cmdProgressRender(cwd, subcommand, raw); break; } case 'stats': { const subcommand = args[1] || 'json'; commands.cmdStats(cwd, subcommand, raw); break; } case 'todo': { const subcommand = args[1]; if (subcommand === 'complete') { commands.cmdTodoComplete(cwd, args[2], raw); } else { error('Unknown todo subcommand. Available: complete'); } break; } case 'scaffold': { const scaffoldType = args[1]; const phaseIndex = args.indexOf('--phase'); const nameIndex = args.indexOf('--name'); const scaffoldOptions = { phase: phaseIndex !== -1 ? args[phaseIndex + 1] : null, name: nameIndex !== -1 ? args.slice(nameIndex + 1).join(' ') : null, }; commands.cmdScaffold(cwd, scaffoldType, scaffoldOptions, raw); break; } case 'init': { const workflow = args[1]; switch (workflow) { case 'execute-phase': init.cmdInitExecutePhase(cwd, args[2], raw); break; case 'plan-phase': init.cmdInitPlanPhase(cwd, args[2], raw); break; case 'new-project': init.cmdInitNewProject(cwd, raw); break; case 'new-milestone': init.cmdInitNewMilestone(cwd, raw); break; case 'quick': init.cmdInitQuick(cwd, args.slice(2).join(' '), raw); break; case 'resume': init.cmdInitResume(cwd, raw); break; case 'verify-work': init.cmdInitVerifyWork(cwd, args[2], raw); break; case 'phase-op': init.cmdInitPhaseOp(cwd, args[2], raw); break; case 'todos': init.cmdInitTodos(cwd, args[2], raw); break; case 'milestone-op': init.cmdInitMilestoneOp(cwd, raw); break; case 'map-codebase': init.cmdInitMapCodebase(cwd, raw); break; case 'progress': init.cmdInitProgress(cwd, raw); break; default: error(`Unknown init workflow: ${workflow}\nAvailable: execute-phase, plan-phase, new-project, new-milestone, quick, resume, verify-work, phase-op, todos, milestone-op, map-codebase, progress`); } break; } case 'phase-plan-index': { phase.cmdPhasePlanIndex(cwd, args[1], raw); break; } case 'state-snapshot': { state.cmdStateSnapshot(cwd, raw); break; } case 'summary-extract': { const summaryPath = args[1]; const fieldsIndex = args.indexOf('--fields'); const fields = fieldsIndex !== -1 ? args[fieldsIndex + 1].split(',') : null; commands.cmdSummaryExtract(cwd, summaryPath, fields, raw); break; } case 'websearch': { const query = args[1]; const limitIdx = args.indexOf('--limit'); const freshnessIdx = args.indexOf('--freshness'); await commands.cmdWebsearch(query, { limit: limitIdx !== -1 ? parseInt(args[limitIdx + 1], 10) : 10, freshness: freshnessIdx !== -1 ? args[freshnessIdx + 1] : null, }, raw); break; } // ─── Profiling Pipeline ──────────────────────────────────────────────── case 'scan-sessions': { const pathIdx = args.indexOf('--path'); const sessionsPath = pathIdx !== -1 ? args[pathIdx + 1] : null; const verboseFlag = args.includes('--verbose'); const jsonFlag = args.includes('--json'); await profilePipeline.cmdScanSessions(sessionsPath, { verbose: verboseFlag, json: jsonFlag }, raw); break; } case 'extract-messages': { const sessionIdx = args.indexOf('--session'); const sessionId = sessionIdx !== -1 ? args[sessionIdx + 1] : null; const limitIdx = args.indexOf('--limit'); const limit = limitIdx !== -1 ? parseInt(args[limitIdx + 1], 10) : null; const pathIdx = args.indexOf('--path'); const sessionsPath = pathIdx !== -1 ? args[pathIdx + 1] : null; const projectArg = args[1]; if (!projectArg || projectArg.startsWith('--')) { error('Usage: gsd-tools extract-messages [--session ] [--limit N] [--path ]\nRun scan-sessions first to see available projects.'); } await profilePipeline.cmdExtractMessages(projectArg, { sessionId, limit }, raw, sessionsPath); break; } case 'profile-sample': { const pathIdx = args.indexOf('--path'); const sessionsPath = pathIdx !== -1 ? args[pathIdx + 1] : null; const limitIdx = args.indexOf('--limit'); const limit = limitIdx !== -1 ? parseInt(args[limitIdx + 1], 10) : 150; const maxPerIdx = args.indexOf('--max-per-project'); const maxPerProject = maxPerIdx !== -1 ? parseInt(args[maxPerIdx + 1], 10) : null; const maxCharsIdx = args.indexOf('--max-chars'); const maxChars = maxCharsIdx !== -1 ? parseInt(args[maxCharsIdx + 1], 10) : 500; await profilePipeline.cmdProfileSample(sessionsPath, { limit, maxPerProject, maxChars }, raw); break; } // ─── Profile Output ────────────────────────────────────────────────── case 'write-profile': { const inputIdx = args.indexOf('--input'); const inputPath = inputIdx !== -1 ? args[inputIdx + 1] : null; if (!inputPath) error('--input is required'); const outputIdx = args.indexOf('--output'); const outputPath = outputIdx !== -1 ? args[outputIdx + 1] : null; profileOutput.cmdWriteProfile(cwd, { input: inputPath, output: outputPath }, raw); break; } case 'profile-questionnaire': { const answersIdx = args.indexOf('--answers'); const answers = answersIdx !== -1 ? args[answersIdx + 1] : null; profileOutput.cmdProfileQuestionnaire({ answers }, raw); break; } case 'generate-dev-preferences': { const analysisIdx = args.indexOf('--analysis'); const analysisPath = analysisIdx !== -1 ? args[analysisIdx + 1] : null; const outputIdx = args.indexOf('--output'); const outputPath = outputIdx !== -1 ? args[outputIdx + 1] : null; const stackIdx = args.indexOf('--stack'); const stack = stackIdx !== -1 ? args[stackIdx + 1] : null; profileOutput.cmdGenerateDevPreferences(cwd, { analysis: analysisPath, output: outputPath, stack }, raw); break; } case 'generate-claude-profile': { const analysisIdx = args.indexOf('--analysis'); const analysisPath = analysisIdx !== -1 ? args[analysisIdx + 1] : null; const outputIdx = args.indexOf('--output'); const outputPath = outputIdx !== -1 ? args[outputIdx + 1] : null; const globalFlag = args.includes('--global'); profileOutput.cmdGenerateClaudeProfile(cwd, { analysis: analysisPath, output: outputPath, global: globalFlag }, raw); break; } case 'generate-claude-md': { const outputIdx = args.indexOf('--output'); const outputPath = outputIdx !== -1 ? args[outputIdx + 1] : null; const autoFlag = args.includes('--auto'); const forceFlag = args.includes('--force'); profileOutput.cmdGenerateClaudeMd(cwd, { output: outputPath, auto: autoFlag, force: forceFlag }, raw); break; } default: error(`Unknown command: ${command}`); } } main();