Skip to main content

Fast, dependency-free workspace search, read, and list exploration for coding-agent tools with Rust backend

Project description

codetool-explore

codetool-explore is a workspace exploration library built for coding-agent harnesses: fast content search, fast filename/path discovery, read-only file viewing, compact structured results, and predictable token usage.

  • Agent-first API: one public explore() call with target="content", "path", "content_or_path", "read", or "list".
  • Performance-oriented: dependency-free Python fallback plus optional Rust CLI acceleration for literal and regex content/path search.
  • Token-compressed output: compact result keys by default for search, tree-compressed text by default for list, plain text by default for read, result_format="text" for raw RTK-style text, and result_format="full" for the uncompressed backend shape.
from codetool_explore import explore

content = explore("UserService", root=".", mode="files")
paths = explore("service", root=".", target="path", glob="*.py")
mixed = explore("UserService", root=".", target="content_or_path")
scoped = explore("search_workspace", root=["src", "webapp", "tests"], regex=False)
snippet = explore("README.md", root=".", target="read", start_line=20, limit=40)
listing = explore("src", root=".", target="list", limit=100)

Patterns are regexes by default, so alternation works without extra flags:

explore("Maximum number of results|Text or regex pattern", root="tests")

Pass regex=False for exact literal matching.

For maximum token compression, request raw text:

print(explore("UserService", root=".", regex=False, result_format="text"))

Raw text omits backend/totals metadata, groups repeated path prefixes in a small tree, crops long snippets/context aggressively, and prints No Match for empty results. It includes a compact pagination header only when another page exists:

-- more: cursor=50
src/
 a.py

Raw mode grammar:

  • mode="files": matching filenames only.
  • mode="count": path xN, where N is the per-file count.
  • mode="snippets": path:line:text without context, or tree-grouped files where line:text marks a match and other indented text is surrounding context. With target="content_or_path", path-only matches are returned as filename rows.

API

explore(
    pattern,
    root=".",               # path, file, or non-empty list/tuple of paths
    target="content",       # "content", "path", "content_or_path", "read", or "list"
    regex=True,             # set False for literal search
    path_scope="path",      # "path" or "basename" for path matching
    glob=None,
    exclude=None,
    case="smart",
    mode="files",          # "files", "snippets", or "count"
    context_lines=0,
    limit=50,
    cursor=None,
    start_line=1,           # first line for target="read"
    backend="auto",        # "auto", "python", "rust"/"native"
    result_format=None,     # default compressed for search, text for read, tree text for list
)

target="content" searches file contents. target="path" searches relative file paths without opening file contents. target="content_or_path" returns files matching either target and marks each row with its match kind. mode="snippets" supports target="content" and target="content_or_path"; path-only rows under target="content_or_path" are returned without line/snippet fields.

target="read" treats pattern as one known file path, resolves relative paths under each root, and returns plain text with no line-number prefixes. When more than one file is read, each file is prefixed by a compact path: header. Use start_line and limit to cap the returned line range; if more lines remain, text output starts with -- more: cursor=N. CSV files are read as ordinary text. Binary-looking, missing, unreadable, or directory paths fail with controlled ExploreError subclasses.

target="list" treats pattern as one file/directory path and returns one directory level under each root. Text output uses the same compact tree display as raw search output when that saves tokens, appending each root's listing in root order. Directories end with /; file paths are returned as one entry. It honors multi-root common-base paths, glob, exclude, ignore files, limit, and cursor. Read/list use the pure-Python stdlib implementation even when backend="auto" or "rust" is requested.

backend="auto" uses the Rust helper when present, then falls back to pure Python. Regex searches use Rust when supported by its regex engine and fall back to Python for compatibility, including Python re.finditer counts for patterns that can match empty spans.

root accepts str | os.PathLike | Sequence[str | os.PathLike]. It may be a workspace directory, a single file, or a non-empty list/tuple of directories and files:

explore("search_workspace", root=["src", "webapp", "tests"], regex=False)

When calling through JSON/tool schemas, pass multi-root values as a JSON array, for example "root": ["src", "webapp", "tests"]. For resilience with coding agents, a space-delimited string such as "root": "src webapp tests" is also treated as multiple roots when that exact path does not exist and every split token is an existing file or directory. Existing paths with spaces still take priority; quote individual spaced paths if combining them in one string.

File roots search/read only that file and report paths relative to the file's parent directory; listing a file path returns one file entry. Multi-root searches/reads/listings report paths relative to the roots' common base, so sibling roots keep prefixes such as src/... and tests/...; this also lets exclude=["src/generated/**"] target one root.

Controlled failures raise ExploreError subclasses:

  • ExploreArgumentError for invalid arguments.
  • ExplorePatternError for invalid/unsupported patterns.
  • ExploreRootError for missing or unsearchable roots.
  • ExploreBackendError for backend runtime failures.

CLI

codetool-explore "UserService" . --literal --format text
codetool-explore "service" . --target path --literal
codetool-explore "User(Service|Repository)" --root src --mode snippets --raw
codetool-explore "search_workspace" --root src --root webapp --root tests --literal
codetool-explore --read README.md --start-line 20 --limit 40
codetool-explore --read settings.py --root src --root tests
codetool-explore --list . --root src --root tests --glob "*.py"

The CLI defaults to compact JSON for search, plain text for --read, and tree-compressed text for --list. Use --format text or --raw for raw search text; no search matches print No Match. Repeat --root for multiple search/read/list roots. A single quoted space-delimited --root is accepted as a compatibility fallback when it can be split into existing roots.

Install

uv install codetool-explore

Wheels can include a platform-specific Rust helper. Without it, the package still works through the Python stdlib backend.

Benchmarks

Reproduce and refresh the generated README data:

cargo build --release --manifest-path rust/Cargo.toml
uv run python benchmarks/benchmark_search.py \
  --output reports/search_benchmark.json \
  --update-readme
uv run python benchmarks/benchmark_output_lengths.py \
  --output reports/rtk_vs_codetool_output_lengths.json
uv run python scripts/update_readme_benchmarks.py \
  --performance reports/search_benchmark.json \
  --tokens reports/rtk_vs_codetool_output_lengths.json

Execution performance

Mean of median wall-clock timings across 5 corpora × 7 scenarios, 5 measured rounds after 1 warmup.

Tool Mean median time Chart
codetool-explore 127.0 ms ███████████░░░░░░░
rg 138.2 ms ████████████░░░░░░
rtk 199.7 ms ██████████████████

codetool-explore is the fastest tool in this run.

Source: reports/search_benchmark.json.

Token compression

Token counts use tiktoken when available. The table compares output across 7 RTK-corpus scenarios.

Output Tokens Bytes Chart
codetool-explore 11,008 34.3 KB ██░░░░░░░░░░░░░░░░
rtk grep stdout 19,646 60.1 KB ███░░░░░░░░░░░░░░░
rg stdout 129,775 402.4 KB ██████████████████

codetool-explore is raw text from explore(..., result_format="text"); it omits backend/totals metadata, includes only a cursor hint when truncated, and prints No Match for empty pages. It is 0.56× the rtk grep token count in this run.

Source: reports/rtk_vs_codetool_output_lengths.json.

Development

uv run pytest
uv run python scripts/package_rust_binary.py
uv build --wheel

Release wheels are built in CI with the staged Rust helper for each target platform.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

codetool_explore-0.6.0.tar.gz (106.3 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

codetool_explore-0.6.0-py3-none-win_arm64.whl (867.4 kB view details)

Uploaded Python 3Windows ARM64

codetool_explore-0.6.0-py3-none-win_amd64.whl (932.6 kB view details)

Uploaded Python 3Windows x86-64

codetool_explore-0.6.0-py3-none-macosx_11_0_arm64.whl (1.1 MB view details)

Uploaded Python 3macOS 11.0+ ARM64

codetool_explore-0.6.0-py3-none-macosx_10_12_x86_64.whl (1.1 MB view details)

Uploaded Python 3macOS 10.12+ x86-64

File details

Details for the file codetool_explore-0.6.0.tar.gz.

File metadata

  • Download URL: codetool_explore-0.6.0.tar.gz
  • Upload date:
  • Size: 106.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for codetool_explore-0.6.0.tar.gz
Algorithm Hash digest
SHA256 af582c49f92a44c20c0dcd9c76ae04ef103cd363e1cad87475aeed5aff3c31a7
MD5 d0e6e768e6994eeb6d2d1002195cbf43
BLAKE2b-256 eab4088c95e14e9b201687136d517bf2a58c59f75a0a6f6eb245851be687bac1

See more details on using hashes here.

Provenance

The following attestation bundles were made for codetool_explore-0.6.0.tar.gz:

Publisher: release.yml on pbi-agent/codetool-explore

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file codetool_explore-0.6.0-py3-none-win_arm64.whl.

File metadata

File hashes

Hashes for codetool_explore-0.6.0-py3-none-win_arm64.whl
Algorithm Hash digest
SHA256 b35d43036d79dc15184d7f139cf1fc8619c3d17a2694f6820811669bc02445f1
MD5 f1d5612ebf89427b794f2215b57d4509
BLAKE2b-256 a9b4a6c90b6636678c8955de6906402c152d0a9059ba43f5a9cc084e0840b4ef

See more details on using hashes here.

Provenance

The following attestation bundles were made for codetool_explore-0.6.0-py3-none-win_arm64.whl:

Publisher: release.yml on pbi-agent/codetool-explore

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file codetool_explore-0.6.0-py3-none-win_amd64.whl.

File metadata

File hashes

Hashes for codetool_explore-0.6.0-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 c9556de6ef2678d91473b4661336bdbe7ac68dcf2547febc2e42a2c61e608805
MD5 5a5b253aa9215b0d9285a64b809356f9
BLAKE2b-256 a9303dfdf74ebdb4ca0b677e1f42b41465ef3a23fbd7a203527b13cfe317fc2a

See more details on using hashes here.

Provenance

The following attestation bundles were made for codetool_explore-0.6.0-py3-none-win_amd64.whl:

Publisher: release.yml on pbi-agent/codetool-explore

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file codetool_explore-0.6.0-py3-none-manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for codetool_explore-0.6.0-py3-none-manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 2d362ef9d36a1c82d09cfaa1bbfba39c8e6ed9496615e3c71290b3de00422eaf
MD5 eff423b1bbdf02230900a97435ced409
BLAKE2b-256 80fb2a6024e39468adbc8a939793a78ed3ae181b3e8609f3c8a6b0a6b4292b83

See more details on using hashes here.

Provenance

The following attestation bundles were made for codetool_explore-0.6.0-py3-none-manylinux2014_x86_64.whl:

Publisher: release.yml on pbi-agent/codetool-explore

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file codetool_explore-0.6.0-py3-none-manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for codetool_explore-0.6.0-py3-none-manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 34817bd0ac17f24fad6df3d355037161c4051c67c14aa41ae9712a256b055135
MD5 1d759d9cbc4fde60500270f3147e5dc1
BLAKE2b-256 7c12739f9eee43fdef21f8438bc32bc7f4fe7078bcff6faff719ac29e33908fa

See more details on using hashes here.

Provenance

The following attestation bundles were made for codetool_explore-0.6.0-py3-none-manylinux2014_aarch64.whl:

Publisher: release.yml on pbi-agent/codetool-explore

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file codetool_explore-0.6.0-py3-none-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for codetool_explore-0.6.0-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 cdebbb772ea41d2fa61f54ad9daa7a05da1e68131482a73336120325b22d2ad6
MD5 562edce15fb02c7379e9979e3c7814b0
BLAKE2b-256 f51aa4415a4e02614f831575443cb12c64b083ca71c6502ac4245280693bc93f

See more details on using hashes here.

Provenance

The following attestation bundles were made for codetool_explore-0.6.0-py3-none-macosx_11_0_arm64.whl:

Publisher: release.yml on pbi-agent/codetool-explore

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file codetool_explore-0.6.0-py3-none-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for codetool_explore-0.6.0-py3-none-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 f57ca1cc549a06208d444f8213359f0407687621939b10c03883c7644a079e87
MD5 8e647071deb2729c480082d77b3d129c
BLAKE2b-256 e2ce754a03a7feb0f68e8097db7374c6d723185ba25fc27505ae2d24e06543ef

See more details on using hashes here.

Provenance

The following attestation bundles were made for codetool_explore-0.6.0-py3-none-macosx_10_12_x86_64.whl:

Publisher: release.yml on pbi-agent/codetool-explore

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page