#!/usr/bin/env node /** * Automated batch migration of ~/.claude/plans/*.md to task-mcp database * * Run from task-mcp directory: node migrate-plans-batch.mjs */ import { readFileSync, readdirSync, renameSync, mkdirSync, existsSync, statSync } from 'fs'; import { join } from 'path'; import { homedir } from 'os'; import dotenv from 'dotenv'; import { archiveAdd } from './dist/tools/archives.js'; // Load environment dotenv.config(); // Configuration const PLANS_DIR = join(homedir(), '.claude', 'plans'); const BACKUP_DIR = join(PLANS_DIR, '.migrated-to-mcp'); const ALREADY_MIGRATED = [ 'adaptive-enchanting-truffle.md', 'adaptive-sleeping-pearl.md' ]; /** * Extract title from markdown content (first H1) */ function extractTitle(content, filename) { const lines = content.split('\n'); for (const line of lines) { if (line.startsWith('# ')) { return line.slice(2).trim().substring(0, 500); } } // Fallback to filename return filename .replace('.md', '') .replace(/-/g, ' ') .split(' ') .map(word => word.charAt(0).toUpperCase() + word.slice(1)) .join(' ') .substring(0, 500); } /** * Migrate a single plan file */ async function migratePlan(filename) { const filePath = join(PLANS_DIR, filename); try { const content = readFileSync(filePath, 'utf-8'); const title = extractTitle(content, filename); const fileSize = statSync(filePath).size; console.log(`\n[${new Date().toISOString().substring(11, 19)}] Migrating: ${filename}`); console.log(` Title: ${title}`); console.log(` Size: ${Math.round(fileSize / 1024)}KB`); // Call archive_add const result = await archiveAdd({ project: 'CF', archive_type: 'session', title, content, original_path: filePath, file_size: fileSize }); console.log(` ✓ Migrated successfully`); // Move to backup if (!existsSync(BACKUP_DIR)) { mkdirSync(BACKUP_DIR, { recursive: true }); } const backupPath = join(BACKUP_DIR, filename); renameSync(filePath, backupPath); console.log(` ✓ Moved to backup`); return { success: true, filename, title, fileSize }; } catch (error) { console.error(` ✗ Error: ${error.message}`); return { success: false, filename, error: error.message }; } } /** * Main migration function */ async function main() { console.log('================================================================================'); console.log('Batch Migration: ~/.claude/plans/*.md → task-mcp database'); console.log('================================================================================\n'); // Get all plan files const allFiles = readdirSync(PLANS_DIR).filter(f => f.endsWith('.md')); const filesToMigrate = allFiles.filter(f => !ALREADY_MIGRATED.includes(f)); console.log(`Total plan files: ${allFiles.length}`); console.log(`Already migrated: ${ALREADY_MIGRATED.length}`); console.log(`To migrate: ${filesToMigrate.length}\n`); if (filesToMigrate.length === 0) { console.log('✓ All files already migrated!'); return; } console.log('Starting migration...\n'); const results = { success: [], failed: [] }; // Migrate each file for (let i = 0; i < filesToMigrate.length; i++) { const filename = filesToMigrate[i]; const result = await migratePlan(filename); if (result.success) { results.success.push(result); } else { results.failed.push(result); } // Progress indicator const progress = Math.round(((i + 1) / filesToMigrate.length) * 100); console.log(` Progress: ${i + 1}/${filesToMigrate.length} (${progress}%)`); // Small delay to avoid overwhelming the database await new Promise(resolve => setTimeout(resolve, 50)); } // Summary console.log('\n================================================================================'); console.log('Migration Complete'); console.log('================================================================================\n'); console.log(`✓ Successfully migrated: ${results.success.length} files`); console.log(`✗ Failed: ${results.failed.length} files`); if (results.failed.length > 0) { console.log('\nFailed files:'); results.failed.forEach(f => { console.log(` - ${f.filename}: ${f.error}`); }); } console.log(`\nBackup location: ${BACKUP_DIR}`); console.log('Original files can be restored if needed.'); // Calculate total size const totalSize = results.success.reduce((sum, r) => sum + (r.fileSize || 0), 0); console.log(`\nTotal data migrated: ${Math.round(totalSize / 1024 / 1024 * 100) / 100}MB`); } // Run migration main() .then(() => { console.log('\n✓ Migration script completed successfully'); process.exit(0); }) .catch(error => { console.error('\n✗ Migration script failed:', error); console.error(error.stack); process.exit(1); });