Reported issues for token-savior-recall
Pod holds 22 of 41 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 token-savior-recall.
Most discussed
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.jsoncOR~/.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 · 2026-07-04 · closed · external user · 4 comments
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
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 · 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
- Start Token Savior as a stdio MCP server on Windows.
- Call a simple tool such as
get_project_summaryfrom an MCP client. - 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 · 2026-04-30 · closed · external user · 3 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 · 2026-07-01 · closed · external user · 2 comments
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`:
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
### 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
Read the thread · 2026-07-27 · closed · outside contributor · 1 comment
CHANGELOG.md, GitHub Releases and PIP package are out of sync
- Latest PIP package is 4.4.1
- Latest GitHub Release (and tag) is 4.0.0
- Latest release according to CHANGELOG.md is 4.8.0
Not sure what's up here, but it would be nice if releases could be kept in-sync-ish
Read the thread · 2026-07-13 · closed · outside contributor · 1 comment
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 · 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 · 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:
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).