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.
Files changed (177) hide show
  1. {diffctx-1.18.3 → diffctx-1.18.4}/CHANGELOG.md +137 -1
  2. {diffctx-1.18.3 → diffctx-1.18.4}/Cargo.lock +1 -1
  3. diffctx-1.18.4/PKG-INFO +135 -0
  4. diffctx-1.18.4/README.md +75 -0
  5. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/Cargo.toml +1 -1
  6. diffctx-1.18.4/crates/diffctx-native/README.md +75 -0
  7. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/bindings.rs +271 -82
  8. diffctx-1.18.4/crates/diffctx-native/src/change_class.rs +637 -0
  9. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/core.rs +32 -3
  10. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/base.rs +162 -0
  11. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/config_edges/generic.rs +40 -7
  12. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/history/cochange.rs +25 -25
  13. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/mod.rs +187 -20
  14. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/nim.rs +51 -12
  15. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/nix.rs +14 -2
  16. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/ocaml.rs +14 -1
  17. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/ruby.rs +31 -3
  18. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/fragmentation.rs +2 -1
  19. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/git.rs +210 -44
  20. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/graph_export.rs +113 -9
  21. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/hook.rs +1315 -286
  22. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/impact.rs +1421 -163
  23. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/in_memory_harness.rs +3 -1
  24. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/interval.rs +12 -0
  25. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/main.rs +48 -3
  26. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/pipeline.rs +346 -111
  27. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/postpass.rs +33 -24
  28. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/pybridge.rs +47 -8
  29. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/render.rs +26 -21
  30. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/resource.rs +5 -5
  31. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/select.rs +226 -31
  32. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/utility/objective.rs +2 -0
  33. {diffctx-1.18.3 → diffctx-1.18.4}/pyproject.toml +7 -8
  34. {diffctx-1.18.3 → diffctx-1.18.4}/src/diffctx/_app.py +75 -27
  35. {diffctx-1.18.3 → diffctx-1.18.4}/src/diffctx/_diffctx.pyi +3 -3
  36. {diffctx-1.18.3 → diffctx-1.18.4}/src/diffctx/_native/graph_export.py +6 -6
  37. {diffctx-1.18.3 → diffctx-1.18.4}/src/diffctx/cli.py +19 -9
  38. {diffctx-1.18.3 → diffctx-1.18.4}/src/diffctx/mcp/legacy.py +7 -4
  39. {diffctx-1.18.3 → diffctx-1.18.4}/src/diffctx/mcp/server.py +44 -20
  40. diffctx-1.18.4/src/diffctx/version.py +1 -0
  41. {diffctx-1.18.3 → diffctx-1.18.4}/src/diffctx/writer.py +2 -1
  42. diffctx-1.18.3/PKG-INFO +0 -372
  43. diffctx-1.18.3/README.md +0 -312
  44. diffctx-1.18.3/crates/diffctx-native/README.md +0 -312
  45. diffctx-1.18.3/crates/diffctx-native/src/change_class.rs +0 -169
  46. diffctx-1.18.3/src/diffctx/version.py +0 -1
  47. {diffctx-1.18.3 → diffctx-1.18.4}/Cargo.toml +0 -0
  48. {diffctx-1.18.3 → diffctx-1.18.4}/LICENSE +0 -0
  49. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/analytics.rs +0 -0
  50. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/candidate_files.rs +0 -0
  51. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/config/analytics.rs +0 -0
  52. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/config/bm25.rs +0 -0
  53. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/config/budget.rs +0 -0
  54. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/config/category_weights.rs +0 -0
  55. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/config/edge_weights.rs +0 -0
  56. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/config/env_overrides.rs +0 -0
  57. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/config/extensions.rs +0 -0
  58. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/config/filtering.rs +0 -0
  59. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/config/fragmentation.rs +0 -0
  60. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/config/git.rs +0 -0
  61. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/config/graph_filtering.rs +0 -0
  62. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/config/importance.rs +0 -0
  63. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/config/limits.rs +0 -0
  64. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/config/mod.rs +0 -0
  65. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/config/mode.rs +0 -0
  66. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/config/needs.rs +0 -0
  67. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/config/parsers.rs +0 -0
  68. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/config/render.rs +0 -0
  69. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/config/scoring.rs +0 -0
  70. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/config/selection.rs +0 -0
  71. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/config/tokenization.rs +0 -0
  72. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/config/weights.rs +0 -0
  73. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/container.rs +0 -0
  74. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/discovery.rs +0 -0
  75. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/config_edges/build_system.rs +0 -0
  76. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/config_edges/cicd.rs +0 -0
  77. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/config_edges/docker.rs +0 -0
  78. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/config_edges/helm.rs +0 -0
  79. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/config_edges/kubernetes.rs +0 -0
  80. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/config_edges/mod.rs +0 -0
  81. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/document/mod.rs +0 -0
  82. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/history/mod.rs +0 -0
  83. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/ansible.rs +0 -0
  84. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/bazel.rs +0 -0
  85. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/c_family.rs +0 -0
  86. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/cargo_edges.rs +0 -0
  87. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/clojure.rs +0 -0
  88. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/css.rs +0 -0
  89. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/dart.rs +0 -0
  90. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/dbt.rs +0 -0
  91. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/dotnet.rs +0 -0
  92. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/elixir.rs +0 -0
  93. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/erlang.rs +0 -0
  94. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/go.rs +0 -0
  95. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/graphql.rs +0 -0
  96. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/haskell.rs +0 -0
  97. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/javascript.rs +0 -0
  98. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/julia.rs +0 -0
  99. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/jvm.rs +0 -0
  100. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/latex.rs +0 -0
  101. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/lua.rs +0 -0
  102. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/mod.rs +0 -0
  103. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/openapi.rs +0 -0
  104. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/perl.rs +0 -0
  105. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/php.rs +0 -0
  106. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/prisma.rs +0 -0
  107. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/protobuf.rs +0 -0
  108. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/python.rs +0 -0
  109. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/r_lang.rs +0 -0
  110. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/rust_lang.rs +0 -0
  111. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/shell.rs +0 -0
  112. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/sql.rs +0 -0
  113. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/swift.rs +0 -0
  114. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/tags.rs +0 -0
  115. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/terraform.rs +0 -0
  116. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/semantic/zig.rs +0 -0
  117. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/similarity/lexical.rs +0 -0
  118. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/similarity/mod.rs +0 -0
  119. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/structural/containment.rs +0 -0
  120. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/structural/mod.rs +0 -0
  121. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/structural/sibling.rs +0 -0
  122. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/edges/structural/testing.rs +0 -0
  123. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/effective_config.rs +0 -0
  124. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/excerpt.rs +0 -0
  125. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/facts/mod.rs +0 -0
  126. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/facts/scala.rs +0 -0
  127. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/filtering.rs +0 -0
  128. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/graph.rs +0 -0
  129. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/languages.rs +0 -0
  130. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/lib.rs +0 -0
  131. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/locate.rs +0 -0
  132. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/mode.rs +0 -0
  133. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/parsers/config_parser.rs +0 -0
  134. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/parsers/generic.rs +0 -0
  135. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/parsers/markdown.rs +0 -0
  136. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/parsers/mod.rs +0 -0
  137. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/parsers/tree_sitter_strategy.rs +0 -0
  138. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/paths.rs +0 -0
  139. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/peak_rss.rs +0 -0
  140. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/ppr.rs +0 -0
  141. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/project_graph.rs +0 -0
  142. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/provenance.rs +0 -0
  143. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/run_provenance.rs +0 -0
  144. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/sanitize.rs +0 -0
  145. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/scoring.rs +0 -0
  146. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/signatures.rs +0 -0
  147. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/source.rs +0 -0
  148. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/stopwords/code.txt +0 -0
  149. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/stopwords/docs.txt +0 -0
  150. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/stopwords.rs +0 -0
  151. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/test_rng.rs +0 -0
  152. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/testfiles.rs +0 -0
  153. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/token_corpus.rs +0 -0
  154. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/tokenizer.rs +0 -0
  155. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/types.rs +0 -0
  156. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/utility/boltzmann.rs +0 -0
  157. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/utility/importance.rs +0 -0
  158. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/utility/mod.rs +0 -0
  159. {diffctx-1.18.3 → diffctx-1.18.4}/crates/diffctx-native/src/utility/needs.rs +0 -0
  160. {diffctx-1.18.3 → diffctx-1.18.4}/rust-toolchain.toml +0 -0
  161. {diffctx-1.18.3 → diffctx-1.18.4}/src/diffctx/__init__.py +0 -0
  162. {diffctx-1.18.3 → diffctx-1.18.4}/src/diffctx/__main__.py +0 -0
  163. {diffctx-1.18.3 → diffctx-1.18.4}/src/diffctx/_native/__init__.py +0 -0
  164. {diffctx-1.18.3 → diffctx-1.18.4}/src/diffctx/_native/graph_analytics.py +0 -0
  165. {diffctx-1.18.3 → diffctx-1.18.4}/src/diffctx/_native/pipeline.py +0 -0
  166. {diffctx-1.18.3 → diffctx-1.18.4}/src/diffctx/_native/project_graph.py +0 -0
  167. {diffctx-1.18.3 → diffctx-1.18.4}/src/diffctx/clipboard.py +0 -0
  168. {diffctx-1.18.3 → diffctx-1.18.4}/src/diffctx/ignore.py +0 -0
  169. {diffctx-1.18.3 → diffctx-1.18.4}/src/diffctx/logger.py +0 -0
  170. {diffctx-1.18.3 → diffctx-1.18.4}/src/diffctx/mcp/__init__.py +0 -0
  171. {diffctx-1.18.3 → diffctx-1.18.4}/src/diffctx/mcp/__main__.py +0 -0
  172. {diffctx-1.18.3 → diffctx-1.18.4}/src/diffctx/mcp/fetch.py +0 -0
  173. {diffctx-1.18.3 → diffctx-1.18.4}/src/diffctx/mcp/launch.py +0 -0
  174. {diffctx-1.18.3 → diffctx-1.18.4}/src/diffctx/mcp/security.py +0 -0
  175. {diffctx-1.18.3 → diffctx-1.18.4}/src/diffctx/py.typed +0 -0
  176. {diffctx-1.18.3 → diffctx-1.18.4}/src/diffctx/tokens.py +0 -0
  177. {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.3...HEAD
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
@@ -194,7 +194,7 @@ checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
194
194
 
195
195
  [[package]]
196
196
  name = "diffctx"
197
- version = "1.18.3"
197
+ version = "1.18.4"
198
198
  dependencies = [
199
199
  "aho-corasick",
200
200
  "anyhow",
@@ -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
+ [![CI](https://github.com/nikolay-e/diffctx/actions/workflows/ci.yml/badge.svg)](https://github.com/nikolay-e/diffctx/actions/workflows/ci.yml)
63
+ [![PyPI](https://img.shields.io/pypi/v/diffctx)](https://pypi.org/project/diffctx/)
64
+ [![crates.io](https://img.shields.io/crates/v/diffctx)](https://crates.io/crates/diffctx)
65
+ [![npm](https://img.shields.io/npm/v/diffctx)](https://www.npmjs.com/package/diffctx)
66
+ [![MCP Registry](https://img.shields.io/badge/MCP_Registry-io.github.nikolay--e%2Fdiffctx-blue)](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
+ ![diffctx demo](https://raw.githubusercontent.com/nikolay-e/diffctx/main/docs/demo/demo.gif)
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
+
@@ -0,0 +1,75 @@
1
+ # diffctx — what a git change reaches, and the code to review it
2
+
3
+ [![CI](https://github.com/nikolay-e/diffctx/actions/workflows/ci.yml/badge.svg)](https://github.com/nikolay-e/diffctx/actions/workflows/ci.yml)
4
+ [![PyPI](https://img.shields.io/pypi/v/diffctx)](https://pypi.org/project/diffctx/)
5
+ [![crates.io](https://img.shields.io/crates/v/diffctx)](https://crates.io/crates/diffctx)
6
+ [![npm](https://img.shields.io/npm/v/diffctx)](https://www.npmjs.com/package/diffctx)
7
+ [![MCP Registry](https://img.shields.io/badge/MCP_Registry-io.github.nikolay--e%2Fdiffctx-blue)](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
+ ![diffctx demo](https://raw.githubusercontent.com/nikolay-e/diffctx/main/docs/demo/demo.gif)
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"
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
+ [![CI](https://github.com/nikolay-e/diffctx/actions/workflows/ci.yml/badge.svg)](https://github.com/nikolay-e/diffctx/actions/workflows/ci.yml)
4
+ [![PyPI](https://img.shields.io/pypi/v/diffctx)](https://pypi.org/project/diffctx/)
5
+ [![crates.io](https://img.shields.io/crates/v/diffctx)](https://crates.io/crates/diffctx)
6
+ [![npm](https://img.shields.io/npm/v/diffctx)](https://www.npmjs.com/package/diffctx)
7
+ [![MCP Registry](https://img.shields.io/badge/MCP_Registry-io.github.nikolay--e%2Fdiffctx-blue)](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
+ ![diffctx demo](https://raw.githubusercontent.com/nikolay-e/diffctx/main/docs/demo/demo.gif)
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. -->