grepmax 0.9.3 → 0.9.4

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
@@ -186,16 +186,17 @@ gmax index --reset # Full re-index from scratch
186
186
 
187
187
  ### `gmax watch`
188
188
 
189
- Background file watcher for live reindexing. Watches for file changes and incrementally updates the centralized index. Uses FSEvents on macOS (kernel-level, low overhead) and polling on Linux.
189
+ Background file watcher for live reindexing. A single daemon process watches all registered projects through native OS file system events (`@parcel/watcher` — FSEvents on macOS, inotify on Linux). File changes are detected in sub-second and incrementally reindexed.
190
190
 
191
191
  ```bash
192
- gmax watch -b # Background mode (auto-stops after 30min idle)
193
- gmax watch --path ~/workspace # Watch a specific directory
194
- gmax watch status # Show running watchers
195
- gmax watch stop --all # Stop all watchers
192
+ gmax watch --daemon -b # Start daemon (watches all projects)
193
+ gmax watch -b # Per-project mode (fallback)
194
+ gmax watch status # Show daemon + watcher status
195
+ gmax watch stop # Stop daemon
196
+ gmax watch stop --all # Stop everything
196
197
  ```
197
198
 
198
- The MCP server auto-starts a watcher on session start. You rarely need to run this manually.
199
+ The daemon auto-starts when you run `gmax search` or use MCP tools. It shuts down after 30 minutes of inactivity. CLI commands communicate with the daemon over a Unix domain socket at `~/.gmax/daemon.sock`.
199
200
 
200
201
  ### `gmax summarize`
201
202
 
@@ -295,6 +296,9 @@ gmax doctor
295
296
  All data lives in `~/.gmax/`:
296
297
  - `~/.gmax/lancedb/` — LanceDB vector store (one database for all indexed directories)
297
298
  - `~/.gmax/cache/meta.lmdb` — file metadata cache (content hashes, mtimes)
299
+ - `~/.gmax/cache/watchers.lmdb` — watcher/daemon registry (LMDB, crash-safe)
300
+ - `~/.gmax/daemon.sock` — Unix domain socket for daemon IPC
301
+ - `~/.gmax/logs/` — daemon and watcher logs (5MB rotation)
298
302
  - `~/.gmax/config.json` — global config (model tier, embed mode)
299
303
  - `~/.gmax/models/` — embedding models
300
304
  - `~/.gmax/grammars/` — Tree-sitter grammars
@@ -304,6 +308,10 @@ All chunks store **absolute file paths**. Search scoping is done via path prefix
304
308
 
305
309
  ### Performance
306
310
 
311
+ - **Single Daemon:** One process watches all projects via native OS events — no polling, sub-second file change detection. Shared VectorDB, MetaCache, and worker pool across projects.
312
+ - **Native File Watching:** `@parcel/watcher` uses FSEvents (macOS), inotify (Linux), ReadDirectoryChangesW (Windows) — zero CPU overhead, no file descriptor exhaustion.
313
+ - **Automatic Compaction:** LanceDB table fragments from incremental inserts are compacted every 5 minutes, preventing performance degradation over time.
314
+ - **LMDB Caching:** File metadata reads use LRU/LFU caching for the watcher's hot path.
307
315
  - **Bounded Concurrency:** Worker threads scale to 50% of CPU cores (min 4). Override with `GMAX_WORKER_THREADS`.
308
316
  - **Smart Chunking:** `tree-sitter` splits code by function/class boundaries for complete logical blocks.
309
317
  - **Deduplication:** Identical code blocks are embedded once and cached.
@@ -389,11 +397,12 @@ See [CLAUDE.md](CLAUDE.md) for development setup, commands, and architecture det
389
397
 
390
398
  ## Troubleshooting
391
399
 
392
- - **Index feels stale?** Run `gmax index` to refresh, or use `gmax watch -b` for live reindexing.
400
+ - **Index feels stale?** Run `gmax index` to refresh. The daemon auto-reindexes on file changes.
393
401
  - **Weird results?** Run `gmax doctor` to verify models.
394
402
  - **Index getting stuck?** Run `gmax index --verbose` to see which file is being processed.
395
403
  - **Need a fresh start?** `rm -rf ~/.gmax/lancedb ~/.gmax/cache` then `gmax index`.
396
- - **MLX server won't start?** Check `/tmp/mlx-embed-server.log` for errors. Use `GMAX_EMBED_MODE=cpu` to fall back to CPU.
404
+ - **Daemon issues?** Check `~/.gmax/logs/daemon.log`. Run `gmax watch stop` then `gmax watch --daemon -b` to restart.
405
+ - **MLX server won't start?** Check `~/.gmax/logs/mlx-embed-server.log` for errors. Use `GMAX_EMBED_MODE=cpu` to fall back to CPU.
397
406
 
398
407
  ## Attribution
399
408
 
@@ -63,7 +63,20 @@ const skeletonizer_1 = require("../lib/skeleton/skeletonizer");
63
63
  const vector_db_1 = require("../lib/store/vector-db");
64
64
  const file_utils_1 = require("../lib/utils/file-utils");
65
65
  const exit_1 = require("../lib/utils/exit");
66
+ const project_registry_1 = require("../lib/utils/project-registry");
66
67
  const project_root_1 = require("../lib/utils/project-root");
68
+ /**
69
+ * Resolve a relative path across all indexed projects.
70
+ * Returns the first match found, or null.
71
+ */
72
+ function resolveAcrossProjects(relativePath) {
73
+ for (const project of (0, project_registry_1.listProjects)()) {
74
+ const candidate = path.join(project.root, relativePath);
75
+ if (fs.existsSync(candidate))
76
+ return candidate;
77
+ }
78
+ return null;
79
+ }
67
80
  /**
68
81
  * Check if target looks like a file path.
69
82
  */
@@ -185,11 +198,16 @@ Examples:
185
198
  }
186
199
  if (isFilePath(target)) {
187
200
  // === FILE MODE ===
188
- const filePath = path.resolve(target);
201
+ let filePath = path.resolve(target);
189
202
  if (!fs.existsSync(filePath)) {
190
- console.error(`File not found: ${filePath}`);
191
- process.exitCode = 1;
192
- return;
203
+ // Try resolving across indexed projects
204
+ const found = resolveAcrossProjects(target);
205
+ if (!found) {
206
+ console.error(`File not found: ${filePath}`);
207
+ process.exitCode = 1;
208
+ return;
209
+ }
210
+ filePath = found;
193
211
  }
194
212
  if (vectorDb) {
195
213
  // Use absolute path for DB lookup (centralized index stores absolute paths)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "grepmax",
3
- "version": "0.9.3",
3
+ "version": "0.9.4",
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.9.3",
3
+ "version": "0.9.4",
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",