Skip to content

Releases: ccf/duckgrep

duckgrep 0.3.0

Choose a tag to compare

@ccf ccf released this 05 Oct 12:51
6b1fd70

Added

  • Type inference, Phase 2 (Python). Confident coverage of in-repo calls, measured against jedi, rose from 89.6% to 95.3% on django, from 93.1% to 95.4% on freqtrade and from 92.0% to 95.6% on requests, at 100% precision. The new cases:
    • named and star re-exports, up to three hops (from django.forms import FileField, migrations.CreateModel);
    • class-body aliases (form_class = Foo, then self.form_class());
    • one attribute hop on a typed instance, class or module (bot.exchange.m(), User.objects.m());
    • call-result receivers (Foo(...).m(), super(C, self).m());
    • unannotated functions whose returns agree, and x = h.m() on a typed h;
    • classes defined in the calling function.
  • The qualified tier no longer reads a class name the calling function rebinds as the class.

Fixed

  • Python star re-exports no longer give confident edges that Python wouldn't follow. from pkg import Foo used to get an edge to each module when pkg star-imported Foo from two of them, and private _names were followed through a star. Both now get no confident edge.
  • Indexing large repos on many-core machines no longer runs out of memory. DuckDB's working memory grows with its thread count, so indexing now uses at most 4 threads (DUCKGREP_THREADS overrides it, as DUCKGREP_MEMORY does the 2 GB limit). With one thread per core, django's full edge rebuild needed nearly all of the 2 GB on a 16-core machine; at 4 threads it fits in 1 GB at the same speed.

duckgrep 0.2.1

Choose a tag to compare

@ccf ccf released this 03 Oct 14:23
cf0ba66

Changed

  • Catching up after many files change is faster. After a branch switch, a big pull or a copied index, the next query re-indexes the changed files. Moving a django checkout 300 commits (698 files) now takes 5.8 s instead of 13.5 s, and a copied index on the same commit catches up in 0.6 s instead of 2.2 s.

duckgrep 0.2.0

Choose a tag to compare

@ccf ccf released this 03 Oct 13:15
1996695

Added

  • The typed tier: Python receiver calls (obj.method()) get one confident edge when the receiver's class can be read from syntax. It covers:

    • x = Foo();
    • annotations, including Optional[...], X | None and string annotations;
    • self.attr set or annotated in the class;
    • one hop of return annotations;
    • imported module-level instances;
    • self and super() through base classes in other files.

    Against jedi, confident coverage of in-repo calls rose from 66.8% to 87.8% on django, 74.3% to 90.9% on freqtrade and 67.6% to 90.1% on requests, with every typed edge exact.

  • Calls on receivers whose class is outside the repo (io.StringIO(), literals, classes with an external base) are now unresolved, not name guesses.

Changed

  • The resolver refuses rather than guesses: a name bound more than once in a file, Python's method resolution order where syntax can't settle it, and a name a nested def or class shares all get no typed edge and keep the older tiers.
  • Edge refresh after an edit reads dirty refs in batches, and falls back to a batched rebuild if it runs out of memory, instead of leaving the index unable to answer call-graph queries.
  • The schema is at version 4 (a new bindings table and symbols.returns). Existing indexes rebuild themselves on first use.
  • The query(sql) tool description names the typed tier.

Fixed

  • Standard-library imports (import json, datetime, math ...) no longer resolve to a nested repo module that happens to share the name.
  • duckgrep.__version__ now reports the installed package's version.

Known gaps

  • A class or return that turns external in another file: when a class's ancestry, or a function's return annotation, starts or stops being external in another file, calls on its instances keep their old name/unresolved tier until those refs are next recomputed.

duckgrep 0.1.0

Choose a tag to compare

@ccf ccf released this 02 Oct 23:31
354dcf0

The first release of duckgrep, on PyPI.

duckgrep gives your coding agent a live, queryable model of your codebase (definitions, callers, imports, history), so structural questions take one query instead of a search loop. It parses the repo with tree-sitter into one DuckDB file and exposes it as one read-only query(sql) MCP tool.

uv tool install duckgrep
claude mcp add duckgrep -- duckgrep mcp
  • Languages: Python, TypeScript/TSX, JavaScript, Go and Rust; other text files for grep().
  • Measured: in 3,620 Claude Code runs on 494 structural questions from 25 repos, agents with duckgrep used 12–19% fewer tool calls and cost 14–25% less, with the same accuracy. See bench/RESULTS.md.
  • Site: https://duckgrep.dev