npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

opencode-bettergrep

v1.1.0

Published

Standalone OpenCode plugin that ports the advanced local grep implementation from oh-my-opencode-slim.

Readme

⚡ opencode-bettergrep

npm License: MIT

An OpenCode plugin that replaces the built-in grep tool. It registers under the same tool ID, searches with ripgrep, and adds the filters, limits and timeout handling an agent needs when it explores a large repository.

It is part of Better OpenCode Tools, next to opencode-betterglob and opencode-betterread.

🚀 Install

npm install opencode-bettergrep
{
  "plugin": ["opencode-bettergrep"]
}

To run it from a local checkout, clone the repository, run bun install and bun run build, and point the plugin entry at file:///path/to/better-opencode-tools/packages/opencode-bettergrep.

🔎 What you can ask for

| Area | Options | | --- | --- | | Output | output_mode: content, files_with_matches or count. | | Matching | fixed_strings, case_sensitive, smart_case, word_regexp, invert_match, multiline, multiline_dotall, pcre2. | | Context | context, before_context, after_context (0 to 20 lines). | | Scope | path or paths, include, globs, exclude_globs, file_type, file_types, exclude_file_types, max_filesize, hidden, follow_symlinks. | | Limits | max_results (500 by default, 5,000 at most), max_count_per_file, timeout_ms (80 s by default, 140 s at most). | | Order | sort_by: none, path or mtime, with sort_order. |

Results list file paths, line numbers and context. When a search was cut short by a limit, a timeout or a cancellation, the output says so, so the agent knows whether the result was exhaustive.

🛡️ How it handles processes

  • Every search runs under a deadline. On timeout or cancellation the process gets SIGTERM and then SIGKILL, so a stubborn child does not outlive the call.
  • The probe that checks the ripgrep binary competes against process termination. A probe that times out resolves even if a child process keeps stdio open.
  • When results tie on modification time, they are ordered by raw path bytes. The output does not depend on which worker finished first or on the system locale.

🧭 Finding ripgrep

The plugin uses a ripgrep it finds on PATH, and installs a managed copy when it finds none. If ripgrep cannot be used, it falls back to GNU grep. The fallback runs with LC_ALL=C.UTF-8 and an empty LANGUAGE, so its version output parses in English even on a machine with a translated locale.

The fallback choice is remembered for 10 minutes. After that the plugin tries ripgrep again, so a single failed probe does not keep the session on GNU grep. It also tries again as soon as the ripgrep binary on PATH changes.

⏱️ Benchmark against the built-in grep

Times in milliseconds, lower is better, for the built-in tool from the OpenCode 1.18.32 source and this plugin at 1.1.0. Both were called in process with the same arguments, on a 4-core Arm Neoverse-N1 VM with ripgrep 15.2.0, over the OpenCode repository (about 6,600 files) and a generated 13 MB log of 200,000 lines. The built-in tool returns at most 100 results, so the plugin ran with max_results: 100. Each figure is a median across separate runs of the suite: 5 for the built-in tool and 4 for the plugin (Bun 1.4.2 and Bun 1.3.14, two runs each). The two Bun versions differ by less than 2 ms on every row.

| Case | Built-in | Plugin | Ratio | | --- | ---: | ---: | ---: | | Rare literal, whole repository | 42 | 36 | 1.2× | | Common word in *.ts | 12 | 6.6 | 1.9× | | Regex in *.ts | 15 | 7.4 | 2.1× | | No match, whole repository | 41 | 34 | 1.2× | | 13 MB log, many hits | 20 | 7.1 | 2.8× | | 13 MB log, one hit | 24 | 7.6 | 3.2× |

Both sides run ripgrep. A search that walks the whole repository takes 34 to 42 ms either way. On searches limited to *.ts the plugin is 1.9× to 2.1× faster, and on the 13 MB log 2.8× to 3.2×. The full method, and the read and glob results, are in the repository README.

⚠️ Known limitations

  • The GNU grep fallback is slower and does not support every ripgrep feature.
  • An include or globs entry that matches every path (*, **, **/*) is not passed to ripgrep, so ignore files such as .gitignore still apply. Any other positive glob is a ripgrep override: it also searches the ignored or hidden files it names. To search an ignored directory, pass it as path.
  • .git directories are skipped even with hidden or a glob such as **/.git/**, unless a search path is inside one (path: '.git'), as in OpenCode's native grep.
  • A very large output can still be expensive for the host UI and the model, even when the search process exits quickly. Use max_results and the filters to keep results small.

🧪 Development

bun run typecheck
bun test
bun run build
bun run check