diffctx 1.18.3__tar.gz → 1.18.4__tar.gz
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.
- {diffctx-1.18.3 → diffctx-1.18.4}/CHANGELOG.md +137 -1
- {diffctx-1.18.3 → diffctx-1.18.4}/Cargo.lock +1 -1
- diffctx-1.18.4/PKG-INFO +135 -0
- diffctx-1.18.4/README.md +75 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/Cargo.toml +1 -1
- diffctx-1.18.4/crates/diffctx-native/README.md +75 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/bindings.rs +271 -82
- diffctx-1.18.4/crates/diffctx-native/src/change_class.rs +637 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/core.rs +32 -3
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/base.rs +162 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/config_edges/generic.rs +40 -7
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/history/cochange.rs +25 -25
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/mod.rs +187 -20
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/nim.rs +51 -12
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/nix.rs +14 -2
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/ocaml.rs +14 -1
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/ruby.rs +31 -3
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/fragmentation.rs +2 -1
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/git.rs +210 -44
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/graph_export.rs +113 -9
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/hook.rs +1315 -286
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/impact.rs +1421 -163
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/in_memory_harness.rs +3 -1
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/interval.rs +12 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/main.rs +48 -3
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/pipeline.rs +346 -111
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/postpass.rs +33 -24
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/pybridge.rs +47 -8
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/render.rs +26 -21
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/resource.rs +5 -5
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/select.rs +226 -31
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/utility/objective.rs +2 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/pyproject.toml +7 -8
- {diffctx-1.18.3 → diffctx-1.18.4}/src/diffctx/_app.py +75 -27
- {diffctx-1.18.3 → diffctx-1.18.4}/src/diffctx/_diffctx.pyi +3 -3
- {diffctx-1.18.3 → diffctx-1.18.4}/src/diffctx/_native/graph_export.py +6 -6
- {diffctx-1.18.3 → diffctx-1.18.4}/src/diffctx/cli.py +19 -9
- {diffctx-1.18.3 → diffctx-1.18.4}/src/diffctx/mcp/legacy.py +7 -4
- {diffctx-1.18.3 → diffctx-1.18.4}/src/diffctx/mcp/server.py +44 -20
- diffctx-1.18.4/src/diffctx/version.py +1 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/src/diffctx/writer.py +2 -1
- diffctx-1.18.3/PKG-INFO +0 -372
- diffctx-1.18.3/README.md +0 -312
- diffctx-1.18.3/crates/diffctx-native/README.md +0 -312
- diffctx-1.18.3/crates/diffctx-native/src/change_class.rs +0 -169
- diffctx-1.18.3/src/diffctx/version.py +0 -1
- {diffctx-1.18.3 → diffctx-1.18.4}/Cargo.toml +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/LICENSE +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/analytics.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/candidate_files.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/config/analytics.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/config/bm25.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/config/budget.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/config/category_weights.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/config/edge_weights.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/config/env_overrides.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/config/extensions.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/config/filtering.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/config/fragmentation.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/config/git.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/config/graph_filtering.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/config/importance.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/config/limits.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/config/mod.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/config/mode.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/config/needs.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/config/parsers.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/config/render.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/config/scoring.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/config/selection.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/config/tokenization.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/config/weights.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/container.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/discovery.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/config_edges/build_system.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/config_edges/cicd.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/config_edges/docker.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/config_edges/helm.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/config_edges/kubernetes.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/config_edges/mod.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/document/mod.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/history/mod.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/ansible.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/bazel.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/c_family.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/cargo_edges.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/clojure.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/css.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/dart.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/dbt.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/dotnet.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/elixir.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/erlang.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/go.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/graphql.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/haskell.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/javascript.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/julia.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/jvm.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/latex.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/lua.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/mod.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/openapi.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/perl.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/php.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/prisma.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/protobuf.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/python.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/r_lang.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/rust_lang.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/shell.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/sql.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/swift.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/tags.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/terraform.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/zig.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/similarity/lexical.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/similarity/mod.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/structural/containment.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/structural/mod.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/structural/sibling.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/structural/testing.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/effective_config.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/excerpt.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/facts/mod.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/facts/scala.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/filtering.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/graph.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/languages.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/lib.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/locate.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/mode.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/parsers/config_parser.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/parsers/generic.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/parsers/markdown.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/parsers/mod.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/parsers/tree_sitter_strategy.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/paths.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/peak_rss.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/ppr.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/project_graph.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/provenance.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/run_provenance.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/sanitize.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/scoring.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/signatures.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/source.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/stopwords/code.txt +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/stopwords/docs.txt +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/stopwords.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/test_rng.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/testfiles.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/token_corpus.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/tokenizer.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/types.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/utility/boltzmann.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/utility/importance.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/utility/mod.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/utility/needs.rs +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/rust-toolchain.toml +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/src/diffctx/__init__.py +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/src/diffctx/__main__.py +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/src/diffctx/_native/__init__.py +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/src/diffctx/_native/graph_analytics.py +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/src/diffctx/_native/pipeline.py +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/src/diffctx/_native/project_graph.py +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/src/diffctx/clipboard.py +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/src/diffctx/ignore.py +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/src/diffctx/logger.py +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/src/diffctx/mcp/__init__.py +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/src/diffctx/mcp/__main__.py +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/src/diffctx/mcp/fetch.py +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/src/diffctx/mcp/launch.py +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/src/diffctx/mcp/security.py +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/src/diffctx/py.typed +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/src/diffctx/tokens.py +0 -0
- {diffctx-1.18.3 → diffctx-1.18.4}/src/diffctx/tree.py +0 -0
|
@@ -7,6 +7,141 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [1.18.4] - 2026-10-07
|
|
11
|
+
|
|
12
|
+
### Security
|
|
13
|
+
|
|
14
|
+
- Impact no longer names a file the run withholds (`.diffctx/ignore`, a
|
|
15
|
+
secret name): a definition removed from it, its deletion or its rename
|
|
16
|
+
reached the answer while pack reported only a withheld count.
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
|
|
20
|
+
- The MCP server runs on the MCP Python SDK 2.3 (`mcp>=2.3,<3`): it answers
|
|
21
|
+
the `server/discover` probe Claude Code opens with, instead of rejecting it
|
|
22
|
+
with 31 validation errors on every connect, and still accepts every
|
|
23
|
+
`initialize` revision back to 2024-11-05 (#366).
|
|
24
|
+
- `ChangeClass` gains `layout`: a file whose diff changes only whitespace,
|
|
25
|
+
comments, quote style, trailing commas, semicolons or import order. Pack
|
|
26
|
+
ranks it with `mechanical` (#370).
|
|
27
|
+
- `diffctx graph --level file|directory` now applies to `-f json`, `-f
|
|
28
|
+
graphml` and the `--summary` counts; without `--level` they stay per
|
|
29
|
+
fragment (#352).
|
|
30
|
+
|
|
31
|
+
### Fixed
|
|
32
|
+
|
|
33
|
+
- Plugin hook: the commit is previewed as the index it will start from — the
|
|
34
|
+
line's own `git add`/`git rm` replayed on a copy of the index, `-a`, a
|
|
35
|
+
pathspec with `--only` semantics, `-i`, `--amend`, a first commit, a linked
|
|
36
|
+
worktree — instead of the whole working tree; a here-document message is no
|
|
37
|
+
pathspec; a multi-commit cherry-pick is reviewed whole; `cd ~/repo` is
|
|
38
|
+
followed; a diff written to a file is no inspection; an empty answer stays
|
|
39
|
+
empty after the commit lands (#384, #373, #380, #377). The session hint
|
|
40
|
+
names `--symbol` again (#379).
|
|
41
|
+
- Impact: the header counts every caller its lines call untested, says
|
|
42
|
+
"callers unresolved" instead of "0 caller(s)" when no binding model could
|
|
43
|
+
resolve them, says when the run stopped early, and counts changed
|
|
44
|
+
definitions no test reaches (#386, #387, #335). A caller registered by a
|
|
45
|
+
decorator (`@register_node`, `@app.route`) is no longer called untested
|
|
46
|
+
(#388). Adding fields or parameters with defaults collapses the call sites
|
|
47
|
+
into one signature-compatible line (#388); formatting- or comment-only edits
|
|
48
|
+
are no contract and list no callers (#370). An unchanged caller in a changed
|
|
49
|
+
file is listed (#362). `pub` inside a `pub(crate)` module is no public API
|
|
50
|
+
(#359); a script named for a schema is no schema contract (#374). A deleted
|
|
51
|
+
path is matched by its path, a relative path, its module name or a
|
|
52
|
+
basename no other file has, never by a bare word (#369, #383). A removed
|
|
53
|
+
member and the remaining `?.()` calls to it are reported (#367).
|
|
54
|
+
- Impact on a large changed module took 74 s on one core; per-file indexes and
|
|
55
|
+
memoized test links bring it to 4 s with byte-identical output (#385). The
|
|
56
|
+
Python CLI's watchdog waits the binary's 30 s grace past `--timeout`, so a
|
|
57
|
+
run that stops at its deadline answers partially instead of exiting 124
|
|
58
|
+
with nothing (#382).
|
|
59
|
+
- MCP: `diff_ref="HEAD"` is documented as the uncommitted work, and a clean
|
|
60
|
+
tree answers with the hint that `HEAD~1..HEAD` is the last commit (#368).
|
|
61
|
+
- Selection: changed code is placed by evidence tier (production, tests,
|
|
62
|
+
config and docs, mechanical or layout edits, generated files) and by how
|
|
63
|
+
densely each piece carries the change, not cheapest-first; a core the
|
|
64
|
+
first pass could only place as its signature stub gets its body when the
|
|
65
|
+
difference fits (#296, #327). A Django migration ("Generated by Django")
|
|
66
|
+
is no longer a generated file ranked last (#311).
|
|
67
|
+
- Graph: a range's own commits no longer vouch for its files in the
|
|
68
|
+
co-change channel, which now links two files once, representative to
|
|
69
|
+
representative (#340). The tags fallback no longer links files of a
|
|
70
|
+
language its own builder parsed (a stdlib module name, a keyword); a key
|
|
71
|
+
most config files carry (`workflow_dispatch` in every CI workflow) links
|
|
72
|
+
no source file to all of them (#286, #297); a setting spelled whole
|
|
73
|
+
(`database_url` in two of four environment files) still links its reader.
|
|
74
|
+
A bare `--diff X` or a time window reads history only up to its base.
|
|
75
|
+
- Imports that spell paths resolve through one rule — next to the importing
|
|
76
|
+
file, then from the root, `..` folded: Nim `import vendor/palette`, Nix
|
|
77
|
+
`import ../vendor/palette.nix` (and a directory's `default.nix`), Ruby
|
|
78
|
+
`require_relative`; OCaml `open Palette` links `palette.ml` (#285). A
|
|
79
|
+
TypeScript import resolves with the nearest `tsconfig*.json`, its relative
|
|
80
|
+
`extends` folded in, not only the root one (#372).
|
|
81
|
+
- Plugin hook: `merge --squash`, `merge -S` and `cherry-pick -S` keep their
|
|
82
|
+
target; a pathspec commit previews the paths the index knows, never an
|
|
83
|
+
untracked file under them; `git apply`, `update-index`, `read-tree` and
|
|
84
|
+
the like before a commit preview the working tree; a step in another
|
|
85
|
+
repository stages nothing; the preview reads a copy of the index, so a
|
|
86
|
+
held index lock neither blocks it nor is taken; a first commit is checked
|
|
87
|
+
once it lands; a manual run that found nothing leaves no reminder;
|
|
88
|
+
`git status && git diff --cached` reviews the index; the `impact_gate`
|
|
89
|
+
option no longer silences PostToolUse answers; merging the branch's own
|
|
90
|
+
upstream (`git merge --ff-only origin/main`) is silence.
|
|
91
|
+
- Impact: a definition moved to another module names the importers of the
|
|
92
|
+
old one; removed methods are found in classes split into fragments, and
|
|
93
|
+
`def self.x`, `func (r T) x`, `const x = () =>` name `x`; a deletion below
|
|
94
|
+
a definition does not change it; a lexical test or caller link stops at
|
|
95
|
+
a sibling project's manifest; a function nested in another has callers
|
|
96
|
+
only inside it, and an untyped `x.name` attribute read is no possible
|
|
97
|
+
caller. Formatting-only detection keeps a docstring
|
|
98
|
+
that is not one, and no longer calls a change layout when it moves a line
|
|
99
|
+
out of its Python or YAML block, drops a one-element tuple's comma, edits
|
|
100
|
+
a mid-word `#` (`${#a}`), or removes a `;` before a line starting with `(`
|
|
101
|
+
or `[` in JS/TS. Compatible extension requires the new field to be
|
|
102
|
+
appended, and a relative path to a moved file is a stale reference.
|
|
103
|
+
- `--symbol` accepts `Owner.name`, `Owner::name` and dotted names; a
|
|
104
|
+
malformed one exits 2 in both CLIs, and over MCP a malformed or unknown
|
|
105
|
+
symbol is a refusal the agent can read, not "Error executing tool"; a
|
|
106
|
+
name in more than 256 files keeps its definition past the cap.
|
|
107
|
+
- The Python budget fitter drops a `layout` witness with `mechanical` ones
|
|
108
|
+
and ranks `unknown` with content, as the native CLI does.
|
|
109
|
+
- Release: post-publish smokes wait until both pip and uv resolve the version
|
|
110
|
+
and fail with a named error after 10 minutes; dispatched runs are found by
|
|
111
|
+
dispatch time (#364).
|
|
112
|
+
- Plugin hook: a path git cannot hash (an untracked nested repository, a
|
|
113
|
+
moved submodule) no longer turns the answer into silence logged as
|
|
114
|
+
"clean"; a multi-commit cherry-pick touching a non-UTF-8 file is reviewed;
|
|
115
|
+
a `cd` that a search printed is not taken for where it ran. `--diff staged`
|
|
116
|
+
writes a copy of the index, so a held `index.lock` is no "unmerged entries?".
|
|
117
|
+
- Impact: a Rust type and its `impl` blocks are one definition with its
|
|
118
|
+
callers, a trait method is reached through its trait (`Display`, not
|
|
119
|
+
`std`), and an unresolved name counts definitions, not "files" (#403).
|
|
120
|
+
Python `//` hides no call; a root `"baseUrl": "."` resolves bare
|
|
121
|
+
specifiers and overlapping `paths` take the longest prefix (#414). A
|
|
122
|
+
non-ASCII path, a `diff.context` setting, a deleted call statement, a
|
|
123
|
+
deletion right under a caller, a column-0 line removed from a body and a
|
|
124
|
+
call still naming a moved Rust function's old module no longer hide or
|
|
125
|
+
invent callers; a body call gaining an argument and an added `__slots__`
|
|
126
|
+
are not signature-compatible; `pub mod r#type;` and an attributed
|
|
127
|
+
`pub mod` are public; a same-language sibling module importing the
|
|
128
|
+
qualified name keeps its test link. `--symbol Owner.name` answers only for
|
|
129
|
+
that owner, and `PATH:Owner::name` parses. A call spread into an object
|
|
130
|
+
(`...workboxPolicy({..})`) is a call, not a member access: four Vite
|
|
131
|
+
configs read as zero callers.
|
|
132
|
+
- Impact counts the files the run withholds instead of reading them as
|
|
133
|
+
nothing: the header says `N more withheld by ignore rules` for a range and
|
|
134
|
+
`N file(s) naming it withheld` for `--symbol`, and that their calls and
|
|
135
|
+
tests were not read (`withheld_files` in the JSON) (#392).
|
|
136
|
+
- Impact: a definition moved within its file with its text unchanged lists
|
|
137
|
+
no callers, as a formatting-only edit does; moved and edited, it still
|
|
138
|
+
does. `@value.setter`, `@attr.s`, `@define`, `@enum.unique` and Lombok
|
|
139
|
+
annotations shape a definition and register it nowhere, so an untested
|
|
140
|
+
setter reads untested instead of "registered by" (#414).
|
|
141
|
+
- The CLI and the MCP server report only the engine's own "nothing defines
|
|
142
|
+
it" as a refusal; a `KeyError` or `IndexError` is an internal error with its
|
|
143
|
+
traceback. Git output is decoded as UTF-8 on every platform.
|
|
144
|
+
|
|
10
145
|
## [1.18.3] - 2026-10-04
|
|
11
146
|
|
|
12
147
|
### Added
|
|
@@ -1903,7 +2038,8 @@ Earlier releases shipped as `treemapper`; see
|
|
|
1903
2038
|
<https://github.com/nikolay-e/diffctx/releases> for the corresponding GitHub
|
|
1904
2039
|
release notes (`1.0.0` through `1.6.1`).
|
|
1905
2040
|
|
|
1906
|
-
[Unreleased]: https://github.com/nikolay-e/diffctx/compare/v1.18.
|
|
2041
|
+
[Unreleased]: https://github.com/nikolay-e/diffctx/compare/v1.18.4...HEAD
|
|
2042
|
+
[1.18.4]: https://github.com/nikolay-e/diffctx/compare/v1.18.3...v1.18.4
|
|
1907
2043
|
[1.18.3]: https://github.com/nikolay-e/diffctx/compare/v1.18.2...v1.18.3
|
|
1908
2044
|
[1.18.2]: https://github.com/nikolay-e/diffctx/compare/v1.18.1...v1.18.2
|
|
1909
2045
|
[1.18.1]: https://github.com/nikolay-e/diffctx/compare/v1.18.0...v1.18.1
|
diffctx-1.18.4/PKG-INFO
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: diffctx
|
|
3
|
+
Version: 1.18.4
|
|
4
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
5
|
+
Classifier: Environment :: Console
|
|
6
|
+
Classifier: Intended Audience :: Developers
|
|
7
|
+
Classifier: Operating System :: OS Independent
|
|
8
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
14
|
+
Classifier: Topic :: Software Development
|
|
15
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
16
|
+
Classifier: Topic :: Software Development :: Version Control :: Git
|
|
17
|
+
Classifier: Topic :: Utilities
|
|
18
|
+
Classifier: Typing :: Typed
|
|
19
|
+
Requires-Dist: pathspec>=0.11,<2.0
|
|
20
|
+
Requires-Dist: black>=23.0.0,<27.0 ; extra == 'dev'
|
|
21
|
+
Requires-Dist: charset-normalizer>=3.0,<4.0 ; extra == 'dev'
|
|
22
|
+
Requires-Dist: coverage>=7.0,<8.0 ; extra == 'dev'
|
|
23
|
+
Requires-Dist: hypothesis>=6.0,<7.0 ; extra == 'dev'
|
|
24
|
+
Requires-Dist: import-linter>=2.0,<3.0 ; extra == 'dev'
|
|
25
|
+
Requires-Dist: mypy>=1.0,<3.0 ; extra == 'dev'
|
|
26
|
+
Requires-Dist: pre-commit>=3.0,<5.0 ; extra == 'dev'
|
|
27
|
+
Requires-Dist: pygit2>=1.12,<2.0 ; extra == 'dev'
|
|
28
|
+
Requires-Dist: pytest>=7.0,<10.0 ; extra == 'dev'
|
|
29
|
+
Requires-Dist: pytest-asyncio>=0.23,<2.0 ; extra == 'dev'
|
|
30
|
+
Requires-Dist: pytest-cov>=3.0,<8.0 ; extra == 'dev'
|
|
31
|
+
Requires-Dist: pytest-timeout>=2.1,<3.0 ; extra == 'dev'
|
|
32
|
+
Requires-Dist: pytest-xdist>=3.0,<4.0 ; extra == 'dev'
|
|
33
|
+
Requires-Dist: pyyaml>=6.0.2,<8.0 ; extra == 'dev'
|
|
34
|
+
Requires-Dist: radon>=6.0,<7.0 ; extra == 'dev'
|
|
35
|
+
Requires-Dist: ruff>=0.4,<1.0 ; extra == 'dev'
|
|
36
|
+
Requires-Dist: tiktoken>=0.9,<1.0 ; extra == 'dev'
|
|
37
|
+
Requires-Dist: types-pyyaml>=6.0,<7.0 ; extra == 'dev'
|
|
38
|
+
Requires-Dist: charset-normalizer>=3.0,<4.0 ; extra == 'full'
|
|
39
|
+
Requires-Dist: anyio>=4.5,<5.0 ; extra == 'mcp'
|
|
40
|
+
Requires-Dist: mcp>=2.3,<3 ; extra == 'mcp'
|
|
41
|
+
Provides-Extra: dev
|
|
42
|
+
Provides-Extra: full
|
|
43
|
+
Provides-Extra: mcp
|
|
44
|
+
License-File: LICENSE
|
|
45
|
+
Summary: Selects the minimum code an LLM needs to review a git diff
|
|
46
|
+
Keywords: ai,chatgpt,claude,code-analysis,code-context,code-review,code-to-prompt,codebase,context,context-selection,diff-context,directory-tree,export,git-diff,json,llm,llm-context,mcp,model-context-protocol,tree,yaml
|
|
47
|
+
Home-Page: https://diffctx.com/
|
|
48
|
+
Author-email: Nikolay Eremeev <nikolay.eremeev@outlook.com>
|
|
49
|
+
License-Expression: Apache-2.0
|
|
50
|
+
Requires-Python: >=3.10
|
|
51
|
+
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
|
|
52
|
+
Project-URL: Author, https://nikolay-eremeev.com
|
|
53
|
+
Project-URL: Changelog, https://github.com/nikolay-e/diffctx/blob/main/CHANGELOG.md
|
|
54
|
+
Project-URL: Documentation, https://diffctx.com/
|
|
55
|
+
Project-URL: Homepage, https://diffctx.com/
|
|
56
|
+
Project-URL: Issues, https://github.com/nikolay-e/diffctx/issues
|
|
57
|
+
Project-URL: Paper, https://doi.org/10.5281/zenodo.18824579
|
|
58
|
+
Project-URL: Repository, https://github.com/nikolay-e/diffctx
|
|
59
|
+
|
|
60
|
+
# diffctx — what a git change reaches, and the code to review it
|
|
61
|
+
|
|
62
|
+
[](https://github.com/nikolay-e/diffctx/actions/workflows/ci.yml)
|
|
63
|
+
[](https://pypi.org/project/diffctx/)
|
|
64
|
+
[](https://crates.io/crates/diffctx)
|
|
65
|
+
[](https://www.npmjs.com/package/diffctx)
|
|
66
|
+
[](https://registry.modelcontextprotocol.io/v0/servers?search=io.github.nikolay-e/diffctx)
|
|
67
|
+
|
|
68
|
+
**diffctx tells an agent or a reviewer what a change reaches outside its
|
|
69
|
+
diff** — the callers, the tests that reach them, the contracts it crosses —
|
|
70
|
+
**and selects the code needed to understand it** under a token budget. Local,
|
|
71
|
+
deterministic, no index, no model calls. Caller resolution is static and per
|
|
72
|
+
language; where it cannot resolve, the answer says so instead of printing a
|
|
73
|
+
zero.
|
|
74
|
+
|
|
75
|
+
> Formerly published as `treemapper` — every command, flag, and API call works unchanged.
|
|
76
|
+
|
|
77
|
+
## Install
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
# Claude Code: the MCP server, /diffctx:impact, and hooks that run it before commit and push
|
|
81
|
+
claude plugin marketplace add nikolay-e/diffctx
|
|
82
|
+
claude plugin install diffctx@diffctx
|
|
83
|
+
|
|
84
|
+
# any MCP client
|
|
85
|
+
claude mcp add diffctx -- uvx --from 'diffctx[mcp]' diffctx-mcp
|
|
86
|
+
|
|
87
|
+
# CLI, zero-install
|
|
88
|
+
uvx diffctx . --diff HEAD~1
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
pipx, pip, cargo, npm, Docker, Scoop, other MCP clients and the Python API:
|
|
92
|
+
[integrations](docs/product/integrations.md).
|
|
93
|
+
|
|
94
|
+
## Usage
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
diffctx . --diff --mode impact # uncommitted work: callers outside the diff, their tests, contracts
|
|
98
|
+
diffctx . --symbol parse_config # the same for a name, no change needed
|
|
99
|
+
diffctx . --diff main...feature # the code to review a branch, packed under the auto budget
|
|
100
|
+
diffctx . --diff HEAD~1 --budget 12000 # the last commit, capped at 12k o200k tokens
|
|
101
|
+
diffctx . --diff 24h --mode locate # today's work as ranked JSON, no source bodies
|
|
102
|
+
diffctx . # whole-tree export, Markdown
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
`--diff` takes a git range, `staged`, or a duration window ending now (`24h`,
|
|
106
|
+
`90min`, `2w`). Every flag, default and exit code:
|
|
107
|
+
[command-line reference](docs/product/cli.md).
|
|
108
|
+
|
|
109
|
+

|
|
110
|
+
|
|
111
|
+
## How it compares
|
|
112
|
+
|
|
113
|
+
Whole-repo packers export everything; code-graph servers answer queries
|
|
114
|
+
against a maintained index. diffctx is **diff-seeded**: the input is a change,
|
|
115
|
+
the output is what it touches and what explains it. Measured results, and when
|
|
116
|
+
the other two fit better: [COMPARISON.md](COMPARISON.md).
|
|
117
|
+
|
|
118
|
+
## More
|
|
119
|
+
|
|
120
|
+
- [Documentation site](https://diffctx.com/) — the pipeline end to end
|
|
121
|
+
- [Command-line reference](docs/product/cli.md) — rendered from `diffctx --help`
|
|
122
|
+
- [Integrations](docs/product/integrations.md) — install, MCP clients, Python API
|
|
123
|
+
- [FAQ](docs/product/faq.md) — heuristic or oracle, ignore rules, monorepos, secrets
|
|
124
|
+
- [Token counting](docs/product/token-budget.md) — `--budget` for non-GPT models
|
|
125
|
+
- [GitHub Action](docs/product/github-action.md) — diff context as a CI step
|
|
126
|
+
- [Benchmarks](BENCHMARKS.md) and the [paper](https://doi.org/10.5281/zenodo.18824579)
|
|
127
|
+
- [Changelog](CHANGELOG.md) · [Security](SECURITY.md)
|
|
128
|
+
- [Parameter strategy](docs/engineering/parameter-strategy.md)
|
|
129
|
+
|
|
130
|
+
Apache 2.0
|
|
131
|
+
|
|
132
|
+
<!-- mcp-name: io.github.nikolay-e/diffctx -->
|
|
133
|
+
<!-- Ownership marker read from the PyPI description by the MCP registry. -->
|
|
134
|
+
<!-- Must survive edits verbatim: one space after the colon, case-sensitive. -->
|
|
135
|
+
|
diffctx-1.18.4/README.md
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# diffctx — what a git change reaches, and the code to review it
|
|
2
|
+
|
|
3
|
+
[](https://github.com/nikolay-e/diffctx/actions/workflows/ci.yml)
|
|
4
|
+
[](https://pypi.org/project/diffctx/)
|
|
5
|
+
[](https://crates.io/crates/diffctx)
|
|
6
|
+
[](https://www.npmjs.com/package/diffctx)
|
|
7
|
+
[](https://registry.modelcontextprotocol.io/v0/servers?search=io.github.nikolay-e/diffctx)
|
|
8
|
+
|
|
9
|
+
**diffctx tells an agent or a reviewer what a change reaches outside its
|
|
10
|
+
diff** — the callers, the tests that reach them, the contracts it crosses —
|
|
11
|
+
**and selects the code needed to understand it** under a token budget. Local,
|
|
12
|
+
deterministic, no index, no model calls. Caller resolution is static and per
|
|
13
|
+
language; where it cannot resolve, the answer says so instead of printing a
|
|
14
|
+
zero.
|
|
15
|
+
|
|
16
|
+
> Formerly published as `treemapper` — every command, flag, and API call works unchanged.
|
|
17
|
+
|
|
18
|
+
## Install
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
# Claude Code: the MCP server, /diffctx:impact, and hooks that run it before commit and push
|
|
22
|
+
claude plugin marketplace add nikolay-e/diffctx
|
|
23
|
+
claude plugin install diffctx@diffctx
|
|
24
|
+
|
|
25
|
+
# any MCP client
|
|
26
|
+
claude mcp add diffctx -- uvx --from 'diffctx[mcp]' diffctx-mcp
|
|
27
|
+
|
|
28
|
+
# CLI, zero-install
|
|
29
|
+
uvx diffctx . --diff HEAD~1
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
pipx, pip, cargo, npm, Docker, Scoop, other MCP clients and the Python API:
|
|
33
|
+
[integrations](docs/product/integrations.md).
|
|
34
|
+
|
|
35
|
+
## Usage
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
diffctx . --diff --mode impact # uncommitted work: callers outside the diff, their tests, contracts
|
|
39
|
+
diffctx . --symbol parse_config # the same for a name, no change needed
|
|
40
|
+
diffctx . --diff main...feature # the code to review a branch, packed under the auto budget
|
|
41
|
+
diffctx . --diff HEAD~1 --budget 12000 # the last commit, capped at 12k o200k tokens
|
|
42
|
+
diffctx . --diff 24h --mode locate # today's work as ranked JSON, no source bodies
|
|
43
|
+
diffctx . # whole-tree export, Markdown
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
`--diff` takes a git range, `staged`, or a duration window ending now (`24h`,
|
|
47
|
+
`90min`, `2w`). Every flag, default and exit code:
|
|
48
|
+
[command-line reference](docs/product/cli.md).
|
|
49
|
+
|
|
50
|
+

|
|
51
|
+
|
|
52
|
+
## How it compares
|
|
53
|
+
|
|
54
|
+
Whole-repo packers export everything; code-graph servers answer queries
|
|
55
|
+
against a maintained index. diffctx is **diff-seeded**: the input is a change,
|
|
56
|
+
the output is what it touches and what explains it. Measured results, and when
|
|
57
|
+
the other two fit better: [COMPARISON.md](COMPARISON.md).
|
|
58
|
+
|
|
59
|
+
## More
|
|
60
|
+
|
|
61
|
+
- [Documentation site](https://diffctx.com/) — the pipeline end to end
|
|
62
|
+
- [Command-line reference](docs/product/cli.md) — rendered from `diffctx --help`
|
|
63
|
+
- [Integrations](docs/product/integrations.md) — install, MCP clients, Python API
|
|
64
|
+
- [FAQ](docs/product/faq.md) — heuristic or oracle, ignore rules, monorepos, secrets
|
|
65
|
+
- [Token counting](docs/product/token-budget.md) — `--budget` for non-GPT models
|
|
66
|
+
- [GitHub Action](docs/product/github-action.md) — diff context as a CI step
|
|
67
|
+
- [Benchmarks](BENCHMARKS.md) and the [paper](https://doi.org/10.5281/zenodo.18824579)
|
|
68
|
+
- [Changelog](CHANGELOG.md) · [Security](SECURITY.md)
|
|
69
|
+
- [Parameter strategy](docs/engineering/parameter-strategy.md)
|
|
70
|
+
|
|
71
|
+
Apache 2.0
|
|
72
|
+
|
|
73
|
+
<!-- mcp-name: io.github.nikolay-e/diffctx -->
|
|
74
|
+
<!-- Ownership marker read from the PyPI description by the MCP registry. -->
|
|
75
|
+
<!-- Must survive edits verbatim: one space after the colon, case-sensitive. -->
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "diffctx"
|
|
3
|
-
version = "1.18.
|
|
3
|
+
version = "1.18.4"
|
|
4
4
|
edition = "2024"
|
|
5
5
|
rust-version = "1.85"
|
|
6
6
|
description = "Selects the minimum code an LLM needs to review a git diff: walks the dependency graph outward from changed lines and stops when extra context stops paying for itself"
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# diffctx — what a git change reaches, and the code to review it
|
|
2
|
+
|
|
3
|
+
[](https://github.com/nikolay-e/diffctx/actions/workflows/ci.yml)
|
|
4
|
+
[](https://pypi.org/project/diffctx/)
|
|
5
|
+
[](https://crates.io/crates/diffctx)
|
|
6
|
+
[](https://www.npmjs.com/package/diffctx)
|
|
7
|
+
[](https://registry.modelcontextprotocol.io/v0/servers?search=io.github.nikolay-e/diffctx)
|
|
8
|
+
|
|
9
|
+
**diffctx tells an agent or a reviewer what a change reaches outside its
|
|
10
|
+
diff** — the callers, the tests that reach them, the contracts it crosses —
|
|
11
|
+
**and selects the code needed to understand it** under a token budget. Local,
|
|
12
|
+
deterministic, no index, no model calls. Caller resolution is static and per
|
|
13
|
+
language; where it cannot resolve, the answer says so instead of printing a
|
|
14
|
+
zero.
|
|
15
|
+
|
|
16
|
+
> Formerly published as `treemapper` — every command, flag, and API call works unchanged.
|
|
17
|
+
|
|
18
|
+
## Install
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
# Claude Code: the MCP server, /diffctx:impact, and hooks that run it before commit and push
|
|
22
|
+
claude plugin marketplace add nikolay-e/diffctx
|
|
23
|
+
claude plugin install diffctx@diffctx
|
|
24
|
+
|
|
25
|
+
# any MCP client
|
|
26
|
+
claude mcp add diffctx -- uvx --from 'diffctx[mcp]' diffctx-mcp
|
|
27
|
+
|
|
28
|
+
# CLI, zero-install
|
|
29
|
+
uvx diffctx . --diff HEAD~1
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
pipx, pip, cargo, npm, Docker, Scoop, other MCP clients and the Python API:
|
|
33
|
+
[integrations](docs/product/integrations.md).
|
|
34
|
+
|
|
35
|
+
## Usage
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
diffctx . --diff --mode impact # uncommitted work: callers outside the diff, their tests, contracts
|
|
39
|
+
diffctx . --symbol parse_config # the same for a name, no change needed
|
|
40
|
+
diffctx . --diff main...feature # the code to review a branch, packed under the auto budget
|
|
41
|
+
diffctx . --diff HEAD~1 --budget 12000 # the last commit, capped at 12k o200k tokens
|
|
42
|
+
diffctx . --diff 24h --mode locate # today's work as ranked JSON, no source bodies
|
|
43
|
+
diffctx . # whole-tree export, Markdown
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
`--diff` takes a git range, `staged`, or a duration window ending now (`24h`,
|
|
47
|
+
`90min`, `2w`). Every flag, default and exit code:
|
|
48
|
+
[command-line reference](docs/product/cli.md).
|
|
49
|
+
|
|
50
|
+

|
|
51
|
+
|
|
52
|
+
## How it compares
|
|
53
|
+
|
|
54
|
+
Whole-repo packers export everything; code-graph servers answer queries
|
|
55
|
+
against a maintained index. diffctx is **diff-seeded**: the input is a change,
|
|
56
|
+
the output is what it touches and what explains it. Measured results, and when
|
|
57
|
+
the other two fit better: [COMPARISON.md](COMPARISON.md).
|
|
58
|
+
|
|
59
|
+
## More
|
|
60
|
+
|
|
61
|
+
- [Documentation site](https://diffctx.com/) — the pipeline end to end
|
|
62
|
+
- [Command-line reference](docs/product/cli.md) — rendered from `diffctx --help`
|
|
63
|
+
- [Integrations](docs/product/integrations.md) — install, MCP clients, Python API
|
|
64
|
+
- [FAQ](docs/product/faq.md) — heuristic or oracle, ignore rules, monorepos, secrets
|
|
65
|
+
- [Token counting](docs/product/token-budget.md) — `--budget` for non-GPT models
|
|
66
|
+
- [GitHub Action](docs/product/github-action.md) — diff context as a CI step
|
|
67
|
+
- [Benchmarks](BENCHMARKS.md) and the [paper](https://doi.org/10.5281/zenodo.18824579)
|
|
68
|
+
- [Changelog](CHANGELOG.md) · [Security](SECURITY.md)
|
|
69
|
+
- [Parameter strategy](docs/engineering/parameter-strategy.md)
|
|
70
|
+
|
|
71
|
+
Apache 2.0
|
|
72
|
+
|
|
73
|
+
<!-- mcp-name: io.github.nikolay-e/diffctx -->
|
|
74
|
+
<!-- Ownership marker read from the PyPI description by the MCP registry. -->
|
|
75
|
+
<!-- Must survive edits verbatim: one space after the colon, case-sensitive. -->
|