Skip to content

Add WSL invocation support to zoekt-manager.js for Windows #28

@Joxx0r

Description

@Joxx0r

Problem

On Windows, Zoekt binaries don't compile natively (unix.Umask undefined in index/builder.go). Zoekt must be installed and run inside WSL2. However, zoekt-manager.js currently spawns Zoekt processes directly via child_process.spawn(), which only works with native binaries.

The embark-claude-code installer (v0.5.3+) now:

  • Installs Zoekt binaries inside WSL only on Windows
  • Generates config.json with zoekt.wsl: true on Windows
  • Detects Zoekt via wsl -d Ubuntu -- which zoekt-index

But the service itself can't use those WSL-installed binaries yet.

Proposed Changes

src/service/zoekt-manager.js

  1. Constructor — Read config.wsl flag:

    this.wslMode = config.wsl || false;
  2. _findBinaries() — When wslMode, detect binaries via WSL:

    if (this.wslMode) {
      try {
        const wslPath = execSync('wsl -d Ubuntu -- which zoekt-index', { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }).trim();
        if (wslPath) {
          this.zoektIndexPath = wslPath;
          this.zoektWebPath = wslPath.replace('zoekt-index', 'zoekt-webserver');
          return true;
        }
      } catch {}
    }
  3. _spawn(binaryPath, args) — Wrap invocations through WSL with path conversion:

    _spawn(binaryPath, args) {
      if (this.wslMode) {
        const wslArgs = args.map(a => this._toWslPath(a));
        return spawn('wsl', ['-d', 'Ubuntu', '--', binaryPath, ...wslArgs], {
          stdio: ['ignore', 'pipe', 'pipe']
        });
      }
      return spawn(binaryPath, args, { stdio: ['ignore', 'pipe', 'pipe'] });
    }
    
    _toWslPath(p) {
      // Convert C:\foo\bar → /mnt/c/foo/bar
      const m = p.match(/^([A-Za-z]):[\\/](.*)$/);
      if (m) return `/mnt/${m[1].toLowerCase()}/${m[2].replace(/\/g, '/')}`;
      return p;
    }
  4. _killStaleWebservers() — When wslMode, use WSL pkill:

    if (this.wslMode) {
      execSync('wsl -d Ubuntu -- pkill -9 -f zoekt-webserver 2>/dev/null', { stdio: 'ignore', timeout: 5000 });
      return;
    }

Path Conversion (Critical)

The mirror directory, index directory, and project directories are all Windows paths (e.g., C:\Users\...\.claude\repos\unreal-index\data\zoekt-mirror). When passed to Zoekt processes inside WSL, they must be converted to /mnt/c/Users/.../... format. The _toWslPath() helper handles this.

What Doesn't Change

  • HTTP health checks (_waitForHealthy) work unchanged — WSL2 port forwarding makes localhost:6070 accessible from Windows
  • ZoektClient communicates via HTTP, unaffected
  • Non-Windows platforms continue working as before (wslMode defaults to false)

Config Example

The installer generates this on Windows:

{
  "zoekt": {
    "enabled": true,
    "wsl": true,
    "webPort": 6070,
    "indexDir": "./data/zoekt-index",
    "mirrorDir": "./data/zoekt-mirror"
  }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions