grepmax 0.7.34 → 0.7.36

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/README.md CHANGED
@@ -125,6 +125,7 @@ gmax "how is the database connection pooled?"
125
125
 
126
126
  | Flag | Description | Default |
127
127
  | --- | --- | --- |
128
+ | `--agent` | Ultra-compact output for AI agents (one line per result). | `false` |
128
129
  | `-m <n>` | Max total results to return. | `5` |
129
130
  | `--per-file <n>` | Max matches to show per file. | `3` |
130
131
  | `-c`, `--content` | Show full chunk content instead of snippets. | `false` |
@@ -148,13 +149,15 @@ gmax "how is the database connection pooled?"
148
149
 
149
150
  ```bash
150
151
  gmax "API rate limiting logic"
151
- gmax "auth handler" --role ORCHESTRATION --lang ts --plain
152
- gmax "database" --file syncer.ts --plain
153
- gmax "VectorDB" --symbol --plain
154
- gmax "error handling" -C 5 --imports
155
- gmax "handler" --name "handle.*" --exclude tests/
152
+ gmax "auth handler" --role ORCHESTRATION --lang ts --agent
153
+ gmax "database" --file syncer.ts --agent
154
+ gmax "VectorDB" --symbol --agent
155
+ gmax "error handling" -C 5 --imports --plain
156
+ gmax "handler" --name "handle.*" --exclude tests/ --agent
156
157
  ```
157
158
 
159
+ > **For AI agents:** Use `--agent` for the most token-efficient output (~90% fewer tokens than default). Output format: `file:line symbol [role] — summary`
160
+
158
161
  ### `gmax index`
159
162
 
160
163
  Index a directory into the centralized store.
@@ -345,6 +345,7 @@ exports.search = new commander_1.Command("search")
345
345
  .option("--imports", "Prepend file imports to each result", false)
346
346
  .option("--name <regex>", "Filter results by symbol name regex")
347
347
  .option("-C, --context <n>", "Include N lines before/after each result")
348
+ .option("--agent", "Ultra-compact output for AI agents (one line per result)", false)
348
349
  .argument("<pattern>", "Natural language query (e.g. \"where do we handle auth?\")")
349
350
  .argument("[path]", "Restrict search to this path prefix")
350
351
  .addHelpText("after", `
@@ -357,7 +358,7 @@ Examples:
357
358
  gmax "handler" --name "handle.*" --exclude tests/
358
359
  `)
359
360
  .action((pattern, exec_path, _options, cmd) => __awaiter(void 0, void 0, void 0, function* () {
360
- var _a, _b, _c, _d, _e;
361
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
361
362
  const options = cmd.optsWithGlobals();
362
363
  const root = process.cwd();
363
364
  const minScore = Number.isFinite(Number.parseFloat(options.minScore))
@@ -451,8 +452,7 @@ Examples:
451
452
  process.env.GMAX_PROJECT_ROOT = projectRoot;
452
453
  vectorDb = new vector_db_1.VectorDB(paths.lancedbDir);
453
454
  // Check for active indexing lock and warn if present
454
- // This allows agents (via shim) to know results might be partial.
455
- if ((0, lock_1.isLocked)(paths.dataDir)) {
455
+ if (!options.agent && (0, lock_1.isLocked)(paths.dataDir)) {
456
456
  console.warn("⚠️ Warning: Indexing in progress... search results may be incomplete.");
457
457
  }
458
458
  const hasRows = yield vectorDb.hasAnyRows();
@@ -506,7 +506,7 @@ Examples:
506
506
  stdio: "ignore",
507
507
  });
508
508
  }
509
- catch (_f) {
509
+ catch (_p) {
510
510
  // Watcher may already be running — ignore
511
511
  }
512
512
  }
@@ -532,7 +532,7 @@ Examples:
532
532
  if (options.role)
533
533
  searchFilters.role = options.role;
534
534
  const searchResult = yield searcher.search(pattern, parseInt(options.m, 10), { rerank: true }, Object.keys(searchFilters).length > 0 ? searchFilters : undefined, pathFilter);
535
- if ((_e = searchResult.warnings) === null || _e === void 0 ? void 0 : _e.length) {
535
+ if (!options.agent && ((_e = searchResult.warnings) === null || _e === void 0 ? void 0 : _e.length)) {
536
536
  for (const w of searchResult.warnings) {
537
537
  console.warn(`Warning: ${w}`);
538
538
  }
@@ -549,10 +549,65 @@ Examples:
549
549
  return defs.some((d) => regex.test(d));
550
550
  });
551
551
  }
552
- catch (_g) {
552
+ catch (_q) {
553
553
  // Invalid regex — skip
554
554
  }
555
555
  }
556
+ // Agent mode: ultra-compact one-line-per-result output
557
+ if (options.agent) {
558
+ if (!filteredData.length) {
559
+ console.log("(none)");
560
+ }
561
+ else {
562
+ for (const r of filteredData) {
563
+ const absP = (_h = (_f = r.path) !== null && _f !== void 0 ? _f : (_g = r.metadata) === null || _g === void 0 ? void 0 : _g.path) !== null && _h !== void 0 ? _h : "";
564
+ const relPath = absP.startsWith(effectiveRoot)
565
+ ? absP.slice(effectiveRoot.length + 1)
566
+ : absP;
567
+ const startLine = Math.max(1, ((_m = (_k = (_j = r.startLine) !== null && _j !== void 0 ? _j : r.start_line) !== null && _k !== void 0 ? _k : (_l = r.generated_metadata) === null || _l === void 0 ? void 0 : _l.start_line) !== null && _m !== void 0 ? _m : 0) + 1);
568
+ const defs = Array.isArray(r.defined_symbols)
569
+ ? r.defined_symbols
570
+ : [];
571
+ const symbol = defs[0] || "";
572
+ const role = ((_o = r.role) !== null && _o !== void 0 ? _o : "")
573
+ .slice(0, 4)
574
+ .toUpperCase();
575
+ const summary = r.summary
576
+ ? ` — ${r.summary}`
577
+ : "";
578
+ const sym = symbol ? ` ${symbol}` : "";
579
+ const rl = role ? ` [${role}]` : "";
580
+ console.log(`${relPath}:${startLine}${sym}${rl}${summary}`);
581
+ }
582
+ }
583
+ // Agent trace (compact)
584
+ if (options.symbol && vectorDb && filteredData.length > 0) {
585
+ try {
586
+ const { GraphBuilder } = yield Promise.resolve().then(() => __importStar(require("../lib/graph/graph-builder")));
587
+ const builder = new GraphBuilder(vectorDb);
588
+ const graph = yield builder.buildGraphMultiHop(pattern, 1);
589
+ if (graph.center) {
590
+ console.log("---");
591
+ for (const t of graph.callerTree) {
592
+ const rel = t.node.file.startsWith(effectiveRoot)
593
+ ? t.node.file.slice(effectiveRoot.length + 1)
594
+ : t.node.file;
595
+ console.log(`<- ${t.node.symbol} ${rel}:${t.node.line + 1}`);
596
+ }
597
+ for (const c of graph.callees.slice(0, 10)) {
598
+ if (c.file) {
599
+ const rel = c.file.startsWith(effectiveRoot)
600
+ ? c.file.slice(effectiveRoot.length + 1)
601
+ : c.file;
602
+ console.log(`-> ${c.symbol} ${rel}:${c.line + 1}`);
603
+ }
604
+ }
605
+ }
606
+ }
607
+ catch (_r) { }
608
+ }
609
+ return;
610
+ }
556
611
  if (options.skeleton) {
557
612
  yield outputSkeletons(filteredData, projectRoot, parseInt(options.m, 10), vectorDb);
558
613
  return;
@@ -634,7 +689,7 @@ Examples:
634
689
  console.log(lines.join("\n"));
635
690
  }
636
691
  }
637
- catch (_h) {
692
+ catch (_s) {
638
693
  // Trace failed — skip silently
639
694
  }
640
695
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "grepmax",
3
- "version": "0.7.34",
3
+ "version": "0.7.36",
4
4
  "author": "Robert Owens <robowens@me.com>",
5
5
  "homepage": "https://github.com/reowens/grepmax",
6
6
  "bugs": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "grepmax",
3
- "version": "0.7.34",
3
+ "version": "0.7.36",
4
4
  "description": "Semantic code search for Claude Code. Automatically indexes your project and provides intelligent search capabilities.",
5
5
  "author": {
6
6
  "name": "Robert Owens",
@@ -89,7 +89,7 @@ async function main() {
89
89
  hookSpecificOutput: {
90
90
  hookEventName: "SessionStart",
91
91
  additionalContext:
92
- 'gmax ready. PREFER CLI over MCP tools — use Bash(gmax "query" --plain) for search, Bash(gmax trace <symbol>) for call graphs, Bash(gmax skeleton <path>) for file structure. CLI is 2x more token-efficient than MCP tool calls. Always add --plain flag.',
92
+ 'gmax ready. PREFER CLI over MCP — use Bash(gmax "query" --agent) for search (one line per result, 89% fewer tokens). Bash(gmax trace <symbol>) for call graphs. Bash(gmax skeleton <path>) for structure. Always use --agent flag.',
93
93
  },
94
94
  };
95
95
  process.stdout.write(JSON.stringify(response));
@@ -13,29 +13,29 @@ Semantic code search — finds code by meaning, not just strings.
13
13
 
14
14
  ## IMPORTANT: Use CLI, not MCP tools
15
15
 
16
- **Always prefer `Bash(gmax ...)` over MCP tool calls.** The CLI is ~2x more token-efficient because MCP tool schemas add ~800 tokens of overhead per call. The CLI has full feature parity with every MCP tool.
16
+ **Always prefer `Bash(gmax ...)` over MCP tool calls.** Use `--agent` for the most token-efficient output (one line per result, ~89% fewer tokens than default).
17
17
 
18
18
  ```
19
- Bash(gmax "auth handler" --role ORCHESTRATION --lang ts --plain -m 3)
19
+ Bash(gmax "auth handler" --role ORCHESTRATION --lang ts --agent -m 3)
20
20
  ```
21
21
 
22
- **Only use MCP tools** for `index_status` (quick health check) or `summarize_directory` (LLM summaries). For everything else, use CLI.
22
+ **Only use MCP tools** for `index_status` or `summarize_directory`. For everything else, use CLI with `--agent`.
23
23
 
24
24
  ## CLI commands (use these)
25
25
 
26
- ### Search — `gmax "query" --plain`
26
+ ### Search — `gmax "query" --agent`
27
27
  ```
28
- gmax "where do we handle authentication" --plain
29
- gmax "database connection pooling" --role ORCHESTRATION --plain -m 5
30
- gmax "error handling" --lang ts --exclude tests/ --plain
31
- gmax "VectorDB" --symbol --plain # search + call graph in one shot
32
- gmax "handler" --name "handle.*" --plain # regex filter on symbol names
33
- gmax "auth" --file handler.ts --plain # filter by filename
34
- gmax "query" -C 5 --plain # include context lines
35
- gmax "query" --imports --plain # show file imports
28
+ gmax "where do we handle authentication" --agent
29
+ gmax "database connection pooling" --role ORCHESTRATION --agent -m 5
30
+ gmax "error handling" --lang ts --exclude tests/ --agent
31
+ gmax "VectorDB" --symbol --agent # search + call graph in one shot
32
+ gmax "handler" --name "handle.*" --agent # regex filter on symbol names
33
+ gmax "auth" --file handler.ts --agent # filter by filename
36
34
  ```
37
35
 
38
- All flags: `--plain -m <n> --per-file <n> --min-score <n> --root <dir> --file <name> --exclude <prefix> --lang <ext> --role <role> --symbol --imports --name <regex> -C <n> --compact --content --scores --skeleton`
36
+ Output format: `file:line symbol [role] summary` (one line per result, no headers/footers)
37
+
38
+ All flags: `--agent --plain -m <n> --per-file <n> --min-score <n> --root <dir> --file <name> --exclude <prefix> --lang <ext> --role <role> --symbol --imports --name <regex> -C <n> --compact --content --scores --skeleton`
39
39
 
40
40
  ### Trace — `gmax trace <symbol>`
41
41
  ```
@@ -78,7 +78,7 @@ gmax doctor # health check
78
78
  ## Workflow
79
79
 
80
80
  1. **Explore** — `Bash(gmax project)` for overview of a new codebase
81
- 2. **Search** — `Bash(gmax "query" --plain)` to find code. Add `--symbol` for function/class names.
81
+ 2. **Search** — `Bash(gmax "query" --agent)` to find code. Add `--symbol` for function/class names.
82
82
  3. **Read** — `Read file:line` for specific ranges
83
83
  4. **Skeleton** — `Bash(gmax skeleton <path>)` before reading large files
84
84
  5. **Trace** — `Bash(gmax trace <symbol> -d 2)` for call flow
@@ -91,7 +91,7 @@ Use MCP only for `index_status` and `summarize_directory`. Use CLI for everythin
91
91
 
92
92
  ## Tips
93
93
 
94
- - **Always use `--plain`** on CLI searches — agent-friendly output without ANSI codes.
94
+ - **Always use `--agent`** on CLI searches — one line per result, most token-efficient.
95
95
  - **Be specific.** 5+ words. "auth" returns noise. "where does the server validate JWT tokens" is specific.
96
96
  - **Use `--role ORCHESTRATION`** to skip type definitions and find the actual logic.
97
97
  - **Use `--symbol`** when the query is a function/class name — gets search + trace in one call.