@contextmirror/claude-memory 0.3.1 → 0.4.1
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/README.md +76 -6
- package/dist/mcp/server.js +10 -3
- package/dist/utils/updateChecker.d.ts +20 -0
- package/dist/utils/updateChecker.js +155 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -9,18 +9,27 @@ Every Claude Code session starts fresh. Switch to a different project folder and
|
|
|
9
9
|
## The Solution
|
|
10
10
|
|
|
11
11
|
```bash
|
|
12
|
-
npm install -g claude-memory
|
|
12
|
+
npm install -g @contextmirror/claude-memory
|
|
13
13
|
claude-memory scan ~/Projects
|
|
14
14
|
```
|
|
15
15
|
|
|
16
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
17
|
|
|
18
|
+
## Features
|
|
19
|
+
|
|
20
|
+
- **Cross-project awareness** - Claude knows about all your projects
|
|
21
|
+
- **Staleness detection** - Automatically detects when projects need rescanning
|
|
22
|
+
- **Quick scans** - Only rescan projects that have changed
|
|
23
|
+
- **Update notifications** - Get notified when new versions are available
|
|
24
|
+
- **CLAUDE.md generation** - Auto-generate project documentation
|
|
25
|
+
- **MCP integration** - Works seamlessly with Claude Code
|
|
26
|
+
|
|
18
27
|
## Quick Start
|
|
19
28
|
|
|
20
29
|
### 1. Install
|
|
21
30
|
|
|
22
31
|
```bash
|
|
23
|
-
npm install -g claude-memory
|
|
32
|
+
npm install -g @contextmirror/claude-memory
|
|
24
33
|
```
|
|
25
34
|
|
|
26
35
|
### 2. Scan your projects
|
|
@@ -53,11 +62,39 @@ Now Claude has access to your project memory!
|
|
|
53
62
|
| Command | Description |
|
|
54
63
|
|---------|-------------|
|
|
55
64
|
| `claude-memory scan [dir]` | Scan directory for projects |
|
|
65
|
+
| `claude-memory scan --quick` | Only rescan stale projects (faster) |
|
|
66
|
+
| `claude-memory scan --check` | Check what's stale without scanning |
|
|
56
67
|
| `claude-memory list` | List known projects |
|
|
57
68
|
| `claude-memory show <project>` | Show project details |
|
|
69
|
+
| `claude-memory briefing [dir]` | Generate CLAUDE.md for a project |
|
|
58
70
|
| `claude-memory init` | Generate CLAUDE.md for current project |
|
|
59
|
-
| `claude-memory
|
|
71
|
+
| `claude-memory exclude <project>` | Exclude project from future scans |
|
|
72
|
+
| `claude-memory include <project>` | Re-include an excluded project |
|
|
60
73
|
| `claude-memory mcp` | Start MCP server |
|
|
74
|
+
| `claude-memory setup` | Interactive setup wizard |
|
|
75
|
+
|
|
76
|
+
## Staleness Detection
|
|
77
|
+
|
|
78
|
+
claude-memory automatically detects when your projects need rescanning:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
# Check what's stale
|
|
82
|
+
claude-memory scan --check
|
|
83
|
+
|
|
84
|
+
# Output:
|
|
85
|
+
# 🧠 Claude Memory - Staleness Check
|
|
86
|
+
#
|
|
87
|
+
# ⚠️ 2 project(s) need updating:
|
|
88
|
+
# 📝 my-project (New commits since last scan)
|
|
89
|
+
# 📄 another-project (Key files modified since last scan)
|
|
90
|
+
#
|
|
91
|
+
# Run `claude-memory scan --quick` to refresh only stale projects.
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
**Detection methods:**
|
|
95
|
+
- **Git activity** - New commits since last scan
|
|
96
|
+
- **File changes** - package.json, CLAUDE.md, etc. modified
|
|
97
|
+
- **Age** - Projects not scanned in 7+ days
|
|
61
98
|
|
|
62
99
|
## MCP Tools
|
|
63
100
|
|
|
@@ -65,11 +102,25 @@ When connected, Claude Code gets these tools:
|
|
|
65
102
|
|
|
66
103
|
| Tool | Purpose |
|
|
67
104
|
|------|---------|
|
|
68
|
-
| `get_global_context` | Overview of all your projects |
|
|
105
|
+
| `get_global_context` | Overview of all your projects + staleness info |
|
|
69
106
|
| `get_project_summary` | Details about a specific project |
|
|
70
107
|
| `get_project_analysis` | Deep analysis for CLAUDE.md generation |
|
|
71
108
|
| `search_projects` | Search across all projects |
|
|
72
109
|
| `record_insight` | Save cross-project patterns |
|
|
110
|
+
| `search_code` | **[Pro]** Search code across all projects |
|
|
111
|
+
|
|
112
|
+
## Update Notifications
|
|
113
|
+
|
|
114
|
+
claude-memory checks for updates automatically (once per day, cached). When a new version is available, Claude will see:
|
|
115
|
+
|
|
116
|
+
```
|
|
117
|
+
⬆️ Update available: v0.3.0 → v0.4.0
|
|
118
|
+
|
|
119
|
+
Run to update:
|
|
120
|
+
npm update -g @contextmirror/claude-memory
|
|
121
|
+
|
|
122
|
+
After updating, restart Claude Code to use the new version.
|
|
123
|
+
```
|
|
73
124
|
|
|
74
125
|
## How It Works
|
|
75
126
|
|
|
@@ -77,15 +128,17 @@ When connected, Claude Code gets these tools:
|
|
|
77
128
|
2. **Extract** - Pulls name, description, tech stack, git info, CLAUDE.md content
|
|
78
129
|
3. **Store** - Saves to `~/.claude-memory/context.json`
|
|
79
130
|
4. **Serve** - MCP server exposes context to Claude Code
|
|
131
|
+
5. **Detect** - Monitors for staleness on each session start
|
|
80
132
|
|
|
81
133
|
## Example Usage
|
|
82
134
|
|
|
83
135
|
Once set up, you can ask Claude:
|
|
84
136
|
|
|
85
137
|
- "What other projects do I have?"
|
|
86
|
-
- "Tell me about my
|
|
138
|
+
- "Tell me about my project X"
|
|
87
139
|
- "Generate a CLAUDE.md for this project"
|
|
88
140
|
- "Which of my projects use React?"
|
|
141
|
+
- "Is my project data up to date?"
|
|
89
142
|
|
|
90
143
|
Claude will query your project memory and respond with real context.
|
|
91
144
|
|
|
@@ -96,9 +149,22 @@ All data stays local:
|
|
|
96
149
|
```
|
|
97
150
|
~/.claude-memory/
|
|
98
151
|
├── context.json # Project metadata
|
|
99
|
-
|
|
152
|
+
├── context.json.bak # Backup
|
|
153
|
+
├── global-context.md # Human-readable overview
|
|
154
|
+
├── config.json # User configuration
|
|
155
|
+
├── update-check.json # Update check cache
|
|
156
|
+
└── license.json # Pro license (if activated)
|
|
100
157
|
```
|
|
101
158
|
|
|
159
|
+
## Pro Features
|
|
160
|
+
|
|
161
|
+
Activate with `claude-memory activate <key>`. Get a license at https://claude-memory.dev
|
|
162
|
+
|
|
163
|
+
| Feature | Description |
|
|
164
|
+
|---------|-------------|
|
|
165
|
+
| Cross-project code search | Search code patterns across all your projects |
|
|
166
|
+
| Semantic search | Search by meaning, not just keywords (coming soon) |
|
|
167
|
+
|
|
102
168
|
## License
|
|
103
169
|
|
|
104
170
|
MIT
|
|
@@ -106,3 +172,7 @@ MIT
|
|
|
106
172
|
## Author
|
|
107
173
|
|
|
108
174
|
Nathan (with Claude as co-developer)
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
*Part of the [Context Mirror](https://github.com/contextmirror) project*
|
package/dist/mcp/server.js
CHANGED
|
@@ -16,8 +16,9 @@ import { homedir } from 'os';
|
|
|
16
16
|
import { DEFAULT_MEMORY_CONFIG } from '../types/index.js';
|
|
17
17
|
import { isPro, getProFeatureMessage } from '../license/index.js';
|
|
18
18
|
import { detectStaleProjects, checkCurrentProjectStaleness, formatStalenessForMcp } from '../scanner/stalenessDetector.js';
|
|
19
|
+
import { checkForUpdate, formatUpdateMessage } from '../utils/updateChecker.js';
|
|
19
20
|
const MEMORY_DIR = join(homedir(), '.claude-memory');
|
|
20
|
-
const CURRENT_VERSION = '0.
|
|
21
|
+
const CURRENT_VERSION = '0.4.0'; // Update this with each release
|
|
21
22
|
// Tool definitions
|
|
22
23
|
const tools = [
|
|
23
24
|
{
|
|
@@ -227,10 +228,16 @@ function detectCurrentDirectoryStatus(cwd, context, config) {
|
|
|
227
228
|
suggestedAction: 'none',
|
|
228
229
|
};
|
|
229
230
|
}
|
|
230
|
-
function handleGetGlobalContext(cwd) {
|
|
231
|
+
async function handleGetGlobalContext(cwd) {
|
|
231
232
|
const context = loadContext();
|
|
232
233
|
const config = loadConfig();
|
|
233
234
|
const lines = [];
|
|
235
|
+
// Check for updates (cached, won't block)
|
|
236
|
+
const updateResult = await checkForUpdate(CURRENT_VERSION);
|
|
237
|
+
if (updateResult.updateAvailable) {
|
|
238
|
+
lines.push(formatUpdateMessage(updateResult));
|
|
239
|
+
lines.push('');
|
|
240
|
+
}
|
|
234
241
|
// If cwd is provided, check the current directory status first
|
|
235
242
|
if (cwd) {
|
|
236
243
|
const cwdStatus = detectCurrentDirectoryStatus(cwd, context, config);
|
|
@@ -569,7 +576,7 @@ async function main() {
|
|
|
569
576
|
let result;
|
|
570
577
|
switch (name) {
|
|
571
578
|
case 'get_global_context':
|
|
572
|
-
result = handleGetGlobalContext(args.cwd);
|
|
579
|
+
result = await handleGetGlobalContext(args.cwd);
|
|
573
580
|
break;
|
|
574
581
|
case 'get_project_summary':
|
|
575
582
|
result = handleGetProjectSummary(args.project);
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Update checker for claude-memory
|
|
3
|
+
* Checks npm registry for newer versions and caches result
|
|
4
|
+
*/
|
|
5
|
+
interface UpdateCheckResult {
|
|
6
|
+
updateAvailable: boolean;
|
|
7
|
+
currentVersion: string;
|
|
8
|
+
latestVersion: string | null;
|
|
9
|
+
message?: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Check if an update is available
|
|
13
|
+
* Uses cache to avoid checking too frequently
|
|
14
|
+
*/
|
|
15
|
+
export declare function checkForUpdate(currentVersion: string): Promise<UpdateCheckResult>;
|
|
16
|
+
/**
|
|
17
|
+
* Format update message for MCP output
|
|
18
|
+
*/
|
|
19
|
+
export declare function formatUpdateMessage(result: UpdateCheckResult): string;
|
|
20
|
+
export {};
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Update checker for claude-memory
|
|
3
|
+
* Checks npm registry for newer versions and caches result
|
|
4
|
+
*/
|
|
5
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs';
|
|
6
|
+
import { join } from 'path';
|
|
7
|
+
import { homedir } from 'os';
|
|
8
|
+
import https from 'https';
|
|
9
|
+
const MEMORY_DIR = join(homedir(), '.claude-memory');
|
|
10
|
+
const UPDATE_CACHE_FILE = join(MEMORY_DIR, 'update-check.json');
|
|
11
|
+
const PACKAGE_NAME = '@contextmirror/claude-memory';
|
|
12
|
+
const CHECK_INTERVAL_HOURS = 24; // Check once per day
|
|
13
|
+
/**
|
|
14
|
+
* Fetch the latest version from npm registry
|
|
15
|
+
*/
|
|
16
|
+
function fetchLatestVersion() {
|
|
17
|
+
return new Promise((resolve) => {
|
|
18
|
+
const url = `https://registry.npmjs.org/${PACKAGE_NAME}/latest`;
|
|
19
|
+
const req = https.get(url, { timeout: 5000 }, (res) => {
|
|
20
|
+
let data = '';
|
|
21
|
+
res.on('data', (chunk) => {
|
|
22
|
+
data += chunk;
|
|
23
|
+
});
|
|
24
|
+
res.on('end', () => {
|
|
25
|
+
try {
|
|
26
|
+
const json = JSON.parse(data);
|
|
27
|
+
resolve(json.version || null);
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
resolve(null);
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
req.on('error', () => {
|
|
35
|
+
resolve(null);
|
|
36
|
+
});
|
|
37
|
+
req.on('timeout', () => {
|
|
38
|
+
req.destroy();
|
|
39
|
+
resolve(null);
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Load cached update check result
|
|
45
|
+
*/
|
|
46
|
+
function loadCache() {
|
|
47
|
+
try {
|
|
48
|
+
if (existsSync(UPDATE_CACHE_FILE)) {
|
|
49
|
+
return JSON.parse(readFileSync(UPDATE_CACHE_FILE, 'utf-8'));
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
// Ignore errors
|
|
54
|
+
}
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Save update check result to cache
|
|
59
|
+
*/
|
|
60
|
+
function saveCache(cache) {
|
|
61
|
+
try {
|
|
62
|
+
if (!existsSync(MEMORY_DIR)) {
|
|
63
|
+
mkdirSync(MEMORY_DIR, { recursive: true });
|
|
64
|
+
}
|
|
65
|
+
writeFileSync(UPDATE_CACHE_FILE, JSON.stringify(cache, null, 2), 'utf-8');
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
// Ignore errors
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Compare semantic versions
|
|
73
|
+
* Returns true if latestVersion is newer than currentVersion
|
|
74
|
+
*/
|
|
75
|
+
function isNewer(currentVersion, latestVersion) {
|
|
76
|
+
const current = currentVersion.split('.').map(Number);
|
|
77
|
+
const latest = latestVersion.split('.').map(Number);
|
|
78
|
+
for (let i = 0; i < 3; i++) {
|
|
79
|
+
if ((latest[i] || 0) > (current[i] || 0))
|
|
80
|
+
return true;
|
|
81
|
+
if ((latest[i] || 0) < (current[i] || 0))
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Check if an update is available
|
|
88
|
+
* Uses cache to avoid checking too frequently
|
|
89
|
+
*/
|
|
90
|
+
export async function checkForUpdate(currentVersion) {
|
|
91
|
+
const cache = loadCache();
|
|
92
|
+
const now = new Date();
|
|
93
|
+
// Check if we have a recent cache
|
|
94
|
+
if (cache) {
|
|
95
|
+
const lastChecked = new Date(cache.lastChecked);
|
|
96
|
+
const hoursSinceCheck = (now.getTime() - lastChecked.getTime()) / (1000 * 60 * 60);
|
|
97
|
+
if (hoursSinceCheck < CHECK_INTERVAL_HOURS && cache.latestVersion) {
|
|
98
|
+
// Use cached result
|
|
99
|
+
const updateAvailable = isNewer(currentVersion, cache.latestVersion);
|
|
100
|
+
return {
|
|
101
|
+
updateAvailable,
|
|
102
|
+
currentVersion,
|
|
103
|
+
latestVersion: cache.latestVersion,
|
|
104
|
+
message: updateAvailable
|
|
105
|
+
? `⬆️ Update available: v${currentVersion} → v${cache.latestVersion}`
|
|
106
|
+
: undefined,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
// Fetch fresh version info
|
|
111
|
+
const latestVersion = await fetchLatestVersion();
|
|
112
|
+
// Save to cache
|
|
113
|
+
saveCache({
|
|
114
|
+
lastChecked: now.toISOString(),
|
|
115
|
+
latestVersion,
|
|
116
|
+
currentVersion,
|
|
117
|
+
});
|
|
118
|
+
if (!latestVersion) {
|
|
119
|
+
return {
|
|
120
|
+
updateAvailable: false,
|
|
121
|
+
currentVersion,
|
|
122
|
+
latestVersion: null,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
const updateAvailable = isNewer(currentVersion, latestVersion);
|
|
126
|
+
return {
|
|
127
|
+
updateAvailable,
|
|
128
|
+
currentVersion,
|
|
129
|
+
latestVersion,
|
|
130
|
+
message: updateAvailable
|
|
131
|
+
? `⬆️ Update available: v${currentVersion} → v${latestVersion}`
|
|
132
|
+
: undefined,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Format update message for MCP output
|
|
137
|
+
*/
|
|
138
|
+
export function formatUpdateMessage(result) {
|
|
139
|
+
if (!result.updateAvailable || !result.latestVersion) {
|
|
140
|
+
return '';
|
|
141
|
+
}
|
|
142
|
+
return [
|
|
143
|
+
'',
|
|
144
|
+
'---',
|
|
145
|
+
'',
|
|
146
|
+
`### ${result.message}`,
|
|
147
|
+
'',
|
|
148
|
+
'Run to update:',
|
|
149
|
+
'```bash',
|
|
150
|
+
'npm update -g @contextmirror/claude-memory',
|
|
151
|
+
'```',
|
|
152
|
+
'',
|
|
153
|
+
'> After updating, restart Claude Code to use the new version.',
|
|
154
|
+
].join('\n');
|
|
155
|
+
}
|