@cachly-dev/mcp-server 0.9.0 β 0.9.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/CHANGELOG.md +12 -0
- package/README.md +33 -1
- package/dist/index.js +106 -4
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/server.json +2 -2
- package/src/index.ts +117 -4
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,18 @@
|
|
|
7
7
|
|
|
8
8
|
---
|
|
9
9
|
|
|
10
|
+
## [0.9.1] β 2026-05-05
|
|
11
|
+
|
|
12
|
+
### π Memory Crystals β Properly surfaced
|
|
13
|
+
|
|
14
|
+
Memory Crystals were implemented but invisible. Now they're first-class:
|
|
15
|
+
|
|
16
|
+
- **`crystal_view`** β New tool: inspect the current Crystal (patterns by category, freshness status, when to refresh). Previously there was no way to see Crystal contents without triggering a full `session_start`.
|
|
17
|
+
- **`session_end` Crystal reminder** β After saving a session, `session_end` now checks Crystal age. If no Crystal exists, or it's β₯ 30 days old, it reminds you to run `memory_crystalize`. Zero friction β the Brain tells you when it needs a refresh.
|
|
18
|
+
- **`autopilot` updated** β Generated CLAUDE.md now includes: `compact_recover` rule (context compaction), monthly crystal schedule, `syndicate_search` rule (unknown errors), and full Cognitive Tools table. Updated to v0.9.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
10
22
|
## [0.9.0] β 2026-05-05
|
|
11
23
|
|
|
12
24
|
### β‘ compact_recover + π± brain_from_git β The two most-requested missing tools
|
package/README.md
CHANGED
|
@@ -229,7 +229,7 @@ Top lessons extracted:
|
|
|
229
229
|
|
|
230
230
|
---
|
|
231
231
|
|
|
232
|
-
##
|
|
232
|
+
## 68 MCP Tools
|
|
233
233
|
|
|
234
234
|
### π§ Cognitive Cache
|
|
235
235
|
|
|
@@ -275,6 +275,38 @@ Top lessons extracted:
|
|
|
275
275
|
| **`sync_file_changes`** | Track file change history, surface related lessons per file |
|
|
276
276
|
| **`setup_ai_memory`** | Interactive wizard to configure AI memory |
|
|
277
277
|
|
|
278
|
+
### π Memory Crystals
|
|
279
|
+
|
|
280
|
+
Memory Crystals distill **everything** your AI brain has learned into a permanent, compact snapshot β injected into every `session_start` automatically.
|
|
281
|
+
|
|
282
|
+
```
|
|
283
|
+
memory_crystalize(instance_id="...", label="May 2026")
|
|
284
|
+
|
|
285
|
+
π Memory Crystal created: May 2026
|
|
286
|
+
|
|
287
|
+
π Compressed: 47 sessions + 89 lessons β 8 top patterns
|
|
288
|
+
|
|
289
|
+
Top patterns by category:
|
|
290
|
+
β’ auth (12Γ): Use httpOnly cookie for refresh token β Safari blocks third-party localStorage
|
|
291
|
+
β’ k8s (9Γ): PollUntilContextTimeout 3min before namespace recreate
|
|
292
|
+
β’ deploy (8Γ): readinessProbe.failureThreshold must be β₯ 10 on cold starts
|
|
293
|
+
β’ redis (6Γ): pipeline() for N writes, 10Γ faster than sequential
|
|
294
|
+
β¦and 4 more
|
|
295
|
+
|
|
296
|
+
π‘ This crystal will appear in every future session_start briefing.
|
|
297
|
+
π‘ Re-run memory_crystalize monthly to keep it fresh.
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
| Tool | What it does |
|
|
301
|
+
|------|-------------|
|
|
302
|
+
| **`memory_crystalize`** | Distill all sessions + lessons into a Crystal. Run monthly or after every major milestone. |
|
|
303
|
+
| **`crystal_view`** | Inspect the current Crystal: all patterns, freshness status, when to refresh. |
|
|
304
|
+
|
|
305
|
+
**`session_end` reminds you** automatically when the Crystal is missing or 30+ days old.
|
|
306
|
+
**`autopilot`** now generates CLAUDE.md with the monthly crystal schedule pre-wired.
|
|
307
|
+
|
|
308
|
+
---
|
|
309
|
+
|
|
278
310
|
### πΊοΈ Roadmap
|
|
279
311
|
|
|
280
312
|
| Tool | What it does |
|
package/dist/index.js
CHANGED
|
@@ -2976,6 +2976,21 @@ const TOOLS = [
|
|
|
2976
2976
|
required: ['instance_id'],
|
|
2977
2977
|
},
|
|
2978
2978
|
},
|
|
2979
|
+
// ββ crystal_view β inspect current Memory Crystal ββββββββββββββββββββββ
|
|
2980
|
+
{
|
|
2981
|
+
name: 'crystal_view',
|
|
2982
|
+
description: 'View the current Memory Crystal β the distilled snapshot of everything your AI brain has learned. ' +
|
|
2983
|
+
'Shows all top patterns grouped by category, lesson count, crystal age, and when to refresh. ' +
|
|
2984
|
+
'A crystal is created by memory_crystalize and injected into every session_start automatically. ' +
|
|
2985
|
+
'Call this to review what institutional knowledge is preserved, or to decide if a refresh is due.',
|
|
2986
|
+
inputSchema: {
|
|
2987
|
+
type: 'object',
|
|
2988
|
+
properties: {
|
|
2989
|
+
instance_id: { type: 'string', description: 'UUID of the cache instance' },
|
|
2990
|
+
},
|
|
2991
|
+
required: ['instance_id'],
|
|
2992
|
+
},
|
|
2993
|
+
},
|
|
2979
2994
|
// ββ Roadmap β Persistent project plan tracker βββββββββββββββββββββββββββ
|
|
2980
2995
|
{
|
|
2981
2996
|
name: 'roadmap_add',
|
|
@@ -5240,6 +5255,22 @@ async function handleTool(name, args) {
|
|
|
5240
5255
|
}
|
|
5241
5256
|
catch { /* git not available or not a repo β silent skip */ }
|
|
5242
5257
|
}
|
|
5258
|
+
// ββ Crystal age check β remind if > 30 days old or missing ββββββββββββββ
|
|
5259
|
+
let crystalReminder = '';
|
|
5260
|
+
try {
|
|
5261
|
+
const crystalRaw = await redis.get('cachly:crystal:latest');
|
|
5262
|
+
if (!crystalRaw) {
|
|
5263
|
+
crystalReminder = `π **Memory Crystal:** None exists yet. Run \`memory_crystalize(instance_id="${instance_id}")\` to distill your brain into a permanent snapshot β injected into every future session automatically.`;
|
|
5264
|
+
}
|
|
5265
|
+
else {
|
|
5266
|
+
const crystal = JSON.parse(crystalRaw);
|
|
5267
|
+
const crystalAgeDays = Math.round((Date.now() - new Date(crystal.ts).getTime()) / 86_400_000);
|
|
5268
|
+
if (crystalAgeDays >= 30) {
|
|
5269
|
+
crystalReminder = `π **Memory Crystal is ${crystalAgeDays} days old** (${crystal.label ?? 'unnamed'}). Run \`memory_crystalize(instance_id="${instance_id}")\` to refresh it with your latest ${crystal.lesson_count ?? '?'} lessons.`;
|
|
5270
|
+
}
|
|
5271
|
+
}
|
|
5272
|
+
}
|
|
5273
|
+
catch { /* non-critical */ }
|
|
5243
5274
|
const durationStr = durationMin !== undefined ? ` Β· ${durationMin} min` : '';
|
|
5244
5275
|
return [
|
|
5245
5276
|
`β
**Session saved**${durationStr}`,
|
|
@@ -5249,6 +5280,7 @@ async function handleTool(name, args) {
|
|
|
5249
5280
|
lessons_learned !== undefined ? `π§ **Lessons stored:** ${lessons_learned}` : '',
|
|
5250
5281
|
autoLearned.length > 0 ? `π€ **Auto-learned:** ${autoLearned.length} lessons extracted from summary (${autoLearned.slice(0, 3).map(t => `\`${t}\``).join(', ')}${autoLearned.length > 3 ? 'β¦' : ''})` : '',
|
|
5251
5282
|
ambientLearned.length > 0 ? `πΏ **Ambient git learning:** ${ambientLearned.length} commit${ambientLearned.length > 1 ? 's' : ''} auto-learned (${ambientLearned.slice(0, 3).map(t => `\`${t}\``).join(', ')}${ambientLearned.length > 3 ? 'β¦' : ''})` : '',
|
|
5283
|
+
crystalReminder,
|
|
5252
5284
|
``,
|
|
5253
5285
|
`π‘ Next session: \`session_start(focus="...")\` to see this summary.`,
|
|
5254
5286
|
].filter(l => l !== '').join('\n');
|
|
@@ -5637,6 +5669,52 @@ async function handleTool(name, args) {
|
|
|
5637
5669
|
];
|
|
5638
5670
|
return lines.join('\n');
|
|
5639
5671
|
}
|
|
5672
|
+
// ββ crystal_view β show current Memory Crystal βββββββββββββββββββββββββββ
|
|
5673
|
+
case 'crystal_view': {
|
|
5674
|
+
const { instance_id } = args;
|
|
5675
|
+
const redis = await getConnection(instance_id);
|
|
5676
|
+
const crystalRaw = await redis.get('cachly:crystal:latest');
|
|
5677
|
+
if (!crystalRaw) {
|
|
5678
|
+
return [
|
|
5679
|
+
`π **No Memory Crystal yet**`,
|
|
5680
|
+
``,
|
|
5681
|
+
`Your brain has no crystal β all knowledge lives in raw lessons only.`,
|
|
5682
|
+
``,
|
|
5683
|
+
`Run \`memory_crystalize(instance_id="${instance_id}")\` to:`,
|
|
5684
|
+
` β’ Distill everything learned into a permanent, compact snapshot`,
|
|
5685
|
+
` β’ Inject it into every future \`session_start\` automatically`,
|
|
5686
|
+
` β’ Preserve team knowledge even after lesson TTLs expire`,
|
|
5687
|
+
``,
|
|
5688
|
+
`π‘ Recommended: run monthly or after any major milestone.`,
|
|
5689
|
+
].join('\n');
|
|
5690
|
+
}
|
|
5691
|
+
const crystal = JSON.parse(crystalRaw);
|
|
5692
|
+
const ageDays = Math.round((Date.now() - new Date(crystal.ts).getTime()) / 86_400_000);
|
|
5693
|
+
const ageStr = ageDays === 0 ? 'today' : ageDays === 1 ? '1 day ago' : `${ageDays} days ago`;
|
|
5694
|
+
const freshness = ageDays < 14 ? 'π’ Fresh' : ageDays < 30 ? 'π‘ Aging' : 'π΄ Stale β refresh recommended';
|
|
5695
|
+
const lines = [
|
|
5696
|
+
`π **Memory Crystal: ${crystal.label}**`,
|
|
5697
|
+
``,
|
|
5698
|
+
`π
Created: **${ageStr}** Β· Freshness: ${freshness}`,
|
|
5699
|
+
`π Compressed: **${crystal.session_count} sessions** + **${crystal.lesson_count} lessons** β ${crystal.top_patterns.length} patterns`,
|
|
5700
|
+
`ποΈ Categories: ${crystal.categories.slice(0, 10).join(', ')}${crystal.categories.length > 10 ? `β¦ +${crystal.categories.length - 10}` : ''}`,
|
|
5701
|
+
``,
|
|
5702
|
+
`**Top patterns by category:**`,
|
|
5703
|
+
``,
|
|
5704
|
+
];
|
|
5705
|
+
for (const p of crystal.top_patterns) {
|
|
5706
|
+
lines.push(`**${p.category}** (${p.count} lesson${p.count > 1 ? 's' : ''})`);
|
|
5707
|
+
lines.push(` β ${p.insight.slice(0, 150)}${p.insight.length > 150 ? 'β¦' : ''}`);
|
|
5708
|
+
lines.push('');
|
|
5709
|
+
}
|
|
5710
|
+
if (ageDays >= 30) {
|
|
5711
|
+
lines.push(`---`, `β οΈ Crystal is ${ageDays} days old. Run \`memory_crystalize(instance_id="${instance_id}")\` to refresh with your latest lessons.`);
|
|
5712
|
+
}
|
|
5713
|
+
else {
|
|
5714
|
+
lines.push(`---`, `π‘ This crystal is injected automatically into every \`session_start\`. Refresh monthly with \`memory_crystalize\`.`);
|
|
5715
|
+
}
|
|
5716
|
+
return lines.filter(l => l !== undefined).join('\n');
|
|
5717
|
+
}
|
|
5640
5718
|
case 'brain_doctor': {
|
|
5641
5719
|
const { instance_id, workspace_path: drWorkspacePath = '' } = args;
|
|
5642
5720
|
const redis = await getConnection(instance_id);
|
|
@@ -7036,9 +7114,11 @@ async function handleBulkLockStream(name, args) {
|
|
|
7036
7114
|
> Sessions are fully automatic. The Brain starts when you call any tool and saves a summary when you close.
|
|
7037
7115
|
|
|
7038
7116
|
### MANDATORY hooks (always fire, no exceptions):
|
|
7117
|
+
- **Context compacted** β call \`compact_recover(instance_id="${instance_id}", focus="<current task>")\` FIRST
|
|
7039
7118
|
- **Window opens** β call \`session_start(instance_id="${instance_id}", focus="<today's goal>")\`
|
|
7040
7119
|
- **Bug fixed / deployed / discovered** β call \`learn_from_attempts(instance_id="${instance_id}", topic="fix:<area>", outcome="success", what_worked="...")\`
|
|
7041
7120
|
- **Window closes** β call \`session_end(instance_id="${instance_id}", summary="...", files_changed=[...])\`
|
|
7121
|
+
- **Monthly** β call \`memory_crystalize(instance_id="${instance_id}")\` to distill knowledge into a permanent Crystal
|
|
7042
7122
|
`;
|
|
7043
7123
|
const full = `## Cachly AI Brain β Autopilot for ${project_name}
|
|
7044
7124
|
|
|
@@ -7098,18 +7178,40 @@ smart_recall(
|
|
|
7098
7178
|
|
|
7099
7179
|
---
|
|
7100
7180
|
|
|
7101
|
-
## β‘
|
|
7181
|
+
## β‘ Context Recovery (MANDATORY after compaction)
|
|
7182
|
+
|
|
7183
|
+
**If your context window was compacted**, call this FIRST β before reading any file:
|
|
7184
|
+
\`\`\`
|
|
7185
|
+
compact_recover(
|
|
7186
|
+
instance_id = "${instance_id}",
|
|
7187
|
+
focus = "<what you were working on>",
|
|
7188
|
+
)
|
|
7189
|
+
\`\`\`
|
|
7190
|
+
Returns: last checkpoint, pending tasks, top lessons. Instant β no full brain scan.
|
|
7191
|
+
|
|
7192
|
+
---
|
|
7193
|
+
|
|
7194
|
+
## π Scheduled Maintenance (run on schedule)
|
|
7195
|
+
|
|
7196
|
+
| When | Call |
|
|
7197
|
+
|---|---|
|
|
7198
|
+
| **Monthly** | \`memory_crystalize(instance_id="${instance_id}")\` β distill brain into a permanent snapshot |
|
|
7199
|
+
| Weekly review | \`brain_diff(instance_id="${instance_id}", since="7d")\` β see what your AI learned this week |
|
|
7200
|
+
| Before big refactor | \`knowledge_decay(instance_id="${instance_id}")\` β see which lessons to still trust |
|
|
7201
|
+
| After major milestone | \`memory_crystalize(instance_id="${instance_id}", label="v2 launch")\` β preserve milestone knowledge |
|
|
7202
|
+
|
|
7203
|
+
## π§ Cognitive Tools (use anytime)
|
|
7102
7204
|
|
|
7103
7205
|
| When | Call |
|
|
7104
7206
|
|---|---|
|
|
7105
7207
|
| Brain feeling cluttered | \`memory_consolidate(instance_id="${instance_id}")\` |
|
|
7106
|
-
| Weekly review | \`brain_diff(instance_id="${instance_id}", since="7d")\` |
|
|
7107
7208
|
| Weird bug, no idea why | \`causal_trace(instance_id="${instance_id}", problem="<symptom>")\` |
|
|
7108
|
-
|
|
|
7209
|
+
| Unknown error | \`syndicate_search(q="<error message>")\` β global community solutions |
|
|
7210
|
+
| Unknown error that you solved | \`syndicate(instance_id="${instance_id}", topic="fix:<area>", what_worked="...")\` |
|
|
7109
7211
|
|
|
7110
7212
|
---
|
|
7111
7213
|
|
|
7112
|
-
*Cachly v0.
|
|
7214
|
+
*Cachly v0.9 Β· Generated ${new Date().toISOString().slice(0, 10)}*
|
|
7113
7215
|
`;
|
|
7114
7216
|
const content = style === 'minimal' ? minimal : full;
|
|
7115
7217
|
const filename = editor === 'copilot'
|