Reported issues for io.github.Mibayy/token-savior-recall
Pod holds 22 of 40 problems reported by people outside the maintainer team. Issues filed by the project's own owners, members and collaborators are excluded entirely — a maintainer's release checklist is not a warning to a prospective user.
Back to io.github.Mibayy/token-savior-recall.
Most discussed
The two vector distance thresholds are identical, so the documented fusion/solo distinction is inert
Discussion, not a defect report
hybrid_search (src/token_savior/memory/search.py) gained a distance floor in v4.20.0, with this measurement in the comment:
les distances des voisins PERTINENTS vont de 0,85 a 0,99, celles des voisins SANS RAPPORT de 0,97 a 1,07
and then:
_DISTANCE_MAX_FUSION = 0.90
_DISTANCE_MAX_SEULE = 0.90
Taking the measurement at face value, a cut at 0.90 keeps the 0.85–0.90 slice of a relevant band that runs to 0.99. Most relevant neighbours
Read the thread · 2026-07-27 · closed · outside contributor · 3 comments
Circular import: 'import token_savior.memory.observations' fails unless memory_db was imported first
Summary
Importing token_savior.memory.observations before the memory_db facade raises ImportError:
$ python -c "import token_savior.memory.observations"
File "src/token_savior/memory/observations.py", line 13, in <module>
from token_savior import memory_db
File "src/token_savior/memory_db.py", line 138, in <module>
from token_savior.memory.observations import ( # noqa: F401
ImportError: cannot import name '_CORRUPTION_MARKERS' from partially initialized module
'token_
[Read the thread](https://github.com/Mibayy/token-savior/issues/78) · 2026-07-27 · closed · outside contributor · 1 comment
### feat(ts-init): add `--agent opencode` and `--agent kilo` support
`ts init --agent` currently supports claude/cursor/gemini/codex.
Two agents missing from the fleet:
- **OpenCode** (`npm i -g opencode-ai`) — reads `~/.config/opencode/opencode.jsonc`, MCP + hooks fields.
- **Kilo Code** (VS Code extension) — reads `~/.config/kilo/kilo.jsonc` OR `~/.kilocode/mcp.json`.
Both support PreToolUse/PostToolUse hooks in schema-similar shape to Claude Code. Adding them would let `ts init` wire hooks into a 5-agent fleet (CC + OpenCode + Kilo + Antigravity + gh-copilot
[Read the thread](https://github.com/Mibayy/token-savior/issues/43) · 2026-07-04 · closed · external user · 4 comments
### MCP Server Connection Loss
TS regularly stops working.
E.g.
● token-savior-recall - get_function_source (MCP)(name: "BatchController.resolve_image_id")
● token-savior-recall - get_function_source (MCP)(name: "BatchController.start_scan")
get called by a claude code subagent.
It seems like the MCP Server loses connection and doesn't auto reconnect.
This happened multiple times in the past couple of days.
[Read the thread](https://github.com/Mibayy/token-savior/issues/40) · 2026-07-01 · closed · external user · 2 comments
### v3.5.0–v4.0.0: shim TextContent fails CallToolResult pydantic validation — every successful tool call returns isError=True
## Summary
token-savior-recall **3.5.0 .. 4.0.0**: every *successful* MCP tool call returns `isError=True` with a pydantic `CallToolResult` validation failure. v3.4.0 is unaffected.
## Error
5 validation errors for CallToolResult content.0.TextContent Input should be a valid dictionary or instance of TextContent [type=model_type, input_value=TextContent(type='text', ...), input_type=TextContent]
## Root cause
`src/token_savior/_compat.py` defines dataclass shims `TextContent`/`T
[Read the thread](https://github.com/Mibayy/token-savior/issues/32) · 2026-05-19 · closed · external user · 3 comments
### Investigate MCP AbortError and hanging requests on Windows
## Problem
When Token Savior is used through MCP as a stdio server on Windows, some requests abort or appear to hang even though the process remains alive.
## Reproduction
1. Start Token Savior as a stdio MCP server on Windows.
2. Call a simple tool such as `get_project_summary` from an MCP client.
3. Observe that the request may abort or never complete.
## Observed behavior
- Direct manual stdio / JSON-RPC calls to the server can succeed.
- The same functionality can fail when routed through
[Read the thread](https://github.com/Mibayy/token-savior/issues/27) · 2026-04-30 · closed · external user · 3 comments
### Installation guide gaps — 4 issues encountered on fresh macOS install
First off, thanks for the project — the concept is solid and the server works well once connected.
I just did a fresh install on macOS (Apple M4, Python 3.12, Claude Code 2.1.x) following the README and hit four issues before getting `token-savior` connected. Documenting them here in case it helps other users or informs a docs update.
## 1. Quick start install is incomplete
The README quick start suggests:
pip install token-savior-recall
This installs the package but the server fails
[Read the thread](https://github.com/Mibayy/token-savior/issues/12) · 2026-04-14 · closed · external user · 1 comment
### Path traversal in checkpoint restore and edit operations allows arbitrary file writes
## Summary
Found via code audit. The MCP tool operations can write to arbitrary paths on the host filesystem.
## Bug 1: Path traversal in checkpoint restore (HIGH)
**File:** \`src/token_savior/checkpoint_ops.py\`, lines 86-106
If a crafted checkpoint directory contains files with \`../\` in their names, \`restore_checkpoint\` writes files outside the project root.
**Fix:** Validate \`dst\` starts with \`index.root_path\`:
```python
assert os.path.commonpath([dst, index.root_path]) == index.
[Read the thread](https://github.com/Mibayy/token-savior/issues/4) · 2026-04-05 · closed · external user · 2 comments
## Most recent
### MCP spec conformance: 7 requirement(s) violated (via @hasmcp/mcp-spec-test) — spec 2026-07-28
Running the black-box `@hasmcp/mcp-spec-test` conformance suite against `token-savior` (via `uvx --from token-savior-recall token-savior`) with the client requesting the newest 2026-07-28 revision shows `server/discover` returning a JSON-RPC `-32602 Invalid request parameters` error, both before and after the handshake, plus a version-less request being refused rather than served on a default. Because `server/discover` fails, the suite can't verify a further 22 checks that depend on it. This exa
[Read the thread](https://github.com/Mibayy/token-savior/issues/118) · 2026-08-24 · open · external user · 0 comments
### MCP spec conformance: 1 requirement(s) violated (via @hasmcp/mcp-spec-test) — spec 2025-11-25
Running the black-box `@hasmcp/mcp-spec-test` conformance suite against `token-savior` (via `uvx --from token-savior-recall token-savior`) on the 2025-11-25 revision — the one the server actually negotiates by default — shows one real violation: calling an unknown/nonexistent tool name returns a successful-looking `CallToolResult` (`isError: false`) with an error message embedded in the text content, instead of setting `isError: true` as the spec requires for tool-call failures. Everything else
[Read the thread](https://github.com/Mibayy/token-savior/issues/117) · 2026-08-24 · open · external user · 0 comments
### tool_capture_hook: stderr-only Bash outputs are never captured on the sandbox path
### Summary
On the sandbox path, `hooks/tool_capture_hook.py` extracts the content as:
```python
content = response.get("content") or response.get("stdout") or response.get("output") or ""
stderr is never considered. A Bash call that emits its output on stderr only — common for test runners, linters, and anything logging through stderr — produces content = "", falls under the threshold, and is never captured. The compaction path does read stderr (it passes it to compact()), so the
Read the thread · 2026-07-27 · closed · outside contributor · 0 comments
ts init: single-file dedup misses cross-scope duplicate hook registration (hooks fire twice)
Summary
ts init dedups hook entries by (matcher, command) fingerprint — but only within the settings file it is writing (src/token_savior/cli_init/merger.py). Claude Code merges hooks across scopes (~/.claude/settings.json, <project>/.claude/settings.json, settings.local.json), so the same hook registered in two scopes fires twice per event.
This is not hypothetical: I found my own setup double-firing tool_capture_hook (user scope + project scope), which double-stored every c
Read the thread · 2026-07-27 · closed · outside contributor · 0 comments
cli daemon: /tmp/ts.sock is a predictable socket in a world-writable directory
Summary
The CLI daemon socket defaults to a fixed, predictable path in a world-writable directory: /tmp/ts.sock (src/token_savior/cli.py, src/token_savior/daemon_client.py). On multi-user hosts this has two consequences:
- Socket squatting. Another local user can bind
/tmp/ts.sockfirst. The victim'stsCLI and theTS_SEARCH_COLD_DELEGATEpath silently connect to the attacker's socket and consume attacker-controlled "tool results" — context injection into the agent session
Read the thread · 2026-07-27 · closed · outside contributor · 0 comments
bash_rewriter: git diff → --stat rewrite is lossy — the patch never exists for the agent
Summary
The PreToolUse rewriter turns a bare git diff into git diff --no-color --stat=200,5 (src/token_savior/bash_rewriter/rules.py, git-diff rule). Unlike every other rule — which only adds quiet/format flags that preserve the information content — this one changes what the command produces: the agent asked for the patch and receives a diffstat. The hunks never exist anywhere, so the PostToolUse layer cannot recover them, and the model can end up reasoning about "the diff it saw
Read the thread · 2026-07-27 · closed · outside contributor · 0 comments
tool_captures: no dedup and no retention — 731 MiB in 18 days, 40% exact duplicates
Summary
tool_captures grows without bound, and identical outputs are stored multiple times. Field data from my machine after 18 days of normal use:
| Metric | Value |
|---|---|
memory.db size |
731 MiB |
| captures | 36 083 rows / 512 MiB |
exact duplicates (COUNT(*) - COUNT(DISTINCT output_full)) |
14 253 (~40 %) |
Two independent gaps:
- No dedup in
capture_put. Every call inserts blindly. In my case the hook was registered in two Claude Code settings scope
Read the thread · 2026-07-27 · closed · outside contributor · 0 comments
tool_capture: _make_preview renders negative omitted counts and duplicates lines for short-line large outputs
Summary
_make_preview in src/token_savior/memory/tool_capture.py produces a corrupted preview for outputs that are large in bytes but short in lines (> 800 bytes, ≤ 16 lines):
- Negative "omitted" count —
omitted = len(lines) - 2 * _DEFAULT_PREVIEW_LINESgoes negative and is rendered as-is. - Duplicated lines —
head = lines[:8]andtail = lines[-8:]overlap when the output has 9–16 lines, so middle lines appear twice. - The `if len(lines) <= _DEFAULT_PREVIEW_LINES * 2:
Read the thread · 2026-07-27 · closed · outside contributor · 0 comments
ts init ignores CODEX_HOME entirely, and CLAUDE_CONFIG_DIR is unreachable from the CLI
Summary
ts init ignores both agent config-root variables. CODEX_HOME is never consulted for any path, and CLAUDE_CONFIG_DIR — added in #66 for #65 — is consulted only on a code path the CLI never takes. So ts init writes hook configuration where the agent will never read it, and reports a relocated agent as not installed.
Three symptoms, one root cause.
1. CODEX_HOME is read once, and not as a path
It appears exactly once in the tree, in server_runtime._detect_client_name()
Read the thread · 2026-07-27 · closed · outside contributor · 0 comments
Discipline guard session state files accumulate in XDG_STATE_HOME and are never pruned
Summary
hooks/ts_discipline_guard.py keeps per-session state in one JSON file per session:
def state_file(session_id: str) -> Path:
base = Path(os.environ.get("XDG_STATE_HOME", Path.home() / ".local" / "state"))
d = base / "token-savior" / "discipline-guard"
d.mkdir(parents=True, exist_ok=True)
safe = re.sub(r"[^A-Za-z0-9_.-]", "_", session_id or "no-session")[:120]
return d / f"{safe}.json"
Nothing ever removes them. One file accumulates per agent sessi
Read the thread · 2026-07-27 · closed · outside contributor · 0 comments
code_mode sweep SIGKILLs a PID the closed loop no longer owns (asyncio already reaped it)
Summary
_balayer_transports_morts (src/token_savior/code_mode/sandbox.py) sends SIGKILL to a PID read off a subprocess transport whose event loop has since been closed:
pid = getattr(transport, "_pid", None)
if pid:
try:
os.kill(pid, _signal.SIGKILL)
except (ProcessLookupError, OSError, TypeError):
pass
The premise is that the Node worker behind a dead loop is still running and must be reaped. That premise does not hold: since the child watchers
Read the thread · 2026-07-27 · closed · outside contributor · 0 comments
TOKEN_SAVIOR_DATA_DIR is only honoured if set before token_savior.db_core is imported
Summary
MEMORY_DB_PATH is computed once, at import time:
MEMORY_DB_PATH = _resoudre_repertoire_donnees() / "memory.db"
TOKEN_SAVIOR_DATA_DIR and XDG_DATA_HOME are therefore only honoured if they are already set when token_savior.db_core is first imported. Anything that sets them afterwards — a test fixture, a wrapper script that configures the environment after importing the package, an embedding host that sets it per project — is silently ignored, and the memory engi
Read the thread · 2026-07-27 · closed · outside contributor · 0 comments
Discipline guard denies Edit inside node_modules/.venv/dist while allowing Read on the same path
Summary
hooks/ts_discipline_guard.py denies native Edit/Write inside vendored and generated trees, while Read on the very same path is allowed.
verdict_native_read goes through is_indexed_code, which honours TOLERATED_PATHS (node_modules, .git, dist, build, __pycache__, .venv). verdict_native_edit re-implements the check inline and skips it:
def verdict_native_edit(tool_input: dict) -> str | None:
path = str(tool_input.get("file_path") or "")
i
[Read the thread](https://github.com/Mibayy/token-savior/issues/73) · 2026-07-27 · closed · outside contributor · 0 comments
### Memory viewer 404s on archived and superseded observations, hiding the supersession audit trail
## Summary
v4.20.0 made `observation_get` exclude archived rows by default, and added `superseded_by` so that an observation made false by a newer one is *archived, never deleted* — explicitly so that "what was true in April" can still be answered and a wrong supersession can be undone.
The memory viewer's detail route was not updated, so it now returns **404 for every archived or superseded observation**:
```python
# src/token_savior/memory/viewer.py, _handle_obs
rows = memory_db.observation
[Read the thread](https://github.com/Mibayy/token-savior/issues/72) · 2026-07-27 · closed · outside contributor · 0 comments
The remaining reports are on [the project's issue tracker](https://github.com/Mibayy/token-savior/issues).