Skip to content

fix: improve glob tool Windows compatibility and rg resolution#309

Merged
code-yeongyu merged 1 commit into
devfrom
fix/glob-windows-support
Dec 29, 2025
Merged

fix: improve glob tool Windows compatibility and rg resolution#309
code-yeongyu merged 1 commit into
devfrom
fix/glob-windows-support

Conversation

@sisyphus-dev-ai

Copy link
Copy Markdown
Collaborator

Summary

Fixes #307 - glob not working well on Windows/WSL

This PR addresses three issues affecting Windows users:

  1. Wrong path detection for OpenCode's bundled rg - The glob tool wasn't finding ripgrep installed by OpenCode because it only checked paths relative to process.execPath, not the XDG data directory where OpenCode actually installs it (~/.local/share/opencode/bin/rg)

  2. No auto-install capability - Unlike the grep tool, glob used synchronous resolveGrepCli() which doesn't trigger auto-installation when rg is missing

  3. Unix find fallback on Windows - When rg wasn't available, the glob tool fell back to Unix find command with arguments like -maxdepth, -type f which are invalid on Windows (Windows find.exe is a completely different command for text search)

Changes

  • src/tools/grep/constants.ts: Added OpenCode's XDG data path (~/.local/share/opencode/bin/rg) as highest priority candidate in getOpenCodeBundledRg()
  • src/tools/glob/constants.ts: Exported resolveGrepCliWithAutoInstall for use by glob tool
  • src/tools/glob/cli.ts:
    • Added buildPowerShellCommand() for Windows fallback using Get-ChildItem
    • Updated runRgFiles() to accept optional pre-resolved CLI and detect Windows platform
  • src/tools/glob/tools.ts: Now uses resolveGrepCliWithAutoInstall() to ensure rg is auto-downloaded if missing

Resolution Order (for rg)

  1. OpenCode XDG path: ~/.local/share/opencode/bin/rg (new, highest priority)
  2. Legacy exec-relative paths
  3. System PATH
  4. oh-my-opencode cache: ~/.cache/oh-my-opencode/bin/rg
  5. Fallback: PowerShell Get-ChildItem on Windows, Unix find on other platforms

Testing

  • Typecheck passes (bun run typecheck)
  • All 108 tests pass (bun test)
  • Build succeeds (bun run build)

Notes

  • WSL is handled correctly - process.platform returns "linux" in WSL, so it uses Unix commands
  • PowerShell fallback uses -Depth parameter (PowerShell 5.0+, standard on Windows 10+)
  • Pattern escaping implemented for both path and pattern arguments to prevent injection

- Add OpenCode XDG data path (~/.local/share/opencode/bin/rg) to rg candidates
- Enable auto-install for glob tool (uses resolveGrepCliWithAutoInstall)
- Add Windows PowerShell Get-ChildItem fallback when rg is unavailable

Fixes #307
@greptile-apps

greptile-apps Bot commented Dec 28, 2025

Copy link
Copy Markdown

Greptile Summary

Fixed glob tool Windows/WSL compatibility by addressing ripgrep detection, auto-installation, and fallback command issues.

Key Changes:

  • Added OpenCode's XDG data path (~/.local/share/opencode/bin/rg) as the highest priority candidate for finding bundled ripgrep in getOpenCodeBundledRg()
  • Enabled auto-installation in glob tool by using resolveGrepCliWithAutoInstall() instead of synchronous resolveGrepCli()
  • Replaced Unix find fallback on Windows with PowerShell Get-ChildItem command (Windows find.exe is incompatible with Unix find syntax)
  • Refactored runRgFiles() to accept optional pre-resolved CLI and properly route execution based on backend (rg/PowerShell/find)

Resolution Order:

  1. OpenCode XDG path (new, highest priority)
  2. Legacy exec-relative paths
  3. System PATH
  4. oh-my-opencode cache
  5. Platform-specific fallback (PowerShell on Windows, find on Unix)

Testing: All 108 tests pass, typecheck succeeds, build completes successfully.

Notes:

  • WSL correctly uses Unix commands (process.platform === "linux" in WSL)
  • PowerShell fallback requires PowerShell 5.0+ (standard on Windows 10+)
  • Pattern escaping implemented for injection protection

Confidence Score: 4/5

  • This PR is safe to merge with low risk - addresses real compatibility issues with solid fallback strategy
  • Score reflects thorough problem analysis and testing (108 tests pass), but minor improvements possible in PowerShell escaping (only handles single quotes) and multi-path support. The changes are well-scoped, backwards-compatible, and solve a documented issue (glob not working well on windows / wsl? #307).
  • src/tools/glob/cli.ts - review PowerShell command escaping for completeness

Important Files Changed

Filename Overview
src/tools/grep/constants.ts Added OpenCode XDG data path as highest priority for finding bundled rg, fixing detection issue
src/tools/glob/constants.ts Exported resolveGrepCliWithAutoInstall for auto-install capability in glob tool
src/tools/glob/tools.ts Integrated auto-install by calling resolveGrepCliWithAutoInstall and passing resolved CLI to runRgFiles
src/tools/glob/cli.ts Added PowerShell fallback for Windows, refactored command building, added ResolvedCli parameter - handles multiple execution paths correctly

Sequence Diagram

sequenceDiagram
    participant Agent as AI Agent
    participant GlobTool as glob tool
    participant Resolver as resolveGrepCliWithAutoInstall
    participant GetBundled as getOpenCodeBundledRg
    participant Downloader as downloadAndInstallRipgrep
    participant RunRg as runRgFiles
    participant CLI as CLI (rg/find/powershell)

    Agent->>GlobTool: execute({ pattern, path })
    GlobTool->>Resolver: resolveGrepCliWithAutoInstall()
    
    Resolver->>GetBundled: Check XDG data path first
    Note over GetBundled: ~/.local/share/opencode/bin/rg
    
    alt rg found
        GetBundled-->>Resolver: { path: rgPath, backend: "rg" }
    else rg not found
        GetBundled-->>Resolver: null
        Resolver->>Downloader: downloadAndInstallRipgrep()
        Downloader-->>Resolver: rgPath
        Resolver-->>GlobTool: { path: rgPath, backend: "rg" }
    end
    
    GlobTool->>RunRg: runRgFiles(options, resolvedCli)
    
    alt backend === "rg"
        RunRg->>CLI: spawn([rg, --files, --glob=pattern, paths...])
    else platform === "win32"
        RunRg->>CLI: spawn([powershell, Get-ChildItem...])
    else Unix fallback
        RunRg->>CLI: spawn([find, . -maxdepth N -name pattern])
    end
    
    CLI-->>RunRg: stdout (file paths)
    RunRg-->>GlobTool: { files, totalFiles, truncated }
    GlobTool-->>Agent: formatted result
Loading

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

4 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

Comment thread src/tools/glob/cli.ts
Comment on lines +54 to +55
const escapedPath = searchPath.replace(/'/g, "''")
const escapedPattern = options.pattern.replace(/'/g, "''")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: The escaping only handles single quotes by doubling them, but doesn't escape other PowerShell special characters like backticks, $, @, etc. For full injection protection, consider using PowerShell's -LiteralPath parameter for the path, which doesn't interpret wildcards or special characters.

Suggested change
const escapedPath = searchPath.replace(/'/g, "''")
const escapedPattern = options.pattern.replace(/'/g, "''")
// Use -LiteralPath to avoid interpretation of special characters
let psCommand = `Get-ChildItem -LiteralPath '${escapedPath}' -File -Recurse -Depth ${maxDepth - 1} -Filter '${escapedPattern}'`
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/tools/glob/cli.ts
Line: 54:55

Comment:
**style:** The escaping only handles single quotes by doubling them, but doesn't escape other PowerShell special characters like backticks, `$`, `@`, etc. For full injection protection, consider using PowerShell's `-LiteralPath` parameter for the path, which doesn't interpret wildcards or special characters.

```suggestion
  // Use -LiteralPath to avoid interpretation of special characters
  let psCommand = `Get-ChildItem -LiteralPath '${escapedPath}' -File -Recurse -Depth ${maxDepth - 1} -Filter '${escapedPattern}'`
```

How can I resolve this? If you propose a fix, please make it concise.

Comment thread src/tools/glob/cli.ts
Comment on lines +51 to +52
const paths = options.paths?.length ? options.paths : ["."]
const searchPath = paths[0] || "."

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: Only uses the first path when options.paths has multiple entries. Consider that PowerShell's -Path parameter can accept multiple paths (comma-separated).

Suggested change
const paths = options.paths?.length ? options.paths : ["."]
const searchPath = paths[0] || "."
const paths = options.paths?.length ? options.paths : ["."]
const searchPaths = paths.map(p => `'${p.replace(/'/g, "''")}'`).join(", ")
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/tools/glob/cli.ts
Line: 51:52

Comment:
**style:** Only uses the first path when `options.paths` has multiple entries. Consider that PowerShell's `-Path` parameter can accept multiple paths (comma-separated).

```suggestion
  const paths = options.paths?.length ? options.paths : ["."]
  const searchPaths = paths.map(p => `'${p.replace(/'/g, "''")}'`).join(", ")
```

How can I resolve this? If you propose a fix, please make it concise.

@code-yeongyu code-yeongyu merged commit 6dd9825 into dev Dec 29, 2025
3 checks passed
@code-yeongyu code-yeongyu deleted the fix/glob-windows-support branch December 29, 2025 01:10
sssgun pushed a commit to sssgun/oh-my-opencode that referenced this pull request Jan 18, 2026
Rolloniel pushed a commit to Rolloniel/oh-my-opencode that referenced this pull request Feb 22, 2026
luobosibing2 pushed a commit to luobosibing2/oh-my-opencode that referenced this pull request Feb 23, 2026
…-yeongyu#309)

Critical fixes:
- Bug #1: SubagentStop hook defaulted all agents to 'failed' because SDK
  doesn't provide `success` field. Now defaults to 'completed' when undefined.
- Bug code-yeongyu#4: Token stats lost across TokenTracker instances. Constructor now
  restores session stats from global state for the same session ID.
- Bug code-yeongyu#5: Ultrawork session isolation bypassed when both session IDs were
  undefined (undefined === undefined). Now rejects all falsy session IDs.

High priority fixes:
- Bug code-yeongyu#6: Cancel skill force-clear missed 12+ state files (boulder,
  hud-state, subagent-tracking, checkpoints, etc). Added comprehensive list.
- Bug code-yeongyu#7: HUD semverCompare() returned NaN on pre-release versions like
  "3.9.5-beta". Fixed to use parseInt and handle pre-release ordering.
- Bug code-yeongyu#8: Silent JSON parse failures in critical state readers. Added
  error logging to ralph and ultrawork state readers.
- Bug code-yeongyu#9: Stale task detection had no default behavior when onStaleSession
  callback was not configured. Now auto-cleans after 2x threshold.
- Bug code-yeongyu#10: Hardcoded 3-architect assumption in validation. Extracted to
  REQUIRED_ARCHITECTS constant.

Medium priority fixes:
- Bug code-yeongyu#11: Auto-invoke history used non-atomic writes. Now uses
  atomicWriteJson to prevent corruption from concurrent sessions.
- Bug code-yeongyu#12: Ecomode docs said "all tasks" use Haiku, contradicting the
  escalation paths. Clarified to "most tasks" with upgrade criteria.
- Bug code-yeongyu#13: Added safeUnlinkSync/safeRmSync utilities to prevent ENOENT
  crashes during cleanup operations.
- Bug code-yeongyu#14: State files containing user prompts written with 0644
  permissions. Now writes with 0600 (owner-only read/write).
- Bug code-yeongyu#15: Model names recorded inconsistently (e.g., 'claude-3-5-haiku'
  vs 'claude-haiku-4'). Now normalizes at recording time via exported
  normalizeModelName().

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

glob not working well on windows / wsl?

2 participants