codetool-explore 0.5.0__py3-none-win_arm64.whl

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 (33) hide show
  1. codetool_explore/__init__.py +35 -0
  2. codetool_explore/_bin/codetool-explore-rust-windows-arm64.exe +0 -0
  3. codetool_explore/api.py +266 -0
  4. codetool_explore/cli.py +188 -0
  5. codetool_explore/compression.py +150 -0
  6. codetool_explore/cursor.py +71 -0
  7. codetool_explore/errors.py +23 -0
  8. codetool_explore/explorer.py +497 -0
  9. codetool_explore/ignore.py +222 -0
  10. codetool_explore/py.typed +0 -0
  11. codetool_explore/python_backend/__init__.py +154 -0
  12. codetool_explore/python_backend/case.py +19 -0
  13. codetool_explore/python_backend/config.py +35 -0
  14. codetool_explore/python_backend/constants.py +39 -0
  15. codetool_explore/python_backend/file_search.py +51 -0
  16. codetool_explore/python_backend/ignore_rules.py +40 -0
  17. codetool_explore/python_backend/literal.py +79 -0
  18. codetool_explore/python_backend/matcher.py +79 -0
  19. codetool_explore/python_backend/models.py +49 -0
  20. codetool_explore/python_backend/output.py +82 -0
  21. codetool_explore/python_backend/regex_search.py +63 -0
  22. codetool_explore/python_backend/search.py +327 -0
  23. codetool_explore/python_backend/text.py +39 -0
  24. codetool_explore/python_backend/walker.py +119 -0
  25. codetool_explore/ranking.py +384 -0
  26. codetool_explore/roots.py +148 -0
  27. codetool_explore/rust_backend.py +308 -0
  28. codetool_explore/text_output.py +475 -0
  29. codetool_explore-0.5.0.dist-info/METADATA +240 -0
  30. codetool_explore-0.5.0.dist-info/RECORD +33 -0
  31. codetool_explore-0.5.0.dist-info/WHEEL +4 -0
  32. codetool_explore-0.5.0.dist-info/entry_points.txt +2 -0
  33. codetool_explore-0.5.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,240 @@
1
+ Metadata-Version: 2.4
2
+ Name: codetool-explore
3
+ Version: 0.5.0
4
+ Summary: Fast, dependency-free workspace search, read, and list exploration for coding-agent tools with Rust backend
5
+ Project-URL: Homepage, https://github.com/pbi-agent/codetool-explore
6
+ Project-URL: Repository, https://github.com/pbi-agent/codetool-explore
7
+ Project-URL: Issues, https://github.com/pbi-agent/codetool-explore/issues
8
+ Project-URL: Changelog, https://github.com/pbi-agent/codetool-explore/releases
9
+ Author-email: drod <naceur.bs@gmail.com>
10
+ Maintainer-email: drod <naceur.bs@gmail.com>
11
+ License-Expression: MIT
12
+ License-File: LICENSE
13
+ Keywords: agent,code-search,developer-tools,explore,file-search,filesystem,rust,search,text-search
14
+ Classifier: Development Status :: 3 - Alpha
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Operating System :: MacOS
18
+ Classifier: Operating System :: Microsoft :: Windows
19
+ Classifier: Operating System :: POSIX :: Linux
20
+ Classifier: Programming Language :: Python :: 3
21
+ Classifier: Programming Language :: Python :: 3 :: Only
22
+ Classifier: Programming Language :: Python :: 3.12
23
+ Classifier: Programming Language :: Rust
24
+ Classifier: Topic :: Software Development
25
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
26
+ Classifier: Topic :: Text Processing :: Indexing
27
+ Classifier: Typing :: Typed
28
+ Requires-Python: >=3.12
29
+ Description-Content-Type: text/markdown
30
+
31
+ # codetool-explore
32
+
33
+ `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.
34
+
35
+ - **Agent-first API**: one public `explore()` call with `target="content"`, `"path"`, `"content_or_path"`, `"read"`, or `"list"`.
36
+ - **Performance-oriented**: dependency-free Python fallback plus optional Rust CLI acceleration for literal and regex content/path search.
37
+ - **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.
38
+
39
+ ```python
40
+ from codetool_explore import explore
41
+
42
+ content = explore("UserService", root=".", mode="files")
43
+ paths = explore("service", root=".", target="path", glob="*.py")
44
+ mixed = explore("UserService", root=".", target="content_or_path")
45
+ scoped = explore("search_workspace", root=["src", "webapp", "tests"], regex=False)
46
+ snippet = explore("README.md", root=".", target="read", start_line=20, limit=40)
47
+ listing = explore("src", root=".", target="list", limit=100)
48
+ ```
49
+
50
+ Patterns are regexes by default, so alternation works without extra flags:
51
+
52
+ ```python
53
+ explore("Maximum number of results|Text or regex pattern", root="tests")
54
+ ```
55
+
56
+ Pass `regex=False` for exact literal matching.
57
+
58
+ For maximum token compression, request raw text:
59
+
60
+ ```python
61
+ print(explore("UserService", root=".", regex=False, result_format="text"))
62
+ ```
63
+
64
+ Raw text omits backend/totals metadata, groups repeated path prefixes in a small
65
+ tree, crops long snippets/context aggressively, and prints `No Match` for empty
66
+ results. It includes a compact pagination header only when another page exists:
67
+
68
+ ```text
69
+ -- more: cursor=50
70
+ src/
71
+ a.py
72
+ ```
73
+
74
+ Raw mode grammar:
75
+
76
+ - `mode="files"`: matching filenames only.
77
+ - `mode="count"`: `path xN`, where `N` is the per-file count.
78
+ - `mode="snippets"`: `path:line:text` without context, or tree-grouped files
79
+ where `line:text` marks a match and other indented text is surrounding context.
80
+ With `target="content_or_path"`, path-only matches are returned as filename rows.
81
+
82
+ ## API
83
+
84
+ ```python
85
+ explore(
86
+ pattern,
87
+ root=".", # path, file, or non-empty list/tuple of paths
88
+ target="content", # "content", "path", "content_or_path", "read", or "list"
89
+ regex=True, # set False for literal search
90
+ path_scope="path", # "path" or "basename" for path matching
91
+ glob=None,
92
+ exclude=None,
93
+ case="smart",
94
+ mode="files", # "files", "snippets", or "count"
95
+ context_lines=0,
96
+ limit=50,
97
+ cursor=None,
98
+ start_line=1, # first line for target="read"
99
+ backend="auto", # "auto", "python", "rust"/"native"
100
+ result_format=None, # default compressed for search, text for read, tree text for list
101
+ )
102
+ ```
103
+
104
+ `target="content"` searches file contents. `target="path"` searches relative
105
+ file paths without opening file contents. `target="content_or_path"` returns
106
+ files matching either target and marks each row with its match kind.
107
+ `mode="snippets"` supports `target="content"` and `target="content_or_path"`;
108
+ path-only rows under `target="content_or_path"` are returned without
109
+ line/snippet fields.
110
+
111
+ `target="read"` treats `pattern` as one known file path, resolves relative paths
112
+ under a single `root`, and returns plain text with no line-number prefixes.
113
+ Use `start_line` and `limit` to cap the returned line range; if more lines
114
+ remain, text output starts with `-- more: cursor=N`. CSV files are read as
115
+ ordinary text. Binary-looking, missing, unreadable, or directory paths fail with
116
+ controlled `ExploreError` subclasses.
117
+
118
+ `target="list"` treats `pattern` as one file/directory path and returns one
119
+ directory level. Text output uses the same compact tree display as raw search
120
+ output when that saves tokens. Directories end with `/`; file paths are returned
121
+ as one entry. It honors `glob`, `exclude`, ignore files, `limit`, and `cursor`.
122
+ Read/list use the pure-Python stdlib implementation even when `backend="auto"`
123
+ or `"rust"` is requested.
124
+
125
+ `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.
126
+
127
+ `root` accepts `str | os.PathLike | Sequence[str | os.PathLike]`. It may be a
128
+ workspace directory, a single file, or a non-empty list/tuple of directories and
129
+ files:
130
+
131
+ ```python
132
+ explore("search_workspace", root=["src", "webapp", "tests"], regex=False)
133
+ ```
134
+
135
+ When calling through JSON/tool schemas, pass multi-root values as a JSON array,
136
+ for example `"root": ["src", "webapp", "tests"]`. For resilience with coding
137
+ agents, a space-delimited string such as `"root": "src webapp tests"` is also
138
+ treated as multiple roots when that exact path does not exist and every split
139
+ token is an existing file or directory. Existing paths with spaces still take
140
+ priority; quote individual spaced paths if combining them in one string.
141
+
142
+ File roots search only that file and report paths relative to the file's parent
143
+ directory. Multi-root searches report paths relative to the roots' common base,
144
+ so sibling roots keep prefixes such as `src/...` and `tests/...`; this also lets
145
+ `exclude=["src/generated/**"]` target one root.
146
+
147
+ Controlled failures raise `ExploreError` subclasses:
148
+
149
+ - `ExploreArgumentError` for invalid arguments.
150
+ - `ExplorePatternError` for invalid/unsupported patterns.
151
+ - `ExploreRootError` for missing or unsearchable roots.
152
+ - `ExploreBackendError` for backend runtime failures.
153
+
154
+ ## CLI
155
+
156
+ ```bash
157
+ codetool-explore "UserService" . --literal --format text
158
+ codetool-explore "service" . --target path --literal
159
+ codetool-explore "User(Service|Repository)" --root src --mode snippets --raw
160
+ codetool-explore "search_workspace" --root src --root webapp --root tests --literal
161
+ codetool-explore --read README.md --start-line 20 --limit 40
162
+ codetool-explore --list src --glob "*.py"
163
+ ```
164
+
165
+ The CLI defaults to compact JSON for search, plain text for `--read`, and
166
+ tree-compressed text for `--list`.
167
+ Use `--format text` or `--raw` for raw search text; no search matches print
168
+ `No Match`. Repeat `--root` for multiple search roots; read/list accept a single
169
+ root only. A single quoted space-delimited `--root` is accepted as a compatibility
170
+ fallback when it can be split into existing roots.
171
+
172
+ ## Install
173
+
174
+ ```bash
175
+ uv install codetool-explore
176
+ ```
177
+
178
+ Wheels can include a platform-specific Rust helper. Without it, the package still works through the Python stdlib backend.
179
+
180
+ ## Benchmarks
181
+
182
+ Reproduce and refresh the generated README data:
183
+
184
+ ```bash
185
+ cargo build --release --manifest-path rust/Cargo.toml
186
+ uv run python benchmarks/benchmark_search.py \
187
+ --output reports/search_benchmark.json \
188
+ --update-readme
189
+ uv run python benchmarks/benchmark_output_lengths.py \
190
+ --output reports/rtk_vs_codetool_output_lengths.json
191
+ uv run python scripts/update_readme_benchmarks.py \
192
+ --performance reports/search_benchmark.json \
193
+ --tokens reports/rtk_vs_codetool_output_lengths.json
194
+ ```
195
+
196
+ <!-- benchmark-results:start -->
197
+
198
+ <!-- Generated by scripts/update_readme_benchmarks.py; do not edit by hand. -->
199
+
200
+ ### Execution performance
201
+
202
+ Mean of median wall-clock timings across 5 corpora × 7 scenarios, 5 measured rounds after 1 warmup.
203
+
204
+ | Tool | Mean median time | Chart |
205
+ | --- | ---: | --- |
206
+ | `codetool-explore` | 127.0 ms | ███████████░░░░░░░ |
207
+ | `rg` | 138.2 ms | ████████████░░░░░░ |
208
+ | `rtk` | 199.7 ms | ██████████████████ |
209
+
210
+ `codetool-explore` is the fastest tool in this run.
211
+
212
+ Source: `reports/search_benchmark.json`.
213
+
214
+ ### Token compression
215
+
216
+ Token counts use `tiktoken` when available. The table compares output across 7 RTK-corpus scenarios.
217
+
218
+ | Output | Tokens | Bytes | Chart |
219
+ | --- | ---: | ---: | --- |
220
+ | `explore(..., result_format="text")` | 11,008 | 34.3 KB | ██░░░░░░░░░░░░░░░░ |
221
+ | `rtk grep` stdout | 19,646 | 60.1 KB | ███░░░░░░░░░░░░░░░ |
222
+ | default `explore(...)` | 38,393 | 125.3 KB | █████░░░░░░░░░░░░░ |
223
+ | `explore(..., result_format="full")` | 39,027 | 134.7 KB | █████░░░░░░░░░░░░░ |
224
+ | `rg` stdout | 129,775 | 402.4 KB | ██████████████████ |
225
+
226
+ 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.
227
+
228
+ Source: `reports/rtk_vs_codetool_output_lengths.json`.
229
+
230
+ <!-- benchmark-results:end -->
231
+
232
+ ## Development
233
+
234
+ ```bash
235
+ uv run pytest
236
+ uv run python scripts/package_rust_binary.py
237
+ uv build --wheel
238
+ ```
239
+
240
+ Release wheels are built in CI with the staged Rust helper for each target platform.
@@ -0,0 +1,33 @@
1
+ codetool_explore/__init__.py,sha256=4eTGfxKeHutGn4vWnKYdwzHF3YNuI2KMlAxAiGQwW4I,1016
2
+ codetool_explore/api.py,sha256=vTmT-ft_-swP-6Bp9ZI6idA8J6bzyt6mxtYzBdp1oXk,9625
3
+ codetool_explore/cli.py,sha256=fY5UhTtZH2sS5_BPX_AgAuQBEyHOemylSfJMs7pyAj0,6061
4
+ codetool_explore/compression.py,sha256=gB22Ofv9fvsiwjwNnRdOxnm4wBrp-_iHIcSspIEtQXI,5491
5
+ codetool_explore/cursor.py,sha256=-SHdSxUO0gqmrp6lZMtRlfgOo95jJNxl1I_OotPel9U,2113
6
+ codetool_explore/errors.py,sha256=rKaczr3dTmL4ipbuICXyCO5vmyjXGcx85m3YKrX-2UI,663
7
+ codetool_explore/explorer.py,sha256=MVGgQKMZwKQ439OLoXXQ8iyFDAIGkAl40T3etg4f6Nc,16889
8
+ codetool_explore/ignore.py,sha256=rRYT9Irc3X7tZFySDdNSTachXkg0ueNy-Jv4G-Ebw8A,6808
9
+ codetool_explore/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
+ codetool_explore/ranking.py,sha256=s9ekc_rEpy_irC384vekxhYeQXTgTsNf8zSnumYp2Vo,10456
11
+ codetool_explore/roots.py,sha256=DxtP_Ze5Woq2W0k8XiX9vE_7E2Dt1-f6IU4iDJ4bYEc,4557
12
+ codetool_explore/rust_backend.py,sha256=NvYWhsuHUXKY3ukVCktmJBIbz6iGqaX0eFSxPBwYfhI,9867
13
+ codetool_explore/text_output.py,sha256=4mlf28FIVXEJF9DOUp8Jk4KPFQpb2Ry1oH3RwoZ3mhM,14916
14
+ codetool_explore/python_backend/__init__.py,sha256=BpfQ_5ugzAp2PmiGPYtaAMJYWyjeaCeqa6CmuR45QBU,4559
15
+ codetool_explore/python_backend/case.py,sha256=rOUsFhlL6g8La0D4ek1x4j487mloSUeEiUt2qhrGAd4,819
16
+ codetool_explore/python_backend/config.py,sha256=cJuuQUU8WQYlp_bY686IrbHxoBGZYFb8zPulHYwBs8o,1175
17
+ codetool_explore/python_backend/constants.py,sha256=FK_-TOlNR_mrXDTqYhlNnwg4goGYMKXPpSpIc-wcSlc,1303
18
+ codetool_explore/python_backend/file_search.py,sha256=VMF3XXpIoq65RcUnqmN7Mdk_X1yd4VXMTXTSZ-KQR40,1704
19
+ codetool_explore/python_backend/ignore_rules.py,sha256=GEQN4HLr9uCm09cfP45Wm1pa35Qnx4C1XCFTO7ztoYI,1177
20
+ codetool_explore/python_backend/literal.py,sha256=E5FHlIUfYofx7HzuVKGuZD0GBXHgR5NuSdImOZVf_V0,2341
21
+ codetool_explore/python_backend/matcher.py,sha256=WO68HbrNIgRoSqWlQ1jK4YeQTVCdP9e135WMwc-gM_k,2258
22
+ codetool_explore/python_backend/models.py,sha256=b7cYRcRzZxMIS-0ql8pFqThKMOG0pYFrOZF7-_T3snU,1177
23
+ codetool_explore/python_backend/output.py,sha256=A14Kb4IyWUnTpxtuWbaUAuYNAhINDKLTlPgWGeZcygo,2096
24
+ codetool_explore/python_backend/regex_search.py,sha256=Wq6TFdZxtLOjdlHbsa7xLBc11IvIuVFc5csxlfd8B_0,1790
25
+ codetool_explore/python_backend/search.py,sha256=98fCRIy13br1QSA76Cny1jokl1iAKoA84NO5oxrAItY,10968
26
+ codetool_explore/python_backend/text.py,sha256=piBrblyc38EcbBb-gebjwIVP-V-63akkHfSYb4gfyFk,1094
27
+ codetool_explore/python_backend/walker.py,sha256=4fOe914cRAfMtd0eyg2iDjbAWG275prdr6UbacnnnjQ,4497
28
+ codetool_explore/_bin/codetool-explore-rust-windows-arm64.exe,sha256=yK7_M0UUQ_MEXYtReVabGoL1WN1ndxHF-5RP0AsRD3g,2059776
29
+ codetool_explore-0.5.0.dist-info/METADATA,sha256=7H_J77NsSrKy0ryLBsFe0w1fhcfzLELjds3ibXPehk4,10555
30
+ codetool_explore-0.5.0.dist-info/WHEEL,sha256=w7VOCnMnx9r5-lu2GjBVd6BdGrPc0Fm_UFMvUozKtTg,94
31
+ codetool_explore-0.5.0.dist-info/entry_points.txt,sha256=WoDNNkptvfYXekUyd5CDzOWrTwY7ssk6AGKwdoLmClU,62
32
+ codetool_explore-0.5.0.dist-info/licenses/LICENSE,sha256=Vv1XewZgbAhS6ciB2kfJ8y1-Ouwb23Jtj0KCmJl37VA,1080
33
+ codetool_explore-0.5.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.29.0
3
+ Root-Is-Purelib: false
4
+ Tag: py3-none-win_arm64
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ codetool-explore = codetool_explore.cli:run
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 drod
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.