grepmax 0.26.7 → 0.26.9
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.
- package/.claude-plugin/marketplace.json +1 -1
- package/README.md +22 -0
- package/dist/config.js +22 -2
- package/dist/lib/daemon/daemon.js +6 -1
- package/dist/lib/search/searcher.js +22 -8
- package/dist/lib/store/vector-db.js +44 -0
- package/package.json +1 -1
- package/plugins/grepmax/.claude-plugin/plugin.json +1 -1
- package/plugins/grepmax/agents/semantic-explore.md +21 -1
- package/plugins/grepmax/skills/grepmax/SKILL.md +37 -3
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"name": "grepmax",
|
|
11
11
|
"source": "./plugins/grepmax",
|
|
12
12
|
"description": "Semantic code search for Claude Code. Automatically indexes your project and provides intelligent search capabilities.",
|
|
13
|
-
"version": "0.26.
|
|
13
|
+
"version": "0.26.9",
|
|
14
14
|
"author": {
|
|
15
15
|
"name": "Robert Owens",
|
|
16
16
|
"email": "robowens@me.com"
|
package/README.md
CHANGED
|
@@ -221,6 +221,15 @@ The daemon auto-starts when you run `gmax add`, `gmax index`, `gmax remove`, `gm
|
|
|
221
221
|
|
|
222
222
|
gmax can use a local LLM (via llama-server) for agentic codebase investigation. This is entirely opt-in and disabled by default — gmax works fine without it.
|
|
223
223
|
|
|
224
|
+
> **Memory footprint.** `gmax llm start`, `investigate`, `review`, and `summarize` load a multi-GB
|
|
225
|
+
> GGUF model (typical coding models run 16–21 GB). On a memory-constrained machine that can stall
|
|
226
|
+
> or hang the host. Start it deliberately, not as a reflex — and if you run coding agents against
|
|
227
|
+
> this repo, they should be told not to invoke these on their own initiative. The bundled skill
|
|
228
|
+
> already carries that instruction.
|
|
229
|
+
>
|
|
230
|
+
> Everything else in gmax — search, `trace`, `impact`, `context`, `--context-for-llm` — runs off
|
|
231
|
+
> the local index with no model load.
|
|
232
|
+
|
|
224
233
|
```bash
|
|
225
234
|
gmax llm on # Enable LLM features (persists to config)
|
|
226
235
|
gmax llm start # Start llama-server (auto-starts daemon too)
|
|
@@ -393,6 +402,19 @@ gmax watch stop && gmax watch --daemon -b # Restart daemon
|
|
|
393
402
|
|
|
394
403
|
`gmax doctor` reports ANN index state. `ANN: vector index not built` is normal with the default exact-search configuration.
|
|
395
404
|
|
|
405
|
+
### Known issues
|
|
406
|
+
|
|
407
|
+
Some log output looks alarming but is expected and self-healing. Before filing a bug, check
|
|
408
|
+
[`docs/known-limitations.md`](docs/known-limitations.md) — it covers what each case means and
|
|
409
|
+
whether you need to act.
|
|
410
|
+
|
|
411
|
+
| You see | What it means |
|
|
412
|
+
|---|---|
|
|
413
|
+
| `Optimize panicked ... inverted/builder.rs` | Upstream Lance bug in incremental FTS merge ([lance#8310](https://github.com/lance-format/lance/issues/8310)). gmax rebuilds the index and retries automatically; no data loss, no action needed. |
|
|
414
|
+
| `disabling auto-rebuild until an optimize succeeds` | Transient, not a wedge. The next successful optimize clears it. Search stays available. |
|
|
415
|
+
| `ANN: vector index not built` | Normal — exact search is the default. |
|
|
416
|
+
| `npm audit` reports advisories on install | Two transitive advisories (`sharp`, `adm-zip`) have no upstream fix yet; neither is on a code path gmax executes. |
|
|
417
|
+
|
|
396
418
|
## Contributing
|
|
397
419
|
|
|
398
420
|
See [CLAUDE.md](CLAUDE.md) for development setup, commands, and architecture details.
|
package/dist/config.js
CHANGED
|
@@ -251,8 +251,28 @@ exports.DISK_LOW_BYTES = (() => {
|
|
|
251
251
|
const gb = Number.parseFloat((_a = process.env.GMAX_DISK_LOW_GB) !== null && _a !== void 0 ? _a : "20");
|
|
252
252
|
return (Number.isFinite(gb) && gb > 0 ? gb : 20) * 1024 * 1024 * 1024;
|
|
253
253
|
})();
|
|
254
|
-
// Trigger compaction when small (uncompacted) fragment count exceeds this
|
|
255
|
-
|
|
254
|
+
// Trigger compaction when small (uncompacted) fragment count exceeds this.
|
|
255
|
+
//
|
|
256
|
+
// Deliberately high. Lance's optimize() merges the *whole* table into ~2
|
|
257
|
+
// fragments regardless of how many small ones it absorbs, so a compaction costs
|
|
258
|
+
// the same full-table rewrite at 51 fragments as at 400 — the threshold only
|
|
259
|
+
// decides how far that fixed cost is amortized. At 50 it was amortized as little
|
|
260
|
+
// as possible: on a continuously-watched project this fired every ~15-25min and
|
|
261
|
+
// rewrote ~10-14GB each time, measured at 40 compactions / 586GB over 26h.
|
|
262
|
+
//
|
|
263
|
+
// Fragmentation also does not cost what you would expect. With ANN off (the
|
|
264
|
+
// default), vector search is a brute-force scan that Lance parallelizes across
|
|
265
|
+
// fragments, so compacting to 2 fragments collapses it to 2-way parallelism.
|
|
266
|
+
// Interleaved benchmark, 395k rows / 384d, 96 samples per config:
|
|
267
|
+
//
|
|
268
|
+
// fragments | 2 | 50 | 200 | 800
|
|
269
|
+
// vector p50| 165.6 | 73.4 | 61.6 | 66.8 (ms)
|
|
270
|
+
//
|
|
271
|
+
// Flat from 50-800; 2 is 2.5x slower. So raising this wins on writes *and*
|
|
272
|
+
// latency. 400 sits inside the measured range with margin at both ends.
|
|
273
|
+
// Caveat: measured on the no-ANN path — revisit if GMAX_ANN=1 becomes default,
|
|
274
|
+
// since an ANN index partitions independently of fragments.
|
|
275
|
+
exports.FRAGMENT_COMPACT_THRESHOLD = 400;
|
|
256
276
|
// Extensions we consider for indexing to avoid binary noise and improve relevance.
|
|
257
277
|
exports.INDEXABLE_EXTENSIONS = new Set([
|
|
258
278
|
".ts",
|
|
@@ -174,7 +174,11 @@ class Daemon {
|
|
|
174
174
|
return new pool_1.WorkerPool(generation, embedMode);
|
|
175
175
|
}
|
|
176
176
|
createVectorDb(vectorDim, lease) {
|
|
177
|
-
|
|
177
|
+
const db = new vector_db_1.VectorDB(config_1.PATHS.lancedbDir, vectorDim, lease);
|
|
178
|
+
// The daemon owns the store, so it is the one process allowed to create or
|
|
179
|
+
// rebuild the shared FTS index. Readers adopt it; see VectorDB.adoptFTSIndex.
|
|
180
|
+
db.markIndexOwner();
|
|
181
|
+
return db;
|
|
178
182
|
}
|
|
179
183
|
mlxMode(config) {
|
|
180
184
|
if (config.embedMode !== "gpu")
|
|
@@ -318,6 +322,7 @@ class Daemon {
|
|
|
318
322
|
this.activeConfig = (0, index_config_1.readGlobalConfig)();
|
|
319
323
|
this.activeGeneration = (0, embedding_generation_1.resolveEmbeddingGeneration)(this.activeConfig);
|
|
320
324
|
this.vectorDb = new vector_db_1.VectorDB(config_1.PATHS.lancedbDir, this.activeGeneration.vectorDim);
|
|
325
|
+
this.vectorDb.markIndexOwner();
|
|
321
326
|
this.workerPool = this.createWorkerPool(this.activeGeneration, this.activeConfig.embedMode);
|
|
322
327
|
this.vectorDb.startMaintenanceLoop((fn) => this.runSharedOperation("store-maintenance", undefined, () => fn()));
|
|
323
328
|
console.log("[daemon] Opening MetaCache:", config_1.PATHS.lmdbPath);
|
|
@@ -15,6 +15,7 @@ exports.buildWhereClause = buildWhereClause;
|
|
|
15
15
|
const config_1 = require("../../config");
|
|
16
16
|
const ann_config_1 = require("../store/ann-config");
|
|
17
17
|
const filter_builder_1 = require("../utils/filter-builder");
|
|
18
|
+
const logger_1 = require("../utils/logger");
|
|
18
19
|
const pool_1 = require("../workers/pool");
|
|
19
20
|
const intent_1 = require("./intent");
|
|
20
21
|
const pagerank_1 = require("./pagerank");
|
|
@@ -436,12 +437,15 @@ class Searcher {
|
|
|
436
437
|
this.ftsIndexChecked = true;
|
|
437
438
|
this.ftsLastCheckedAt = now;
|
|
438
439
|
try {
|
|
439
|
-
|
|
440
|
+
// Adopt-only: search runs in every process, so building here raced
|
|
441
|
+
// CreateIndex across processes and duplicated a full-size index per
|
|
442
|
+
// winner. Owners build it (daemon pre-warm, `gmax index`, maintenance).
|
|
443
|
+
yield this.db.adoptFTSIndex();
|
|
440
444
|
this.ftsAvailable = true;
|
|
441
445
|
}
|
|
442
446
|
catch (e) {
|
|
443
447
|
this.ftsAvailable = false;
|
|
444
|
-
|
|
448
|
+
(0, logger_1.debug)("searcher", `FTS index unavailable, vector-only search: ${e}`);
|
|
445
449
|
}
|
|
446
450
|
}
|
|
447
451
|
// Phase A: Lightweight retrieval — only columns needed for RRF, cosine, boost, dedup
|
|
@@ -501,13 +505,23 @@ class Searcher {
|
|
|
501
505
|
this.ftsAvailable = false;
|
|
502
506
|
const msg = e instanceof Error ? e.message : String(e);
|
|
503
507
|
if (msg.includes("position")) {
|
|
504
|
-
// FTS index lacks positional data — rebuild it
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
508
|
+
// FTS index lacks positional data — rebuild it, but only from the
|
|
509
|
+
// index owner. This drops the index before recreating it, so a
|
|
510
|
+
// non-owner (CLI fallback, MCP session) would yank the shared index
|
|
511
|
+
// out from under every other process and, with several running at
|
|
512
|
+
// once, race CreateIndex on the way back up. Non-owners degrade to
|
|
513
|
+
// vector-only and let the daemon repair it.
|
|
514
|
+
if (this.db.canBuildIndexes()) {
|
|
515
|
+
try {
|
|
516
|
+
yield this.db.createFTSIndex(true);
|
|
517
|
+
this.ftsAvailable = true;
|
|
518
|
+
console.warn("[Searcher] Rebuilt FTS index with position support — retry search");
|
|
519
|
+
}
|
|
520
|
+
catch (_r) { }
|
|
521
|
+
}
|
|
522
|
+
else {
|
|
523
|
+
(0, logger_1.debug)("searcher", "FTS index lacks positions; deferring rebuild to the index owner");
|
|
509
524
|
}
|
|
510
|
-
catch (_r) { }
|
|
511
525
|
}
|
|
512
526
|
else {
|
|
513
527
|
console.warn(`[Searcher] FTS search failed (will retry later): ${msg}`);
|
|
@@ -102,6 +102,8 @@ class VectorDB {
|
|
|
102
102
|
this.maintainedTableVersion = null;
|
|
103
103
|
this.lastMaintenanceMs = 0;
|
|
104
104
|
this.ftsIndexEnsured = false;
|
|
105
|
+
/** Only an index owner may create/rebuild shared indexes — see markIndexOwner. */
|
|
106
|
+
this.indexOwner = false;
|
|
105
107
|
this.lastOptimizeDidWork = false;
|
|
106
108
|
this.maintenanceRunner = (fn) => fn();
|
|
107
109
|
/** Latched when a from-scratch FTS rebuild failed to stop an optimize
|
|
@@ -735,6 +737,48 @@ class VectorDB {
|
|
|
735
737
|
return this.withWriteGate(() => this.createFTSIndexUnsafe(rebuild, retries));
|
|
736
738
|
});
|
|
737
739
|
}
|
|
740
|
+
/**
|
|
741
|
+
* Mark this instance as the store's index owner — the daemon, or a
|
|
742
|
+
* deliberately exclusive CLI operation. Only an owner may create or rebuild
|
|
743
|
+
* the shared FTS index; see `adoptFTSIndex`.
|
|
744
|
+
*/
|
|
745
|
+
markIndexOwner() {
|
|
746
|
+
this.indexOwner = true;
|
|
747
|
+
}
|
|
748
|
+
/** Whether this instance may create or rebuild shared indexes. */
|
|
749
|
+
canBuildIndexes() {
|
|
750
|
+
return this.indexOwner;
|
|
751
|
+
}
|
|
752
|
+
/**
|
|
753
|
+
* Adopt the FTS index if one already exists, without ever building it.
|
|
754
|
+
*
|
|
755
|
+
* Search runs in *every* process — the daemon, each CLI invocation that falls
|
|
756
|
+
* back in-process, each MCP session. `createFTSIndex` on a miss meant N
|
|
757
|
+
* processes could issue `CreateIndex` against the same table version
|
|
758
|
+
* concurrently: Lance rejects the losers with a retryable commit conflict
|
|
759
|
+
* (observed 2026-08-17T00:03, all 5 retries lost) and every winner writes a
|
|
760
|
+
* full-size inverted index — ~1.4GB each on this store, which is how
|
|
761
|
+
* `_indices` reached 47GB across 35 near-identical copies.
|
|
762
|
+
*
|
|
763
|
+
* Building is therefore reserved for the explicit paths that already run
|
|
764
|
+
* under an owner: daemon pre-warm, `gmax index`, and post-optimize
|
|
765
|
+
* maintenance. Throws when no index exists so callers set `ftsAvailable =
|
|
766
|
+
* false` and degrade to vector-only search — never silently reports FTS as
|
|
767
|
+
* ready.
|
|
768
|
+
*/
|
|
769
|
+
adoptFTSIndex() {
|
|
770
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
771
|
+
if (this.ftsIndexEnsured)
|
|
772
|
+
return;
|
|
773
|
+
const table = yield this.ensureTable();
|
|
774
|
+
const indices = yield table.listIndices();
|
|
775
|
+
const existing = indices.find((index) => index.name === "content_idx" || index.columns.includes("content"));
|
|
776
|
+
if (!existing) {
|
|
777
|
+
throw new Error("[vector-db] FTS index not built yet; this process is not the index owner");
|
|
778
|
+
}
|
|
779
|
+
this.ftsIndexEnsured = true;
|
|
780
|
+
});
|
|
781
|
+
}
|
|
738
782
|
createVectorIndex() {
|
|
739
783
|
return __awaiter(this, arguments, void 0, function* (rebuild = false, retries = 5, checkOnly = false) {
|
|
740
784
|
if (this.checkDiskPressure() !== "ok") {
|
package/package.json
CHANGED
|
@@ -49,11 +49,26 @@ gmax skeleton src/lib/auth.ts
|
|
|
49
49
|
gmax project
|
|
50
50
|
```
|
|
51
51
|
|
|
52
|
+
**Dependency shape** — god nodes, hub files, cycles, dead candidates in one pass:
|
|
53
|
+
```
|
|
54
|
+
gmax audit --agent --top 10
|
|
55
|
+
```
|
|
56
|
+
Start here for "explain this codebase" and "what's central here" questions. Rows are
|
|
57
|
+
`god <symbol> <path:line> <refs> <chunks>`, `hub <file> <refs> <deps>`, `cycle <files> <n>`,
|
|
58
|
+
`dead <symbol> <path:line>`. Dead candidates are hypotheses — dynamic dispatch and reflection
|
|
59
|
+
are invisible to the static graph.
|
|
60
|
+
|
|
52
61
|
**Related files** — dependencies and dependents:
|
|
53
62
|
```
|
|
54
63
|
gmax related src/lib/auth.ts
|
|
55
64
|
```
|
|
56
65
|
|
|
66
|
+
**Blast radius / test coverage** — before reporting on the risk of a change:
|
|
67
|
+
```
|
|
68
|
+
gmax impact handleAuth --agent # dependents + affected tests
|
|
69
|
+
gmax test handleAuth --agent # tests exercising the symbol
|
|
70
|
+
```
|
|
71
|
+
|
|
57
72
|
### Secondary: Standard tools
|
|
58
73
|
|
|
59
74
|
- `Grep` — for exact string matches (identifiers, error codes, imports)
|
|
@@ -62,13 +77,18 @@ gmax related src/lib/auth.ts
|
|
|
62
77
|
|
|
63
78
|
## Strategy
|
|
64
79
|
|
|
80
|
+
0. **Never start a local model.** `gmax investigate`, `review`, `summarize`, and `llm start` load a
|
|
81
|
+
multi-GB LLM and can stall the machine. They are not part of your toolkit — the index answers
|
|
82
|
+
these questions without them.
|
|
65
83
|
1. **Start semantic** — use `gmax "query" --agent` first. Be specific (5+ words).
|
|
66
84
|
2. **Peek before reading** — `gmax peek <symbol>` gives you signature + context in one call. Only `Read` the file if you need more.
|
|
67
85
|
3. **Skeleton before reading** — `gmax skeleton <path>` before reading large files.
|
|
68
86
|
4. **Trace for flow** — `gmax trace <symbol>` to understand call chains.
|
|
69
87
|
5. **Use `--role ORCHESTRATION`** to skip type definitions and find actual logic.
|
|
70
88
|
6. **Use `--agent` on everything** — compact output saves tokens.
|
|
71
|
-
7. **
|
|
89
|
+
7. **Scope big repos** — `--in <subpath>` / `--exclude <subpath>` (repeatable) on audit, dead, log,
|
|
90
|
+
surprises, and search.
|
|
91
|
+
8. **Parallelize** — fire multiple gmax/grep/read calls in parallel when independent.
|
|
72
92
|
|
|
73
93
|
## If gmax search returns nothing
|
|
74
94
|
|
|
@@ -9,6 +9,7 @@ allowed-tools: "Bash(gmax:*), Read"
|
|
|
9
9
|
- **Know the exact string/symbol?** → `Grep` tool (fastest, zero overhead)
|
|
10
10
|
- **Know the file already?** → `Read` tool directly
|
|
11
11
|
- **Searching by concept/behavior?** → `Bash(gmax "query" --agent)` (semantic search)
|
|
12
|
+
- **New to the codebase?** → `Bash(gmax audit --agent)` (god nodes, hubs, cycles in one pass)
|
|
12
13
|
- **Need full function body?** → `Bash(gmax extract <symbol>)` (complete source with line numbers)
|
|
13
14
|
- **Quick symbol overview?** → `Bash(gmax peek <symbol>)` (signature + callers + callees)
|
|
14
15
|
- **Need file structure?** → `Bash(gmax skeleton <path>)`
|
|
@@ -186,6 +187,25 @@ gmax dead handleAuth --in src/ # restrict to a sub-path
|
|
|
186
187
|
```
|
|
187
188
|
Status is `DEAD` (no callers, not exported), `PUBLIC EXPORT` (no internal callers but the defining chunk is exported — check external usage), or `LIVE` (with caller count + top-3 file:line). The call graph reflects what tree-sitter chunked: dynamic dispatch, reflection, eval, and string-built call sites won't show up — `DEAD` is a hypothesis, not a proof.
|
|
188
189
|
|
|
190
|
+
### Audit — `gmax audit`
|
|
191
|
+
```
|
|
192
|
+
gmax audit # god nodes, hub files, cycles, dead candidates
|
|
193
|
+
gmax audit --agent --top 5 # compact TSV, 5 per category
|
|
194
|
+
gmax audit --in src/ --exclude tests/ # scope to a sub-path
|
|
195
|
+
```
|
|
196
|
+
One pass over the static reference graph — the fastest way to get the shape of an unfamiliar
|
|
197
|
+
codebase. Agent rows are `god <symbol> <path:line> <refs> <chunks>`, `hub <file> <refs> <deps>`,
|
|
198
|
+
`cycle <comma-separated files> <n>`, `dead <symbol> <path:line>`, plus `scanned`/`dead_total`.
|
|
199
|
+
Dynamic dispatch, reflection, and eval are invisible to it, so dead candidates are hypotheses.
|
|
200
|
+
|
|
201
|
+
### Surprises — `gmax surprises` (experimental)
|
|
202
|
+
```
|
|
203
|
+
gmax surprises --agent # embedding-similar file pairs the static graph misses
|
|
204
|
+
gmax surprises --top 10 --min-sim 0.7 # tighten the similarity floor
|
|
205
|
+
```
|
|
206
|
+
Orientation only — surfaces cross-directory pairs that look related by embedding but share no
|
|
207
|
+
static edge. Useful for spotting duplication or missing abstractions, not for proving anything.
|
|
208
|
+
|
|
189
209
|
### Context — `gmax context <topic-or-path> --budget <tokens>`
|
|
190
210
|
```
|
|
191
211
|
gmax context "authentication system" --budget 4000
|
|
@@ -195,7 +215,16 @@ gmax context src/lib/auth/ --budget 3000
|
|
|
195
215
|
```
|
|
196
216
|
Use the path form when you already know the file or directory; it skips semantic search and gives deterministic structure/excerpt context.
|
|
197
217
|
|
|
198
|
-
### Investigate — `gmax investigate "question"` (
|
|
218
|
+
### Investigate — `gmax investigate "question"` (loads a multi-GB local LLM)
|
|
219
|
+
|
|
220
|
+
> **Ask the user first.** `investigate`, `review`, and `summarize` start `llama-server` with a
|
|
221
|
+
> multi-GB local model. On memory-constrained machines that can stall or hang the host. Never run
|
|
222
|
+
> them — or `gmax llm start` — on your own initiative, including "just to check" or as a fallback
|
|
223
|
+
> when search seems insufficient. Run them only when the user asks for that command in the moment.
|
|
224
|
+
>
|
|
225
|
+
> You almost never need them: `gmax context`, `--context-for-llm`, and `trace`/`impact` answer the
|
|
226
|
+
> same questions using the index you already have, with no model load.
|
|
227
|
+
|
|
199
228
|
```
|
|
200
229
|
gmax investigate "how does authentication work?"
|
|
201
230
|
gmax investigate "what would break if I changed VectorDB?" -v
|
|
@@ -210,16 +239,19 @@ gmax status --agent # compact: name\tchunks\tage\tstatus
|
|
|
210
239
|
gmax related src/file.ts --agent # compact: dep:/rev: path\tcount
|
|
211
240
|
gmax project --agent # compact: key\tvalue pairs
|
|
212
241
|
gmax index # reindex current directory
|
|
242
|
+
gmax help-agent # reprint this cheatsheet in the terminal
|
|
213
243
|
gmax config # view/change settings
|
|
214
244
|
gmax doctor # health check
|
|
215
245
|
gmax doctor --fix # auto-repair (compact, prune, clear stale locks)
|
|
216
|
-
gmax
|
|
246
|
+
gmax repair --rebuild # last resort: destructive whole-store rebuild
|
|
247
|
+
gmax llm on/off/start/stop/status # local LLM server — see the warning above; ask first
|
|
217
248
|
```
|
|
218
249
|
|
|
219
250
|
## Workflow
|
|
220
251
|
|
|
221
252
|
1. **Add** — `Bash(gmax add)` to register and index a new project
|
|
222
|
-
2. **Explore** — `Bash(gmax project)` for overview of a new codebase
|
|
253
|
+
2. **Explore** — `Bash(gmax project)` for overview of a new codebase, then
|
|
254
|
+
`Bash(gmax audit --agent)` for the dependency shape (god nodes, hubs, cycles)
|
|
223
255
|
3. **Search** — `Bash(gmax "query" --agent)` to find code. Add `--symbol` for function/class names.
|
|
224
256
|
4. **Peek** — `Bash(gmax peek <symbol>)` for a quick overview (signature + callers + callees)
|
|
225
257
|
5. **Extract** — `Bash(gmax extract <symbol>)` for the full function body with line numbers
|
|
@@ -244,6 +276,8 @@ gmax llm on/off/start/stop/status # manage local LLM server
|
|
|
244
276
|
- **Use `--skeleton`** when `--agent` results aren't enough — shows file structure for top matches.
|
|
245
277
|
- **Use `--imports`** when you need to understand a file's dependencies.
|
|
246
278
|
- **Use `--root <dir>`** to search/trace/query a different project from your current directory.
|
|
279
|
+
- **Scope with `--in <subpath>` / `--exclude <subpath>`** (both repeatable) on `audit`, `surprises`,
|
|
280
|
+
`dead`, `log`, and search — narrows a big repo to the area you care about.
|
|
247
281
|
- **Don't search for exact strings** — use grep/Grep for that. gmax finds concepts.
|
|
248
282
|
|
|
249
283
|
## If search fails or returns nothing
|