# Reported issues for diffctx

Pod holds 18 of 20 GitHub reports that passed its relevance review. This can include external user reports, maintainer-confirmed bugs, and concrete feature gaps. Treat them as evidence to inspect, not a count of distinct defects.

Back to [diffctx](/mcp/diffctx).

## Most discussed

### Agents do not call diffctx_context unprompted, and get little when they do

Observed 2026-09-23 while an agent (Claude Code) worked in this repo for a whole session with the diffctx MCP server installed: it never called `diffctx_context` until the owner asked why. Two calls made afterwards, on 1.17.0:

- `cc89b04b..a320ccaf` (the session's real work: `.github/workflows/*.yml` + `uv.lock`) → **0 items**. The repo's own `.diffctx/ignore` withholds `*.yml`, `*.yaml` and `tests`, so CI/infra changes and test context are invisible here.
- `373bbf3d..f047eeae` (55 changed…

[Read the thread](https://github.com/nikolay-e/diffctx/issues/289) · 2026-09-23 · closed · 11 comments

### plugin: 1.18.0 `hook pretooluse/posttooluse` prints nothing where the CLI reports callers

**Version:** diffctx 1.18.0 release binary (the plugin's `data/bin/diffctx-1.18.0`), macOS arm64, 2026-10-01.

**Observed.** `diffctx hook pretooluse` and `diffctx hook posttooluse` print nothing, exit 0, write nothing to stderr, for every command tried — on a staged change whose impact is not empty. Same repository, same index, the CLI answers:

```
$ diffctx . --diff --mode impact -f md
diffctx impact for HEAD: 1 changed file(s), 49 caller(s) outside the diff, 43 untested
-…

[Read the thread](https://github.com/nikolay-e/diffctx/issues/323) · 2026-09-30 · closed · 4 comments

### Unprompted use is 0/260: inject a ≤2k impact table at commit/merge/push via hook instead of asking the model to call

**Summary.** A survey of 8 live agent sessions on 2026-09-29 (transcript-counted, ~260 code changes across a dozen repositories, diffctx 1.17.0 installed as plugin + CLI everywhere) found **0 unprompted calls** of `diffctx_context` or the plugin skills. Every one of the 7 calls that happened was forced by a QA checklist. Detailed tallies are on #289. This issue is the design conclusion, not more evidence.

**Why the model does not decide to call it (converging causes):**
1. The tool is deferred…

[Read the thread](https://github.com/nikolay-e/diffctx/issues/310) · 2026-09-29 · closed · 4 comments

### Self-diff impact-oracle mode (WIP patch -> callers/tests/blast radius)

> **Status 2026-09-22:** the presentation half shipped in 1.12.x (worktree input, blast-radius summary, impact groups). What remains is gated: scoring preset (Q-class), `mode=impact` (#127), latency (#134), acceptance eval (#128).

## Context
The unique wedge vs the query-seeded codegraph-MCP crowd: nobody answers questions about the patch the agent is writing *right now*. diffctx's native input is a diff; backward PPR / reverse edges already exist. Self-diff mode = agent calls diffctx on its…

[Read the thread](https://github.com/nikolay-e/diffctx/issues/135) · 2026-07-25 · closed · 4 comments

### Plugin impact hook goes silent for the rest of a session after a plugin upgrade (binary version mismatch, exit 0)

**Observed.** In one long Claude Code session (~65 commits, ~40 pushes, many of them multi-file), the plugin's PreToolUse/PostToolUse impact hook injected nothing, not once. Nothing told the agent the hook was inactive, so "no impact context" read as "nothing outside the diff".

**Why.** `hooks/diffctx-impact.sh` resolves `bin="$data/bin/diffctx-$version"`, where `$version` comes from the plugin root the session loaded at start. The plugin was upgraded 1.17.0 → 1.18.0 mid-session (the installer…

[Read the thread](https://github.com/nikolay-e/diffctx/issues/315) · 2026-09-29 · closed · 3 comments

### CLI default budget: unbounded dumps (145 KB) teach agents to skip the mandatory run

**Version:** diffctx 1.17.0, CLI `diffctx . --diff <range>` with no `--budget`.

**Observed.** Two sessions, counted from transcripts:
- a 28-file range with no `--budget` produced 145 KB (~36k tokens). The agent read only the section headers. A real bug (a gate reading a missing findings file as a clean pass) was inside the unread part and was found by hand a day later.
- the same class of range with `--budget 12000` produced 28 KB; the agent read all of it and caught a real off-by-cap bug in…

[Read the thread](https://github.com/nikolay-e/diffctx/issues/307) · 2026-09-29 · open · 3 comments

### locate on a CI YAML change returns only same-file proximity; referenced templates and sibling configs are absent

**Version:** diffctx 1.17.0 (MCP `diffctx_context`, `mode="locate"`)

**Range:** one commit in a Kubernetes/Argo infra repo that changes a single CI event-sensor YAML. It adds a second event dependency with an inline Lua filter and gives all 11 triggers an explicit `conditions:`.

**Observed:** all 142 returned items come from **the changed file itself**: 14 `changed` fragments plus 128 context fragments whose only reasons are `edge, proximity`. That is neighbouring blocks of the same YAML…

[Read the thread](https://github.com/nikolay-e/diffctx/issues/301) · 2026-09-27 · open · 3 comments

### Files excluded by .diffctx/ignore still surface as context fragments

## Observed

A path excluded via `.diffctx/ignore` is correctly dropped from `changed_files` and carries no `role: changed` — but the graph can still pull it back as a context fragment, content included.

```
repo/
  .diffctx/ignore   -> "excluded.py"
  keep.py           (changed)
  excluded.py       (changed, tracked)
```

`diffctx . --diff HEAD~1 --format yaml`:

```yaml
changed_files:
- keep.py            # correct: excluded.py is absent
fragments:
- path: keep.py
  role: changed
  ...
-…

[Read the thread](https://github.com/nikolay-e/diffctx/issues/173) · 2026-07-26 · closed · 2 comments

## Most recent

### impact/locate misses direct callers and reports tests:0 despite existing tests referencing the changed class

## Summary

On a Java Maven repo, `diffctx_context` (engine 1.18.2, build f5e2a42e) for diff `HEAD~1..HEAD` missed the direct call sites of the changed class entirely and reported `summary.tests = 0` even though test classes referencing the changed class exist in the repo.

## Environment

- diffctx 1.18.2 via MCP (`uvx --from 'diffctx[mcp]' diffctx-mcp`)
- Call: `diffctx_context(repo_path=..., diff_ref omitted, mode default)` — the repo had a clean tree, so HEAD was used; effective range was…

[Read the thread](https://github.com/nikolay-e/diffctx/issues/335) · 2026-10-02 · open · external user · 0 comments

### `diffctx-mcp` lacks `--version`/`-v` despite exposing package version to MCP clients

## Summary

`diffctx-mcp` rejects `--version` even though the main CLI supports version reporting and the MCP server already imports `diffctx.version.__version__` and injects it into the MCP server metadata.

Observed on **diffctx 1.18.2**.

## Reproduction

```bash
diffctx --version
diffctx-mcp --version
```

Observed:

```text
diffctx 1.18.2
usage: diffctx-mcp [-h]
diffctx-mcp: error: unrecognized arguments: --version
```

The MCP server itself is installed and functional; only the executable…

[Read the thread](https://github.com/nikolay-e/diffctx/issues/334) · 2026-10-02 · open · 0 comments

### Plain `diffctx` install exposes `diffctx-mcp` executable that crashes without MCP extras

## Summary

Installing the base package creates both `diffctx` and `diffctx-mcp` console scripts, but the latter is not runnable unless the optional `mcp` extra was installed. The result is a published executable that fails immediately with a Python traceback.

Observed on **diffctx 1.18.2** on macOS arm64.

## Reproduction

```bash
uv tool install --force 'diffctx@latest'
diffctx --version
diffctx-mcp --help
```

Base CLI succeeds:

```text
diffctx 1.18.2
```

MCP entrypoint fails because its…

[Read the thread](https://github.com/nikolay-e/diffctx/issues/333) · 2026-10-02 · open · 0 comments

### impact: an import-only fragment is listed as a caller and counted UNTESTED

**Version:** diffctx 1.18.0, `diffctx . --diff 0d75e73a..ae7b4886 --mode impact -f md` on this repository (the 1.18.0 epoch: 53 changed files).

**Observed.** Under `src/diffctx/mcp/server.py::diffctx_context` the impact lists

```
- called from src/diffctx/mcp/legacy.py:1-28 — UNTESTED
```

Lines 1-28 of that file are the module docstring and the import block; nothing there calls `diffctx_context`. The import edge from the language builder reaches the changed symbol, the fragment has no symbol…

[Read the thread](https://github.com/nikolay-e/diffctx/issues/316) · 2026-09-29 · closed · 1 comment

### plugin: identical impact block injected five times in one commit sequence

**Version:** diffctx 1.17.0, Claude Code plugin hooks, 2026-09-29.

**Observed:** in one commit sequence on an unchanged working tree the plugin injected the same impact block five times, ~1.5k tokens each, byte-identical apart from the range label (`HEAD` vs `HEAD..<index sha>`):
- PostToolUse after `git status --short`
- PostToolUse after `git diff --cached --numstat`
- PostToolUse after `git add -A && git diff --cached --stat`
- PreToolUse before `git commit` (failed on a formatter hook)
-…

[Read the thread](https://github.com/nikolay-e/diffctx/issues/314) · 2026-09-29 · closed · 1 comment

### Kotlin files are all 'unparsed': locate returns text excerpts only, confidence 0.09

**Observed** (diffctx 1.17.0, build bf723ad0, MCP `diffctx_context`, `mode=locate`, `budget_tokens=6000`) on a one-commit range in a Kotlin/Spring backend: 11 changed files, 10 of them `.kt`.

- `coverage.unparsed_files` lists **all 10** Kotlin files; `confidence` is **0.09**.
- Every changed Kotlin fragment comes back as `kind: excerpt` or `chunk` with `score: 0.0` — no function/class fragments, no symbol-level edges.
- The context that would have explained the change was reachable only…

[Read the thread](https://github.com/nikolay-e/diffctx/issues/303) · 2026-09-29 · open · 1 comment

### --diff drops a file the range deletes: no fragment, no deletion marker

Observed with `diffctx . --diff 6ff54b5f..25f66008` on nikolay-e/yay-tsa (diffctx from `$PATH`, 2026-09-28).

`git diff --name-only` lists 34 files; the context covers 33. The one missing is a file the range **deletes outright**: `apps/backend/infra-karaoke-worker/src/main/kotlin/dev/yaytsa/worker/karaoke/KaraokePriorityQueue.kt` (0 insertions, 70 deletions). There is no fragment for it and no line saying it was removed.

A deletion is part of what a change does. Here the removed class held the…

[Read the thread](https://github.com/nikolay-e/diffctx/issues/302) · 2026-09-28 · closed · 1 comment

### locate: serialized response is ~3x budget_tokens and overflows the MCP client on a one-file commit

**Version:** diffctx 1.17.0 (MCP `diffctx_context`, Claude Code plugin)

**Command:** `diffctx_context(repo_path=<infra repo>, diff_ref=<sha>^..<sha>, mode="locate")`, all other arguments at their defaults (`budget_tokens=8000`, `max_tokens=25000`).

**Range:** one commit that changes a single 800-line YAML file: 14 changed lines (a new event dependency and a `conditions:` line on 11 triggers).

**Observed:** the result has 142 items whose `tokens` add up to **7,879**, which is inside the…

[Read the thread](https://github.com/nikolay-e/diffctx/issues/300) · 2026-09-27 · open · 1 comment

### diffctx_context returns a JSON string, so MCP clients get the locate document double-encoded in {"result": ...}

`diffctx_context` is declared `-> str` and returns `json.dumps(doc)` (`mcp/server.py:142`). FastMCP wraps a string return as structured output `{"result": "<string>"}`, so the client receives the locate document JSON-encoded inside a JSON string:

```
{"result":"{\"schema\":\"diffctx.locate.v1\",\"name\":\"...\",\"items\":[{\"path\":\"src/...\", ...
```

Every quote is escaped once more, so the payload costs more tokens than the document itself, and a model has to mentally decode it before it…

[Read the thread](https://github.com/nikolay-e/diffctx/issues/292) · 2026-09-25 · closed · 0 comments

### MCP server breaks after an in-place upgrade: lazy imports hit the new package tree

Observed 2026-09-26: `uv tool install --force "diffctx[mcp]@latest"` (1.16.0 → 1.17.0) while a Claude Code session held the MCP server (`diffctx mcp`) open. The next `diffctx_context` call failed with:

```
Error executing tool diffctx_context: No module named 'diffctx.tokens'
```

The running process kept the 1.16.0 modules it had already imported, but the tool body imports lazily (`from diffctx.tokens import count_tokens` in `mcp/server.py:81`, `from .fetch import fetch_result` at :254, `from…

[Read the thread](https://github.com/nikolay-e/diffctx/issues/291) · 2026-09-25 · closed · 0 comments

The remaining reports are on [the project's issue tracker](https://github.com/nikolay-e/diffctx/issues).
