| name | tensor-grep-multi-project-search |
| description | Use when searching across a multi-project workspace root (many sibling repos) with tensor-grep — bare unscoped search is refused; scope with --glob/--type/--max-depth or opt in with --allow-broad-generated-scan; prefer per-repo paths for agent/symbol/find work; pass explicit --deadline on whole-repo agent; narrow mega-repo PATH when result_incomplete. |
tensor-grep multi-project workspace search
Use this when the cwd is a workspace parent (e.g. /mnt/c/dev/projects) containing many unrelated repos, not a single git root.
Verified against tg 1.110.14 (2026-08-11 Windows uvx; prior stamps 1.95.0 / 1.91.0 WSL).
Do this
tg search PATTERN . --glob "*.py" --max-depth 3 --json
tg search PATTERN . --glob "*.js" --max-depth 3 --json
tg search PATTERN my-repo --rank --json
tg find "intent phrase" my-repo/src --deadline 20 --json
tg orient my-repo --ignore "node_modules/**" --json
tg orient . --ignore "node_modules/**" --json
tg agent my-repo/src "task" --json
tg agent my-repo "task" --deadline 20 --json
tg agent my-repo/subdir "task" --json
Do not do this
tg search PATTERN
tg search PATTERN --glob "*.py"
tg agent . "task"
tg callers . SYMBOL
tg codemap my-repo
tg search TODO . --type ts --max-depth 4
The bare-tg search refusal (A9, v1.92.3) is a single generic mechanism, not a special multi-project
case. IMPLICIT_SEARCH_WALK_FILE_CEILING = 1500 is one constant. Content check (this pass): it is
defined in io/scan_limits.py (grep -n IMPLICIT_SEARCH_WALK_FILE_CEILING src/tensor_grep/io/scan_limits.py
→ = 1500), and merely re-exported from io/directory_scanner.py for import convenience — the prior
wording of this note ("single-sourced in io/directory_scanner.py") named the re-export site as the
source, not the definition site. It is checked coherently across all 3 doors (the Python bootstrap probe
bootstrap._search_paths_include_oversized_implicit_root, main.py's _LARGE_ROOT_SCAN_FILE_CEILING
alias, and the Rust rg_passthrough.rs::IMPLICIT_SEARCH_WALK_FILE_CEILING constant — all three confirmed
present via grep this pass) — it fires whenever the scan PATH was defaulted (no path argument
given at all) and the resulting root is over 1500 files, workspace-parent or not. Before this shipped,
the same shape was a silent ~60s timeout, not a fast refusal — don't describe the old magnitude as
current.
The bypasses in "Do this" above (--max-depth, an explicit PATH like . or my-repo) work because they
give the walk an explicit scope — they are the SAME gate's escape hatches, not a separate multi-project
allowance. --glob/--type alone do NOT bypass the ceiling when the path itself is still defaulted
— only an explicit PATH, --max-depth, or the deliberate opt-in --allow-broad-generated-scan count as
scoping the walk.
How to read exit codes
| Exit | Meaning in this CUJ |
|---|
0 | Complete enough for the scoped ask |
1 | Complete with zero matches (not a refuse) — common on scoped parent walks |
2 | Incomplete / refused / deadline partial — parse JSON; do not treat as full coverage |
| timeout / empty | Prefer narrower PATH or explicit --deadline; skip codemap |
Parent-root refuse class (1.110.x): unscoped
tg search needle C:\dev\projects --json → exit 2 with
incomplete_reason_class=workspace_root_refused and error.code=workspace_root_refused
(not generic scan_limit). Scoped --glob/--max-depth on an explicit parent PATH should
not emit that refuse class.
Related
tensor-grep, tensor-grep-find-and-route, tensor-grep-workspace-dogfood, tensor-grep-enterprise-agent