@contextmirror/claude-memory 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +10 -0
- package/README.md +108 -0
- package/dist/cli.d.ts +11 -0
- package/dist/cli.js +139 -0
- package/dist/generator/claudeMdGenerator.d.ts +20 -0
- package/dist/generator/claudeMdGenerator.js +202 -0
- package/dist/mcp/server.d.ts +10 -0
- package/dist/mcp/server.js +391 -0
- package/dist/scanner/contextGenerator.d.ts +16 -0
- package/dist/scanner/contextGenerator.js +98 -0
- package/dist/scanner/projectScanner.d.ts +8 -0
- package/dist/scanner/projectScanner.js +319 -0
- package/dist/types/index.d.ts +87 -0
- package/dist/types/index.js +10 -0
- package/package.json +37 -0
package/README.md
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# claude-memory
|
|
2
|
+
|
|
3
|
+
Cross-project memory for Claude Code. Give Claude awareness of ALL your projects, not just the one you're in.
|
|
4
|
+
|
|
5
|
+
## The Problem
|
|
6
|
+
|
|
7
|
+
Every Claude Code session starts fresh. Switch to a different project folder and Claude has no idea about your other work. You end up re-explaining your codebase, your patterns, your other projects.
|
|
8
|
+
|
|
9
|
+
## The Solution
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install -g claude-memory
|
|
13
|
+
claude-memory scan ~/Projects
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Now Claude knows about all your projects. Ask "What other projects do I have?" or "Generate a CLAUDE.md for this project" and Claude just knows.
|
|
17
|
+
|
|
18
|
+
## Quick Start
|
|
19
|
+
|
|
20
|
+
### 1. Install
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm install -g claude-memory
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### 2. Scan your projects
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
claude-memory scan ~/Projects # or wherever your code lives
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### 3. Add MCP to Claude Code
|
|
33
|
+
|
|
34
|
+
Create `.mcp.json` in your home directory or project:
|
|
35
|
+
|
|
36
|
+
```json
|
|
37
|
+
{
|
|
38
|
+
"mcpServers": {
|
|
39
|
+
"claude-memory": {
|
|
40
|
+
"command": "claude-memory",
|
|
41
|
+
"args": ["mcp"]
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### 4. Restart Claude Code
|
|
48
|
+
|
|
49
|
+
Now Claude has access to your project memory!
|
|
50
|
+
|
|
51
|
+
## Commands
|
|
52
|
+
|
|
53
|
+
| Command | Description |
|
|
54
|
+
|---------|-------------|
|
|
55
|
+
| `claude-memory scan [dir]` | Scan directory for projects |
|
|
56
|
+
| `claude-memory list` | List known projects |
|
|
57
|
+
| `claude-memory show <project>` | Show project details |
|
|
58
|
+
| `claude-memory init` | Generate CLAUDE.md for current project |
|
|
59
|
+
| `claude-memory generate` | Generate CLAUDE.md for all projects |
|
|
60
|
+
| `claude-memory mcp` | Start MCP server |
|
|
61
|
+
|
|
62
|
+
## MCP Tools
|
|
63
|
+
|
|
64
|
+
When connected, Claude Code gets these tools:
|
|
65
|
+
|
|
66
|
+
| Tool | Purpose |
|
|
67
|
+
|------|---------|
|
|
68
|
+
| `get_global_context` | Overview of all your projects |
|
|
69
|
+
| `get_project_summary` | Details about a specific project |
|
|
70
|
+
| `get_project_analysis` | Deep analysis for CLAUDE.md generation |
|
|
71
|
+
| `search_projects` | Search across all projects |
|
|
72
|
+
| `record_insight` | Save cross-project patterns |
|
|
73
|
+
|
|
74
|
+
## How It Works
|
|
75
|
+
|
|
76
|
+
1. **Scan** - Finds projects by looking for package.json, Cargo.toml, pyproject.toml, .git
|
|
77
|
+
2. **Extract** - Pulls name, description, tech stack, git info, CLAUDE.md content
|
|
78
|
+
3. **Store** - Saves to `~/.claude-memory/context.json`
|
|
79
|
+
4. **Serve** - MCP server exposes context to Claude Code
|
|
80
|
+
|
|
81
|
+
## Example Usage
|
|
82
|
+
|
|
83
|
+
Once set up, you can ask Claude:
|
|
84
|
+
|
|
85
|
+
- "What other projects do I have?"
|
|
86
|
+
- "Tell me about my CM Remake project"
|
|
87
|
+
- "Generate a CLAUDE.md for this project"
|
|
88
|
+
- "Which of my projects use React?"
|
|
89
|
+
|
|
90
|
+
Claude will query your project memory and respond with real context.
|
|
91
|
+
|
|
92
|
+
## Data Storage
|
|
93
|
+
|
|
94
|
+
All data stays local:
|
|
95
|
+
|
|
96
|
+
```
|
|
97
|
+
~/.claude-memory/
|
|
98
|
+
├── context.json # Project metadata
|
|
99
|
+
└── global-context.md # Human-readable overview
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## License
|
|
103
|
+
|
|
104
|
+
MIT
|
|
105
|
+
|
|
106
|
+
## Author
|
|
107
|
+
|
|
108
|
+
Nathan (with Claude as co-developer)
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Claude Memory CLI
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* claude-memory scan [directory] Scan projects and update global context
|
|
7
|
+
* claude-memory list List known projects
|
|
8
|
+
* claude-memory show <project> Show details for a project
|
|
9
|
+
* claude-memory mcp Start MCP server
|
|
10
|
+
*/
|
|
11
|
+
export {};
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Claude Memory CLI
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* claude-memory scan [directory] Scan projects and update global context
|
|
7
|
+
* claude-memory list List known projects
|
|
8
|
+
* claude-memory show <project> Show details for a project
|
|
9
|
+
* claude-memory mcp Start MCP server
|
|
10
|
+
*/
|
|
11
|
+
import { Command } from 'commander';
|
|
12
|
+
import { readFileSync, existsSync } from 'fs';
|
|
13
|
+
import { join } from 'path';
|
|
14
|
+
import { homedir } from 'os';
|
|
15
|
+
import { scanProjects } from './scanner/projectScanner.js';
|
|
16
|
+
import { generateGlobalContext, writeGlobalContext, getMemoryDir } from './scanner/contextGenerator.js';
|
|
17
|
+
const program = new Command();
|
|
18
|
+
program
|
|
19
|
+
.name('claude-memory')
|
|
20
|
+
.description('Cross-project memory for Claude Code')
|
|
21
|
+
.version('0.1.0');
|
|
22
|
+
// Scan command
|
|
23
|
+
program
|
|
24
|
+
.command('scan')
|
|
25
|
+
.description('Scan projects and update global context')
|
|
26
|
+
.argument('[directory]', 'Root directory to scan', `${homedir()}/Project`)
|
|
27
|
+
.option('-d, --depth <number>', 'Max depth to search', '2')
|
|
28
|
+
.option('--generate-claude-md', 'Generate CLAUDE.md for projects without one')
|
|
29
|
+
.action(async (directory, options) => {
|
|
30
|
+
console.log('🧠 Claude Memory Scanner\n');
|
|
31
|
+
const projects = await scanProjects({
|
|
32
|
+
rootDir: directory,
|
|
33
|
+
maxDepth: parseInt(options.depth, 10),
|
|
34
|
+
generateClaudeMd: options.generateClaudeMd,
|
|
35
|
+
});
|
|
36
|
+
const context = generateGlobalContext(projects);
|
|
37
|
+
writeGlobalContext(context);
|
|
38
|
+
console.log('\n✅ Done! Global context updated.');
|
|
39
|
+
console.log('\nTo use with Claude Code, add the MCP server to your config:');
|
|
40
|
+
console.log(' claude-memory mcp');
|
|
41
|
+
});
|
|
42
|
+
// List command
|
|
43
|
+
program
|
|
44
|
+
.command('list')
|
|
45
|
+
.description('List known projects')
|
|
46
|
+
.action(() => {
|
|
47
|
+
const context = loadContext();
|
|
48
|
+
if (!context) {
|
|
49
|
+
console.log('No projects scanned yet. Run: claude-memory scan');
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
console.log('🧠 Known Projects\n');
|
|
53
|
+
for (const project of context.projects) {
|
|
54
|
+
const dirty = project.isDirty ? ' ⚠️' : '';
|
|
55
|
+
console.log(` ${project.name}${dirty}`);
|
|
56
|
+
console.log(` ${project.path}`);
|
|
57
|
+
console.log(` ${project.techStack.join(', ')}`);
|
|
58
|
+
console.log('');
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
// Show command
|
|
62
|
+
program
|
|
63
|
+
.command('show')
|
|
64
|
+
.description('Show details for a project')
|
|
65
|
+
.argument('<project>', 'Project name or path')
|
|
66
|
+
.action((projectName) => {
|
|
67
|
+
const context = loadContext();
|
|
68
|
+
if (!context) {
|
|
69
|
+
console.log('No projects scanned yet. Run: claude-memory scan');
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
const project = context.projects.find((p) => p.name.toLowerCase() === projectName.toLowerCase() || p.path.includes(projectName));
|
|
73
|
+
if (!project) {
|
|
74
|
+
console.log(`Project not found: ${projectName}`);
|
|
75
|
+
console.log('\nKnown projects:');
|
|
76
|
+
context.projects.forEach((p) => console.log(` - ${p.name}`));
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
console.log(`\n📁 ${project.name}\n`);
|
|
80
|
+
console.log(`Path: ${project.path}`);
|
|
81
|
+
console.log(`Language: ${project.language}`);
|
|
82
|
+
console.log(`Stack: ${project.techStack.join(', ')}`);
|
|
83
|
+
console.log(`Branch: ${project.currentBranch}${project.isDirty ? ' (dirty)' : ''}`);
|
|
84
|
+
console.log(`Last Activity: ${new Date(project.lastActivity).toLocaleString()}`);
|
|
85
|
+
console.log(`\nDescription:\n ${project.description}`);
|
|
86
|
+
console.log(`\nKey Files:`);
|
|
87
|
+
console.log(` CLAUDE.md: ${project.hasFiles.claudeMd ? '✓' : '✗'}`);
|
|
88
|
+
console.log(` README.md: ${project.hasFiles.readme ? '✓' : '✗'}`);
|
|
89
|
+
});
|
|
90
|
+
// Init command - shows how to generate CLAUDE.md
|
|
91
|
+
program
|
|
92
|
+
.command('init')
|
|
93
|
+
.description('Generate CLAUDE.md for the current project')
|
|
94
|
+
.action(async () => {
|
|
95
|
+
const projectPath = process.cwd();
|
|
96
|
+
console.log('🧠 Claude Memory - CLAUDE.md Generator\n');
|
|
97
|
+
console.log(`📁 Project: ${projectPath}\n`);
|
|
98
|
+
// Quick analysis of current project
|
|
99
|
+
const projects = await scanProjects({
|
|
100
|
+
rootDir: projectPath,
|
|
101
|
+
maxDepth: 0,
|
|
102
|
+
});
|
|
103
|
+
if (projects.length === 0) {
|
|
104
|
+
console.log('❌ No project detected in current directory');
|
|
105
|
+
console.log(' (Looking for package.json, Cargo.toml, pyproject.toml, or .git)');
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
const project = projects[0];
|
|
109
|
+
console.log(`✅ Found project: ${project.name}`);
|
|
110
|
+
console.log(` Language: ${project.language}`);
|
|
111
|
+
console.log(` Stack: ${project.techStack.join(', ')}`);
|
|
112
|
+
console.log(` Has CLAUDE.md: ${project.hasFiles.claudeMd ? 'Yes' : 'No'}`);
|
|
113
|
+
console.log('\n📝 To generate a CLAUDE.md file:');
|
|
114
|
+
console.log(' 1. Open this project in Claude Code');
|
|
115
|
+
console.log(' 2. Ask Claude: "Generate a CLAUDE.md for this project"');
|
|
116
|
+
console.log(' 3. Claude will use the MCP tools to analyze and write it');
|
|
117
|
+
console.log('\n💡 This uses your existing Claude session - no extra API costs!');
|
|
118
|
+
});
|
|
119
|
+
// MCP command - start the MCP server
|
|
120
|
+
program
|
|
121
|
+
.command('mcp')
|
|
122
|
+
.description('Start MCP server for Claude Code integration')
|
|
123
|
+
.action(async () => {
|
|
124
|
+
// Import and run the MCP server
|
|
125
|
+
await import('./mcp/server.js');
|
|
126
|
+
});
|
|
127
|
+
function loadContext() {
|
|
128
|
+
const contextPath = join(getMemoryDir(), 'context.json');
|
|
129
|
+
if (!existsSync(contextPath)) {
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
try {
|
|
133
|
+
return JSON.parse(readFileSync(contextPath, 'utf-8'));
|
|
134
|
+
}
|
|
135
|
+
catch {
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
program.parse();
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLAUDE.md Generator
|
|
3
|
+
*
|
|
4
|
+
* Analyzes a project and generates a CLAUDE.md file using Claude API
|
|
5
|
+
*/
|
|
6
|
+
import { ProjectInfo } from '../types/index.js';
|
|
7
|
+
/**
|
|
8
|
+
* Generate a CLAUDE.md file for a project
|
|
9
|
+
*/
|
|
10
|
+
export declare function generateClaudeMd(projectPath: string, projectInfo: ProjectInfo, options?: {
|
|
11
|
+
overwrite?: boolean;
|
|
12
|
+
dryRun?: boolean;
|
|
13
|
+
}): Promise<string>;
|
|
14
|
+
/**
|
|
15
|
+
* Generate CLAUDE.md for multiple projects
|
|
16
|
+
*/
|
|
17
|
+
export declare function generateClaudeMdBatch(projects: ProjectInfo[], options?: {
|
|
18
|
+
overwrite?: boolean;
|
|
19
|
+
dryRun?: boolean;
|
|
20
|
+
}): Promise<Map<string, string>>;
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLAUDE.md Generator
|
|
3
|
+
*
|
|
4
|
+
* Analyzes a project and generates a CLAUDE.md file using Claude API
|
|
5
|
+
*/
|
|
6
|
+
import Anthropic from '@anthropic-ai/sdk';
|
|
7
|
+
import { readFileSync, existsSync, readdirSync, statSync, writeFileSync } from 'fs';
|
|
8
|
+
import { join } from 'path';
|
|
9
|
+
/**
|
|
10
|
+
* Generate a CLAUDE.md file for a project
|
|
11
|
+
*/
|
|
12
|
+
export async function generateClaudeMd(projectPath, projectInfo, options = {}) {
|
|
13
|
+
const claudeMdPath = join(projectPath, 'CLAUDE.md');
|
|
14
|
+
// Check if CLAUDE.md already exists
|
|
15
|
+
if (existsSync(claudeMdPath) && !options.overwrite) {
|
|
16
|
+
console.log(` ⏭️ Skipping ${projectInfo.name} - CLAUDE.md already exists`);
|
|
17
|
+
return readFileSync(claudeMdPath, 'utf-8');
|
|
18
|
+
}
|
|
19
|
+
console.log(` 🔍 Analyzing ${projectInfo.name}...`);
|
|
20
|
+
// Gather project information
|
|
21
|
+
const analysis = analyzeProjectDeep(projectPath, projectInfo);
|
|
22
|
+
console.log(` 🤖 Generating CLAUDE.md...`);
|
|
23
|
+
// Generate CLAUDE.md content using Claude
|
|
24
|
+
const content = await callClaudeForGeneration(analysis);
|
|
25
|
+
if (options.dryRun) {
|
|
26
|
+
console.log(` 📝 [Dry run] Would write CLAUDE.md`);
|
|
27
|
+
return content;
|
|
28
|
+
}
|
|
29
|
+
// Write the file
|
|
30
|
+
writeFileSync(claudeMdPath, content, 'utf-8');
|
|
31
|
+
console.log(` ✅ Created CLAUDE.md for ${projectInfo.name}`);
|
|
32
|
+
return content;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Deep analysis of a project for CLAUDE.md generation
|
|
36
|
+
*/
|
|
37
|
+
function analyzeProjectDeep(projectPath, projectInfo) {
|
|
38
|
+
// Get directory structure (limited depth)
|
|
39
|
+
const structure = getDirectoryStructure(projectPath, 3);
|
|
40
|
+
// Read README if exists
|
|
41
|
+
let readme = null;
|
|
42
|
+
const readmePath = join(projectPath, 'README.md');
|
|
43
|
+
if (existsSync(readmePath)) {
|
|
44
|
+
readme = readFileSync(readmePath, 'utf-8').slice(0, 3000); // Limit size
|
|
45
|
+
}
|
|
46
|
+
// Read package.json / pyproject.toml / Cargo.toml
|
|
47
|
+
let packageInfo = null;
|
|
48
|
+
const pkgPath = join(projectPath, 'package.json');
|
|
49
|
+
if (existsSync(pkgPath)) {
|
|
50
|
+
try {
|
|
51
|
+
packageInfo = JSON.parse(readFileSync(pkgPath, 'utf-8'));
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
// Invalid JSON
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
// Find key files
|
|
58
|
+
const keyFiles = findKeyFiles(projectPath);
|
|
59
|
+
return {
|
|
60
|
+
name: projectInfo.name,
|
|
61
|
+
description: projectInfo.description,
|
|
62
|
+
techStack: projectInfo.techStack,
|
|
63
|
+
structure,
|
|
64
|
+
readme,
|
|
65
|
+
packageInfo,
|
|
66
|
+
keyFiles,
|
|
67
|
+
recentCommits: [], // TODO: Add git log
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Get directory structure as a string tree
|
|
72
|
+
*/
|
|
73
|
+
function getDirectoryStructure(dir, maxDepth, prefix = '', depth = 0) {
|
|
74
|
+
if (depth >= maxDepth)
|
|
75
|
+
return '';
|
|
76
|
+
const ignore = ['node_modules', '.git', 'dist', 'build', '__pycache__', 'target', '.next', '.nuxt', 'coverage', '.cache'];
|
|
77
|
+
let result = '';
|
|
78
|
+
try {
|
|
79
|
+
const entries = readdirSync(dir).filter(e => !ignore.includes(e) && !e.startsWith('.'));
|
|
80
|
+
entries.sort((a, b) => {
|
|
81
|
+
// Directories first
|
|
82
|
+
const aIsDir = statSync(join(dir, a)).isDirectory();
|
|
83
|
+
const bIsDir = statSync(join(dir, b)).isDirectory();
|
|
84
|
+
if (aIsDir && !bIsDir)
|
|
85
|
+
return -1;
|
|
86
|
+
if (!aIsDir && bIsDir)
|
|
87
|
+
return 1;
|
|
88
|
+
return a.localeCompare(b);
|
|
89
|
+
});
|
|
90
|
+
for (let i = 0; i < entries.length; i++) {
|
|
91
|
+
const entry = entries[i];
|
|
92
|
+
const fullPath = join(dir, entry);
|
|
93
|
+
const isLast = i === entries.length - 1;
|
|
94
|
+
const connector = isLast ? '└── ' : '├── ';
|
|
95
|
+
const newPrefix = prefix + (isLast ? ' ' : '│ ');
|
|
96
|
+
try {
|
|
97
|
+
const stat = statSync(fullPath);
|
|
98
|
+
if (stat.isDirectory()) {
|
|
99
|
+
result += `${prefix}${connector}${entry}/\n`;
|
|
100
|
+
result += getDirectoryStructure(fullPath, maxDepth, newPrefix, depth + 1);
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
result += `${prefix}${connector}${entry}\n`;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
// Skip inaccessible
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
// Skip inaccessible
|
|
113
|
+
}
|
|
114
|
+
return result;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Find key files in the project
|
|
118
|
+
*/
|
|
119
|
+
function findKeyFiles(projectPath) {
|
|
120
|
+
const keyPatterns = [
|
|
121
|
+
'src/index.ts', 'src/index.js', 'src/main.ts', 'src/main.js',
|
|
122
|
+
'src/app.ts', 'src/app.js', 'src/cli.ts', 'src/cli.js',
|
|
123
|
+
'index.ts', 'index.js', 'main.ts', 'main.js', 'app.ts', 'app.js',
|
|
124
|
+
'main.py', 'app.py', '__main__.py',
|
|
125
|
+
'src/lib.rs', 'src/main.rs',
|
|
126
|
+
'main.go', 'cmd/main.go',
|
|
127
|
+
];
|
|
128
|
+
const found = [];
|
|
129
|
+
for (const pattern of keyPatterns) {
|
|
130
|
+
if (existsSync(join(projectPath, pattern))) {
|
|
131
|
+
found.push(pattern);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return found;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Call Claude API to generate CLAUDE.md content
|
|
138
|
+
*/
|
|
139
|
+
async function callClaudeForGeneration(analysis) {
|
|
140
|
+
const client = new Anthropic();
|
|
141
|
+
const prompt = `You are generating a CLAUDE.md file for a software project. This file helps future Claude Code sessions understand the project quickly.
|
|
142
|
+
|
|
143
|
+
PROJECT INFO:
|
|
144
|
+
- Name: ${analysis.name}
|
|
145
|
+
- Description: ${analysis.description}
|
|
146
|
+
- Tech Stack: ${analysis.techStack.join(', ')}
|
|
147
|
+
- Key entry files: ${analysis.keyFiles.join(', ') || 'None detected'}
|
|
148
|
+
|
|
149
|
+
DIRECTORY STRUCTURE:
|
|
150
|
+
${analysis.structure || 'Not available'}
|
|
151
|
+
|
|
152
|
+
${analysis.readme ? `README CONTENT:\n${analysis.readme}\n` : ''}
|
|
153
|
+
|
|
154
|
+
${analysis.packageInfo ? `PACKAGE.JSON SCRIPTS:\n${JSON.stringify(analysis.packageInfo.scripts || {}, null, 2)}\n` : ''}
|
|
155
|
+
|
|
156
|
+
Generate a CLAUDE.md file that includes:
|
|
157
|
+
1. A brief project title and one-line description
|
|
158
|
+
2. What the project does (2-3 sentences max)
|
|
159
|
+
3. Tech stack overview
|
|
160
|
+
4. Project structure explanation (key directories)
|
|
161
|
+
5. How to run/build (based on package.json scripts or standard conventions)
|
|
162
|
+
6. Any important notes for Claude sessions
|
|
163
|
+
|
|
164
|
+
Keep it concise - this is a quick reference, not documentation. Use markdown formatting.
|
|
165
|
+
Do NOT include placeholder text like "[Add X here]" - only include sections you have real information for.
|
|
166
|
+
Start the file with "# ${analysis.name}" as the title.`;
|
|
167
|
+
const response = await client.messages.create({
|
|
168
|
+
model: 'claude-sonnet-4-20250514',
|
|
169
|
+
max_tokens: 2000,
|
|
170
|
+
messages: [
|
|
171
|
+
{ role: 'user', content: prompt }
|
|
172
|
+
]
|
|
173
|
+
});
|
|
174
|
+
// Extract text from response
|
|
175
|
+
const textBlock = response.content.find(block => block.type === 'text');
|
|
176
|
+
if (!textBlock || textBlock.type !== 'text') {
|
|
177
|
+
throw new Error('No text response from Claude');
|
|
178
|
+
}
|
|
179
|
+
return textBlock.text;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Generate CLAUDE.md for multiple projects
|
|
183
|
+
*/
|
|
184
|
+
export async function generateClaudeMdBatch(projects, options = {}) {
|
|
185
|
+
const results = new Map();
|
|
186
|
+
const needsGeneration = projects.filter(p => !p.hasFiles.claudeMd || options.overwrite);
|
|
187
|
+
if (needsGeneration.length === 0) {
|
|
188
|
+
console.log('All projects already have CLAUDE.md files');
|
|
189
|
+
return results;
|
|
190
|
+
}
|
|
191
|
+
console.log(`\n📝 Generating CLAUDE.md for ${needsGeneration.length} projects...\n`);
|
|
192
|
+
for (const project of needsGeneration) {
|
|
193
|
+
try {
|
|
194
|
+
const content = await generateClaudeMd(project.path, project, options);
|
|
195
|
+
results.set(project.path, content);
|
|
196
|
+
}
|
|
197
|
+
catch (err) {
|
|
198
|
+
console.error(` ❌ Failed to generate for ${project.name}:`, err);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
return results;
|
|
202
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claude Memory MCP Server
|
|
3
|
+
*
|
|
4
|
+
* Exposes tools for Claude Code to query cross-project context:
|
|
5
|
+
* - get_global_context: Overview of all projects
|
|
6
|
+
* - get_project_summary: Details about a specific project
|
|
7
|
+
* - search_projects: Search across all projects
|
|
8
|
+
* - record_insight: Save a cross-project insight
|
|
9
|
+
*/
|
|
10
|
+
export {};
|