2. MEMORY.md 设计
2.1 文件结构
markdown
# Project Memory
> Auto-generated memory file. Lines after 200 will be truncated.
## Tech Stack
- Framework: React 18 + TypeScript
- Build: Vite 5
- State: Zustand
- Styling: Tailwind CSS
## Project Structure
- `/src/components` - React components
- `/src/hooks` - Custom hooks
- `/src/store` - Zustand stores
- `/src/utils` - Utility functions
## Coding Conventions
- Use functional components with hooks
- Prefer named exports over default
- Use TypeScript strict mode
- Follow Airbnb style guide
## User Preferences
- Always use `tnpm` instead of `npm`
- Run `tnpm run lint:fix` after code changes
- Prefer composition over inheritance
## Important Decisions
- [2026-03-10] Migrated from Redux to Zustand for simpler state management
- [2026-03-08] Adopted Tailwind CSS for consistent styling
## Common Issues
- **Build errors**: Check Node version (requires 18+)
- **Type errors**: Run `tnpm run type-check` first
## Links to Detailed Memory
- [Debugging Guide](./debugging.md)
- [Component Patterns](./patterns.md)
- [API Integration](./api-integration.md)2.2 自动管理机制
typescript
class MemoryManager {
private memoryPath: string;
private maxLines = 200;
constructor(projectRoot: string) {
this.memoryPath = path.join(
projectRoot,
'.claude',
'projects',
projectRoot.replace(/\//g, '-'),
'memory',
'MEMORY.md'
);
}
// 读取记忆
async read(): Promise<string> {
if (!await fs.exists(this.memoryPath)) {
return '';
}
const content = await fs.readFile(this.memoryPath, 'utf-8');
const lines = content.split('\n');
// 只返回前 200 行
if (lines.length > this.maxLines) {
return lines.slice(0, this.maxLines).join('\n') +
'\n\n<!-- Truncated at 200 lines -->';
}
return content;
}
// 写入记忆
async write(content: string) {
await fs.ensureDir(path.dirname(this.memoryPath));
await fs.writeFile(this.memoryPath, content, 'utf-8');
}
// 追加记忆
async append(section: string, content: string) {
const current = await this.read();
const updated = this.insertOrUpdate(current, section, content);
// 检查是否超过限制
if (updated.split('\n').length > this.maxLines) {
console.warn('⚠️ MEMORY.md exceeds 200 lines. Consider moving content to topic files.');
}
await this.write(updated);
}
// 插入或更新章节
private insertOrUpdate(content: string, section: string, newContent: string): string {
const sectionRegex = new RegExp(`## ${section}[\\s\\S]*?(?=## |$)`);
if (sectionRegex.test(content)) {
// 更新现有章节
return content.replace(sectionRegex, `## ${section}\n${newContent}\n\n`);
} else {
// 添加新章节
return content + `\n## ${section}\n${newContent}\n`;
}
}
// 压缩记忆(当接近 200 行时)
async compress() {
const content = await this.read();
const lines = content.split('\n');
if (lines.length < 180) return; // 还有空间
// 1. 移除过时的决策记录
const decisions = this.extractSection(content, 'Important Decisions');
const recentDecisions = this.keepRecentOnly(decisions, 30); // 只保留 30 天内的
// 2. 将详细内容移到主题文件
const detailedSections = ['Common Issues', 'Debugging Guide'];
for (const section of detailedSections) {
const sectionContent = this.extractSection(content, section);
if (sectionContent.length > 500) {
// 移到单独文件
await this.moveToTopicFile(section, sectionContent);
// 在 MEMORY.md 中保留链接
content = this.replaceSection(
content,
section,
`See [${section}](./${this.slugify(section)}.md)`
);
}
}
await this.write(content);
}
}