# Reported issues for io.github.Mibayy/token-savior

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](/mcp/io-github-mibayy-token-savior).

## 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:

```python
_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](https://github.com/Mibayy/token-savior/issues/79) · 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](https://github.com/Mibayy/token-savior/issues/100) · 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](https://github.com/Mibayy/token-savior/issues/99) · 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:

1. **Socket squatting.** Another local user can bind `/tmp/ts.sock` first. The victim's `ts` CLI and the `TS_SEARCH_COLD_DELEGATE` path silently connect to the attacker's socket and consume attacker-controlled "tool results" — context injection into the agent session

[Read the thread](https://github.com/Mibayy/token-savior/issues/98) · 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](https://github.com/Mibayy/token-savior/issues/97) · 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:

1. **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](https://github.com/Mibayy/token-savior/issues/96) · 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):

1. **Negative "omitted" count** — `omitted = len(lines) - 2 * _DEFAULT_PREVIEW_LINES` goes negative and is rendered as-is.
2. **Duplicated lines** — `head = lines[:8]` and `tail = lines[-8:]` overlap when the output has 9–16 lines, so middle lines appear twice.
3. The `if len(lines) <= _DEFAULT_PREVIEW_LINES * 2:

[Read the thread](https://github.com/Mibayy/token-savior/issues/95) · 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](https://github.com/Mibayy/token-savior/issues/88) · 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:

```python
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](https://github.com/Mibayy/token-savior/issues/77) · 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:

```python
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](https://github.com/Mibayy/token-savior/issues/76) · 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:

```python
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](https://github.com/Mibayy/token-savior/issues/75) · 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:

```python
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).
