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 a single root, and returns plain text with no line-number prefixes. 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. Text output uses the same compact tree display as raw search output when that saves tokens. Directories end with /; file paths are returned as one entry. It honors 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 only that file and report paths relative to the file's parent directory. Multi-root searches 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 --list src --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 roots; read/list accept a single root only. 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
explore(..., result_format="text") 11,008 34.3 KB ██░░░░░░░░░░░░░░░░
rtk grep stdout 19,646 60.1 KB ███░░░░░░░░░░░░░░░
default explore(...) 38,393 125.3 KB █████░░░░░░░░░░░░░
explore(..., result_format="full") 39,027 134.7 KB █████░░░░░░░░░░░░░
rg stdout 129,775 402.4 KB ██████████████████

Default structured output is 7.03% smaller than the full structured shape. Raw text omits backend/totals metadata, includes only a cursor hint when truncated, and prints No Match for empty pages. Raw text 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.5.0.tar.gz (105.1 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.5.0-py3-none-win_arm64.whl (866.4 kB view details)

Uploaded Python 3Windows ARM64

codetool_explore-0.5.0-py3-none-win_amd64.whl (931.6 kB view details)

Uploaded Python 3Windows x86-64

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

Uploaded Python 3macOS 11.0+ ARM64

codetool_explore-0.5.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.5.0.tar.gz.

File metadata

  • Download URL: codetool_explore-0.5.0.tar.gz
  • Upload date:
  • Size: 105.1 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.5.0.tar.gz
Algorithm Hash digest
SHA256 4bdec699ef85930129615114789feedfb610cbd2878f2fb1560d61b2ace36be3
MD5 4b03efcbd3d349c52f906307b9ac6cf4
BLAKE2b-256 0f44f1e7dcaa7527358b86f9fc2ddbcf2e7a35c0c72c3dc8d41e348fcc235b9d

See more details on using hashes here.

Provenance

The following attestation bundles were made for codetool_explore-0.5.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.5.0-py3-none-win_arm64.whl.

File metadata

File hashes

Hashes for codetool_explore-0.5.0-py3-none-win_arm64.whl
Algorithm Hash digest
SHA256 63ce39ab6b251c76bd411bed2375791a2b4d9174a51734e1681d5c685d1c9580
MD5 4f318111072f0d368cbb4dcfe66217ca
BLAKE2b-256 e2947999dc43896dec3d82ed56d87ec690016526c212ffadf054a306be468ae7

See more details on using hashes here.

Provenance

The following attestation bundles were made for codetool_explore-0.5.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.5.0-py3-none-win_amd64.whl.

File metadata

File hashes

Hashes for codetool_explore-0.5.0-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 1bc63d33e06d3b71b310f063b1591409a1dd3846a6f1ec333fbca711445d3163
MD5 2d2131ad26db1fce59c6252d2ccf3ce7
BLAKE2b-256 7745932ceef8403395edbe0348cb51dbf9ff95b89ea474e099279e3f9dab00cc

See more details on using hashes here.

Provenance

The following attestation bundles were made for codetool_explore-0.5.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.5.0-py3-none-manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for codetool_explore-0.5.0-py3-none-manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 e848422adba3078b6ba074ac4780f303f30450e36fb9219eb10a19a9c9da3575
MD5 de1706be046fd3231fc3f514b7da95c1
BLAKE2b-256 f922be765f5a8cc85deb15f6cc17f2425302d9c2ed91efed328c473e74f4e88a

See more details on using hashes here.

Provenance

The following attestation bundles were made for codetool_explore-0.5.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.5.0-py3-none-manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for codetool_explore-0.5.0-py3-none-manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 f96291f8657c8db6383522efeb0ac3291ad71314fa154d7329c4544111de96de
MD5 46efeb795b1ce84e64309bcac22abe54
BLAKE2b-256 7317f20d4b4180c09afdd41c50b4c322fbad2e8fa06d043466d8b45f3b2c4ef3

See more details on using hashes here.

Provenance

The following attestation bundles were made for codetool_explore-0.5.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.5.0-py3-none-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for codetool_explore-0.5.0-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 6e4bd1af24c797cb35e895cb1f96c3f467f8dbeb414b6bfc9d7897ae4c4219b3
MD5 2ee41e653291901d2729e9ff0001c3f4
BLAKE2b-256 7f8f261443580a0aa40fe0b94235cc651e3e3ffdd523abf3ac4b14e84ce0e43d

See more details on using hashes here.

Provenance

The following attestation bundles were made for codetool_explore-0.5.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.5.0-py3-none-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for codetool_explore-0.5.0-py3-none-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 47dab6509026fd72643fb8b14748d47af748908b8cf97c11533afadd46ad7977
MD5 de2406c4f44d6f7595753e816a789a19
BLAKE2b-256 19ae9c9da93e5ccbe874278672cc3183c1ffeea8621c5360514235618a665fca

See more details on using hashes here.

Provenance

The following attestation bundles were made for codetool_explore-0.5.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