superlocalmemory 3.6.10 → 3.6.11

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 CHANGED
@@ -5,6 +5,40 @@ All notable changes to SuperLocalMemory V3 will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [3.6.11] - 2026-06-14 — Optimize Everywhere: three surfaces (proxy · MCP tools · skill)
9
+
10
+ Cache + compress across **every setup** — proxy, MCP tools, or skill. Five new MCP tools land directly inside `slm mcp` (no proxy, full 1M context window preserved). A new `slm-optimize` skill makes compression and routed-result caching zero-config for Claude Code users. Overclaim in prior docs fixed; three-surfaces table added.
11
+
12
+ ### Added — Surface B: MCP Optimize Tools (proxy-free)
13
+
14
+ Five new tools registered in `slm mcp` from v3.6.11+:
15
+
16
+ - **`slm_compress`** — compress text or tool output. `mode=normalize` is lossless whitespace normalization; `mode=auto`/`aggressive` delegates to the existing CompressRouter engine. Lossy + reversible stores the original in CCR and returns a `ccr_id`. Content >1 MB is stored unreversed. All fail-open.
17
+ - **`slm_retrieve`** — recover the exact original bytes from a `ccr_id` UUID4 returned by `slm_compress`. Validates UUID format before lookup.
18
+ - **`slm_cache_set`** — cache any string result the agent routes through SLM (file reads, bash output, search results, sub-model calls). Key is SHA-256 namespaced `mcpkv:{agent_id}:{key}` — no cross-agent collisions. TTL default 24 h.
19
+ - **`slm_cache_get`** — retrieve a cached result by key. Returns `hit:True/False`. Increments in-module `_kv_hits`/`_kv_misses` counters for stats.
20
+ - **`slm_optimize_stats`** — session compression + cache statistics. Proxy counters read from `CacheDB.metrics_load()` (daemon-persisted, accurate across restarts); KV counters are in-module for this MCP process session.
21
+
22
+ All five are **fail-open**: any internal error returns `{ok: False, note: <error>}` with the original content unchanged — never raises to the agent.
23
+
24
+ ### Added — Surface C: slm-optimize Skill (zero-config)
25
+
26
+ - **`skills/slm-optimize/SKILL.md`** and **`ide/skills/slm-optimize/SKILL.md`** — agent-behavior instruction file. Eight behavioral rules: compress CLAUDE.md at session start, compress large tool outputs via `slm_compress`, KV-cache repeated file reads and bash/search results, recover originals with `slm_retrieve`, never-compress list (secrets, JSON, code/Edit/Write outputs), emit stats on request, fail-open on `ok:False`. Compatible with Claude Code, Cursor, Antigravity, Codex, and any IDE that supports MCP tool calls.
27
+ - **`skills/slm-optimize/README.md`** — human install guide: prerequisites, install steps, activation options, feature table, and explicit "what it does NOT do" section.
28
+
29
+ ### Changed — `CacheDB` (new public method)
30
+
31
+ - **`CacheDB.get_value(cache_key, tenant_id)`** added to `optimize/storage/db.py` — pure `SELECT` lookup with no `hit_count` side-effect (unlike `get()`). Used by `slm_cache_get` to avoid inflating proxy cache counters when agents read KV entries. Fail-open: returns `None` on any SQLite/decryption/zlib error.
32
+
33
+ ### Changed — MCP server registration
34
+
35
+ - Five optimize tool names added to `_ESSENTIAL_TOOLS` frozenset in `mcp/server.py` (v3.6.11 Surface B). Without this the `_FilteredServer` wrapper silently drops tools whose names are not in the set.
36
+ - `register_optimize_tools(_target)` call added after other `register_*` calls.
37
+
38
+ ### Fixed — Overclaim in README / docs
39
+
40
+ - Replaced "Save up to 90% on every LLM API call" headline with accurate three-surfaces framing: proxy (full-turn caching on metered API), MCP tools (routed-result caching + compression), skill (auto-applied compression). Hard constraint documented: primary Claude conversation turn cannot be cached without a proxy — never implied otherwise.
41
+
8
42
  ## [3.6.10] - 2026-06-14 — Optimize correctness (cache + lossless compression) · MCP per-agent identity · runtime toggles · benchmark + shadow-capture · Issue #38
9
43
 
10
44
  This release makes the **Optimize** subsystem (the HTTP proxy that caches and compresses LLM API calls) correct, observable, and **independently controllable at runtime**, adds **per-agent identity** to the HTTP MCP transport, ships a **benchmark + shadow-capture** harness that proves the cache and compression behaviour, and fixes GitHub issue #38. Cache and compression remain **default-OFF** and are now separately toggleable from the dashboard.
package/README.md CHANGED
@@ -2,18 +2,18 @@
2
2
  <img src="https://superlocalmemory.com/assets/logo-mark.png" alt="SuperLocalMemory" width="200"/>
3
3
  </p>
4
4
 
5
- <h1 align="center">SuperLocalMemory V3.6</h1>
6
- <p align="center"><strong>Save up to 90% on every LLM API call. Cache. Compress. Remember.</strong><br/><em>The only local-first memory system that SKIPS repeat calls (100% saved), SHRINKS prompts 60-95%, and REMEMBERS everything locally, for free. For Claude Code, Cursor, Windsurf, and any AI client.</em></p>
7
- <p align="center"><code>v3.6.0 "Optimize"</code> — <strong>Cache & Compress & Align. Save up to 90% on every LLM API call — locally.</strong> One command: <code>slm wrap claude</code><br>Also includes v3.5 Scale-Ready: 6-channel recall &lt;1s, CozoDB + LanceDB, Core Memory Block. Your database auto-migrates.</p>
5
+ <h1 align="center">SuperLocalMemory V3.6.11</h1>
6
+ <p align="center"><strong>Cache. Compress. Remember. Three surfaces proxy, MCP tools, or skill. Every setup covered.</strong><br/><em>The only local-first layer that pairs persistent memory with compression + caching across every Claude plan. Full 1M window preserved in MCP and skill mode.</em></p>
7
+ <p align="center"><code>v3.6.11 "Optimize Everywhere"</code> — <strong>Compress + cache on any plan, three ways in.</strong><br/>Proxy (full-turn cache): <code>slm wrap claude</code> &nbsp;·&nbsp; MCP (proxy-free): add <code>slm_compress</code> to your MCP config &nbsp;·&nbsp; Skill (zero-config): <code>~/.claude/skills/slm-optimize/</code></p>
8
8
  <p align="center"><strong>Backed by 3 published research papers</strong> (arXiv preprints + Zenodo-archived) · <a href="https://arxiv.org/abs/2603.02240">arXiv:2603.02240</a> · <a href="https://arxiv.org/abs/2603.14588">arXiv:2603.14588</a> · <a href="https://arxiv.org/abs/2604.04514">arXiv:2604.04514</a></p>
9
9
 
10
10
  <p align="center">
11
- <code>Saves up to 90% on LLM API costs</code> &nbsp;·&nbsp; <code>+10.6pp vs Mem0 zero-LLM</code> &nbsp;·&nbsp; <code>85% Open-Domain (best zero-LLM score)</code> &nbsp;·&nbsp; <code>EU AI Act Ready</code>
11
+ <code>Proxy · MCP tools · Skill three surfaces</code> &nbsp;·&nbsp; <code>+10.6pp vs Mem0 zero-LLM</code> &nbsp;·&nbsp; <code>85% Open-Domain (best zero-LLM score)</code> &nbsp;·&nbsp; <code>EU AI Act Ready</code>
12
12
  </p>
13
13
 
14
14
  <p align="center">
15
15
  <a href="https://arxiv.org/abs/2603.14588"><img src="https://img.shields.io/badge/arXiv-2603.14588-b31b1b?style=for-the-badge&logo=arxiv&logoColor=white" alt="arXiv Paper"/></a>
16
- <a href="https://img.shields.io/badge/Saves_90%25_on_LLM_Costs-22c55e?style=for-the-badge"><img src="https://img.shields.io/badge/Saves_90%25_on_LLM_Costs-22c55e?style=for-the-badge" alt="Saves 90% on LLM Costs"/></a>
16
+ <a href="#three-surfaces-proxy--mcp-tools--skill"><img src="https://img.shields.io/badge/Proxy_|_MCP_|_Skill-22c55e?style=for-the-badge" alt="Three Surfaces: Proxy, MCP Tools, Skill"/></a>
17
17
  <a href="https://pypi.org/project/superlocalmemory/"><img src="https://img.shields.io/pypi/v/superlocalmemory?style=for-the-badge&logo=pypi&logoColor=white" alt="PyPI"/></a>
18
18
  <a href="https://www.npmjs.com/package/superlocalmemory"><img src="https://img.shields.io/npm/v/superlocalmemory?style=for-the-badge&logo=npm&logoColor=white" alt="npm"/></a>
19
19
  <a href="https://www.gnu.org/licenses/agpl-3.0"><img src="https://img.shields.io/badge/License-AGPL_v3-blue.svg?style=for-the-badge" alt="AGPL v3"/></a>
@@ -33,7 +33,9 @@
33
33
  <details>
34
34
  <summary><strong>What's New in V3.6 — Optimize: SKIP, SHRINK, DISCOUNT, REMEMBER</strong> (click to expand)</summary>
35
35
 
36
- > V3.6 is the only local-first layer that SKIPS repeat LLM calls (cache: 100% saved on a hit), SHRINKS prose prompts (compress: lossless-by-default, opt-in LLMLingua-2), and DISCOUNTS prefix costs (align: native KV-cache) — and remembers everything — in one install. **Your first cache hit pays for the install time. Hours of coding on repeat, minimal API cost.**
36
+ > V3.6 is the only local-first layer that SKIPS repeat LLM calls (cache: 100% on a hit), SHRINKS tool outputs and injected context (compress: lossless-by-default, opt-in LLMLingua-2), and DISCOUNTS prefix costs (align: native KV-cache) — and remembers everything — in one install.
37
+ >
38
+ > **v3.6.11 "Optimize Everywhere":** Three surfaces. **Proxy** (Surface A) — full-turn cache + compress on transport; needs `ANTHROPIC_BASE_URL`, shrinks the context window. **MCP tools** (Surface B) — `slm_compress`, `slm_retrieve`, `slm_cache_set`, `slm_cache_get`, `slm_optimize_stats`; no proxy, no window shrink, works on any Claude subscription. **Skill** (Surface C) — `slm-optimize` installs in `~/.claude/skills/`; zero-config auto-compress for large tool outputs and CLAUDE.md. No proxy, full 1M window. [See Three Surfaces →](#three-surfaces-proxy--mcp-tools--skill)
37
39
  >
38
40
  > **v3.6.10:** cache and compression are now **independent runtime switches** (cache-only, compress-only, both, or neither — toggle live from the dashboard, no restart). Compression was rebuilt to be **lossless by default** (the old string/array/code truncation is gone); aggressive mode adds LLMLingua-2 for **prose only** — never code, numbers, structured data, or the current turn.
39
41
 
@@ -120,6 +122,57 @@ Full docs:
120
122
 
121
123
  ---
122
124
 
125
+ ## Three Surfaces: Proxy · MCP Tools · Skill
126
+
127
+ v3.6.11 delivers one engine across **three ways in** — choose the surface that fits your setup:
128
+
129
+ | Surface | How you use it | Requires proxy? | Window effect | Cache scope |
130
+ |---------|---------------|:---------------:|:-------------:|-------------|
131
+ | **A — Proxy** | `slm wrap claude` or `ANTHROPIC_BASE_URL=http://127.0.0.1:8765` | **Yes** | Shrinks (proxy intercepts full context) | Full-turn cache — every Claude call |
132
+ | **B — MCP tools** | Add 5 tools to MCP config; call `slm_compress`, `slm_cache_set/get` | **No** | **Preserved** (full 1M) | Results you explicitly route through SLM |
133
+ | **C — Skill** | Copy `skills/slm-optimize/SKILL.md` → `~/.claude/skills/` | **No** | **Preserved** (full 1M) | Auto-applied by the agent per skill rules |
134
+
135
+ **How to choose:**
136
+ - On a **metered API** (pay-per-token) and want to cache every call → **Proxy (A)**
137
+ - On a **Pro/Max/Team subscription** or any plan where you can't or won't run a proxy → **MCP tools (B)** or **Skill (C)**
138
+ - Want zero configuration → **Skill (C)**: install once, auto-compresses CLAUDE.md and large outputs
139
+ - Want agent-controlled caching of repeated file reads and tool outputs → **MCP tools (B)**
140
+
141
+ **The hard constraint:** The primary Claude conversation turn cannot be cached without a proxy — the MCP/skill path caches results you explicitly route through SLM (tool outputs, file reads, sub-model calls).
142
+
143
+ ### MCP Tools Setup (Surface B)
144
+
145
+ Add to your `claude_desktop_config.json` or IDE MCP config alongside your existing SLM entry:
146
+
147
+ ```json
148
+ {
149
+ "mcpServers": {
150
+ "superlocalmemory": {
151
+ "command": "slm",
152
+ "args": ["mcp"]
153
+ }
154
+ }
155
+ }
156
+ ```
157
+
158
+ The 5 optimize tools (`slm_compress`, `slm_retrieve`, `slm_cache_set`, `slm_cache_get`, `slm_optimize_stats`) are included automatically from v3.6.11+. Verify with `slm_optimize_stats()`.
159
+
160
+ ### Skill Setup (Surface C)
161
+
162
+ ```bash
163
+ mkdir -p ~/.claude/skills/slm-optimize
164
+ cp $(pip show superlocalmemory | grep Location | awk '{print $2}')/superlocalmemory/skills/slm-optimize/SKILL.md \
165
+ ~/.claude/skills/slm-optimize/SKILL.md
166
+ ```
167
+
168
+ Then reference in your `CLAUDE.md`:
169
+ ```markdown
170
+ ## Context Management
171
+ Use the `slm-optimize` skill to compress large outputs and cache repeated reads.
172
+ ```
173
+
174
+ ---
175
+
123
176
  <details>
124
177
  <summary><strong>What's New in V3.3 — The Living Brain Evolves</strong> (click to expand)</summary>
125
178
 
@@ -296,6 +349,7 @@ No manual commands. No data loss. Zero downtime.
296
349
 
297
350
  | Version | Codename | Key Features |
298
351
  |---|---|---|
352
+ | **v3.6.11** | Optimize Everywhere | **Three surfaces** — Proxy (A: full-turn cache), MCP tools (B: `slm_compress`/`slm_retrieve`/`slm_cache_set`/`slm_cache_get`/`slm_optimize_stats` — proxy-free, 1M window), Skill (C: `slm-optimize` zero-config). `CacheDB.get_value()` (pure KV lookup). 23 new tests. Links: [Three Surfaces →](#three-surfaces-proxy--mcp-tools--skill) · [docs/optimize-overview.md](docs/optimize-overview.md) |
299
353
  | **v3.6.0** | Optimize | **Cache** (skip repeat calls, 100% on hit) · **Compress** (shrink prompts 60-95%) · **Align** (KV-cache stabilization) · `slm optimize\|cache\|compress\|proxy\|wrap` CLI · Live savings dashboard (USD/INR/tokens) · Hot-reload config · Safe defaults · Links: [docs/optimize-overview.md](docs/optimize-overview.md) · [V3.6 Wiki](https://github.com/qualixar/superlocalmemory/wiki/V3.6-Overview) |
300
354
  | **v3.5.0** | Scale-Ready + Context Injection v2 | CozoDB/LanceDB migration, 6-channel recall <1s, Core Memory Block, BM25→FTS5, context injection v2, score normalization |
301
355
  | **v3.4.5** | Scale-Ready (foundation) | Tiered storage (active/warm/cold), graph pruning, BackendOrchestrator scaffolding, CozoDB + LanceDB init + migration code (read path wired in v3.5.0) |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "superlocalmemory",
3
- "version": "3.6.10",
3
+ "version": "3.6.11",
4
4
  "description": "Information-geometric agent memory with mathematical guarantees. 4-channel retrieval, Fisher-Rao similarity, zero-LLM mode, EU AI Act compliant. Works with Claude, Cursor, Windsurf, and 17+ AI tools.",
5
5
  "keywords": [
6
6
  "ai-memory",
package/pyproject.toml CHANGED
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "superlocalmemory"
3
- version = "3.6.10"
3
+ version = "3.6.11"
4
4
  description = "Information-geometric agent memory with mathematical guarantees"
5
5
  readme = "README.md"
6
6
  license = {text = "AGPL-3.0-or-later"}
@@ -0,0 +1,55 @@
1
+ # slm-optimize — Context Optimizer Skill
2
+
3
+ Automatically compresses large tool outputs and caches repeated reads, reducing
4
+ context window usage without a proxy and without losing the full 1M window.
5
+
6
+ ## Prerequisites
7
+
8
+ - SuperLocalMemory v3.6.11+
9
+ - `slm mcp` daemon running
10
+ - `slm_compress` visible in `tools/list` (verify with your IDE's MCP tool inspector)
11
+
12
+ ## Install (Claude Code)
13
+
14
+ ```bash
15
+ cp skills/slm-optimize/SKILL.md ~/.claude/skills/slm-optimize/SKILL.md
16
+ ```
17
+
18
+ ## Activate
19
+
20
+ **Option A — On demand:**
21
+ Invoke via the `Skill` tool: `Skill("slm-optimize")`
22
+
23
+ **Option B — Auto-activate:**
24
+ Add to your project or global `CLAUDE.md`:
25
+ ```markdown
26
+ ## Context Management
27
+ Use the `slm-optimize` skill to compress large outputs and cache repeated reads.
28
+ Invoke at session start if context > 50k tokens.
29
+ ```
30
+
31
+ ## Verify
32
+
33
+ After activation, run `slm_optimize_stats()` from Claude Code. If it returns `ok:True`,
34
+ all 5 optimize tools are reachable and the skill is working.
35
+
36
+ ## What it does
37
+
38
+ | Feature | How |
39
+ |---|---|
40
+ | Compresses large tool outputs | `slm_compress` → compressed text + optional `ccr_id` |
41
+ | Caches repeated file reads | `slm_cache_set` / `slm_cache_get` keyed by file path |
42
+ | Caches repeated bash/search | Same KV tools, keyed by command |
43
+ | Recovers exact originals | `slm_retrieve(ccr_id)` when byte-identical content needed |
44
+ | Session stats | `slm_optimize_stats()` |
45
+
46
+ ## What it does NOT do
47
+
48
+ - **Full-turn caching**: impossible without a proxy (`ANTHROPIC_BASE_URL`).
49
+ Use Surface A (proxy mode) for that.
50
+ - **Guarantee savings**: results depend on content type and daemon compress config.
51
+
52
+ ## For Cursor, Antigravity, Codex
53
+
54
+ Same SKILL.md works — all IDEs that support MCP tool calls can use the 5 tools.
55
+ The skill itself is pure Markdown with no IDE-specific code.
@@ -0,0 +1,139 @@
1
+ ---
2
+ name: slm-optimize
3
+ description: >
4
+ Context optimizer for Claude Code + SLM. Compresses large outputs via
5
+ slm_compress (reversible CCR), caches repeated reads via slm_cache_set/get,
6
+ recovers originals via slm_retrieve. Works on any Claude plan, no proxy,
7
+ full context window preserved.
8
+ Requires SuperLocalMemory v3.6.11+ with optimize MCP tools enabled.
9
+ version: "3.6.11"
10
+ license: AGPL-3.0-or-later
11
+ triggers:
12
+ - "slm-optimize"
13
+ - "compress context"
14
+ - "optimize context"
15
+ - "reduce tokens"
16
+ ---
17
+
18
+ # slm-optimize: Context Optimizer for Claude Code
19
+
20
+ Reduces context window usage through compression and caching.
21
+ No proxy required. Full 1M window preserved.
22
+
23
+ **What this skill does NOT do:**
24
+ - Cache the primary Claude conversation turn (impossible without a proxy).
25
+ - Guarantee any specific savings percentage — results depend on content type and daemon config.
26
+
27
+ ---
28
+
29
+ ## When This Skill Is Active
30
+
31
+ Apply these rules automatically throughout the session once this skill is loaded.
32
+
33
+ ---
34
+
35
+ ## Decision Rules
36
+
37
+ ### RULE 1 — Session start: compress CLAUDE.md if large
38
+
39
+ At the start of any session where this skill is loaded:
40
+ 1. Read `CLAUDE.md` (or project CLAUDE.md).
41
+ 2. If `len(content) > 3000` characters: call `slm_compress(content=<text>, mode="normalize", reversible=False)`.
42
+ 3. Replace the in-context CLAUDE.md block with the compressed version.
43
+ 4. **Do not modify the actual file** — compress only the in-context representation.
44
+
45
+ ### RULE 2 — Large tool output: compress before processing
46
+
47
+ After any tool call that returns > 2000 characters:
48
+ 1. Call `slm_compress(content=<output>, mode="auto", reversible=True)`.
49
+ 2. Work from `compressed` in the response.
50
+ 3. If `lossy=True`, store the returned `ccr_id` — call `slm_retrieve` only if you need the exact original for verification, diffing, or code parsing.
51
+
52
+ **Never compress** (see RULE 6 for the complete exclusion list).
53
+
54
+ ### RULE 3 — Repeated file reads: KV cache
55
+
56
+ Before calling `Read(file_path)` for a file you have already read this session:
57
+ 1. `slm_cache_get(key=f"file:{file_path}")`.
58
+ 2. If `hit=True` → use `value` directly. Skip the `Read` call.
59
+ 3. If `hit=False` → call `Read`, then `slm_cache_set(key=f"file:{file_path}", value=<content>, ttl_seconds=1800)`.
60
+
61
+ If you edit a file via Edit/Write, immediately update or invalidate the cache entry.
62
+
63
+ ### RULE 4 — Repeated bash/search results: KV cache
64
+
65
+ For any Bash or WebSearch call whose result you expect to reuse:
66
+ 1. `slm_cache_set(key=f"bash:{command[:64]}", value=<output>, ttl_seconds=600)`.
67
+ 2. On the next identical call: `slm_cache_get` first.
68
+
69
+ Use `ttl_seconds=3600` for web search results (more expensive to re-run).
70
+
71
+ ### RULE 5 — Retrieve original via slm_retrieve
72
+
73
+ If you compressed content with `lossy=True` and need the exact original:
74
+ 1. Call `slm_retrieve(ccr_id=<ccr_id from prior compress response>)`.
75
+ 2. Check `size_bytes` before retrieving if context is nearly full.
76
+ 3. Do not retrieve unless you actually need byte-identical content.
77
+
78
+ ### RULE 6 — What NOT to compress or cache
79
+
80
+ - **Code being sent to Edit/Write**: never compress — the editor needs exact bytes.
81
+ - **JSON or structured data you will parse**: compression can alter whitespace and break parsers.
82
+ - **Secrets, API keys, credentials, tokens**: never store via `slm_cache_set`.
83
+ - **CCR IDs**: never cache via `slm_cache_set` — treat as ephemeral session values.
84
+ - **Very short outputs (< 500 chars)**: compression overhead exceeds the gain.
85
+
86
+ ### RULE 7 — Stats and awareness
87
+
88
+ If the user asks "how much context have you saved?" or "what is the optimization status?":
89
+ 1. Call `slm_optimize_stats()`.
90
+ 2. Report `cache_kv_hits`, `compress_runs`, and `tokens_saved_compress` clearly.
91
+ 3. Note that proxy stats are daemon-persisted; KV stats are this session only.
92
+
93
+ ### RULE 8 — Fail-open behavior
94
+
95
+ If any `slm_compress`, `slm_retrieve`, `slm_cache_set`, `slm_cache_get`, or
96
+ `slm_optimize_stats` call returns `ok:False`:
97
+ - Continue with the original (uncompressed/uncached) content.
98
+ - Do not retry. Do not surface the error unless the user asks about optimization.
99
+ - Optimization is always advisory — it must never block any primary task.
100
+
101
+ ---
102
+
103
+ ## Examples
104
+
105
+ ### Compress a large file read
106
+
107
+ ```
108
+ # Instead of working with 8000-char file output directly:
109
+ result = slm_compress(content=<file_content>, mode="auto", reversible=True)
110
+ # Work from result["compressed"]; keep result["ccr_id"] if lossy=True
111
+ ```
112
+
113
+ ### Cache a repeated grep result
114
+
115
+ ```
116
+ cached = slm_cache_get(key="bash:grep -rn MyClass src/")
117
+ if not cached["hit"]:
118
+ output = Bash("grep -rn MyClass src/")
119
+ slm_cache_set(key="bash:grep -rn MyClass src/", value=output, ttl_seconds=600)
120
+ ```
121
+
122
+ ### Recover original when needed
123
+
124
+ ```
125
+ original = slm_retrieve(ccr_id=<ccr_id>)
126
+ # original["content"] is byte-identical to what was compressed
127
+ ```
128
+
129
+ ---
130
+
131
+ ## Stats and Troubleshooting
132
+
133
+ Run `slm_optimize_stats()` to see current session counters.
134
+
135
+ If tools return `ok:False`, the daemon may be down or the optimize module may not be
136
+ configured. Continue with normal tool calls — this skill degrades gracefully.
137
+
138
+ Verify tools are available: check that `slm_compress` appears in your MCP `tools/list`.
139
+ Requires SuperLocalMemory v3.6.11+ with `slm mcp` running.
@@ -104,6 +104,8 @@ _ESSENTIAL_TOOLS: set[str] = {
104
104
  "reinforce_assertion", "contradict_assertion",
105
105
  # v3.4.11: Skill evolution (3)
106
106
  "evolve_skill", "skill_health", "skill_lineage",
107
+ # v3.6.11: Surface B Optimize tools (5)
108
+ "slm_compress", "slm_retrieve", "slm_cache_set", "slm_cache_get", "slm_optimize_stats",
107
109
  }
108
110
 
109
111
  # v3.4.4: Mesh tools — enabled if mesh_enabled in config or SLM_MCP_MESH_TOOLS=1
@@ -189,6 +191,8 @@ register_code_graph_tools(_target, get_engine) # CodeGraph: filtered like other
189
191
  register_mesh_tools(_target, get_engine) # v3.4.4: Mesh P2P tools — ships with SLM, no separate slm-mesh needed
190
192
  register_learning_tools(_target, get_engine) # v3.4.7: Two-way learning tools
191
193
  register_evolution_tools(_target, get_engine) # v3.4.11: Skill evolution tools
194
+ from superlocalmemory.mcp.tools_optimize import register_optimize_tools
195
+ register_optimize_tools(_target) # v3.6.11: Surface B Optimize tools (proxy-free)
192
196
 
193
197
 
194
198
  # V3.3.21: Eager engine warmup — start initializing BEFORE first tool call.
@@ -0,0 +1,304 @@
1
+ # Copyright (c) 2026 Varun Pratap Bhardwaj / Qualixar
2
+ # Licensed under AGPL-3.0-or-later - see LICENSE file
3
+ # Part of SuperLocalMemory V3 | https://qualixar.com | https://varunpratap.com
4
+
5
+ """SLM v3.6.11 — Surface B: MCP Optimize Tools.
6
+
7
+ Five proxy-free tools exposing compression (reversible via CCR) and
8
+ routed-result caching WITHOUT touching ANTHROPIC_BASE_URL, so the full
9
+ 1M context window is preserved on any Claude subscription.
10
+
11
+ Primary Claude conversation turns CANNOT be cached without a proxy.
12
+ These tools cache results the agent explicitly routes through SLM.
13
+
14
+ Fail-open: every tool body is wrapped in try/except Exception.
15
+ Any internal error returns the input unchanged with ok:False — never raises.
16
+ """
17
+
18
+ from __future__ import annotations
19
+
20
+ import hashlib
21
+ import logging
22
+ import threading
23
+ import time
24
+
25
+ from mcp.types import ToolAnnotations
26
+
27
+ from superlocalmemory.mcp.agent_context import get_current_agent_id
28
+ from superlocalmemory.optimize.compress.ccr import CCRStore, _UUID4_RE
29
+ from superlocalmemory.optimize.compress.router import CompressRouter
30
+ from superlocalmemory.optimize.storage.db import CacheDB, _normalize_tenant_id
31
+
32
+ logger = logging.getLogger("slm.mcp.tools_optimize")
33
+
34
+ # ─── Size caps (CWE-400 guards) ───────────────────────────────────────────────
35
+
36
+ _MAX_COMPRESS_BYTES: int = 1_000_000
37
+ _MAX_KV_VALUE_BYTES: int = 1_000_000
38
+ _MAX_KV_KEY_CHARS: int = 512
39
+
40
+ # ─── Exported tool name list (used by server.py + tests) ─────────────────────
41
+
42
+ _OPTIMIZE_TOOL_NAMES = (
43
+ "slm_compress",
44
+ "slm_retrieve",
45
+ "slm_cache_set",
46
+ "slm_cache_get",
47
+ "slm_optimize_stats",
48
+ )
49
+
50
+ # ─── In-module KV counters (thread-safe; MetricsCollector is process-scoped) ─
51
+
52
+ _kv_lock = threading.Lock()
53
+ _kv_hits: int = 0
54
+ _kv_misses: int = 0
55
+
56
+
57
+ def _tenant() -> str:
58
+ # get_current_agent_id() never returns ""; "mcp_client" is its stdio sentinel.
59
+ return get_current_agent_id()
60
+
61
+
62
+ # ─── Tool registration ────────────────────────────────────────────────────────
63
+
64
+
65
+ def register_optimize_tools(server) -> None:
66
+ """Register the 5 Surface B optimize tools on *server*.
67
+
68
+ *server* is duck-typed: must support @server.tool() decorator pattern.
69
+ Compatible with FastMCP, _FilteredServer, and test _MockServer.
70
+ """
71
+
72
+ @server.tool(annotations=ToolAnnotations(readOnlyHint=False, destructiveHint=False))
73
+ async def slm_compress(
74
+ content: str,
75
+ mode: str = "auto",
76
+ reversible: bool = True,
77
+ ttl_seconds: int = 86400,
78
+ ) -> dict:
79
+ """Compress text or tool output to reduce context window usage.
80
+
81
+ Returns compressed text. If lossy and reversible=True, also returns a
82
+ ccr_id — pass it to slm_retrieve to recover the exact original.
83
+
84
+ Args:
85
+ content: Text to compress (max 1MB).
86
+ mode: "normalize" (lossless whitespace) | "auto" | "aggressive".
87
+ reversible: Store original in CCR for later retrieval.
88
+ ttl_seconds: CCR lifetime in seconds (default 24h).
89
+ """
90
+ try:
91
+ if not isinstance(content, str) or not content:
92
+ return {
93
+ "ok": False, "compressed": content or "",
94
+ "strategy": "none", "tokens_before": 0, "tokens_after": 0,
95
+ "ratio": 1.0, "lossy": False, "ccr_id": None,
96
+ "note": "empty input",
97
+ }
98
+
99
+ note_parts: list[str] = []
100
+ if len(content.encode("utf-8")) > _MAX_COMPRESS_BYTES:
101
+ reversible = False
102
+ note_parts.append("content over 1MB: ccr skipped")
103
+
104
+ if mode == "normalize":
105
+ # @staticmethod — lossless whitespace collapse, no config/daemon dep.
106
+ normalized = CompressRouter._normalize_whitespace(content)
107
+ tb = len(content.split())
108
+ ta = len(normalized.split())
109
+ ratio = round(ta / tb, 4) if tb else 1.0
110
+ return {
111
+ "ok": True, "compressed": normalized, "strategy": "normalize",
112
+ "tokens_before": tb, "tokens_after": ta, "ratio": ratio,
113
+ "lossy": False, "ccr_id": None,
114
+ "note": " | ".join(note_parts) or None,
115
+ }
116
+
117
+ if mode == "aggressive":
118
+ note_parts.append(
119
+ "aggressive mode requires daemon compress_mode=aggressive in config"
120
+ )
121
+
122
+ res = CompressRouter.get_instance().compress_text(content)
123
+
124
+ ccr_id = None
125
+ if res.lossy and reversible:
126
+ stored = CCRStore.get_instance().store(
127
+ content.encode("utf-8"),
128
+ tenant_id=_tenant(),
129
+ ttl_seconds=ttl_seconds,
130
+ )
131
+ ccr_id = stored or None
132
+ if ccr_id:
133
+ note_parts.append("reversible: call slm_retrieve with this ccr_id")
134
+
135
+ ratio = (
136
+ round(res.tokens_after / res.tokens_before, 4)
137
+ if res.tokens_before else 1.0
138
+ )
139
+ return {
140
+ "ok": True, "compressed": res.compressed_text, "strategy": res.strategy,
141
+ "tokens_before": res.tokens_before, "tokens_after": res.tokens_after,
142
+ "ratio": ratio, "lossy": res.lossy, "ccr_id": ccr_id,
143
+ "note": " | ".join(note_parts) or None,
144
+ }
145
+
146
+ except Exception as exc:
147
+ logger.error("slm_compress failed (fail-open): %s", exc)
148
+ t = len(content.split()) if isinstance(content, str) else 0
149
+ return {
150
+ "ok": False,
151
+ "compressed": content if isinstance(content, str) else "",
152
+ "strategy": "none", "tokens_before": t, "tokens_after": t,
153
+ "ratio": 1.0, "lossy": False, "ccr_id": None,
154
+ "note": f"internal error: {exc}",
155
+ }
156
+
157
+ @server.tool(annotations=ToolAnnotations(readOnlyHint=True))
158
+ async def slm_retrieve(ccr_id: str) -> dict:
159
+ """Retrieve original text stored during a lossy slm_compress call.
160
+
161
+ Do not log or share ccr_ids — they are unguessable session tokens, but
162
+ if exposed they allow retrieval by anyone with the daemon's decryption key.
163
+
164
+ Args:
165
+ ccr_id: UUID4 returned by slm_compress when reversible=True.
166
+ """
167
+ try:
168
+ if not ccr_id or not _UUID4_RE.match(ccr_id):
169
+ return {
170
+ "ok": False, "content": None, "size_bytes": 0,
171
+ "error": "ccr_id must be a UUID4",
172
+ }
173
+ original = CCRStore.get_instance().retrieve(ccr_id)
174
+ if original is None:
175
+ return {
176
+ "ok": False, "content": None, "size_bytes": 0,
177
+ "error": "not found (expired / never stored / wrong id)",
178
+ }
179
+ size = len(original)
180
+ try:
181
+ text = original.decode("utf-8")
182
+ except UnicodeDecodeError:
183
+ text = original.decode("latin-1")
184
+ return {"ok": True, "content": text, "size_bytes": size, "error": None}
185
+
186
+ except Exception as exc:
187
+ logger.error("slm_retrieve failed (fail-open): %s", exc)
188
+ return {
189
+ "ok": False, "content": None, "size_bytes": 0,
190
+ "error": f"internal error: {exc}",
191
+ }
192
+
193
+ @server.tool(annotations=ToolAnnotations(readOnlyHint=False, destructiveHint=False))
194
+ async def slm_cache_set(key: str, value: str, ttl_seconds: int = 86400) -> dict:
195
+ """Cache a result you want to reuse (tool output, file read, search result).
196
+
197
+ This caches results the agent explicitly routes through SLM — NOT the
198
+ Claude conversation turn (impossible without a proxy).
199
+
200
+ Do not cache secrets, credentials, or ccr_ids via this tool.
201
+
202
+ Args:
203
+ key: Cache key (max 512 chars). Namespaced per agent automatically.
204
+ value: Value to store as string (max 1MB).
205
+ ttl_seconds: Time-to-live in seconds (default 24h).
206
+ """
207
+ try:
208
+ if not key or len(key) > _MAX_KV_KEY_CHARS:
209
+ return {
210
+ "ok": False, "stored": False,
211
+ "note": f"key must be 1–{_MAX_KV_KEY_CHARS} chars",
212
+ }
213
+ value_bytes = value.encode("utf-8")
214
+ if len(value_bytes) > _MAX_KV_VALUE_BYTES:
215
+ return {"ok": False, "stored": False, "note": "value exceeds 1MB limit"}
216
+
217
+ tenant = _tenant()
218
+ cache_key = hashlib.sha256(f"mcpkv:{tenant}:{key}".encode()).hexdigest()
219
+ norm_tid = _normalize_tenant_id(tenant)
220
+ ttl_exp = time.time() + ttl_seconds
221
+
222
+ CacheDB.get_default().set(
223
+ cache_key, norm_tid, value_bytes,
224
+ model="mcp-kv", ttl_expires=ttl_exp, tags=["mcp-kv"],
225
+ )
226
+ return {"ok": True, "stored": True, "note": None}
227
+
228
+ except Exception as exc:
229
+ logger.error("slm_cache_set failed (fail-open): %s", exc)
230
+ return {"ok": False, "stored": False, "note": f"internal error: {exc}"}
231
+
232
+ @server.tool(annotations=ToolAnnotations(readOnlyHint=True))
233
+ async def slm_cache_get(key: str) -> dict:
234
+ """Retrieve a previously cached result.
235
+
236
+ Returns hit:True + value if the key exists and has not expired.
237
+ Returns hit:False (never raises) on miss, expiry, or any error.
238
+
239
+ Args:
240
+ key: Cache key used in slm_cache_set.
241
+ """
242
+ global _kv_hits, _kv_misses
243
+ try:
244
+ if not key or len(key) > _MAX_KV_KEY_CHARS:
245
+ return {
246
+ "ok": False, "hit": False, "value": None,
247
+ "note": f"key must be 1–{_MAX_KV_KEY_CHARS} chars",
248
+ }
249
+ tenant = _tenant()
250
+ cache_key = hashlib.sha256(f"mcpkv:{tenant}:{key}".encode()).hexdigest()
251
+ norm_tid = _normalize_tenant_id(tenant)
252
+
253
+ blob = CacheDB.get_default().get_value(cache_key, norm_tid)
254
+ if blob is None:
255
+ with _kv_lock:
256
+ _kv_misses += 1
257
+ return {"ok": True, "hit": False, "value": None, "note": None}
258
+ with _kv_lock:
259
+ _kv_hits += 1
260
+ return {"ok": True, "hit": True, "value": blob.decode("utf-8"), "note": None}
261
+
262
+ except Exception as exc:
263
+ logger.error("slm_cache_get failed (fail-open): %s", exc)
264
+ return {
265
+ "ok": False, "hit": False, "value": None,
266
+ "note": f"internal error: {exc}",
267
+ }
268
+
269
+ @server.tool(annotations=ToolAnnotations(readOnlyHint=True))
270
+ async def slm_optimize_stats() -> dict:
271
+ """Return compression and cache statistics.
272
+
273
+ Proxy/compress stats are daemon-persisted (accurate across restarts).
274
+ KV stats are in-module counters for this MCP process session only.
275
+ """
276
+ try:
277
+ snap = CacheDB.get_default().metrics_load()
278
+ with _kv_lock:
279
+ kv_h = _kv_hits
280
+ kv_m = _kv_misses
281
+ return {
282
+ "ok": True,
283
+ "compress_runs": snap.compress_runs,
284
+ "tokens_saved_compress": snap.tokens_saved_compress,
285
+ "cache_proxy_hits": snap.hits,
286
+ "cache_proxy_misses": snap.misses,
287
+ "cache_kv_hits": kv_h,
288
+ "cache_kv_misses": kv_m,
289
+ "ccr_note": (
290
+ "CCR entry count not tracked per-session; "
291
+ "see daemon /api/v1/metrics"
292
+ ),
293
+ "note": "proxy stats are daemon-persisted; kv stats are this session only",
294
+ }
295
+ except Exception as exc:
296
+ logger.error("slm_optimize_stats failed (fail-open): %s", exc)
297
+ return {
298
+ "ok": False,
299
+ "compress_runs": 0, "tokens_saved_compress": 0,
300
+ "cache_proxy_hits": 0, "cache_proxy_misses": 0,
301
+ "cache_kv_hits": 0, "cache_kv_misses": 0,
302
+ "ccr_note": None,
303
+ "note": f"internal error: {exc}",
304
+ }
@@ -421,6 +421,30 @@ class CacheDB:
421
421
  logger.warning("CacheDB.get failed (cache miss): %s", exc)
422
422
  return None
423
423
 
424
+ def get_value(self, cache_key: str, tenant_id: str) -> bytes | None:
425
+ """Pure value lookup — no hit_count increment (unlike get()).
426
+
427
+ Used by MCP KV tools which manage their own hit/miss counters.
428
+ Caller must have already normalized tenant_id. Fail-open: returns None on error.
429
+ """
430
+ try:
431
+ rows = self._db.execute(
432
+ "SELECT value_blob, compressed FROM llmcache_entries "
433
+ "WHERE cache_key = ? AND tenant_id = ? "
434
+ "AND (ttl_expires IS NULL OR ttl_expires > ?) LIMIT 1",
435
+ (cache_key, tenant_id, time.time()),
436
+ )
437
+ if not rows:
438
+ return None
439
+ row = dict(rows[0])
440
+ plaintext = self._decrypt(row["value_blob"])
441
+ if row.get("compressed", 0):
442
+ plaintext = zlib.decompress(plaintext)
443
+ return plaintext
444
+ except (sqlite3.Error, ValueError, zlib.error) as exc:
445
+ logger.warning("CacheDB.get_value failed (fail-open): %s", exc)
446
+ return None
447
+
424
448
  def set(
425
449
  self,
426
450
  key: str,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: superlocalmemory
3
- Version: 3.6.10
3
+ Version: 3.6.11
4
4
  Summary: Information-geometric agent memory with mathematical guarantees
5
5
  Author-email: Varun Pratap Bhardwaj <admin@superlocalmemory.com>
6
6
  License: AGPL-3.0-or-later
@@ -95,18 +95,18 @@ Dynamic: license-file
95
95
  <img src="https://superlocalmemory.com/assets/logo-mark.png" alt="SuperLocalMemory" width="200"/>
96
96
  </p>
97
97
 
98
- <h1 align="center">SuperLocalMemory V3.6</h1>
99
- <p align="center"><strong>Save up to 90% on every LLM API call. Cache. Compress. Remember.</strong><br/><em>The only local-first memory system that SKIPS repeat calls (100% saved), SHRINKS prompts 60-95%, and REMEMBERS everything locally, for free. For Claude Code, Cursor, Windsurf, and any AI client.</em></p>
100
- <p align="center"><code>v3.6.0 "Optimize"</code> — <strong>Cache & Compress & Align. Save up to 90% on every LLM API call — locally.</strong> One command: <code>slm wrap claude</code><br>Also includes v3.5 Scale-Ready: 6-channel recall &lt;1s, CozoDB + LanceDB, Core Memory Block. Your database auto-migrates.</p>
98
+ <h1 align="center">SuperLocalMemory V3.6.11</h1>
99
+ <p align="center"><strong>Cache. Compress. Remember. Three surfaces proxy, MCP tools, or skill. Every setup covered.</strong><br/><em>The only local-first layer that pairs persistent memory with compression + caching across every Claude plan. Full 1M window preserved in MCP and skill mode.</em></p>
100
+ <p align="center"><code>v3.6.11 "Optimize Everywhere"</code> — <strong>Compress + cache on any plan, three ways in.</strong><br/>Proxy (full-turn cache): <code>slm wrap claude</code> &nbsp;·&nbsp; MCP (proxy-free): add <code>slm_compress</code> to your MCP config &nbsp;·&nbsp; Skill (zero-config): <code>~/.claude/skills/slm-optimize/</code></p>
101
101
  <p align="center"><strong>Backed by 3 published research papers</strong> (arXiv preprints + Zenodo-archived) · <a href="https://arxiv.org/abs/2603.02240">arXiv:2603.02240</a> · <a href="https://arxiv.org/abs/2603.14588">arXiv:2603.14588</a> · <a href="https://arxiv.org/abs/2604.04514">arXiv:2604.04514</a></p>
102
102
 
103
103
  <p align="center">
104
- <code>Saves up to 90% on LLM API costs</code> &nbsp;·&nbsp; <code>+10.6pp vs Mem0 zero-LLM</code> &nbsp;·&nbsp; <code>85% Open-Domain (best zero-LLM score)</code> &nbsp;·&nbsp; <code>EU AI Act Ready</code>
104
+ <code>Proxy · MCP tools · Skill three surfaces</code> &nbsp;·&nbsp; <code>+10.6pp vs Mem0 zero-LLM</code> &nbsp;·&nbsp; <code>85% Open-Domain (best zero-LLM score)</code> &nbsp;·&nbsp; <code>EU AI Act Ready</code>
105
105
  </p>
106
106
 
107
107
  <p align="center">
108
108
  <a href="https://arxiv.org/abs/2603.14588"><img src="https://img.shields.io/badge/arXiv-2603.14588-b31b1b?style=for-the-badge&logo=arxiv&logoColor=white" alt="arXiv Paper"/></a>
109
- <a href="https://img.shields.io/badge/Saves_90%25_on_LLM_Costs-22c55e?style=for-the-badge"><img src="https://img.shields.io/badge/Saves_90%25_on_LLM_Costs-22c55e?style=for-the-badge" alt="Saves 90% on LLM Costs"/></a>
109
+ <a href="#three-surfaces-proxy--mcp-tools--skill"><img src="https://img.shields.io/badge/Proxy_|_MCP_|_Skill-22c55e?style=for-the-badge" alt="Three Surfaces: Proxy, MCP Tools, Skill"/></a>
110
110
  <a href="https://pypi.org/project/superlocalmemory/"><img src="https://img.shields.io/pypi/v/superlocalmemory?style=for-the-badge&logo=pypi&logoColor=white" alt="PyPI"/></a>
111
111
  <a href="https://www.npmjs.com/package/superlocalmemory"><img src="https://img.shields.io/npm/v/superlocalmemory?style=for-the-badge&logo=npm&logoColor=white" alt="npm"/></a>
112
112
  <a href="https://www.gnu.org/licenses/agpl-3.0"><img src="https://img.shields.io/badge/License-AGPL_v3-blue.svg?style=for-the-badge" alt="AGPL v3"/></a>
@@ -126,7 +126,9 @@ Dynamic: license-file
126
126
  <details>
127
127
  <summary><strong>What's New in V3.6 — Optimize: SKIP, SHRINK, DISCOUNT, REMEMBER</strong> (click to expand)</summary>
128
128
 
129
- > V3.6 is the only local-first layer that SKIPS repeat LLM calls (cache: 100% saved on a hit), SHRINKS prose prompts (compress: lossless-by-default, opt-in LLMLingua-2), and DISCOUNTS prefix costs (align: native KV-cache) — and remembers everything — in one install. **Your first cache hit pays for the install time. Hours of coding on repeat, minimal API cost.**
129
+ > V3.6 is the only local-first layer that SKIPS repeat LLM calls (cache: 100% on a hit), SHRINKS tool outputs and injected context (compress: lossless-by-default, opt-in LLMLingua-2), and DISCOUNTS prefix costs (align: native KV-cache) — and remembers everything — in one install.
130
+ >
131
+ > **v3.6.11 "Optimize Everywhere":** Three surfaces. **Proxy** (Surface A) — full-turn cache + compress on transport; needs `ANTHROPIC_BASE_URL`, shrinks the context window. **MCP tools** (Surface B) — `slm_compress`, `slm_retrieve`, `slm_cache_set`, `slm_cache_get`, `slm_optimize_stats`; no proxy, no window shrink, works on any Claude subscription. **Skill** (Surface C) — `slm-optimize` installs in `~/.claude/skills/`; zero-config auto-compress for large tool outputs and CLAUDE.md. No proxy, full 1M window. [See Three Surfaces →](#three-surfaces-proxy--mcp-tools--skill)
130
132
  >
131
133
  > **v3.6.10:** cache and compression are now **independent runtime switches** (cache-only, compress-only, both, or neither — toggle live from the dashboard, no restart). Compression was rebuilt to be **lossless by default** (the old string/array/code truncation is gone); aggressive mode adds LLMLingua-2 for **prose only** — never code, numbers, structured data, or the current turn.
132
134
 
@@ -213,6 +215,57 @@ Full docs:
213
215
 
214
216
  ---
215
217
 
218
+ ## Three Surfaces: Proxy · MCP Tools · Skill
219
+
220
+ v3.6.11 delivers one engine across **three ways in** — choose the surface that fits your setup:
221
+
222
+ | Surface | How you use it | Requires proxy? | Window effect | Cache scope |
223
+ |---------|---------------|:---------------:|:-------------:|-------------|
224
+ | **A — Proxy** | `slm wrap claude` or `ANTHROPIC_BASE_URL=http://127.0.0.1:8765` | **Yes** | Shrinks (proxy intercepts full context) | Full-turn cache — every Claude call |
225
+ | **B — MCP tools** | Add 5 tools to MCP config; call `slm_compress`, `slm_cache_set/get` | **No** | **Preserved** (full 1M) | Results you explicitly route through SLM |
226
+ | **C — Skill** | Copy `skills/slm-optimize/SKILL.md` → `~/.claude/skills/` | **No** | **Preserved** (full 1M) | Auto-applied by the agent per skill rules |
227
+
228
+ **How to choose:**
229
+ - On a **metered API** (pay-per-token) and want to cache every call → **Proxy (A)**
230
+ - On a **Pro/Max/Team subscription** or any plan where you can't or won't run a proxy → **MCP tools (B)** or **Skill (C)**
231
+ - Want zero configuration → **Skill (C)**: install once, auto-compresses CLAUDE.md and large outputs
232
+ - Want agent-controlled caching of repeated file reads and tool outputs → **MCP tools (B)**
233
+
234
+ **The hard constraint:** The primary Claude conversation turn cannot be cached without a proxy — the MCP/skill path caches results you explicitly route through SLM (tool outputs, file reads, sub-model calls).
235
+
236
+ ### MCP Tools Setup (Surface B)
237
+
238
+ Add to your `claude_desktop_config.json` or IDE MCP config alongside your existing SLM entry:
239
+
240
+ ```json
241
+ {
242
+ "mcpServers": {
243
+ "superlocalmemory": {
244
+ "command": "slm",
245
+ "args": ["mcp"]
246
+ }
247
+ }
248
+ }
249
+ ```
250
+
251
+ The 5 optimize tools (`slm_compress`, `slm_retrieve`, `slm_cache_set`, `slm_cache_get`, `slm_optimize_stats`) are included automatically from v3.6.11+. Verify with `slm_optimize_stats()`.
252
+
253
+ ### Skill Setup (Surface C)
254
+
255
+ ```bash
256
+ mkdir -p ~/.claude/skills/slm-optimize
257
+ cp $(pip show superlocalmemory | grep Location | awk '{print $2}')/superlocalmemory/skills/slm-optimize/SKILL.md \
258
+ ~/.claude/skills/slm-optimize/SKILL.md
259
+ ```
260
+
261
+ Then reference in your `CLAUDE.md`:
262
+ ```markdown
263
+ ## Context Management
264
+ Use the `slm-optimize` skill to compress large outputs and cache repeated reads.
265
+ ```
266
+
267
+ ---
268
+
216
269
  <details>
217
270
  <summary><strong>What's New in V3.3 — The Living Brain Evolves</strong> (click to expand)</summary>
218
271
 
@@ -389,6 +442,7 @@ No manual commands. No data loss. Zero downtime.
389
442
 
390
443
  | Version | Codename | Key Features |
391
444
  |---|---|---|
445
+ | **v3.6.11** | Optimize Everywhere | **Three surfaces** — Proxy (A: full-turn cache), MCP tools (B: `slm_compress`/`slm_retrieve`/`slm_cache_set`/`slm_cache_get`/`slm_optimize_stats` — proxy-free, 1M window), Skill (C: `slm-optimize` zero-config). `CacheDB.get_value()` (pure KV lookup). 23 new tests. Links: [Three Surfaces →](#three-surfaces-proxy--mcp-tools--skill) · [docs/optimize-overview.md](docs/optimize-overview.md) |
392
446
  | **v3.6.0** | Optimize | **Cache** (skip repeat calls, 100% on hit) · **Compress** (shrink prompts 60-95%) · **Align** (KV-cache stabilization) · `slm optimize\|cache\|compress\|proxy\|wrap` CLI · Live savings dashboard (USD/INR/tokens) · Hot-reload config · Safe defaults · Links: [docs/optimize-overview.md](docs/optimize-overview.md) · [V3.6 Wiki](https://github.com/qualixar/superlocalmemory/wiki/V3.6-Overview) |
393
447
  | **v3.5.0** | Scale-Ready + Context Injection v2 | CozoDB/LanceDB migration, 6-channel recall <1s, Core Memory Block, BM25→FTS5, context injection v2, score normalization |
394
448
  | **v3.4.5** | Scale-Ready (foundation) | Tiered storage (active/warm/cold), graph pruning, BackendOrchestrator scaffolding, CozoDB + LanceDB init + migration code (read path wired in v3.5.0) |
@@ -283,6 +283,7 @@ src/superlocalmemory/mcp/tools_core.py
283
283
  src/superlocalmemory/mcp/tools_evolution.py
284
284
  src/superlocalmemory/mcp/tools_learning.py
285
285
  src/superlocalmemory/mcp/tools_mesh.py
286
+ src/superlocalmemory/mcp/tools_optimize.py
286
287
  src/superlocalmemory/mcp/tools_v28.py
287
288
  src/superlocalmemory/mcp/tools_v3.py
288
289
  src/superlocalmemory/mcp/tools_v33.py