claude_memory 0.8.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.
- checksums.yaml +4 -4
- data/.claude/memory.sqlite3 +0 -0
- data/.claude/rules/claude_memory.generated.md +94 -2
- data/.claude/settings.json +30 -52
- data/.claude/settings.local.json +3 -1
- data/.claude/skills/release/SKILL.md +168 -0
- data/.claude/skills/upgrade-dependencies/SKILL.md +154 -0
- data/.claude-plugin/marketplace.json +2 -2
- data/.claude-plugin/plugin.json +3 -3
- data/.claude-plugin/scripts/hook-runner.sh +14 -0
- data/.claude-plugin/scripts/serve-mcp.sh +14 -0
- data/.ruby-version +1 -1
- data/CHANGELOG.md +47 -0
- data/CLAUDE.md +31 -17
- data/README.md +35 -0
- data/db/migrations/013_add_mcp_tool_calls.rb +26 -0
- data/db/migrations/014_canonicalize_predicates.rb +30 -0
- data/docs/improvements.md +58 -20
- data/docs/influence/claude-mem.md +1 -0
- data/docs/influence/claude-supermemory.md +1 -0
- data/docs/influence/episodic-memory.md +1 -0
- data/docs/influence/grepai.md +1 -0
- data/docs/influence/kbs.md +1 -0
- data/docs/influence/lossless-claw.md +1 -0
- data/docs/influence/qmd.md +1 -0
- data/lib/claude_memory/commands/completion_command.rb +1 -31
- data/lib/claude_memory/commands/embeddings_command.rb +198 -0
- data/lib/claude_memory/commands/help_command.rb +8 -1
- data/lib/claude_memory/commands/registry.rb +47 -34
- data/lib/claude_memory/commands/reject_command.rb +62 -0
- data/lib/claude_memory/commands/restore_command.rb +77 -0
- data/lib/claude_memory/commands/skills/distill-transcripts.md +5 -1
- data/lib/claude_memory/commands/stats_command.rb +98 -2
- data/lib/claude_memory/configuration.rb +14 -1
- data/lib/claude_memory/distill/json_schema.md +8 -4
- data/lib/claude_memory/distill/null_distiller.rb +2 -0
- data/lib/claude_memory/domain/entity.rb +13 -1
- data/lib/claude_memory/domain/fact.rb +26 -2
- data/lib/claude_memory/embeddings/api_adapter.rb +5 -4
- data/lib/claude_memory/embeddings/fastembed_adapter.rb +43 -13
- data/lib/claude_memory/embeddings/inspector.rb +91 -0
- data/lib/claude_memory/embeddings/model_registry.rb +210 -0
- data/lib/claude_memory/embeddings/resolver.rb +32 -6
- data/lib/claude_memory/ingest/ingester.rb +17 -0
- data/lib/claude_memory/mcp/handlers/management_handlers.rb +24 -0
- data/lib/claude_memory/mcp/handlers/stats_handlers.rb +5 -2
- data/lib/claude_memory/mcp/instructions_builder.rb +17 -0
- data/lib/claude_memory/mcp/server.rb +30 -3
- data/lib/claude_memory/mcp/telemetry.rb +86 -0
- data/lib/claude_memory/mcp/tool_definitions.rb +86 -3
- data/lib/claude_memory/mcp/tools.rb +10 -0
- data/lib/claude_memory/publish.rb +40 -5
- data/lib/claude_memory/recall.rb +81 -0
- data/lib/claude_memory/resolve/predicate_policy.rb +63 -3
- data/lib/claude_memory/resolve/resolver.rb +43 -0
- data/lib/claude_memory/store/schema_manager.rb +1 -1
- data/lib/claude_memory/store/sqlite_store.rb +250 -1
- data/lib/claude_memory/store/store_manager.rb +50 -1
- data/lib/claude_memory/sweep/maintenance.rb +115 -1
- data/lib/claude_memory/sweep/sweeper.rb +3 -0
- data/lib/claude_memory/version.rb +1 -1
- data/lib/claude_memory.rb +5 -0
- metadata +27 -8
- data/.claude/memory.sqlite3-shm +0 -0
- data/.claude/memory.sqlite3-wal +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b6df0a3f58a88c1bbec82ec20e26789d51ad2712408d058337a196c5eac90654
|
|
4
|
+
data.tar.gz: beb9c2ef59ef6a45430eeb03466e37f6b1f741ef1745b5303a1443b02a7c84b4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: '06905bca1f77df5642caf0846cde7394ba9a1baf3c954138383ac39927fcaae2ef097ff79dd3c866e6930fa0eac0d0fb958366bded54a0616d8e356a316e616c'
|
|
7
|
+
data.tar.gz: 9a8e3c455c20ae616bc239b766e1d4e2aa4c6e5448f494294d9c6a646a8a613428e9b63218624c5cae7e30f389704dd3bee6b788e97a369cb719b115abffddd7
|
data/.claude/memory.sqlite3
CHANGED
|
Binary file
|
|
@@ -1,21 +1,113 @@
|
|
|
1
|
-
<!--
|
|
1
|
+
<!--
|
|
2
2
|
This file is auto-generated by claude-memory.
|
|
3
3
|
Do not edit manually - changes will be overwritten.
|
|
4
|
-
Generated: 2026-
|
|
4
|
+
Generated: 2026-04-16T17:54:51Z
|
|
5
5
|
-->
|
|
6
6
|
|
|
7
7
|
# Project Memory
|
|
8
8
|
|
|
9
9
|
## Current Decisions
|
|
10
10
|
|
|
11
|
+
- MCP tool-call telemetry stores minimal columns (tool_name, duration_ms, result_count, scope, error_class) — deliberately no query_text or query_hash. YAGNI: hashes are write-only without the raw text, and raw text adds privacy concerns without clear value beyond existing shortcut tools (memory.decisions, memory.conventions).
|
|
11
12
|
- From QMD 2026-02-02 restudy: adopt Claude Code plugin format, MCP structured content pattern, MCP query guide prompt, inline status checks. Carry forward sqlite-vec, RRF, docids, smart expansion from 2026-01-26. Reject custom fine-tuned models, LLM reranking, YAML collections.
|
|
12
13
|
- From claude-supermemory study: adopt SessionStart hook context injection (hookSpecificOutput.additionalContext), tool-specific observation compression, and relative time formatting. Reject cloud storage dependency and no-test approach.
|
|
13
14
|
|
|
14
15
|
## Conventions
|
|
15
16
|
|
|
17
|
+
- Curated predicate vocabulary has 8 entries: multi-value (convention, decision, architecture, uses_framework, uses_language) and single-value (uses_database, deployment_platform, auth_method). Pruned 7 dead predicates after multi-project survey confirmed zero usage.
|
|
18
|
+
- Before making design changes to schemas, vocabularies, or policies, survey actual usage data across multiple project databases under ~/src/ — single-project analysis can validate wrong assumptions. The uses_framework cardinality bug was only visible across multi-project data.
|
|
19
|
+
- A/B testing memory plugin: use 'claude --bare --mcp-config=/tmp/mcp-test.json -p' with serve-mcp.sh path. --plugin-dir doesn't work with --bare despite docs claiming it should. Architecture/convention/preference questions differentiate best; grep-able and one-shot code-gen questions don't.
|
|
20
|
+
- NullDistiller emits uses_language for language-type entities (added 0.9.0), alongside existing uses_database, uses_framework, deployment_platform. Migration v14 canonicalizes stale predicate names (has_convention → convention, primary_language → uses_language) in existing facts.
|
|
21
|
+
- CLAUDE.md scope-system example text ('this app uses PostgreSQL') causes recurring distiller hallucinations. Reject + re-ingest creates rejection churn because rejection metadata doesn't block re-insertion at content level. Open product gap — workaround: wrap example text in <no-memory> tags.
|
|
22
|
+
- claude-memory restore --predicate NAME recovers facts superseded by obsolete single-value classifications. Uses Jaccard token overlap (threshold 0.5) to distinguish bug-caused supersession from real corrections. Only operates on predicates currently classified multi-value. Opt-in per DB, supports --dry-run.
|
|
23
|
+
- claude-memory reject <id_or_docid> marks facts as rejected and resolves associated open conflicts in a single transaction. Accepts integer fact IDs or 8-char hex docids. memory.reject_fact MCP tool mirrors the CLI.
|
|
24
|
+
- The /release skill automates gem releases in three phases: prepare (version bump across 3 files, bundle install, MCP verify, tests, lint, CHANGELOG check, commit), publish (user-driven: git push + rake release), announce (fix GitHub Latest flags, create gh release from CHANGELOG). Never auto-pushes.
|
|
25
|
+
- Never use Sequel.sqlite for DB reads; this gem only depends on extralite. Use Sequel.connect("extralite://#{db_path}") or SQLiteStore.new. Sequel.sqlite requires the ungem'd sqlite3 adapter and fails at runtime.
|
|
26
|
+
- Two distinct tool_calls tables exist: tool_calls (v3) for transcript-observed Claude Code tool usage, and mcp_tool_calls (v13) for MCP server telemetry. Disjoint purposes, never join.
|
|
27
|
+
- MCP tool-call telemetry is recorded via MCP::Telemetry wrapping Server#handle_tools_call. Writes to mcp_tool_calls table in the project DB. Swallows DB errors so telemetry never breaks a real tool response. Viewable via 'claude-memory stats --tools [--since DAYS]'.
|
|
28
|
+
- mcp_tool_calls retention is 90 days, enforced by Sweep::Maintenance#prune_old_mcp_tool_calls wired into Sweeper#run!. Configurable via mcp_tool_call_retention_days in Maintenance DEFAULT_CONFIG.
|
|
29
|
+
- CLAUDE_CONFIG_DIR env var overrides the default ~/.claude location for Configuration#global_db_path. Access via Configuration#claude_config_dir. Additive, backwards compatible.
|
|
30
|
+
- Registry::COMMANDS stores {class:, description:} entries as the single source of truth for command name, class reference, and shell-completion description. Class constants stored directly (no const_get). Registry.descriptions feeds CompletionCommand; adding a new command requires updating only this hash.
|
|
31
|
+
- Prefer do...end over braces when a block has repeated argument names, multiple expressions, or non-trivial body. Single-expression simple blocks can still use braces.
|
|
32
|
+
- EXPECTED_HOOKS constant must stay in sync with events in HooksConfigurator#build_hooks_config. Adding a new hook event without updating EXPECTED_HOOKS causes false doctor warnings.
|
|
33
|
+
- Tests using --db for hook context only set the project DB path. StoreManager still connects to the real global DB. Must stub Configuration to return a temp global path for isolation.
|
|
34
|
+
- Version must be updated in three places: lib/claude_memory/version.rb, .claude-plugin/plugin.json, .claude-plugin/marketplace.json. Runtime code uses ClaudeMemory::VERSION dynamically.
|
|
35
|
+
- Use module inclusion (not class extraction) to break up god objects — preserves public API so zero tests need modification
|
|
36
|
+
- Configuration class has instance methods only — use Configuration.new.global_db_path, not Configuration.global_db_path. Stub with instance_double + allow(Configuration).to receive(:new).and_return(config)
|
|
37
|
+
- OperationTracker.reset_stuck_operations only resets operations older than 24 hours (STALE_THRESHOLD_SECONDS). Tests must backdate started_at to trigger resets.
|
|
38
|
+
- SCHEMA_VERSION constant lives in Store::SchemaManager module but is accessible as SQLiteStore::SCHEMA_VERSION via Ruby include-based constant lookup
|
|
16
39
|
- MCP tools return dual content (text summary) + structuredContent (JSON) via TextSummary module and Server#handle_tools_call. Compact mode (compact: true) omits receipts for ~60% smaller responses.
|
|
17
40
|
- ContentSanitizer strips system-reminder, local-command-caveat, command-message, command-name, command-args tags in addition to private/no-memory/secret/claude-memory-context.
|
|
18
41
|
- Core::RelativeTime module provides progressive time formatting: just now → Xm ago → Xh ago → Xd ago → YYYY-MM-DD. Used in ResponseFormatter for *_ago fields.
|
|
19
42
|
- MCP server registers memory_guide prompt via prompts/list and prompts/get endpoints. QueryGuide module holds prompt content.
|
|
20
43
|
- Claude Code plugin with marketplace.json, skill definitions, MCP server bundling. 5,700+ stars, by Tobi Lütke. Custom fine-tuned query expansion (Qwen3-1.7B, SFT+GRPO). Dual content/structuredContent MCP pattern.
|
|
21
44
|
- Cloud-backed Claude Code plugin (~1,195 LOC JavaScript) using Supermemory API for persistent memory across sessions. Uses hooks for SessionStart context injection and Stop transcript capture. No local database.
|
|
45
|
+
|
|
46
|
+
## Technical Constraints
|
|
47
|
+
|
|
48
|
+
- **Uses framework**: rails
|
|
49
|
+
- **Deployment platform**: aws
|
|
50
|
+
- **Uses database**: sqlite
|
|
51
|
+
|
|
52
|
+
## Additional Knowledge
|
|
53
|
+
|
|
54
|
+
### Architecture
|
|
55
|
+
|
|
56
|
+
- repo: PredicatePolicy is the single source of truth for predicate vocabulary (POLICIES), cardinality, snapshot section mapping (SECTION_MAP), synonym canonicalization (SYNONYMS), and LLM guidance. tool_definitions.rb, publish.rb, and distill-transcripts.md all derive from PredicatePolicy. Never hardcode predicate names elsewhere.
|
|
57
|
+
- MCP::Tools: Thin 104-line dispatcher that includes 6 handler modules in mcp/handlers/: QueryHandlers, ShortcutHandlers, ContextHandlers, ManagementHandlers, StatsHandlers, SetupHandlers
|
|
58
|
+
- Recall: 94-line facade delegating to @engine (DualEngine or LegacyEngine), both include shared QueryCore module with all store-level query logic
|
|
59
|
+
- SQLiteStore: 386-line CRUD class that includes RetryHandler (retry/connection logic) and SchemaManager (migrations/version sync) modules
|
|
60
|
+
- Embeddings: Pluggable providers via Embeddings.resolve(name, env:). Three providers: tfidf (default), fastembed, api. Duck-typed contract: name, dimensions, generate(text). ENV: CLAUDE_MEMORY_EMBEDDING_PROVIDER
|
|
61
|
+
- Embeddings::DimensionCheck: Pure value object — DimensionCheck.call(store, provider) returns Data.define Result with :fresh/:match/:mismatch status. No side effects; caller decides how to handle mismatch.
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
## Open Conflicts
|
|
65
|
+
|
|
66
|
+
The following facts are in conflict and need resolution:
|
|
67
|
+
|
|
68
|
+
- Conflict #12: Fact 21 vs Fact 43
|
|
69
|
+
- Conflict #13: Fact 21 vs Fact 44
|
|
70
|
+
- Conflict #14: Fact 45 vs Fact 46
|
|
71
|
+
- Conflict #15: Fact 45 vs Fact 47
|
|
72
|
+
- Conflict #16: Fact 48 vs Fact 49
|
|
73
|
+
- Conflict #17: Fact 45 vs Fact 50
|
|
74
|
+
- Conflict #18: Fact 21 vs Fact 51
|
|
75
|
+
- Conflict #19: Fact 48 vs Fact 52
|
|
76
|
+
- Conflict #20: Fact 21 vs Fact 53
|
|
77
|
+
- Conflict #21: Fact 21 vs Fact 54
|
|
78
|
+
- Conflict #22: Fact 21 vs Fact 55
|
|
79
|
+
- Conflict #23: Fact 21 vs Fact 56
|
|
80
|
+
- Conflict #24: Fact 21 vs Fact 57
|
|
81
|
+
- Conflict #25: Fact 48 vs Fact 58
|
|
82
|
+
- Conflict #26: Fact 48 vs Fact 59
|
|
83
|
+
- Conflict #27: Fact 48 vs Fact 60
|
|
84
|
+
- Conflict #28: Fact 21 vs Fact 61
|
|
85
|
+
- Conflict #29: Fact 21 vs Fact 62
|
|
86
|
+
- Conflict #30: Fact 21 vs Fact 63
|
|
87
|
+
- Conflict #31: Fact 45 vs Fact 64
|
|
88
|
+
- Conflict #32: Fact 21 vs Fact 65
|
|
89
|
+
- Conflict #33: Fact 21 vs Fact 66
|
|
90
|
+
- Conflict #34: Fact 21 vs Fact 67
|
|
91
|
+
- Conflict #35: Fact 45 vs Fact 68
|
|
92
|
+
- Conflict #36: Fact 45 vs Fact 69
|
|
93
|
+
- Conflict #37: Fact 48 vs Fact 70
|
|
94
|
+
- Conflict #38: Fact 48 vs Fact 71
|
|
95
|
+
- Conflict #39: Fact 21 vs Fact 72
|
|
96
|
+
- Conflict #40: Fact 21 vs Fact 73
|
|
97
|
+
- Conflict #41: Fact 21 vs Fact 74
|
|
98
|
+
- Conflict #42: Fact 21 vs Fact 75
|
|
99
|
+
- Conflict #43: Fact 21 vs Fact 76
|
|
100
|
+
- Conflict #44: Fact 45 vs Fact 77
|
|
101
|
+
- Conflict #45: Fact 45 vs Fact 78
|
|
102
|
+
- Conflict #46: Fact 45 vs Fact 79
|
|
103
|
+
- Conflict #47: Fact 45 vs Fact 80
|
|
104
|
+
- Conflict #48: Fact 45 vs Fact 81
|
|
105
|
+
- Conflict #49: Fact 48 vs Fact 82
|
|
106
|
+
- Conflict #50: Fact 48 vs Fact 83
|
|
107
|
+
- Conflict #51: Fact 48 vs Fact 84
|
|
108
|
+
- Conflict #52: Fact 48 vs Fact 85
|
|
109
|
+
- Conflict #53: Fact 48 vs Fact 86
|
|
110
|
+
- Conflict #54: Fact 48 vs Fact 87
|
|
111
|
+
- Conflict #55: Fact 48 vs Fact 88
|
|
112
|
+
- Conflict #56: Fact 48 vs Fact 89
|
|
113
|
+
- Conflict #57: Fact 48 vs Fact 90
|
data/.claude/settings.json
CHANGED
|
@@ -5,17 +5,21 @@
|
|
|
5
5
|
"hooks": [
|
|
6
6
|
{
|
|
7
7
|
"type": "command",
|
|
8
|
-
"command": "claude-memory hook ingest",
|
|
9
|
-
"timeout": 5
|
|
8
|
+
"command": "claude-memory hook ingest --db /Users/valentinostoll/src/claude_memory/.claude/memory.sqlite3",
|
|
9
|
+
"timeout": 5,
|
|
10
|
+
"statusMessage": "Saving memory..."
|
|
10
11
|
}
|
|
11
12
|
]
|
|
12
|
-
}
|
|
13
|
+
}
|
|
14
|
+
],
|
|
15
|
+
"StopFailure": [
|
|
13
16
|
{
|
|
14
17
|
"hooks": [
|
|
15
18
|
{
|
|
16
19
|
"type": "command",
|
|
17
20
|
"command": "claude-memory hook ingest --db /Users/valentinostoll/src/claude_memory/.claude/memory.sqlite3",
|
|
18
|
-
"timeout": 5
|
|
21
|
+
"timeout": 5,
|
|
22
|
+
"statusMessage": "Saving memory..."
|
|
19
23
|
}
|
|
20
24
|
]
|
|
21
25
|
}
|
|
@@ -26,87 +30,56 @@
|
|
|
26
30
|
{
|
|
27
31
|
"type": "command",
|
|
28
32
|
"command": "claude-memory hook context",
|
|
29
|
-
"timeout": 5
|
|
33
|
+
"timeout": 5,
|
|
34
|
+
"statusMessage": "Loading memory..."
|
|
30
35
|
}
|
|
31
36
|
]
|
|
32
37
|
}
|
|
33
38
|
],
|
|
34
39
|
"PreCompact": [
|
|
35
|
-
{
|
|
36
|
-
"hooks": [
|
|
37
|
-
{
|
|
38
|
-
"type": "command",
|
|
39
|
-
"command": "claude-memory hook ingest",
|
|
40
|
-
"timeout": 30
|
|
41
|
-
},
|
|
42
|
-
{
|
|
43
|
-
"type": "command",
|
|
44
|
-
"command": "claude-memory hook sweep",
|
|
45
|
-
"timeout": 30
|
|
46
|
-
}
|
|
47
|
-
]
|
|
48
|
-
},
|
|
49
40
|
{
|
|
50
41
|
"hooks": [
|
|
51
42
|
{
|
|
52
43
|
"type": "command",
|
|
53
44
|
"command": "claude-memory hook ingest --db /Users/valentinostoll/src/claude_memory/.claude/memory.sqlite3",
|
|
54
|
-
"timeout": 30
|
|
45
|
+
"timeout": 30,
|
|
46
|
+
"statusMessage": "Saving memory..."
|
|
55
47
|
},
|
|
56
48
|
{
|
|
57
49
|
"type": "command",
|
|
58
50
|
"command": "claude-memory hook sweep --db /Users/valentinostoll/src/claude_memory/.claude/memory.sqlite3",
|
|
59
|
-
"timeout": 30
|
|
51
|
+
"timeout": 30,
|
|
52
|
+
"statusMessage": "Sweeping memory..."
|
|
60
53
|
}
|
|
61
54
|
]
|
|
62
55
|
}
|
|
63
56
|
],
|
|
64
57
|
"SessionEnd": [
|
|
65
|
-
{
|
|
66
|
-
"hooks": [
|
|
67
|
-
{
|
|
68
|
-
"type": "command",
|
|
69
|
-
"command": "claude-memory hook ingest",
|
|
70
|
-
"timeout": 30
|
|
71
|
-
},
|
|
72
|
-
{
|
|
73
|
-
"type": "command",
|
|
74
|
-
"command": "claude-memory hook sweep",
|
|
75
|
-
"timeout": 30
|
|
76
|
-
}
|
|
77
|
-
]
|
|
78
|
-
},
|
|
79
58
|
{
|
|
80
59
|
"hooks": [
|
|
81
60
|
{
|
|
82
61
|
"type": "command",
|
|
83
62
|
"command": "claude-memory hook ingest --db /Users/valentinostoll/src/claude_memory/.claude/memory.sqlite3",
|
|
84
|
-
"timeout": 30
|
|
63
|
+
"timeout": 30,
|
|
64
|
+
"statusMessage": "Saving memory..."
|
|
85
65
|
},
|
|
86
66
|
{
|
|
87
67
|
"type": "command",
|
|
88
68
|
"command": "claude-memory hook sweep --db /Users/valentinostoll/src/claude_memory/.claude/memory.sqlite3",
|
|
89
|
-
"timeout": 30
|
|
69
|
+
"timeout": 30,
|
|
70
|
+
"statusMessage": "Sweeping memory..."
|
|
90
71
|
}
|
|
91
72
|
]
|
|
92
73
|
}
|
|
93
74
|
],
|
|
94
75
|
"TaskCompleted": [
|
|
95
|
-
{
|
|
96
|
-
"hooks": [
|
|
97
|
-
{
|
|
98
|
-
"type": "command",
|
|
99
|
-
"command": "claude-memory hook ingest",
|
|
100
|
-
"timeout": 10
|
|
101
|
-
}
|
|
102
|
-
]
|
|
103
|
-
},
|
|
104
76
|
{
|
|
105
77
|
"hooks": [
|
|
106
78
|
{
|
|
107
79
|
"type": "command",
|
|
108
80
|
"command": "claude-memory hook ingest --db /Users/valentinostoll/src/claude_memory/.claude/memory.sqlite3",
|
|
109
|
-
"timeout": 10
|
|
81
|
+
"timeout": 10,
|
|
82
|
+
"statusMessage": "Saving memory..."
|
|
110
83
|
}
|
|
111
84
|
]
|
|
112
85
|
}
|
|
@@ -116,17 +89,22 @@
|
|
|
116
89
|
"hooks": [
|
|
117
90
|
{
|
|
118
91
|
"type": "command",
|
|
119
|
-
"command": "claude-memory hook ingest",
|
|
120
|
-
"timeout": 15
|
|
92
|
+
"command": "claude-memory hook ingest --db /Users/valentinostoll/src/claude_memory/.claude/memory.sqlite3",
|
|
93
|
+
"timeout": 15,
|
|
94
|
+
"statusMessage": "Saving memory..."
|
|
121
95
|
}
|
|
122
96
|
]
|
|
123
|
-
}
|
|
97
|
+
}
|
|
98
|
+
],
|
|
99
|
+
"Notification": [
|
|
124
100
|
{
|
|
101
|
+
"matcher": "idle_prompt",
|
|
125
102
|
"hooks": [
|
|
126
103
|
{
|
|
127
104
|
"type": "command",
|
|
128
|
-
"command": "claude-memory hook
|
|
129
|
-
"timeout":
|
|
105
|
+
"command": "claude-memory hook sweep --db /Users/valentinostoll/src/claude_memory/.claude/memory.sqlite3",
|
|
106
|
+
"timeout": 10,
|
|
107
|
+
"statusMessage": "Sweeping memory..."
|
|
130
108
|
}
|
|
131
109
|
]
|
|
132
110
|
}
|
data/.claude/settings.local.json
CHANGED
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: release
|
|
3
|
+
description: Prepare and publish a new gem release — bumps version across all required files, validates tests/linting/MCP server, commits, and creates the GitHub release. Use this skill when the user says "release", "publish a new version", "bump the version", "cut a release", "prepare for release", "ship it", or any variation of wanting to publish a new gem version. Also use when the user asks about the release process or what steps are needed to release.
|
|
4
|
+
agent: general-purpose
|
|
5
|
+
allowed-tools: Read, Grep, Edit, Write, Bash
|
|
6
|
+
arguments:
|
|
7
|
+
- name: version
|
|
8
|
+
description: "The new version number (e.g., '0.10.0'). If omitted, you'll be asked."
|
|
9
|
+
required: false
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Release Workflow
|
|
13
|
+
|
|
14
|
+
Automate the full release lifecycle for the ClaudeMemory gem. This workflow was codified from the actual 0.9.0 release process.
|
|
15
|
+
|
|
16
|
+
The release has three phases: **prepare** (automated), **publish** (user-driven), and **announce** (automated). The middle phase requires user action because it pushes to a shared remote and publishes to RubyGems — destructive operations that must never happen without explicit confirmation.
|
|
17
|
+
|
|
18
|
+
## Phase 1: Prepare
|
|
19
|
+
|
|
20
|
+
### Step 1: Determine the new version
|
|
21
|
+
|
|
22
|
+
If a version was passed as an argument, use it. Otherwise, read the current version from `lib/claude_memory/version.rb` and ask the user what the new version should be.
|
|
23
|
+
|
|
24
|
+
### Step 2: Find and update all version references
|
|
25
|
+
|
|
26
|
+
The version lives in exactly three files. Grep to confirm there are no others:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
grep -rn "CURRENT_VERSION" --include="*.rb" --include="*.json" --include="*.gemspec" . | grep -v "CHANGELOG\|node_modules\|vendor\|\.git/"
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Update all three:
|
|
33
|
+
|
|
34
|
+
1. **`lib/claude_memory/version.rb`** — the `VERSION` constant (canonical source)
|
|
35
|
+
2. **`.claude-plugin/plugin.json`** — the `"version"` field
|
|
36
|
+
3. **`.claude-plugin/marketplace.json`** — the `"version"` field inside the plugins array
|
|
37
|
+
|
|
38
|
+
If grep reveals any additional hardcoded references, update those too and flag them to the user as something that should be DRYed up.
|
|
39
|
+
|
|
40
|
+
### Step 3: Update Gemfile.lock
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
bundle install
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Verify both `claude_memory (X.Y.Z)` entries in Gemfile.lock match the new version.
|
|
47
|
+
|
|
48
|
+
### Step 4: Verify MCP server reports the new version
|
|
49
|
+
|
|
50
|
+
The MCP server reads `ClaudeMemory::VERSION` dynamically. Confirm it picks up the change:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}' | bundle exec claude-memory serve-mcp 2>/dev/null | grep -o '"version":"[^"]*"'
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Expected output: `"version":"X.Y.Z"` matching the new version. If it doesn't match, something is wrong with the require chain — investigate before proceeding.
|
|
57
|
+
|
|
58
|
+
### Step 5: Run the full test suite
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
bundle exec rspec
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
All tests must pass. Do not proceed with any failures. Fix them first.
|
|
65
|
+
|
|
66
|
+
### Step 6: Run the linter
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
bundle exec rake standard:fix
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Ensure no remaining violations.
|
|
73
|
+
|
|
74
|
+
### Step 7: Verify CHANGELOG.md
|
|
75
|
+
|
|
76
|
+
The CHANGELOG should already have a release section written during development (via `/improve`, manual commits, or other workflow). **Do not auto-generate release notes** — they should reflect the actual development narrative.
|
|
77
|
+
|
|
78
|
+
Check that:
|
|
79
|
+
- The `## [X.Y.Z] - YYYY-MM-DD` section exists with today's date
|
|
80
|
+
- It has Added, Changed, Fixed subsections as appropriate
|
|
81
|
+
- Upgrade Notes are included if there are breaking changes or manual migration steps
|
|
82
|
+
- The `## [Unreleased]` section above it is empty or ready for the next cycle
|
|
83
|
+
|
|
84
|
+
If the CHANGELOG section is missing or incomplete, **stop and ask the user**. Do not fabricate release notes.
|
|
85
|
+
|
|
86
|
+
### Step 8: Commit the version bump
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
git add lib/claude_memory/version.rb .claude-plugin/plugin.json .claude-plugin/marketplace.json Gemfile.lock
|
|
90
|
+
git commit -m "[Release] Bump version to X.Y.Z"
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Do NOT push yet. Report what was committed and proceed to Phase 2.
|
|
94
|
+
|
|
95
|
+
## Phase 2: Publish (User-Driven)
|
|
96
|
+
|
|
97
|
+
This phase involves pushing to a shared remote and publishing to RubyGems. These are **irreversible shared-state operations** — never execute them automatically.
|
|
98
|
+
|
|
99
|
+
Tell the user:
|
|
100
|
+
|
|
101
|
+
> Version X.Y.Z is prepared and committed locally. To publish:
|
|
102
|
+
>
|
|
103
|
+
> ```bash
|
|
104
|
+
> git push origin main
|
|
105
|
+
> rake release
|
|
106
|
+
> ```
|
|
107
|
+
>
|
|
108
|
+
> `rake release` will create the git tag, build the gem, and push to RubyGems. Let me know when that's done and I'll create the GitHub release.
|
|
109
|
+
|
|
110
|
+
Wait for the user to confirm before proceeding to Phase 3.
|
|
111
|
+
|
|
112
|
+
## Phase 3: Announce
|
|
113
|
+
|
|
114
|
+
### Step 9: Fix any stale "Latest" flags on GitHub releases
|
|
115
|
+
|
|
116
|
+
Check current release state:
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
gh release list --limit 5
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
If an older release is incorrectly marked "Latest" (this happens when releases are created out of order or with `--latest` set manually):
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
gh release edit v<old-version> --latest=false
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Step 10: Create the GitHub release
|
|
129
|
+
|
|
130
|
+
Extract the release notes from CHANGELOG.md — everything between `## [X.Y.Z]` and the next `## [` heading. Write to a temp file:
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
# Extract the section between the new version header and the next version header
|
|
134
|
+
sed -n '/^## \[X\.Y\.Z\]/,/^## \[/{ /^## \[X\.Y\.Z\]/d; /^## \[/d; p; }' CHANGELOG.md > /tmp/release-notes.md
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Create the release:
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
gh release create vX.Y.Z \
|
|
141
|
+
--title "vX.Y.Z — Short descriptive title" \
|
|
142
|
+
--latest \
|
|
143
|
+
--verify-tag \
|
|
144
|
+
--notes-file /tmp/release-notes.md
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
The title should capture the theme of the release in a few words (e.g., "Predicate Design Overhaul, Reject/Restore, Telemetry"). Read the CHANGELOG to derive this — don't ask the user unless the theme isn't obvious.
|
|
148
|
+
|
|
149
|
+
### Step 11: Verify the release
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
gh release list --limit 5
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Confirm:
|
|
156
|
+
- The new release appears at the top
|
|
157
|
+
- It's marked "Latest"
|
|
158
|
+
- No older release is incorrectly marked "Latest"
|
|
159
|
+
|
|
160
|
+
Report the release URL to the user.
|
|
161
|
+
|
|
162
|
+
## Error Handling
|
|
163
|
+
|
|
164
|
+
- **Tests fail**: Fix first. Never release with failing tests.
|
|
165
|
+
- **CHANGELOG missing**: Ask the user. Never fabricate release notes.
|
|
166
|
+
- **Version already tagged**: The tag may exist from a prior attempt. Ask the user whether to delete and recreate, or use a different version.
|
|
167
|
+
- **`gh` not available**: Tell the user to create the GitHub release manually, providing the release notes content.
|
|
168
|
+
- **`rake release` fails**: Common causes: not logged into RubyGems, tag already exists, uncommitted changes. Help the user diagnose but don't retry automatically.
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: upgrade-dependencies
|
|
3
|
+
description: "Upgrade all Ruby gem dependencies to their latest versions with release note review and codebase alignment checks. Use this skill whenever the user asks to update, upgrade, or bump dependencies, gems, or packages — even casually like 'update my gems' or 'are my deps up to date?'"
|
|
4
|
+
agent: general-purpose
|
|
5
|
+
allowed-tools: Read, Grep, Glob, Bash, Edit, Write, Agent, WebFetch
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Dependency Upgrade Skill
|
|
9
|
+
|
|
10
|
+
Systematically upgrade Ruby gem dependencies by researching latest versions, reviewing release notes for breaking changes, updating version constraints, verifying with tests, and confirming codebase alignment.
|
|
11
|
+
|
|
12
|
+
The goal is a *thoughtful* upgrade — not blindly bumping versions, but understanding what changed and ensuring the codebase is compatible. This matters because a silent API change can introduce bugs that tests don't catch if the tests don't exercise the affected code path.
|
|
13
|
+
|
|
14
|
+
## Process Overview
|
|
15
|
+
|
|
16
|
+
1. **Discover** current dependencies and their constraints
|
|
17
|
+
2. **Research** latest versions and release notes (in parallel)
|
|
18
|
+
3. **Analyze** breaking changes and codebase impact
|
|
19
|
+
4. **Upgrade** version constraints and install
|
|
20
|
+
5. **Verify** with the full test suite
|
|
21
|
+
6. **Report** a summary table with upgrade details
|
|
22
|
+
|
|
23
|
+
## Step 1: Discover Current Dependencies
|
|
24
|
+
|
|
25
|
+
Read the gemspec and Gemfile to build a complete dependency inventory.
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
Read *.gemspec → runtime dependencies (add_dependency)
|
|
29
|
+
Read Gemfile → development dependencies (gem declarations)
|
|
30
|
+
Run: bundle outdated → current vs latest versions, which are constrained
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Build a working list with these columns:
|
|
34
|
+
- **Gem name**
|
|
35
|
+
- **Source** (gemspec or Gemfile)
|
|
36
|
+
- **Current constraint** (e.g., `~> 5.0`)
|
|
37
|
+
- **Installed version** (from `bundle outdated` or `Gemfile.lock`)
|
|
38
|
+
- **Latest version** (from `bundle outdated`)
|
|
39
|
+
- **Constrained?** (is the version constraint preventing upgrade?)
|
|
40
|
+
|
|
41
|
+
## Step 2: Research Release Notes
|
|
42
|
+
|
|
43
|
+
For each gem that has a newer version available, research what changed. Launch these as parallel Agent subagents — one per gem — to avoid sequential delays.
|
|
44
|
+
|
|
45
|
+
Each research agent should:
|
|
46
|
+
|
|
47
|
+
1. Run `gem search <name> --exact --versions` to confirm the latest version
|
|
48
|
+
2. Fetch the changelog or release notes from GitHub (check CHANGELOG.md, CHANGES, HISTORY.md, or GitHub Releases)
|
|
49
|
+
3. Summarize changes between the installed version and latest version
|
|
50
|
+
4. Flag any **breaking changes**, **deprecations**, or **API changes**
|
|
51
|
+
5. Note if it's a **major version bump** (higher risk)
|
|
52
|
+
|
|
53
|
+
For transitive dependencies (not directly declared but showing in `bundle outdated`), research is optional — focus on direct dependencies. Transitive deps are upgraded automatically when their parent gem allows it.
|
|
54
|
+
|
|
55
|
+
### What to look for in release notes
|
|
56
|
+
|
|
57
|
+
- **Removed methods or classes** the codebase might use
|
|
58
|
+
- **Renamed options or changed defaults** that could silently alter behavior
|
|
59
|
+
- **New required arguments** to methods we call
|
|
60
|
+
- **Deprecated features** we rely on (working now, but will break later)
|
|
61
|
+
- **Changed return types** or data structures
|
|
62
|
+
- **Minimum Ruby version bumps** that could affect CI or deployment
|
|
63
|
+
|
|
64
|
+
## Step 3: Analyze Codebase Impact
|
|
65
|
+
|
|
66
|
+
For each gem with breaking changes or API modifications:
|
|
67
|
+
|
|
68
|
+
1. **Grep the codebase** for usage of affected APIs
|
|
69
|
+
2. **Check test coverage** — are the affected code paths tested?
|
|
70
|
+
3. **Determine if changes are needed** before or after the upgrade
|
|
71
|
+
|
|
72
|
+
Classify each upgrade:
|
|
73
|
+
|
|
74
|
+
- **Safe** — no breaking changes, or breaking changes don't affect our usage
|
|
75
|
+
- **Needs code changes** — our code uses a deprecated or removed API
|
|
76
|
+
- **Held back** — a transitive dependency constraint prevents the upgrade (explain which parent gem and why)
|
|
77
|
+
|
|
78
|
+
If code changes are needed, make them *before* bumping the version constraint so the upgrade commit is clean.
|
|
79
|
+
|
|
80
|
+
## Step 4: Upgrade Dependencies
|
|
81
|
+
|
|
82
|
+
### Gemspec dependencies (runtime)
|
|
83
|
+
|
|
84
|
+
Update version constraints to target the latest version. Use `~>` with the appropriate precision:
|
|
85
|
+
|
|
86
|
+
- For stable gems (1.0+): `~> X.Y` allows patch updates (e.g., `~> 5.102` allows 5.102.x)
|
|
87
|
+
- For pre-1.0 gems: `~> 0.X, ">= 0.X.Y"` to pin a minimum while allowing patches
|
|
88
|
+
- For gems where a specific fix matters: add `">= X.Y.Z"` as an additional constraint
|
|
89
|
+
|
|
90
|
+
### Gemfile dependencies (development)
|
|
91
|
+
|
|
92
|
+
Same approach. If a major version bump is available (e.g., lefthook 1.x → 2.x), check the migration guide before bumping.
|
|
93
|
+
|
|
94
|
+
### Install
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
bundle update
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
If `bundle update` fails due to dependency conflicts, resolve them. Common strategies:
|
|
101
|
+
- Relax an overly tight constraint
|
|
102
|
+
- Update the conflicting parent gem first
|
|
103
|
+
- Accept that a gem can't be upgraded yet and document why
|
|
104
|
+
|
|
105
|
+
## Step 5: Verify with Tests
|
|
106
|
+
|
|
107
|
+
Run the full test suite:
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
bundle exec rspec
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Also run the linter to catch any style issues:
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
bundle exec rake standard
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
If tests fail:
|
|
120
|
+
1. Read the failure carefully — is it caused by the upgrade or pre-existing?
|
|
121
|
+
2. If caused by the upgrade, fix the code to work with the new version
|
|
122
|
+
3. If unfixable, revert that specific gem's upgrade and note it in the report
|
|
123
|
+
|
|
124
|
+
## Step 6: Present Summary
|
|
125
|
+
|
|
126
|
+
Present a clear summary table of all changes:
|
|
127
|
+
|
|
128
|
+
```markdown
|
|
129
|
+
| Gem | Old Version | New Version | Old Constraint | New Constraint | Notes |
|
|
130
|
+
|-----|------------|-------------|----------------|----------------|-------|
|
|
131
|
+
| sequel | 5.100.0 | 5.102.0 | ~> 5.0 | ~> 5.102 | No breaking changes |
|
|
132
|
+
| lefthook | 1.13.6 | 2.1.4 | ~> 1.6 | ~> 2.1 | Major version bump, reviewed migration guide |
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Follow the table with:
|
|
136
|
+
|
|
137
|
+
1. **Breaking changes found** — what changed and how the codebase was updated
|
|
138
|
+
2. **Gems held back** — which gems couldn't be upgraded and why (e.g., "diff-lcs 2.0 held back by rspec's ~> 1.4 constraint")
|
|
139
|
+
3. **Notable new features** — anything worth adopting from the new versions
|
|
140
|
+
4. **Test results** — confirmation that all tests pass
|
|
141
|
+
|
|
142
|
+
## Edge Cases
|
|
143
|
+
|
|
144
|
+
### Gems with no GitHub repository
|
|
145
|
+
Fall back to `gem info <name>` and the RubyGems page for release history. Note reduced confidence in the review.
|
|
146
|
+
|
|
147
|
+
### Yanked versions
|
|
148
|
+
If `bundle update` fails because a version was yanked, try the next most recent version.
|
|
149
|
+
|
|
150
|
+
### Pre-release versions
|
|
151
|
+
Do not upgrade to pre-release or alpha versions unless the user explicitly asks. Stick to stable releases.
|
|
152
|
+
|
|
153
|
+
### Monorepo gems
|
|
154
|
+
Some gems (like rails components) are versioned together. Upgrade them as a group.
|
|
@@ -7,9 +7,9 @@
|
|
|
7
7
|
"plugins": [
|
|
8
8
|
{
|
|
9
9
|
"name": "claude-memory",
|
|
10
|
-
"version": "0.
|
|
10
|
+
"version": "0.9.1",
|
|
11
11
|
"source": "./",
|
|
12
|
-
"description": "Long-term
|
|
12
|
+
"description": "Long-term memory for Claude Code. Recalls architecture, conventions, and decisions across sessions — so Claude explains your codebase without file traversal, follows your patterns, and never re-asks what it already learned.",
|
|
13
13
|
"repository": "https://github.com/codenamev/claude_memory"
|
|
14
14
|
}
|
|
15
15
|
]
|
data/.claude-plugin/plugin.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-memory",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Long-term
|
|
3
|
+
"version": "0.9.1",
|
|
4
|
+
"description": "Long-term memory for Claude Code. Recalls architecture, conventions, and decisions across sessions — so Claude explains your codebase without file traversal, follows your patterns, and never re-asks what it already learned.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Valentino Stoll",
|
|
7
7
|
"email": "v@codenamev.com"
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"homepage": "https://github.com/codenamev/claude_memory",
|
|
10
10
|
"repository": "https://github.com/codenamev/claude_memory",
|
|
11
11
|
"license": "MIT",
|
|
12
|
-
"keywords": ["memory", "
|
|
12
|
+
"keywords": ["memory", "architecture", "conventions", "decisions", "recall", "preferences", "long-term-memory"],
|
|
13
13
|
"mcpServers": {
|
|
14
14
|
"memory": {
|
|
15
15
|
"command": "${CLAUDE_PLUGIN_ROOT}/scripts/serve-mcp.sh",
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Generic hook delegate for claude-memory.
|
|
3
|
+
# Used by the Claude Code plugin to run hook subcommands.
|
|
4
|
+
# Usage: hook-runner.sh <subcommand> [args...]
|
|
5
|
+
# Exit 0 on missing binary to avoid blocking Claude Code.
|
|
6
|
+
|
|
7
|
+
set -uo pipefail
|
|
8
|
+
|
|
9
|
+
if command -v claude-memory > /dev/null 2>&1; then
|
|
10
|
+
exec claude-memory hook "$@"
|
|
11
|
+
else
|
|
12
|
+
echo "claude-memory gem not found. Install with: gem install claude_memory" >&2
|
|
13
|
+
exit 0
|
|
14
|
+
fi
|