@@ -94,20 +94,19 @@ const IDE_CONFIGS: Record<string, IdeConfig> = {
9494 common : { commandsDir : '.agents/commands' , skillsDir : '.agents/skills' } ,
9595} ;
9696
97- // Entry file templates configuration
97+ // Entry file configuration (single template, dynamic generation for IDE-specific files)
98+ // Entry file configuration - single template for AGENTS.md, dynamic generation for others
9899const ENTRY_TEMPLATES = {
99100 AGENTS : {
100101 template : 'AGENTS.md.template' ,
101102 output : 'AGENTS.md' ,
102103 displayName : 'AGENTS.md (通用入口文件)' ,
103104 } ,
104105 CLAUDE : {
105- template : 'CLAUDE.md.template' ,
106106 output : 'CLAUDE.md' ,
107107 displayName : 'CLAUDE.md (Claude Code 入口文件)' ,
108108 } ,
109109 CURSOR : {
110- template : 'cursor-rule.mdc.template' ,
111110 outputDir : '.cursor/rules' ,
112111 output : 'openmemory.mdc' ,
113112 displayName : '.cursor/rules/openmemory.mdc (Cursor 规则文件)' ,
@@ -421,9 +420,67 @@ function processTemplate(content: string, projectName: string, ideList?: string[
421420// Entry File Generation
422421// ============================================================================
423422
423+ // Marker to detect if OpenMemory Plus reference already exists
424+ const OMP_REFERENCE_MARKER = '<!-- OpenMemory Plus Integration -->' ;
425+
426+ // Single source of truth for MANDATORY reference content (DRY principle)
427+ const MANDATORY_CONTENT = `## 🚨 MANDATORY - BEFORE ANY OUTPUT
428+
429+ **Load \`_omp/AGENTS.md\` NOW and follow all instructions.**
430+
431+ If file not found, report error: "OpenMemory Plus not initialized. Run: npx openmemory-plus install"` ;
432+
433+ // Universal MANDATORY reference content (used for append mode)
434+ const OMP_REFERENCE_CONTENT = `
435+ ${ OMP_REFERENCE_MARKER }
436+
437+ ${ MANDATORY_CONTENT }
438+ ` ;
439+
440+ // Dynamic content generators for IDE-specific entry files
441+ function generateClaudeMdContent ( projectName : string , createdAt : string ) : string {
442+ return `# ${ projectName } - Claude Code Instructions
443+
444+ ${ OMP_REFERENCE_MARKER }
445+
446+ ${ MANDATORY_CONTENT }
447+
448+ ---
449+ *Generated by OpenMemory Plus on ${ createdAt } *
450+ ` ;
451+ }
452+
453+ function generateCursorMdcContent ( projectName : string , createdAt : string ) : string {
454+ return `---
455+ description: OpenMemory Plus - Dual-layer memory system for AI agents
456+ globs: ["**/*"]
457+ alwaysApply: true
458+ ---
459+
460+ # ${ projectName } - Memory System
461+
462+ ${ OMP_REFERENCE_MARKER }
463+
464+ ${ MANDATORY_CONTENT }
465+
466+ ---
467+ *Generated by OpenMemory Plus on ${ createdAt } *
468+ ` ;
469+ }
470+
471+ // Check if file already contains OMP reference
472+ function hasOmpReference ( content : string ) : boolean {
473+ return content . includes ( OMP_REFERENCE_MARKER ) || content . includes ( '_omp/AGENTS.md' ) ;
474+ }
475+
424476/**
425477 * Generate entry files (AGENTS.md, CLAUDE.md, etc.) based on selected IDEs
426478 * Entry files are what AI agents read at startup to understand the project
479+ *
480+ * For AGENTS.md: Uses progressive append mode
481+ * - If file doesn't exist: create with template
482+ * - If file exists but no OMP reference: append reference
483+ * - If file exists with OMP reference: skip (already configured)
427484 */
428485function generateEntryFiles (
429486 targetDir : string ,
@@ -440,7 +497,7 @@ function generateEntryFiles(
440497 return ;
441498 }
442499
443- // Helper function to safely generate entry file
500+ // Helper function to safely generate entry file (for non-AGENTS.md files)
444501 const generateFile = (
445502 templatePath : string ,
446503 targetPath : string ,
@@ -469,33 +526,115 @@ function generateEntryFiles(
469526 }
470527 } ;
471528
472- // Always generate AGENTS.md (universal entry file)
473- generateFile (
474- join ( entryTemplatesDir , ENTRY_TEMPLATES . AGENTS . template ) ,
475- join ( targetDir , ENTRY_TEMPLATES . AGENTS . output ) ,
476- ENTRY_TEMPLATES . AGENTS . displayName
477- ) ;
529+ // Handle AGENTS.md with progressive append mode
530+ const agentsPath = join ( targetDir , ENTRY_TEMPLATES . AGENTS . output ) ;
531+ const agentsTemplatePath = join ( entryTemplatesDir , ENTRY_TEMPLATES . AGENTS . template ) ;
532+
533+ try {
534+ if ( ! existsSync ( agentsPath ) ) {
535+ // Case 1: No AGENTS.md exists - create with template
536+ if ( existsSync ( agentsTemplatePath ) ) {
537+ const template = readFileSync ( agentsTemplatePath , 'utf-8' ) ;
538+ const content = processTemplate ( template , projectName , selectedIdes ) ;
539+ writeFileSync ( agentsPath , content ) ;
540+ console . log ( chalk . green ( ` ✓ 创建 ${ ENTRY_TEMPLATES . AGENTS . displayName } ` ) ) ;
541+ }
542+ } else if ( force ) {
543+ // Case 2: Force mode - overwrite with template
544+ if ( existsSync ( agentsTemplatePath ) ) {
545+ const template = readFileSync ( agentsTemplatePath , 'utf-8' ) ;
546+ const content = processTemplate ( template , projectName , selectedIdes ) ;
547+ writeFileSync ( agentsPath , content ) ;
548+ console . log ( chalk . green ( ` ✓ 覆盖 ${ ENTRY_TEMPLATES . AGENTS . displayName } ` ) ) ;
549+ }
550+ } else {
551+ // Case 3: AGENTS.md exists - check if OMP reference already present
552+ const existingContent = readFileSync ( agentsPath , 'utf-8' ) ;
553+
554+ if ( existingContent . includes ( OMP_REFERENCE_MARKER ) || existingContent . includes ( '_omp/AGENTS.md' ) ) {
555+ // Already has OMP reference
556+ console . log ( chalk . gray ( ` ○ ${ ENTRY_TEMPLATES . AGENTS . displayName } 已包含 OMP 引用` ) ) ;
557+ } else {
558+ // Append OMP reference to existing file
559+ const updatedContent = existingContent . trimEnd ( ) + '\n\n---\n' + OMP_REFERENCE_CONTENT ;
560+ writeFileSync ( agentsPath , updatedContent ) ;
561+ console . log ( chalk . green ( ` ✓ 更新 ${ ENTRY_TEMPLATES . AGENTS . displayName } (追加 OMP 引用)` ) ) ;
562+ }
563+ }
564+ } catch ( error ) {
565+ const errorMessage = error instanceof Error ? error . message : String ( error ) ;
566+ console . log ( chalk . red ( ` ✗ 处理 ${ ENTRY_TEMPLATES . AGENTS . displayName } 失败: ${ errorMessage } ` ) ) ;
567+ }
568+
569+ // Generate IDE-specific entry files using dynamic generators
570+ const createdAt = new Date ( ) . toISOString ( ) . split ( 'T' ) [ 0 ] ;
478571
479- // Generate IDE-specific entry files
480572 for ( const ide of selectedIdes ) {
481573 switch ( ide ) {
482574 case 'claude' :
483- case 'claude-desktop' :
484- generateFile (
485- join ( entryTemplatesDir , ENTRY_TEMPLATES . CLAUDE . template ) ,
486- join ( targetDir , ENTRY_TEMPLATES . CLAUDE . output ) ,
487- ENTRY_TEMPLATES . CLAUDE . displayName
488- ) ;
575+ case 'claude-desktop' : {
576+ const claudePath = join ( targetDir , ENTRY_TEMPLATES . CLAUDE . output ) ;
577+ try {
578+ if ( ! existsSync ( claudePath ) ) {
579+ // Case 1: No CLAUDE.md exists - create new
580+ const content = generateClaudeMdContent ( projectName , createdAt ) ;
581+ writeFileSync ( claudePath , content ) ;
582+ console . log ( chalk . green ( ` ✓ 创建 ${ ENTRY_TEMPLATES . CLAUDE . displayName } ` ) ) ;
583+ } else if ( force ) {
584+ // Case 2: Force mode - overwrite
585+ const content = generateClaudeMdContent ( projectName , createdAt ) ;
586+ writeFileSync ( claudePath , content ) ;
587+ console . log ( chalk . green ( ` ✓ 覆盖 ${ ENTRY_TEMPLATES . CLAUDE . displayName } ` ) ) ;
588+ } else {
589+ // Case 3: CLAUDE.md exists - check if OMP reference already present
590+ const existingContent = readFileSync ( claudePath , 'utf-8' ) ;
591+ if ( hasOmpReference ( existingContent ) ) {
592+ console . log ( chalk . gray ( ` ○ ${ ENTRY_TEMPLATES . CLAUDE . displayName } 已包含 OMP 引用` ) ) ;
593+ } else {
594+ // Append OMP reference to existing file
595+ const updatedContent = existingContent . trimEnd ( ) + '\n\n---\n' + OMP_REFERENCE_CONTENT ;
596+ writeFileSync ( claudePath , updatedContent ) ;
597+ console . log ( chalk . green ( ` ✓ 更新 ${ ENTRY_TEMPLATES . CLAUDE . displayName } (追加 OMP 引用)` ) ) ;
598+ }
599+ }
600+ } catch ( error ) {
601+ const errorMessage = error instanceof Error ? error . message : String ( error ) ;
602+ console . log ( chalk . red ( ` ✗ 处理 ${ ENTRY_TEMPLATES . CLAUDE . displayName } 失败: ${ errorMessage } ` ) ) ;
603+ }
489604 break ;
605+ }
490606
491607 case 'cursor' : {
492608 const cursorRulesDir = join ( targetDir , ENTRY_TEMPLATES . CURSOR . outputDir ) ;
493- generateFile (
494- join ( entryTemplatesDir , ENTRY_TEMPLATES . CURSOR . template ) ,
495- join ( cursorRulesDir , ENTRY_TEMPLATES . CURSOR . output ) ,
496- ENTRY_TEMPLATES . CURSOR . displayName ,
497- cursorRulesDir
498- ) ;
609+ const cursorPath = join ( cursorRulesDir , ENTRY_TEMPLATES . CURSOR . output ) ;
610+ try {
611+ mkdirSync ( cursorRulesDir , { recursive : true } ) ;
612+ if ( ! existsSync ( cursorPath ) ) {
613+ // Case 1: No .mdc exists - create new
614+ const content = generateCursorMdcContent ( projectName , createdAt ) ;
615+ writeFileSync ( cursorPath , content ) ;
616+ console . log ( chalk . green ( ` ✓ 创建 ${ ENTRY_TEMPLATES . CURSOR . displayName } ` ) ) ;
617+ } else if ( force ) {
618+ // Case 2: Force mode - overwrite
619+ const content = generateCursorMdcContent ( projectName , createdAt ) ;
620+ writeFileSync ( cursorPath , content ) ;
621+ console . log ( chalk . green ( ` ✓ 覆盖 ${ ENTRY_TEMPLATES . CURSOR . displayName } ` ) ) ;
622+ } else {
623+ // Case 3: .mdc exists - check if OMP reference already present
624+ const existingContent = readFileSync ( cursorPath , 'utf-8' ) ;
625+ if ( hasOmpReference ( existingContent ) ) {
626+ console . log ( chalk . gray ( ` ○ ${ ENTRY_TEMPLATES . CURSOR . displayName } 已包含 OMP 引用` ) ) ;
627+ } else {
628+ // Append OMP reference to existing file (after frontmatter)
629+ const updatedContent = existingContent . trimEnd ( ) + '\n\n---\n' + OMP_REFERENCE_CONTENT ;
630+ writeFileSync ( cursorPath , updatedContent ) ;
631+ console . log ( chalk . green ( ` ✓ 更新 ${ ENTRY_TEMPLATES . CURSOR . displayName } (追加 OMP 引用)` ) ) ;
632+ }
633+ }
634+ } catch ( error ) {
635+ const errorMessage = error instanceof Error ? error . message : String ( error ) ;
636+ console . log ( chalk . red ( ` ✗ 处理 ${ ENTRY_TEMPLATES . CURSOR . displayName } 失败: ${ errorMessage } ` ) ) ;
637+ }
499638 break ;
500639 }
501640
0 commit comments