@@ -523,6 +523,35 @@ function copyDirRecursive(src, dst, transform, exclude) {
523523 return count ;
524524}
525525
526+ /**
527+ * Scaffold empty rule category directories with .gitkeep.
528+ * Reads all subdirectories from rules/ and creates them in outDir.
529+ * Writes a .gitkeep file in categories that have no .md/.mdc rule files.
530+ */
531+ function scaffoldEmptyRuleCategories ( outDir ) {
532+ const rulesDir = path . join ( ROOT , "rules" ) ;
533+ if ( ! fs . existsSync ( rulesDir ) ) return ;
534+
535+ const dirs = fs
536+ . readdirSync ( rulesDir , { withFileTypes : true } )
537+ . filter ( ( d ) => d . isDirectory ( ) )
538+ . sort ( ( a , b ) => a . name . localeCompare ( b . name ) ) ;
539+
540+ for ( const dir of dirs ) {
541+ const categoryDir = path . join ( rulesDir , dir . name ) ;
542+ const hasRules = fs
543+ . readdirSync ( categoryDir )
544+ . some ( ( f ) => ( f . endsWith ( ".md" ) || f . endsWith ( ".mdc" ) ) && f !== ".gitkeep" ) ;
545+
546+ const outCategoryDir = path . join ( outDir , dir . name ) ;
547+ ensureDir ( outCategoryDir ) ;
548+
549+ if ( ! hasRules ) {
550+ fs . writeFileSync ( path . join ( outCategoryDir , ".gitkeep" ) , "" ) ;
551+ }
552+ }
553+ }
554+
526555/**
527556 * Join frontmatter and body with exactly one blank line separator.
528557 */
@@ -637,7 +666,7 @@ function generateAtToolAgents(toolDir, rewriteFn) {
637666 * Keeps original directory structure (phase folders).
638667 * Frontmatter: name, description, argument-hint.
639668 */
640- function generateAtToolCommands ( toolDir , rewriteFn ) {
669+ function generateAtToolCommands ( toolDir , rewriteFn , brandPrefix = null ) {
641670 const srcDir = path . join ( ROOT , "commands" ) ;
642671 const outDir = path . join ( DIST_DIR , toolDir , "commands" ) ;
643672 ensureDir ( outDir ) ;
@@ -651,7 +680,14 @@ function generateAtToolCommands(toolDir, rewriteFn) {
651680
652681 for ( const phaseDir of phaseDirs ) {
653682 const cmdDir = path . join ( srcDir , phaseDir . name ) ;
654- const cmdOutDir = path . join ( outDir , phaseDir . name ) ;
683+
684+ let cmdOutDir ;
685+ if ( brandPrefix ) {
686+ const phase = extractPhase ( phaseDir . name ) ;
687+ cmdOutDir = path . join ( outDir , brandPrefix , phase || phaseDir . name ) ;
688+ } else {
689+ cmdOutDir = path . join ( outDir , phaseDir . name ) ;
690+ }
655691 ensureDir ( cmdOutDir ) ;
656692
657693 const cmdFiles = fs
@@ -670,8 +706,9 @@ function generateAtToolCommands(toolDir, rewriteFn) {
670706 }
671707
672708 const body = stripFrontmatter ( content ) ;
709+ const phase = brandPrefix ? extractPhase ( phaseDir . name ) : null ;
673710 const fmObj = {
674- name : fm . name ,
711+ name : brandPrefix ? ` ${ brandPrefix } : ${ phase } : ${ fm . name } ` : fm . name ,
675712 description : fm . description || "" ,
676713 } ;
677714 if ( fm [ "argument-hint" ] ) {
@@ -782,6 +819,8 @@ function generateClaudeRules() {
782819 return 0 ;
783820 }
784821
822+ scaffoldEmptyRuleCategories ( outDir ) ;
823+
785824 const dirs = fs
786825 . readdirSync ( rulesDir , { withFileTypes : true } )
787826 . filter ( ( d ) => d . isDirectory ( ) )
@@ -877,6 +916,8 @@ function generateCursorRules() {
877916 return 0 ;
878917 }
879918
919+ scaffoldEmptyRuleCategories ( outDir ) ;
920+
880921 const dirs = fs
881922 . readdirSync ( rulesDir , { withFileTypes : true } )
882923 . filter ( ( d ) => d . isDirectory ( ) )
@@ -1714,7 +1755,7 @@ function main() {
17141755 console . log ( "\nClaude Code (.claude/):" ) ;
17151756 const claudeAgents = generateAtToolAgents ( ".claude" , rewriteClaude ) ;
17161757 console . log ( ` agents: ${ claudeAgents } ` ) ;
1717- const claudeCommands = generateAtToolCommands ( ".claude" , rewriteClaude ) ;
1758+ const claudeCommands = generateAtToolCommands ( ".claude" , rewriteClaude , "aidd" ) ;
17181759 console . log ( ` commands: ${ claudeCommands } ` ) ;
17191760 const claudeRules = generateClaudeRules ( ) ;
17201761 console . log ( ` rules: ${ claudeRules } ` ) ;
0 commit comments