From 5b141c18f021dda1c2eb647cf37d6cd345f8b127 Mon Sep 17 00:00:00 2001 From: felixzsh Date: Mon, 12 Jan 2026 17:47:29 -0600 Subject: [PATCH 1/6] feat: add list command the list command prints all the working directories where all the watch commands were ran, this is useful for scripting or just knowing how many and which watch processes are currently running on the system --- package.json | 2 ++ pnpm-lock.yaml | 17 +++++++++++++++++ src/commands/list.ts | 44 ++++++++++++++++++++++++++++++++++++++++++++ src/index.ts | 2 ++ 4 files changed, 65 insertions(+) create mode 100644 src/commands/list.ts diff --git a/package.json b/package.json index 9a94855..837c62b 100644 --- a/package.json +++ b/package.json @@ -53,6 +53,8 @@ "istextorbinary": "^9.5.0", "open": "^10.2.0", "ora": "^5.4.1", + "pid-cwd": "^1.2.0", + "ps-list": "^9.0.0", "p-limit": "^3.1.0", "winston": "^3.18.3", "winston-daily-rotate-file": "^5.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 337c240..262dd08 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -47,6 +47,12 @@ importers: p-limit: specifier: ^3.1.0 version: 3.1.0 + pid-cwd: + specifier: ^1.2.0 + version: 1.2.0 + ps-list: + specifier: ^9.0.0 + version: 9.0.0 winston: specifier: ^3.18.3 version: 3.18.3 @@ -796,6 +802,9 @@ packages: picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + pid-cwd@1.2.0: + resolution: {integrity: sha512-8QQzIdBmy4bd2l1NKWON1X8flO5TQQRzU2uRDua/XaxSC0iJ+rgbDrlX76t0W3DaJ7OevTYpftyvQ6oMe3hclQ==} + pkce-challenge@5.0.1: resolution: {integrity: sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ==} engines: {node: '>=16.20.0'} @@ -804,6 +813,10 @@ packages: resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} engines: {node: '>= 0.10'} + ps-list@9.0.0: + resolution: {integrity: sha512-lxMEoIL/BQlk2KunFzxwUPwMvjFH7x7cmvzSLsSHpyMXl9FFfLUlfKrYwFc4wx/ZaIxxuXC4n8rjQ1CX/tkXVQ==} + engines: {node: '>=20'} + pvtsutils@1.3.6: resolution: {integrity: sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg==} @@ -1782,6 +1795,8 @@ snapshots: picocolors@1.1.1: {} + pid-cwd@1.2.0: {} + pkce-challenge@5.0.1: {} proxy-addr@2.0.7: @@ -1789,6 +1804,8 @@ snapshots: forwarded: 0.2.0 ipaddr.js: 1.9.1 + ps-list@9.0.0: {} + pvtsutils@1.3.6: dependencies: tslib: 2.8.1 diff --git a/src/commands/list.ts b/src/commands/list.ts new file mode 100644 index 0000000..cf32671 --- /dev/null +++ b/src/commands/list.ts @@ -0,0 +1,44 @@ +import { Command } from 'commander'; +import psList from 'ps-list'; +import pidCwd from 'pid-cwd'; + +interface WatcherInfo { + pid: number; + directory: string; +} + +async function getWatchers(): Promise { + const processes = await psList(); + const watchers: WatcherInfo[] = []; + + for (const proc of processes) { + const cmd = proc.cmd || ''; + if (cmd.includes('mgrep') && cmd.includes('watch')) { + const cwd = await pidCwd(proc.pid).catch(() => null); + if (cwd) { + watchers.push({ pid: proc.pid, directory: cwd }); + } + } + } + + return watchers; +} + +export async function listAction(): Promise { + const watchers = await getWatchers(); + + if (watchers.length === 0) { + console.log('No active mgrep watch processes found.'); + return; + } + + for (const w of watchers) { + console.log(w.directory); + } +} + +export const list = new Command('list') + .description('List active mgrep watch processes') + .action(async () => { + await listAction(); + }); diff --git a/src/index.ts b/src/index.ts index 9eafb04..696d2df 100644 --- a/src/index.ts +++ b/src/index.ts @@ -9,6 +9,7 @@ import { search } from "./commands/search.js"; import { switchOrg } from "./commands/switch-org.js"; import { watch } from "./commands/watch.js"; import { watchMcp } from "./commands/watch_mcp.js"; +import { list } from "./commands/list.js"; import { installClaudeCode, uninstallClaudeCode, @@ -39,6 +40,7 @@ program program.addCommand(search, { isDefault: true }); program.addCommand(watch); +program.addCommand(list); program.addCommand(installClaudeCode); program.addCommand(uninstallClaudeCode); program.addCommand(installCodex); From 38a21cb10dfb99bc06b85f440adef7656564ac6d Mon Sep 17 00:00:00 2001 From: felixzsh Date: Mon, 12 Jan 2026 18:11:23 -0600 Subject: [PATCH 2/6] docs: add list command mention to readme --- README.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/README.md b/README.md index 19c7278..c4d4e13 100644 --- a/README.md +++ b/README.md @@ -151,6 +151,7 @@ Web search queries the `mixedbread/web` store in addition to your local store, m | --- | --- | | `mgrep` / `mgrep search [path]` | Natural-language search with many `grep`-style flags (`-i`, `-r`, `-m`...). | | `mgrep watch` | Index current repo and keep the Mixedbread store in sync via file watchers. | +| `mgrep list` | List active mgrep watch processes with their working directories. | | `mgrep login` & `mgrep logout` | Manage device-based authentication with Mixedbread. | | `mgrep install-claude-code` | Authenticate, add the Mixedbread mgrep plugin to Claude Code. | | `mgrep install-opencode` | Authenticate and add the Mixedbread mgrep to OpenCode. | @@ -208,6 +209,19 @@ mgrep watch --max-file-size 1048576 # limit uploads to files under 1MB mgrep watch --max-file-count 5000 # limit uploads to directories with 5000 files or fewer ``` +### mgrep list + +`mgrep list` shows all running `mgrep watch` processes with their working directories. + +**Example:** +```bash +mgrep list +# /home/user/project-a +# /home/user/project-b +``` + +Output is one directory per line. + ## Mixedbread under the hood - Every file is pushed into a Mixedbread Store using the same SDK your apps get. From 6494b1dea3d14d182a84e8e9b0952f09b3f1fa09 Mon Sep 17 00:00:00 2001 From: felixzsh Date: Mon, 12 Jan 2026 18:27:42 -0600 Subject: [PATCH 3/6] fix: enhance watch process detection since ps-list cwd property gives the exact command used to create the process in matter, check if cwd strictly containts the base watch command is cleaner, and by no means should give false positives. --- src/commands/list.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/list.ts b/src/commands/list.ts index cf32671..098a2b7 100644 --- a/src/commands/list.ts +++ b/src/commands/list.ts @@ -13,7 +13,7 @@ async function getWatchers(): Promise { for (const proc of processes) { const cmd = proc.cmd || ''; - if (cmd.includes('mgrep') && cmd.includes('watch')) { + if (cmd.includes('mgrep watch')) { const cwd = await pidCwd(proc.pid).catch(() => null); if (cwd) { watchers.push({ pid: proc.pid, directory: cwd }); From 9b2c9b77614bec5826ea9de7c754e34894aa4c99 Mon Sep 17 00:00:00 2001 From: felixzsh Date: Mon, 12 Jan 2026 18:33:46 -0600 Subject: [PATCH 4/6] fix: show not available command in windows since ps-list doesnt give useful properties in windows machines, avoid silet fail and explictly print the situation. --- src/commands/list.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/commands/list.ts b/src/commands/list.ts index 098a2b7..ad87a2e 100644 --- a/src/commands/list.ts +++ b/src/commands/list.ts @@ -25,6 +25,11 @@ async function getWatchers(): Promise { } export async function listAction(): Promise { + if (process.platform === 'win32') { + console.log('mgrep list is not supported on Windows.'); + return; + } + const watchers = await getWatchers(); if (watchers.length === 0) { From d8de38069d8903372b2fda124f0c4e20db6e4785 Mon Sep 17 00:00:00 2001 From: felixzsh Date: Mon, 12 Jan 2026 20:52:43 -0600 Subject: [PATCH 5/6] fix: correct pipe streams --- src/commands/list.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/commands/list.ts b/src/commands/list.ts index ad87a2e..759f6b2 100644 --- a/src/commands/list.ts +++ b/src/commands/list.ts @@ -26,14 +26,16 @@ async function getWatchers(): Promise { export async function listAction(): Promise { if (process.platform === 'win32') { - console.log('mgrep list is not supported on Windows.'); + console.error('mgrep list is not supported on Windows.'); + process.exitCode = 1; return; } const watchers = await getWatchers(); if (watchers.length === 0) { - console.log('No active mgrep watch processes found.'); + console.error('No active mgrep watch processes found.'); + process.exitCode = 0; return; } From ee6baf8f1e6630e178377b51b5f5c60607eb69cc Mon Sep 17 00:00:00 2001 From: felixzsh Date: Thu, 15 Jan 2026 10:51:40 -0600 Subject: [PATCH 6/6] style: fix ci lint/format errors --- src/commands/list.ts | 20 ++++++++++---------- src/index.ts | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/commands/list.ts b/src/commands/list.ts index 759f6b2..addb7e3 100644 --- a/src/commands/list.ts +++ b/src/commands/list.ts @@ -1,6 +1,6 @@ -import { Command } from 'commander'; -import psList from 'ps-list'; -import pidCwd from 'pid-cwd'; +import { Command } from "commander"; +import pidCwd from "pid-cwd"; +import psList from "ps-list"; interface WatcherInfo { pid: number; @@ -12,8 +12,8 @@ async function getWatchers(): Promise { const watchers: WatcherInfo[] = []; for (const proc of processes) { - const cmd = proc.cmd || ''; - if (cmd.includes('mgrep watch')) { + const cmd = proc.cmd || ""; + if (cmd.includes("mgrep watch")) { const cwd = await pidCwd(proc.pid).catch(() => null); if (cwd) { watchers.push({ pid: proc.pid, directory: cwd }); @@ -25,8 +25,8 @@ async function getWatchers(): Promise { } export async function listAction(): Promise { - if (process.platform === 'win32') { - console.error('mgrep list is not supported on Windows.'); + if (process.platform === "win32") { + console.error("mgrep list is not supported on Windows."); process.exitCode = 1; return; } @@ -34,7 +34,7 @@ export async function listAction(): Promise { const watchers = await getWatchers(); if (watchers.length === 0) { - console.error('No active mgrep watch processes found.'); + console.error("No active mgrep watch processes found."); process.exitCode = 0; return; } @@ -44,8 +44,8 @@ export async function listAction(): Promise { } } -export const list = new Command('list') - .description('List active mgrep watch processes') +export const list = new Command("list") + .description("List active mgrep watch processes") .action(async () => { await listAction(); }); diff --git a/src/index.ts b/src/index.ts index 696d2df..fc6472c 100644 --- a/src/index.ts +++ b/src/index.ts @@ -3,13 +3,13 @@ import * as fs from "node:fs"; import * as path from "node:path"; import { fileURLToPath } from "node:url"; import { program } from "commander"; +import { list } from "./commands/list.js"; import { login } from "./commands/login.js"; import { logout } from "./commands/logout.js"; import { search } from "./commands/search.js"; import { switchOrg } from "./commands/switch-org.js"; import { watch } from "./commands/watch.js"; import { watchMcp } from "./commands/watch_mcp.js"; -import { list } from "./commands/list.js"; import { installClaudeCode, uninstallClaudeCode,