Skip to main content
Glama

myAI Memory Sync

by Jktfe
cli.ts9.34 kB
#!/usr/bin/env node import { printVersion } from './version.js'; import { templateService } from './services/templateService.js'; import { platformService } from './services/platformService.js'; import { generateTemplate } from './templateParser.js'; import { main as startHttpServer } from './server.js'; import fs from 'fs/promises'; import path from 'path'; import { homedir } from 'os'; import { ensureFileWritable } from './platformSync.js'; import { config } from './config.js'; import { program } from 'commander'; import { processMemoryCommand } from './naturalLanguageParser.js'; async function printHelp() { console.log(` myAI Memory Sync - CLI Usage Available commands: --version Print version information --help Show this help message --http Start the HTTP server for SSE transport --stdio Start the stdio server for MCP transport --debug Enable debug mode --emergency-sync Perform emergency sync across all platforms --remember <command> Process a natural language memory command Environment variables: CLAUDE_WEB_SYNC_ENABLED=true Enable Claude Web synchronization CLAUDE_WEB_HEADLESS=true Run Chrome in headless mode for Claude Web CLAUDE_WEB_EMAIL=you@email.com Set your Claude Web email for auto-login `); } async function emergencySync() { try { console.log('Starting emergency sync...'); // Read the master template const masterPath = config.paths?.masterTemplate || path.join(process.cwd(), 'myAI Master.md'); console.log(`Reading master template from: ${masterPath}`); const templateContent = await fs.readFile(masterPath, 'utf-8'); // Get myAI Memory section const myAIMemoryMatch = templateContent.match(/(# myAI Memory[\s\S]*)/); if (!myAIMemoryMatch) { console.error('Could not find "# myAI Memory" section in the template'); process.exit(1); } const memorySection = myAIMemoryMatch[1]; // Sync to windsurf const windsurfPath = config.paths?.windsurfMemoryPath || path.join(homedir(), '.codeium', 'windsurf', 'memories', 'global_rules.md'); console.log(`Syncing to Windsurf at: ${windsurfPath}`); try { // Ensure the file is writable const windsurfWritable = await ensureFileWritable(windsurfPath); if (windsurfWritable) { // Read existing content if it exists let windsurfContent = ''; try { windsurfContent = await fs.readFile(windsurfPath, 'utf-8'); } catch (err) { // File might not exist, that's okay } // Check if it has myAI Memory section const hasMemorySection = windsurfContent.includes('# myAI Memory'); if (hasMemorySection) { // Replace existing section windsurfContent = windsurfContent.replace(/# myAI Memory[\s\S]*$/, memorySection); } else { // Append memory section windsurfContent = windsurfContent.trim() + '\n\n' + memorySection; } // Write updated content await fs.writeFile(windsurfPath, windsurfContent); console.log('✅ Successfully updated Windsurf memory'); } else { console.error('❌ Could not make Windsurf file writable:', windsurfPath); } } catch (err) { console.error('❌ Error updating Windsurf:', err); } // Sync to CLAUDE.md files const claudeProjectsPath = config.paths?.claudeProjectsPath || path.join(homedir(), 'CascadeProjects'); // Start with home directory const homeClaudeMdPath = path.join(homedir(), 'CLAUDE.md'); console.log(`Syncing to home CLAUDE.md at: ${homeClaudeMdPath}`); try { // Ensure the file is writable const homeClaudeWritable = await ensureFileWritable(homeClaudeMdPath); if (homeClaudeWritable) { // Read existing content if it exists let claudeContent = ''; try { claudeContent = await fs.readFile(homeClaudeMdPath, 'utf-8'); } catch (err) { // File might not exist, that's okay } // Check if it has myAI Memory section const hasMemorySection = claudeContent.includes('# myAI Memory'); if (hasMemorySection) { // Replace existing section claudeContent = claudeContent.replace(/# myAI Memory[\s\S]*$/, memorySection); } else { // Append memory section claudeContent = claudeContent.trim() + '\n\n' + memorySection; } // Write updated content await fs.writeFile(homeClaudeMdPath, claudeContent); console.log('✅ Successfully updated home CLAUDE.md'); } else { console.error('❌ Could not make home CLAUDE.md file writable'); } } catch (err) { console.error('❌ Error updating home CLAUDE.md:', err); } // Check if projects directory exists console.log(`Syncing to project CLAUDE.md files in: ${claudeProjectsPath}`); try { // Get all subdirectories const dirEntries = await fs.readdir(claudeProjectsPath, { withFileTypes: true }); const directories = dirEntries.filter(entry => entry.isDirectory()); console.log(`Found ${directories.length} project directories`); let successCount = 0; let failCount = 0; // Process each directory for (const dir of directories) { const dirPath = path.join(claudeProjectsPath, dir.name); const claudeMdPath = path.join(dirPath, 'CLAUDE.md'); try { // Ensure the file is writable const claudeWritable = await ensureFileWritable(claudeMdPath); if (claudeWritable) { // Read existing content if it exists let claudeContent = ''; try { claudeContent = await fs.readFile(claudeMdPath, 'utf-8'); } catch (err) { // File might not exist, that's okay } // Check if it has myAI Memory section const hasMemorySection = claudeContent.includes('# myAI Memory'); if (hasMemorySection) { // Replace existing section claudeContent = claudeContent.replace(/# myAI Memory[\s\S]*$/, memorySection); } else { // Append memory section claudeContent = claudeContent.trim() + '\n\n' + memorySection; } // Write updated content await fs.writeFile(claudeMdPath, claudeContent); successCount++; } else { failCount++; } } catch (err) { console.error(`Error updating ${claudeMdPath}:`, err); failCount++; } } console.log(`✅ Successfully updated ${successCount} project CLAUDE.md files`); if (failCount > 0) { console.log(`❌ Failed to update ${failCount} project CLAUDE.md files`); } } catch (err) { console.error('❌ Error accessing projects directory:', err); } console.log('Emergency sync completed'); } catch (err) { console.error('❌ Emergency sync failed:', err); process.exit(1); } } async function main() { program .name('myAI Memory Sync') .description('Sync memory templates across platforms') .version('1.0.0') .option('--help', 'Show this help message') .option('--http', 'Start the HTTP server for SSE transport') .option('--stdio', 'Start the stdio server for MCP transport') .option('--debug', 'Enable debug mode') .option('--emergency-sync', 'Emergency sync - fixes permissions and updates all platforms') .option('--remember <command>', 'Process a natural language memory command') .action(async (options: any) => { if (options.help) { await printHelp(); process.exit(0); } if (options.http) { startHttpServer(); return; } if (options.debug) { // Enable debug process.env.DEBUG = 'true'; } if (options.emergencySync) { await emergencySync(); process.exit(0); } if (options.remember) { // Process natural language memory command console.log('Processing memory command:', options.remember); try { const result = await processMemoryCommand(options.remember); if (result.success) { console.log('✅', result.message); } else { console.error('❌', result.message); } process.exit(0); } catch (error) { console.error('Error processing memory command:', error); process.exit(1); } } else if (options.stdio) { // Continue with stdio server console.error('Starting myAI Memory Sync with stdio transport'); } else { console.error(`Unknown command: ${options[0]}`); await printHelp(); process.exit(1); } }); program.parse(process.argv); } // Run main if this file is being executed directly if (import.meta.url === `file://${process.argv[1]}`) { main().catch(err => { console.error('Error in main:', err); process.exit(1); }); }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Jktfe/myAImemory-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server