@hir4ta/mneme 0.24.2 → 0.24.3
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-plugin/plugin.json +1 -1
- package/README.ja.md +1 -1
- package/README.md +1 -1
- package/dist/server.js +1 -1
- package/hooks/user-prompt-submit.sh +95 -81
- package/package.json +1 -1
- package/skills/save/SKILL.md +3 -3
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mneme",
|
|
3
3
|
"description": "A plugin that provides long-term memory for Claude Code. It automatically saves context lost during auto-compact, offering features for session restoration, recording technical decisions, and learning developer patterns.",
|
|
4
|
-
"version": "0.24.
|
|
4
|
+
"version": "0.24.3",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "hir4ta"
|
|
7
7
|
},
|
package/README.ja.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# mneme
|
|
2
2
|
|
|
3
|
-

|
|
4
4
|

|
|
5
5
|
[](https://www.npmjs.com/package/@hir4ta/mneme)
|
|
6
6
|
[](https://github.com/hir4ta/mneme/blob/main/LICENSE)
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# mneme
|
|
2
2
|
|
|
3
|
-

|
|
4
4
|

|
|
5
5
|
[](https://www.npmjs.com/package/@hir4ta/mneme)
|
|
6
6
|
[](https://github.com/hir4ta/mneme/blob/main/LICENSE)
|
package/dist/server.js
CHANGED
|
@@ -4,8 +4,9 @@
|
|
|
4
4
|
#
|
|
5
5
|
# Purpose: Search mneme for relevant context and approved rules,
|
|
6
6
|
# inject as additionalContext using shared search-core logic.
|
|
7
|
+
# Also injects Claude Session ID (workaround for anthropics/claude-code#16538).
|
|
7
8
|
#
|
|
8
|
-
# Input (stdin): JSON with prompt, cwd
|
|
9
|
+
# Input (stdin): JSON with prompt, session_id, cwd
|
|
9
10
|
# Output (stdout): JSON with hookSpecificOutput.additionalContext (if matches found)
|
|
10
11
|
#
|
|
11
12
|
|
|
@@ -23,13 +24,16 @@ fi
|
|
|
23
24
|
|
|
24
25
|
prompt=$(echo "$input_json" | jq -r ".prompt // empty" 2>/dev/null || echo "")
|
|
25
26
|
cwd=$(echo "$input_json" | jq -r ".cwd // empty" 2>/dev/null || echo "")
|
|
27
|
+
session_id=$(echo "$input_json" | jq -r ".session_id // empty" 2>/dev/null || echo "")
|
|
26
28
|
|
|
29
|
+
# Determine if search should run (session ID is always injected regardless)
|
|
30
|
+
run_search=true
|
|
27
31
|
if [ -z "$prompt" ] || [ ${#prompt} -lt 10 ]; then
|
|
28
|
-
|
|
32
|
+
run_search=false
|
|
29
33
|
fi
|
|
30
34
|
|
|
31
35
|
if [[ "$prompt" == /mneme* ]]; then
|
|
32
|
-
|
|
36
|
+
run_search=false
|
|
33
37
|
fi
|
|
34
38
|
|
|
35
39
|
if [ -z "$cwd" ]; then
|
|
@@ -37,104 +41,114 @@ if [ -z "$cwd" ]; then
|
|
|
37
41
|
fi
|
|
38
42
|
cwd=$(cd "$cwd" 2>/dev/null && pwd || echo "$cwd")
|
|
39
43
|
|
|
40
|
-
# Cap very large prompts to avoid overly expensive search
|
|
41
|
-
if [ ${#prompt} -gt 4000 ]; then
|
|
42
|
-
prompt="${prompt:0:4000}"
|
|
43
|
-
fi
|
|
44
|
-
|
|
45
44
|
if ! validate_mneme "$cwd"; then
|
|
46
45
|
exit 0
|
|
47
46
|
fi
|
|
48
47
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
if [ -z "$search_script" ]; then
|
|
53
|
-
exit 0
|
|
54
|
-
fi
|
|
55
|
-
|
|
56
|
-
# Detect changed files for file-based session recommendation
|
|
57
|
-
changed_files=""
|
|
58
|
-
if command -v git >/dev/null 2>&1 && git -C "$cwd" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
|
59
|
-
changed_files=$(cd "$cwd" && {
|
|
60
|
-
git diff --name-only HEAD 2>/dev/null
|
|
61
|
-
git diff --name-only --cached 2>/dev/null
|
|
62
|
-
} | sort -u | head -20 | paste -sd "," - 2>/dev/null || echo "")
|
|
63
|
-
fi
|
|
64
|
-
|
|
65
|
-
search_output=$(invoke_node "$search_script" \
|
|
66
|
-
--query "$prompt" --project "$cwd" --limit 5 \
|
|
67
|
-
${changed_files:+--files "$changed_files"} 2>/dev/null || echo "")
|
|
48
|
+
# --- Search (skipped for short prompts and /mneme commands) ---
|
|
49
|
+
context_message=""
|
|
50
|
+
rules_message=""
|
|
68
51
|
|
|
69
|
-
if [
|
|
70
|
-
|
|
71
|
-
|
|
52
|
+
if [ "$run_search" = true ]; then
|
|
53
|
+
# Cap very large prompts to avoid overly expensive search
|
|
54
|
+
if [ ${#prompt} -gt 4000 ]; then
|
|
55
|
+
prompt="${prompt:0:4000}"
|
|
56
|
+
fi
|
|
72
57
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
58
|
+
PLUGIN_ROOT="$(get_plugin_root)"
|
|
59
|
+
|
|
60
|
+
search_script=$(find_script "$PLUGIN_ROOT" "prompt-search")
|
|
61
|
+
if [ -n "$search_script" ]; then
|
|
62
|
+
# Detect changed files for file-based session recommendation
|
|
63
|
+
changed_files=""
|
|
64
|
+
if command -v git >/dev/null 2>&1 && git -C "$cwd" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
|
65
|
+
changed_files=$(cd "$cwd" && {
|
|
66
|
+
git diff --name-only HEAD 2>/dev/null
|
|
67
|
+
git diff --name-only --cached 2>/dev/null
|
|
68
|
+
} | sort -u | head -20 | paste -sd "," - 2>/dev/null || echo "")
|
|
69
|
+
fi
|
|
77
70
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
'
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
71
|
+
search_output=$(invoke_node "$search_script" \
|
|
72
|
+
--query "$prompt" --project "$cwd" --limit 5 \
|
|
73
|
+
${changed_files:+--files "$changed_files"} 2>/dev/null || echo "")
|
|
74
|
+
|
|
75
|
+
if [ -n "$search_output" ]; then
|
|
76
|
+
success=$(echo "$search_output" | jq -r ".success // false" 2>/dev/null || echo "false")
|
|
77
|
+
if [ "$success" = "true" ]; then
|
|
78
|
+
# Format session/interaction context
|
|
79
|
+
context_lines=$(echo "$search_output" | jq -r '
|
|
80
|
+
.results
|
|
81
|
+
| map(select(.score >= 3 and (.type == "session" or .type == "unit")))
|
|
82
|
+
| .[:3]
|
|
83
|
+
| map("[\(.type):\(.id)] \(.title) | match: \((.matchedFields // []) | join(","))")
|
|
84
|
+
| join("\n")
|
|
85
|
+
')
|
|
86
|
+
|
|
87
|
+
# Format file-based session recommendations
|
|
88
|
+
file_rec_lines=$(echo "$search_output" | jq -r '
|
|
89
|
+
.fileRecommendations // []
|
|
90
|
+
| .[:3]
|
|
91
|
+
| map("[session:\(.sessionId)] \(.title) | files: \(.matchedFiles | join(", "))")
|
|
92
|
+
| join("\n")
|
|
93
|
+
')
|
|
94
|
+
|
|
95
|
+
if [ -n "$context_lines" ] && [ "$context_lines" != "null" ] || \
|
|
96
|
+
[ -n "$file_rec_lines" ] && [ "$file_rec_lines" != "null" ]; then
|
|
97
|
+
context_parts=""
|
|
98
|
+
if [ -n "$context_lines" ] && [ "$context_lines" != "null" ]; then
|
|
99
|
+
context_parts="Related context found (sessions/units):
|
|
101
100
|
${context_lines}"
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
101
|
+
fi
|
|
102
|
+
if [ -n "$file_rec_lines" ] && [ "$file_rec_lines" != "null" ]; then
|
|
103
|
+
if [ -n "$context_parts" ]; then
|
|
104
|
+
context_parts="${context_parts}
|
|
106
105
|
"
|
|
107
|
-
|
|
108
|
-
|
|
106
|
+
fi
|
|
107
|
+
context_parts="${context_parts}Related sessions (editing same files):
|
|
109
108
|
${file_rec_lines}"
|
|
110
|
-
|
|
111
|
-
|
|
109
|
+
fi
|
|
110
|
+
context_message="<mneme-context>
|
|
112
111
|
${context_parts}
|
|
113
112
|
To explore deeper: use /mneme:search with specific technical terms, error messages, or file paths.
|
|
114
113
|
</mneme-context>"
|
|
115
|
-
fi
|
|
116
|
-
|
|
117
|
-
# Format approved rules
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
rules_message="<mneme-rules>
|
|
114
|
+
fi
|
|
115
|
+
|
|
116
|
+
# Format approved rules
|
|
117
|
+
rules_lines=$(echo "$search_output" | jq -r '
|
|
118
|
+
.rules // []
|
|
119
|
+
| map(select(.score >= 2))
|
|
120
|
+
| .[:5]
|
|
121
|
+
| map("[\(.sourceType):\(.id)] (\(.priority // "—")) \(.text)")
|
|
122
|
+
| join("\n")
|
|
123
|
+
')
|
|
124
|
+
|
|
125
|
+
if [ -n "$rules_lines" ] && [ "$rules_lines" != "null" ]; then
|
|
126
|
+
rules_message="<mneme-rules>
|
|
129
127
|
Approved development rules (apply during this response):
|
|
130
128
|
${rules_lines}
|
|
131
129
|
</mneme-rules>"
|
|
130
|
+
fi
|
|
131
|
+
fi
|
|
132
|
+
fi
|
|
133
|
+
fi
|
|
132
134
|
fi
|
|
133
135
|
|
|
134
|
-
#
|
|
136
|
+
# --- Assemble full context ---
|
|
135
137
|
full_context=""
|
|
138
|
+
|
|
139
|
+
# Session ID injection (workaround for anthropics/claude-code#16538:
|
|
140
|
+
# Plugin SessionStart hooks don't surface additionalContext to Claude)
|
|
141
|
+
if [ -n "$session_id" ]; then
|
|
142
|
+
full_context="**Claude Session ID:** ${session_id}"
|
|
143
|
+
fi
|
|
144
|
+
|
|
136
145
|
if [ -n "$context_message" ]; then
|
|
137
|
-
|
|
146
|
+
if [ -n "$full_context" ]; then
|
|
147
|
+
full_context="${full_context}
|
|
148
|
+
${context_message}"
|
|
149
|
+
else
|
|
150
|
+
full_context="$context_message"
|
|
151
|
+
fi
|
|
138
152
|
fi
|
|
139
153
|
if [ -n "$rules_message" ]; then
|
|
140
154
|
if [ -n "$full_context" ]; then
|
package/package.json
CHANGED
package/skills/save/SKILL.md
CHANGED
|
@@ -45,7 +45,7 @@ Always render missing required fields as blocking errors before write.
|
|
|
45
45
|
|
|
46
46
|
**STOP. Before doing ANYTHING else, find the Claude Session ID.**
|
|
47
47
|
|
|
48
|
-
|
|
48
|
+
The UserPromptSubmit hook injects the session ID into every prompt's context. Look for this exact line in the system-reminder messages above:
|
|
49
49
|
|
|
50
50
|
```
|
|
51
51
|
**Claude Session ID:** <UUID>
|
|
@@ -54,8 +54,8 @@ Scan upward in this conversation for the SessionStart context block. It contains
|
|
|
54
54
|
Copy the full UUID value (36 characters, e.g. `a1b2c3d4-e5f6-7890-abcd-ef1234567890`).
|
|
55
55
|
|
|
56
56
|
<required>
|
|
57
|
-
- The Claude Session ID is ALREADY in this conversation — injected by the
|
|
58
|
-
- Search for the literal text `**Claude Session ID:**` in
|
|
57
|
+
- The Claude Session ID is ALREADY in this conversation — injected by the UserPromptSubmit hook on every prompt
|
|
58
|
+
- Search for the literal text `**Claude Session ID:**` in system-reminder messages above
|
|
59
59
|
- Copy the full 36-character UUID that follows it
|
|
60
60
|
- Do NOT run Bash, Glob, Grep, or any other tool to discover the session ID
|
|
61
61
|
- Do NOT call `mneme_list_sessions` to find it (that is only for the fallback below)
|