@@ -41,11 +41,32 @@ const EXCLUDED_FILES = ['settings.json', 'settings.local.json', 'CLAUDE.md'];
4141// CCW marker in CLAUDE.md for tracking ccw-added content
4242const CCW_REFERENCE_LINE = '- **CCW Instructions**: @~/.claude/CLAUDE.CCW.md' ;
4343
44+ // Lite mode: minimal installation with specific commands and skills only
45+ const LITE_CLAUDE_COMMANDS = [
46+ 'workflow/analyze-with-file.md' ,
47+ 'workflow/debug-with-file.md' ,
48+ ] ;
49+
50+ const LITE_CLAUDE_SKILLS = [
51+ 'workflow-lite-plan' ,
52+ 'workflow-lite-execute' ,
53+ 'team-coordinate' ,
54+ ] ;
55+
56+ const LITE_CODEX_SKILLS = [
57+ 'analyze-with-file' ,
58+ 'debug-with-file' ,
59+ 'workflow-lite-planex' ,
60+ 'team-coordinate' ,
61+ 'csv-wave-pipeline' ,
62+ ] ;
63+
4464interface InstallOptions {
4565 mode ?: string ;
4666 path ?: string ;
4767 force ?: boolean ;
4868 target ?: string ; // 'claude', 'codex', or 'all'
69+ lite ?: boolean ;
4970}
5071
5172interface CopyResult {
@@ -298,6 +319,205 @@ async function backupDirectoryRecursive(
298319 return count ;
299320}
300321
322+ /**
323+ * Lite mode: streamlined installation of specific commands and skills
324+ */
325+ async function installLite (
326+ sourceDir : string ,
327+ installPath : string ,
328+ mode : string ,
329+ target : string ,
330+ version : string
331+ ) : Promise < void > {
332+ // Build item list for display
333+ const claudeItems = ( target === 'claude' || target === 'all' )
334+ ? [ ...LITE_CLAUDE_COMMANDS . map ( c => `command: ${ c } ` ) , ...LITE_CLAUDE_SKILLS . map ( s => `skill: ${ s } ` ) ]
335+ : [ ] ;
336+ const codexItems = ( target === 'codex' || target === 'all' )
337+ ? LITE_CODEX_SKILLS . map ( s => `codex skill: ${ s } ` )
338+ : [ ] ;
339+
340+ console . log ( '' ) ;
341+ info ( 'Lite mode — installing minimal workflow set:' ) ;
342+ for ( const item of [ ...claudeItems , ...codexItems ] ) {
343+ console . log ( chalk . gray ( ` • ${ item } ` ) ) ;
344+ }
345+ console . log ( '' ) ;
346+
347+ const manifest = createManifest ( mode , installPath ) ;
348+ const spinner = createSpinner ( 'Installing lite mode files...' ) . start ( ) ;
349+
350+ try {
351+ // Install specific commands and skills
352+ const { totalFiles, totalDirs } = await installLiteModeItems (
353+ sourceDir , installPath , mode , target , manifest , spinner
354+ ) ;
355+
356+ let files = totalFiles ;
357+ let dirs = totalDirs ;
358+
359+ // Install CLAUDE.CCW.md to global
360+ const srcClaudeCcwMd = join ( sourceDir , '.claude' , 'CLAUDE.CCW.md' ) ;
361+ if ( existsSync ( srcClaudeCcwMd ) ) {
362+ const globalClaudeDir = join ( homedir ( ) , '.claude' ) ;
363+ if ( ! existsSync ( globalClaudeDir ) ) {
364+ mkdirSync ( globalClaudeDir , { recursive : true } ) ;
365+ }
366+ const destFile = join ( globalClaudeDir , 'CLAUDE.CCW.md' ) ;
367+ spinner . text = 'Installing CLAUDE.CCW.md to global...' ;
368+ copyFileSync ( srcClaudeCcwMd , destFile ) ;
369+ addFileEntry ( manifest , destFile ) ;
370+ files ++ ;
371+ }
372+
373+ // Handle CLAUDE.md reference
374+ const shouldHandleClaudeMd = target === 'claude' || target === 'all' ;
375+ const claudeMdPath = join ( installPath , '.claude' , 'CLAUDE.md' ) ;
376+ const minimalClaudeMd = '# Project Instructions\n\n- **CCW Instructions**: @~/.claude/CLAUDE.CCW.md\n' ;
377+
378+ if ( shouldHandleClaudeMd ) {
379+ if ( existsSync ( claudeMdPath ) ) {
380+ const content = readFileSync ( claudeMdPath , 'utf8' ) ;
381+ if ( ! content . includes ( 'CLAUDE.CCW.md' ) ) {
382+ // Append reference line
383+ const updated = content . trimEnd ( ) + '\n' + CCW_REFERENCE_LINE + '\n' ;
384+ writeFileSync ( claudeMdPath , updated , 'utf8' ) ;
385+ }
386+ } else {
387+ const claudeDir = join ( installPath , '.claude' ) ;
388+ if ( ! existsSync ( claudeDir ) ) {
389+ mkdirSync ( claudeDir , { recursive : true } ) ;
390+ }
391+ writeFileSync ( claudeMdPath , minimalClaudeMd , 'utf8' ) ;
392+ addFileEntry ( manifest , claudeMdPath ) ;
393+ files ++ ;
394+ }
395+ }
396+
397+ // Create version.json
398+ const versionDir = join ( installPath , '.claude' ) ;
399+ if ( ! existsSync ( versionDir ) ) mkdirSync ( versionDir , { recursive : true } ) ;
400+ const versionPath = join ( versionDir , 'version.json' ) ;
401+ writeFileSync ( versionPath , JSON . stringify ( {
402+ version, installedAt : new Date ( ) . toISOString ( ) , mode, installer : 'ccw' , lite : true
403+ } , null , 2 ) , 'utf8' ) ;
404+ addFileEntry ( manifest , versionPath ) ;
405+ files ++ ;
406+
407+ // Initialize CLI tools config
408+ spinner . text = 'Initializing CLI tools configuration...' ;
409+ const cliToolsInitResult = initCliToolsConfig ( ) ;
410+ if ( cliToolsInitResult . created . length > 0 ) {
411+ files += cliToolsInitResult . created . length ;
412+ }
413+
414+ spinner . succeed ( 'Lite mode installation complete!' ) ;
415+
416+ // Save manifest
417+ const manifestPath = saveManifest ( manifest ) ;
418+
419+ // Show summary
420+ console . log ( '' ) ;
421+ summaryBox ( {
422+ title : ' Lite Install Summary ' ,
423+ lines : [
424+ chalk . green . bold ( '✓ Lite Installation Successful' ) ,
425+ '' ,
426+ chalk . white ( `Mode: ${ chalk . cyan ( mode ) } ` ) ,
427+ chalk . white ( `Path: ${ chalk . cyan ( installPath ) } ` ) ,
428+ chalk . white ( `Target: ${ chalk . cyan ( target ) } ` ) ,
429+ chalk . white ( `Version: ${ chalk . cyan ( version ) } ` ) ,
430+ '' ,
431+ chalk . gray ( `Files installed: ${ files } ` ) ,
432+ chalk . gray ( `Directories created: ${ dirs } ` ) ,
433+ ...( cliToolsInitResult . created . length > 0
434+ ? [ chalk . gray ( `CLI config initialized: ${ cliToolsInitResult . created . join ( ', ' ) } ` ) ]
435+ : [ ] ) ,
436+ '' ,
437+ chalk . gray ( `Manifest: ${ basename ( manifestPath ) } ` ) ,
438+ ] ,
439+ borderColor : 'green'
440+ } ) ;
441+
442+ console . log ( '' ) ;
443+ info ( 'Next steps:' ) ;
444+ console . log ( chalk . gray ( ' 1. Restart Claude Code or your IDE' ) ) ;
445+ console . log ( chalk . gray ( ' 2. Try: /workflow-lite-plan or /team-coordinate' ) ) ;
446+ console . log ( chalk . gray ( ' 3. Run: ccw install (without --lite) for full installation' ) ) ;
447+ console . log ( '' ) ;
448+
449+ } catch ( err ) {
450+ spinner . fail ( 'Lite mode installation failed' ) ;
451+ error ( ( err as Error ) . message ) ;
452+ process . exit ( 1 ) ;
453+ }
454+ }
455+
456+ /**
457+ * Install lite mode items: specific commands and skills only
458+ */
459+ async function installLiteModeItems (
460+ sourceDir : string ,
461+ installPath : string ,
462+ mode : string ,
463+ target : string ,
464+ manifest : any ,
465+ spinner : Ora
466+ ) : Promise < { totalFiles : number ; totalDirs : number } > {
467+ let totalFiles = 0 ;
468+ let totalDirs = 0 ;
469+
470+ // Install Claude commands and skills
471+ if ( ( target === 'claude' || target === 'all' ) && existsSync ( join ( sourceDir , '.claude' ) ) ) {
472+ // Commands
473+ for ( const cmd of LITE_CLAUDE_COMMANDS ) {
474+ const srcFile = join ( sourceDir , '.claude' , 'commands' , cmd ) ;
475+ if ( ! existsSync ( srcFile ) ) continue ;
476+
477+ const destFile = join ( installPath , '.claude' , 'commands' , cmd ) ;
478+ const destDir = dirname ( destFile ) ;
479+ if ( ! existsSync ( destDir ) ) {
480+ mkdirSync ( destDir , { recursive : true } ) ;
481+ totalDirs ++ ;
482+ addDirectoryEntry ( manifest , destDir ) ;
483+ }
484+
485+ spinner . text = `Installing command: ${ cmd } ` ;
486+ copyFileSync ( srcFile , destFile ) ;
487+ addFileEntry ( manifest , destFile ) ;
488+ totalFiles ++ ;
489+ }
490+
491+ // Skills
492+ for ( const skill of LITE_CLAUDE_SKILLS ) {
493+ const srcSkill = join ( sourceDir , '.claude' , 'skills' , skill ) ;
494+ if ( ! existsSync ( srcSkill ) ) continue ;
495+
496+ const destSkill = join ( installPath , '.claude' , 'skills' , skill ) ;
497+ spinner . text = `Installing skill: ${ skill } ` ;
498+ const result = await copyDirectory ( srcSkill , destSkill , manifest ) ;
499+ totalFiles += result . files ;
500+ totalDirs += result . directories ;
501+ }
502+ }
503+
504+ // Install Codex skills
505+ if ( ( target === 'codex' || target === 'all' ) && existsSync ( join ( sourceDir , '.codex' ) ) ) {
506+ for ( const skill of LITE_CODEX_SKILLS ) {
507+ const srcSkill = join ( sourceDir , '.codex' , 'skills' , skill ) ;
508+ if ( ! existsSync ( srcSkill ) ) continue ;
509+
510+ const destSkill = join ( installPath , '.codex' , 'skills' , skill ) ;
511+ spinner . text = `Installing codex skill: ${ skill } ` ;
512+ const result = await copyDirectory ( srcSkill , destSkill , manifest ) ;
513+ totalFiles += result . files ;
514+ totalDirs += result . directories ;
515+ }
516+ }
517+
518+ return { totalFiles, totalDirs } ;
519+ }
520+
301521// Get package root directory (ccw/src/commands -> ccw)
302522function getPackageRoot ( ) : string {
303523 return join ( __dirname , '..' , '..' ) ;
@@ -414,6 +634,12 @@ export async function installCommand(options: InstallOptions): Promise<void> {
414634 process . exit ( 1 ) ;
415635 }
416636
637+ // Lite mode: install only specific commands and skills, then return
638+ if ( options . lite ) {
639+ await installLite ( sourceDir , installPath , mode , target , version ) ;
640+ return ;
641+ }
642+
417643 console . log ( '' ) ;
418644 info ( `Found ${ availableDirs . length } directories to install: ${ availableDirs . join ( ', ' ) } ` ) ;
419645
0 commit comments