claude-session-continuity-mcp 1.15.0 → 1.15.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 +31 -4
- package/dist/hooks/user-prompt-submit.js +33 -7
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
# claude-session-continuity-mcp
|
|
1
|
+
# claude-session-continuity-mcp
|
|
2
2
|
|
|
3
|
-
> **
|
|
3
|
+
> **Never re-explain your project to Claude again.** 100% local session memory for Claude Code — auto context injection, semantic search, and error→solution recall. Zero config, zero API cost.
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/claude-session-continuity-mcp)
|
|
6
|
+
[](https://www.npmjs.com/package/claude-session-continuity-mcp)
|
|
6
7
|
[](https://opensource.org/licenses/MIT)
|
|
7
|
-
[]()
|
|
8
|
-
[]()
|
|
9
8
|
[](https://glama.ai/mcp/servers/leesgit/claude-session-continuity-mcp)
|
|
10
9
|
|
|
10
|
+

|
|
11
|
+
|
|
11
12
|
## The Problem
|
|
12
13
|
|
|
13
14
|
Every new Claude Code session:
|
|
@@ -62,6 +63,24 @@ Every new Claude Code session:
|
|
|
62
63
|
|
|
63
64
|
---
|
|
64
65
|
|
|
66
|
+
## Why this over other memory tools?
|
|
67
|
+
|
|
68
|
+
Most Claude memory tools rely on **explicit tool calls** ("remember this"), a **cloud API**, or a **background AI worker**. This one is deliberately different:
|
|
69
|
+
|
|
70
|
+
| | claude-session-continuity-mcp | Typical cloud/AI-memory MCP |
|
|
71
|
+
|---|---|---|
|
|
72
|
+
| **Setup** | `npm i -g` → hooks auto-install | Manual server + API key |
|
|
73
|
+
| **Trigger** | 5 automatic hooks (no commands) | You call a `remember` tool |
|
|
74
|
+
| **Storage** | 100% local SQLite | Cloud / external service |
|
|
75
|
+
| **API cost** | **$0** — local embeddings | Per-token / subscription |
|
|
76
|
+
| **Latency** | < 5ms (on-device) | Network round-trip |
|
|
77
|
+
| **Privacy** | Never leaves your machine | Sent to a provider |
|
|
78
|
+
| **Search** | FTS5 + local semantic, KO/EN/JA cross-lingual | Varies |
|
|
79
|
+
|
|
80
|
+
If you want zero-config, offline, no-cost memory that just *happens* while you work — this is it.
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
65
84
|
## Quick Start
|
|
66
85
|
|
|
67
86
|
### Recommended: Global Installation
|
|
@@ -635,3 +654,11 @@ PRs welcome! Please:
|
|
|
635
654
|
|
|
636
655
|
- [Model Context Protocol](https://modelcontextprotocol.io/) by Anthropic
|
|
637
656
|
- [Xenova Transformers](https://github.com/xenova/transformers.js) for embeddings
|
|
657
|
+
|
|
658
|
+
---
|
|
659
|
+
|
|
660
|
+
<div align="center">
|
|
661
|
+
|
|
662
|
+
**If this saves you from re-explaining your project, consider giving it a ⭐ — it genuinely helps others find it.**
|
|
663
|
+
|
|
664
|
+
</div>
|
|
@@ -83,6 +83,10 @@ const STOPWORDS = new Set([
|
|
|
83
83
|
'하나', '둘', '셋', '정말', '진짜', '아주', '너무', '매우', '조금', '약간', '대충', '그냥', '일단',
|
|
84
84
|
'그리고', '하지만', '그래서', '그래도', '근데', '그런데', '또는', '또한', '이런데', '그런데',
|
|
85
85
|
'진행', '확인', '시작', '완료', '종료', '해줘', '해주세요', '부탁', '알려', '알려줘',
|
|
86
|
+
// 흔한 작업 동사·부사 (P1, 2026-07-08: 작은 코퍼스에서 df가 낮아 IDF를 통과해
|
|
87
|
+
// 오탐을 유발했음. "저장/기억/다시" 등이 GCP·영상 메모리를 엉뚱하게 소환)
|
|
88
|
+
'저장', '기억', '삭제', '수정', '검색', '등록', '변경', '추가', '제거', '생성', '실행', '설정',
|
|
89
|
+
'전체', '다시', '이렇게', '그렇게', '저렇게', '계속', '먼저', '바로', '같이', '제대로', '하나하나',
|
|
86
90
|
// 범용 명사 (LIKE 검색 시 아무 메모리나 잡는 오탐원 — 2026-07-08 C3)
|
|
87
91
|
'이름', '정보', '내용', '관련', '부분', '상태', '방법', '문제', '경우', '생각', '이야기', '얘기',
|
|
88
92
|
'어떻게', '무엇', '뭐가', '왜', '어디', '언제', '어느', '어떤', '어떻', '얼마',
|
|
@@ -91,6 +95,11 @@ const STOPWORDS = new Set([
|
|
|
91
95
|
// 영어 빈출 추가 — Next.js 같은 동음이의 발생하는 토큰
|
|
92
96
|
'next', 'last', 'first', 'prev', 'previous', 'check', 'test', 'run', 'live', 'ready', 'verify', 'verification',
|
|
93
97
|
'session', 'task', 'item', 'case', 'file', 'line', 'data', 'code', 'word', 'time', 'step', 'part', 'side',
|
|
98
|
+
// 영어 작업 동사 (P1 audit-7, 2026-07-08: 한국어 저장/기억/검색과 대칭. 이들이
|
|
99
|
+
// df 낮아 IDF 통과 시 오탐 유발. inCorpus 게이트가 사후 방어하나 명시 차단이 견고)
|
|
100
|
+
'save', 'store', 'remember', 'search', 'find', 'delete', 'remove', 'update', 'create', 'add',
|
|
101
|
+
'change', 'edit', 'fix', 'make', 'show', 'list', 'get', 'set', 'build', 'lint', 'deploy',
|
|
102
|
+
'whole', 'thing', 'again', 'entire', 'stuff', 'something', 'anything', 'everything',
|
|
94
103
|
// 영어 빈출 stopwords
|
|
95
104
|
'the', 'a', 'an', 'is', 'are', 'was', 'were', 'be', 'been', 'being', 'have', 'has', 'had',
|
|
96
105
|
'do', 'does', 'did', 'will', 'would', 'should', 'could', 'can', 'may', 'might', 'must',
|
|
@@ -120,6 +129,12 @@ function extractTriggerKeywords(prompt) {
|
|
|
120
129
|
.split(/[\s,.!?;:/\\|]+/)
|
|
121
130
|
.map(t => t.trim().toLowerCase())
|
|
122
131
|
.filter(t => /^[a-z0-9가-힣]+$/i.test(t)) // 영숫자+한글만
|
|
132
|
+
// P1 (2026-07-08): 흔한 한국어 동사 어미만 벗겨 stopword 체크가 먹게 함.
|
|
133
|
+
// "저장해줘"→"저장"이 안 되면 STOPWORDS(저장)를 우회해 오탐.
|
|
134
|
+
// ⚠️ 단일 글자 조사(로/를/이/가 등)는 절삭 금지 — "경로→경","추가→추"처럼
|
|
135
|
+
// 진짜 2글자 명사를 훼손함(실측 확인). 명확한 다글자 동사 어미만.
|
|
136
|
+
.map(t => t.replace(/(해줘|해주세요|해주라|했어|했지|하는|하고|해서|합니다|드려|드릴게)$/, ''))
|
|
137
|
+
.filter(t => t.length > 0)
|
|
123
138
|
.filter(t => {
|
|
124
139
|
// 한국어 단일 음절은 거의 무의미, 2글자 이상 허용
|
|
125
140
|
const hasHangul = /[가-힣]/.test(t);
|
|
@@ -154,7 +169,8 @@ function extractTriggerKeywords(prompt) {
|
|
|
154
169
|
* 토큰("Next.js")에 의해 false positive 발생. df=0 토큰은 FTS5 매칭에
|
|
155
170
|
* 기여 0이므로 trigger 조건 자체에서 제외하는 게 맞음.
|
|
156
171
|
*
|
|
157
|
-
* @returns 살아남은 키워드 (
|
|
172
|
+
* @returns 살아남은 키워드 + 각 df (P1 audit-7 2026-07-08: df를 함께 반환해
|
|
173
|
+
* searchTriggeredMemories의 inCorpus 재쿼리 제거)
|
|
158
174
|
*/
|
|
159
175
|
function filterByIdf(db, keywords) {
|
|
160
176
|
if (keywords.length === 0)
|
|
@@ -173,22 +189,22 @@ function filterByIdf(db, keywords) {
|
|
|
173
189
|
// 예: 메모리에 "비번"으로 적혔지만 사용자가 "비밀번호" 입력 → df=0, 그러나
|
|
174
190
|
// 같이 추출된 "서명키"가 매칭해주면 trigger 정상 작동
|
|
175
191
|
if (df === 0) {
|
|
176
|
-
survived.push(kw);
|
|
192
|
+
survived.push({ kw, df: 0 });
|
|
177
193
|
continue;
|
|
178
194
|
}
|
|
179
195
|
const idf = Math.log(N / df);
|
|
180
196
|
if (idf >= 2.0) {
|
|
181
|
-
survived.push(kw);
|
|
197
|
+
survived.push({ kw, df });
|
|
182
198
|
}
|
|
183
199
|
}
|
|
184
200
|
catch {
|
|
185
|
-
survived.push(kw); // FTS5 구문 오류 시 보수적으로 살림
|
|
201
|
+
survived.push({ kw, df: -1 }); // FTS5 구문 오류 시 보수적으로 살림 (df 불명=-1)
|
|
186
202
|
}
|
|
187
203
|
}
|
|
188
204
|
return survived;
|
|
189
205
|
}
|
|
190
206
|
catch {
|
|
191
|
-
return keywords; // DF 측정 실패 시 원본 그대로
|
|
207
|
+
return keywords.map(kw => ({ kw, df: -1 })); // DF 측정 실패 시 원본 그대로
|
|
192
208
|
}
|
|
193
209
|
}
|
|
194
210
|
/**
|
|
@@ -203,8 +219,17 @@ function searchTriggeredMemories(db, keywords, project) {
|
|
|
203
219
|
const meaningful = filterByIdf(db, keywords);
|
|
204
220
|
if (meaningful.length < 2)
|
|
205
221
|
return []; // IDF 통과 토큰 2개 이상일 때만 trigger
|
|
222
|
+
// P1 (2026-07-08): 실제 코퍼스에 존재하는(df>0) 토큰이 2개 이상일 때만 trigger.
|
|
223
|
+
// filterByIdf가 df=0 토큰(코퍼스에 없음)을 살려주는데, 그게 length>=2 게이트를
|
|
224
|
+
// 우회시켜 실질 단일 토큰 매칭으로 trigger되던 오탐 차단.
|
|
225
|
+
// 예: "gmail draft로 저장" → gmail(df=1) + draft로(df=0) → 실매칭 1개인데 trigger됐음.
|
|
226
|
+
// audit-7 2026-07-08: filterByIdf가 반환한 df를 재사용(중복 쿼리 제거).
|
|
227
|
+
const inCorpus = meaningful.filter(m => m.df > 0);
|
|
228
|
+
if (inCorpus.length < 2)
|
|
229
|
+
return [];
|
|
230
|
+
const meaningfulKws = meaningful.map(m => m.kw);
|
|
206
231
|
try {
|
|
207
|
-
const ftsQuery =
|
|
232
|
+
const ftsQuery = meaningfulKws.map(k => `"${k.replace(/"/g, '""')}"`).join(' OR ');
|
|
208
233
|
const projectFilter = project ? `AND (m.project = ? OR m.project IS NULL)` : '';
|
|
209
234
|
const params = [ftsQuery];
|
|
210
235
|
if (project)
|
|
@@ -239,7 +264,8 @@ function searchPastWork(db, keyword) {
|
|
|
239
264
|
if (rawTokens.length === 0)
|
|
240
265
|
return result;
|
|
241
266
|
// IDF로 흔한 토큰 추가 제거. 남는 게 없으면(전부 흔함) 검색 안 함.
|
|
242
|
-
|
|
267
|
+
// audit-7 2026-07-08: filterByIdf가 {kw,df} 반환하도록 바뀜 → kw만 추출.
|
|
268
|
+
const searchTokens = filterByIdf(db, rawTokens).map(m => m.kw);
|
|
243
269
|
if (searchTokens.length === 0)
|
|
244
270
|
return result;
|
|
245
271
|
// 1. sessions 검색 (최근 30일, 상위 3건) — 토큰 LIKE OR
|