开发指南
从源码构建
先决条件
- Node.js 18.0.0 或更高版本
- npm(随 Node.js 一起提供)
- Git
克隆与构建
bash
# Clone repository
git clone https://github.com/thedotmack/claude-mem.git
cd claude-mem
# Install dependencies
npm install
# Build all components
npm run build构建过程
构建过程使用 esbuild 来编译 TypeScript:
- 将 TypeScript 编译为 JavaScript
- 为
plugin/scripts/中的每个钩子创建独立的可执行文件 - 将 MCP 搜索服务器打包到
plugin/scripts/mcp-server.cjs - 将Worker 进程打包到
plugin/scripts/worker-service.cjs - 将网页查看器 UI 打包到
plugin/ui/viewer.html
构建输出:
- 挂钩可执行文件:
*-hook.js(ESM 格式) - 智能安装程序:
smart-install.js(ESM 格式) - Worker 进程服务:
worker-service.cjs(CJS 格式) - MCP 服务器:
mcp-server.cjs(CJS 格式) - 查看器界面:
viewer.html(独立 HTML 包)
构建脚本
bash
# Build everything
npm run build
# Build only hooks
npm run build:hooks
# The build script is defined in scripts/build-hooks.js开发工作流程
1. 进行更改
在 src/ 中编辑 TypeScript 源文件:
src/
├── hooks/ # Hook implementations (entry points + logic)
├── services/ # Worker service and database
├── servers/ # MCP search server
├── sdk/ # Claude Agent SDK integration
├── shared/ # Shared utilities
├── ui/
│ └── viewer/ # React web viewer UI components
└── utils/ # General utilities2. 构建
bash
npm run build3. 测试
bash
# Run all tests
npm test
# Test specific file
node --test tests/session-lifecycle.test.ts
# Test context injection
npm run test:context
# Verbose context test
npm run test:context:verbose4. 手动测试
bash
# Start worker manually
npm run worker:start
# Check worker status
npm run worker:status
# View logs
npm run worker:logs
# Test hooks manually
echo '{"session_id":"test-123","cwd":"'$(pwd)'","source":"startup"}' | node plugin/scripts/context-hook.js5. 迭代
重复步骤1-4,直到你的更改按预期工作。
查看器界面开发
使用 React 查看器
网页查看器 UI 是一个内置在自包含 HTML 包中的 React 应用程序。
地点: src/ui/viewer/
结构:
src/ui/viewer/
├── index.tsx # Entry point
├── App.tsx # Main application component
├── components/ # React components
│ ├── Header.tsx # Header with logo and actions
│ ├── Sidebar.tsx # Project filter sidebar
│ ├── Feed.tsx # Main feed with infinite scroll
│ ├── cards/ # Card components
│ │ ├── ObservationCard.tsx
│ │ ├── PromptCard.tsx
│ │ ├── SummaryCard.tsx
│ │ └── SkeletonCard.tsx
├── hooks/ # Custom React hooks
│ ├── useSSE.ts # Server-Sent Events connection
│ ├── usePagination.ts # Infinite scroll pagination
│ ├── useSettings.ts # Settings persistence
│ └── useStats.ts # Database statistics
├── utils/ # Utilities
│ ├── constants.ts # Constants (API URLs, etc.)
│ ├── formatters.ts # Date/time formatting
│ └── merge.ts # Data merging and deduplication
└── assets/ # Static assets (fonts, logos)建筑查看器界面
bash
# Build everything including viewer
npm run build
# The viewer is built to plugin/ui/viewer.html
# It's a self-contained HTML file with inlined JS and CSS测试查看器更改
- 在
src/ui/viewer/中对 React 组件进行更改 - 版本:
npm run build - 同步到已安装插件:
npm run sync-marketplace - 重启Worker 进程:
npm run worker:restart - 在 http://localhost:37777 刷新浏览器
热重载:当前不支持。更改需要完全重建并重启。
添加新的查看器功能
示例:添加一种新卡类型
- 在
src/ui/viewer/components/cards/YourCard.tsx中创建组件:
tsx
// Your data structure
}
return (
<div className="card">
{/* Your UI */}
</div>
);
};- 在
Feed.tsx中导入和使用:
tsx
// In render logic:
{item.type === 'your_type' && <YourCard {...item} />}如有必要,在
src/ui/viewer/types.ts中更新类型重建并测试
查看器用户界面架构
数据流:
- Worker 服务暴露 HTTP SSE 端点
- React 应用通过 HTTP 获取初始数据(分页)
- SSE 连接提供实时更新
- 自定义钩子处理状态管理和数据合并
- 组件根据项目类型渲染卡片
关键模式:
- 无限滚动:使用 Intersection Observer 的
usePagination钩子 - 实时更新:带自动重连的
useSSE钩子 - 去重:
merge.ts工具可以防止重复项 - 设置持久性:
useSettings钩子与 localStorage - 主题支持:带有亮色/暗色/系统主题的 CSS 变量
添加新功能
添加新钩子
- 在
src/hooks/your-hook.ts中创建钩子实现:
typescript
#!/usr/bin/env node
async function main() {
const input = await readStdin();
// Hook implementation
const result = {
hookSpecificOutput: 'Optional output'
};
console.log(JSON.stringify(result));
}
main().catch(console.error);注意:从 v4.3.1 版本开始,hooks 是自包含的文件。shebang 将在构建过程中由 esbuild 自动添加。
- 添加到
plugin/hooks/hooks.json:
json
{
"YourHook": [{
"hooks": [{
"type": "command",
"command": "node ${CLAUDE_PLUGIN_ROOT}/scripts/your-hook.js",
"timeout": 120
}]
}]
}- 重建:
bash
npm run build修改数据库模式
- 向
src/services/sqlite/migrations.ts添加迁移:
typescript
version: 11,
up: (db: Database) => {
db.run(`
ALTER TABLE observations ADD COLUMN new_field TEXT;
`);
},
down: (db: Database) => {
// Optional: define rollback
}
};src/services/sqlite/types.ts中的更新类型:
typescript
// ... existing fields
new_field?: string;
}- 更新
src/services/sqlite/SessionStore.ts中的数据库方法:
typescript
createObservation(obs: Observation) {
// Include new_field in INSERT
}- 测试迁移:
bash
# Backup database first!
cp ~/.claude-mem/claude-mem.db ~/.claude-mem/claude-mem.db.backup
# Run tests
npm test扩展 SDK 提示
- 修改
src/sdk/prompts.ts中的提示:
typescript
return `
<observation>
<!-- Add new XML structure -->
</observation>
`;
}- 更新
src/sdk/parser.ts中的解析器:
typescript
// Parse new XML fields
}- 测试:
bash
npm test添加 MCP 搜索工具
- 在
src/servers/mcp-server.ts中添加工具定义:
typescript
server.setRequestHandler(CallToolRequestSchema, async (request) => {
if (request.params.name === 'your_new_tool') {
// Implement tool logic
const results = await search.yourNewSearch(params);
return formatResults(results);
}
});- 在
src/services/sqlite/SessionSearch.ts中添加搜索方法:
typescript
yourNewSearch(params: YourParams): SearchResult[] {
// Implement FTS5 search
}- 重建并测试:
bash
npm run build
npm test测试
测试哲学
Claude-mem 依赖于真实世界的使用和手动测试,而不是传统的单元测试。该项目的理念优先考虑:
- 手动验证 - 在实际的 Claude Code 会话中测试功能
- 集成测试 - 运行完整系统的端到端测试
- 数据库检查 - 通过 SQLite 查询验证数据的正确性
- 命令行工具 - 用于检查系统状态的交互式工具
- 可观察性 - 全面的日志记录和工作节点健康检查
选择这种方法的原因是:
- 钩子行为在很大程度上取决于Claude Code的运行时环境
- SDK 交互需要真实的 API 调用和响应
- SQLite 和 Bun 运行时提供稳定性保证
- 手动测试可以发现单元测试未能检测到的集成问题
手动测试工作流程
在开发新功能时:
构建和同步:
bashnpm run build npm run sync-marketplace npm run worker:restart在实际课程中测试:
- 启动Claude代码
- 触发你正在测试的功能
- 验证预期行为
检查数据库状态:
bashsqlite3 ~/.claude-mem/claude-mem.db "SELECT * FROM your_table;"监控 Worker 日志:
bashnpm run worker:logs验证队列健康状况(用于恢复功能)
bashbun scripts/check-pending-queue.ts
测试工具
健康检查:
bash
# Worker status
npm run worker:status
# Queue inspection
curl http://localhost:37777/api/pending-queue
# Database integrity
sqlite3 ~/.claude-mem/claude-mem.db "PRAGMA integrity_check;"钩子测试:
bash
# Test context hook manually
echo '{"session_id":"test-123","cwd":"'$(pwd)'","source":"startup"}' | node plugin/scripts/context-hook.js
# Test new hook
echo '{"session_id":"test-123","cwd":"'$(pwd)'","prompt":"test"}' | node plugin/scripts/new-hook.js数据验证:
bash
# Check recent observations
sqlite3 ~/.claude-mem/claude-mem.db "
SELECT id, tool_name, created_at
FROM observations
ORDER BY created_at_epoch DESC
LIMIT 10;
"
# Check summaries
sqlite3 ~/.claude-mem/claude-mem.db "
SELECT id, request, completed
FROM session_summaries
ORDER BY created_at_epoch DESC
LIMIT 5;
"恢复功能测试
专门针对手动恢复功能:
模拟卡住的消息:
bash# Manually create stuck message (for testing only) sqlite3 ~/.claude-mem/claude-mem.db " UPDATE pending_messages SET status = 'processing', started_processing_at_epoch = strftime('%s', 'now', '-10 minutes') * 1000 WHERE id = 123; "测试恢复:
bashbun scripts/check-pending-queue.ts验证结果:
bashcurl http://localhost:37777/api/pending-queue | jq '.queue'
回归测试
发布前:
测试所有钩子触发器:
- 会话开始:启动新的Claude Code会话
- 用户提示提交:提交提示
- 使用工具后:使用像 Read 这样的工具
- 摘要:让会话完成
- 会话结束:关闭Claude代码
测试核心功能:
- 上下文注入(最近的会话显示)
- 观察处理(生成的摘要)
- MCP 搜索工具(搜索返回结果)
- 查看器界面(在 http://localhost:37777 加载)
- 手动恢复(卡住的消息已恢复)
测试边界情况:
- Worker 崩溃恢复
- 数据库锁
- 端口冲突
- 大型数据库
- 跨平台(如适用):
- macOS
- Linux
- 窗口
代码风格
TypeScript 指南
- 使用 TypeScript 严格模式
- 为所有数据结构定义接口
- 对异步代码使用 async/await
- 明确处理错误
- 为公共 API 添加 JSDoc 注释
格式化
- 遵循现有的代码格式
- 使用 2 空格缩进
- 字符串使用单引号
- 在对象/数组中添加尾随逗号
例子
typescript
/**
* Create a new observation in the database
*/
obs: Observation
): Promise<number> {
try {
const result = await db.insert('observations', {
session_id: obs.session_id,
tool_name: obs.tool_name,
// ...
});
return result.id;
} catch (error) {
logger.error('Failed to create observation', error);
throw error;
}
}调试
启用调试日志
bash
npm run worker:restart
npm run worker:logs检查数据库
bash
sqlite3 ~/.claude-mem/claude-mem.db
# View schema
.schema observations
# Query data
SELECT * FROM observations LIMIT 10;痕迹观察
使用相关 ID 跟踪整个流程中的观察记录:
bash
sqlite3 ~/.claude-mem/claude-mem.db
SELECT correlation_id, tool_name, created_at
FROM observations
WHERE session_id = 'YOUR_SESSION_ID'
ORDER BY created_at;调试钩子
使用测试输入手动运行钩子:
bash
# Test context hook
echo '{"session_id":"test-123","cwd":"'$(pwd)'","source":"startup"}' | node plugin/scripts/context-hook.js
# Test new hook
echo '{"session_id":"test-123","cwd":"'$(pwd)'","prompt":"test"}' | node plugin/scripts/new-hook.js出版
NPM 发布
bash
# Update version in package.json
npm version patch # or minor, or major
# Build
npm run build
# Publish to NPM
npm run releaserelease 脚本:
- 运行测试
- 构建所有组件
- 发布到 NPM 注册表
创建发布
- 在
package.json中更新版本 - 更新
CHANGELOG.md - 提交更改
- 创建 git 标签
- 推送到 GitHub
- 发布到 NPM
bash
# Manual version bump:
# 1. Update version in package.json
# 2. Update version in plugin/.claude-plugin/plugin.json
# 3. Update version at top of CLAUDE.md
# 4. Update version badge in README.md
# 5. Run: npm run build && npm run sync-marketplace
# Or use npm version command:
npm version 4.3.2
# Update changelog
# Edit CHANGELOG.md manually
# Commit
git add .
git commit -m "chore: Release v4.3.2"
# Tag
git tag v4.3.2
# Push
git push origin main --tags
# Publish to NPM
npm run release贡献
贡献工作流程
- 派生该仓库
- 创建一个功能分支 (
git checkout -b feature/amazing-feature) - 进行更改
- 编写测试
- 更新文档
- 提交你的更改 (
git commit -m 'Add amazing feature') - 推送到分支 (
git push origin feature/amazing-feature) - 打开拉取请求
拉取请求指南
- 清晰标题:描述该 PR 的作用
- 描述:解释为什么需要进行更改
- 测试:包括新功能的测试
- 文档:根据需要更新文档
- 更新日志:在 CHANGELOG.md 中添加条目
- 提交:使用清晰、描述性的提交信息
代码审查流程
- 自动化测试必须通过
- 维护者的代码审查
- 处理反馈
- 最终批准
- 合并到主分支
开发工具
推荐的 VSCode 扩展
- TypeScript
- ESLint
- 更漂亮
- SQLite 查看器
有用的命令
bash
# Check TypeScript types
npx tsc --noEmit
# Lint code (if configured)
npm run lint
# Format code (if configured)
npm run format
# Clean build artifacts
rm -rf plugin/scripts/*.js plugin/scripts/*.cjs开发故障排除
构建失败
清理 node_modules:
bashrm -rf node_modules npm install检查 Node.js 版本:
bashnode --version # Should be >= 18.0.0检查语法错误:
bashnpx tsc --noEmit
测试失败
检查数据库:
bashrm ~/.claude-mem/claude-mem.db npm test检查工作状态:
bashnpm run worker:status查看日志:
bashnpm run worker:logs
Worker 进程无法启动
结束现有进程:
bashnpm run worker:stop检查端口:
bashlsof -i :37777尝试自定义端口:
bashnpm run worker:start
下一步
- Architecture Overview - 了解系统
- Configuration - 自定义 Claude-Mem
- Troubleshooting - 常见问题