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

@wrongstack/tools

v0.318.0

Published

WrongStack built-in tools: read/write/edit, bash/exec, grep/glob, git, fetch, test, lint, and more.

Readme

@wrongstack/tools

Built-in tools the WrongStack agent uses to read, edit, and act on the user's project.

Each tool implements the Tool interface from @wrongstack/core, with a JSON schema, an execute function, a permission level (auto / confirm / deny), and security gates appropriate to its blast radius.

Install

pnpm add @wrongstack/tools @wrongstack/core

Catalog

Filesystem

| Tool | Permission | Mutating | Notes | |------|------------|----------|-------| | read | auto | no | Records mtime for stale-read detection | | write | confirm | yes | Creates new files | | edit | confirm | yes | str_replace; requires prior read; FAT-aware mtime tolerance | | replace | confirm | yes | Regex replace across files; symlink-skipped + realpath-revalidated | | glob | auto | no | Glob pattern matching | | grep | auto | no | rg-backed; ReDoS-guarded regex, default ignores, accurate count totals | | tree | auto | no | Project tree; clears its polling timer (no leaks) | | patch | confirm | yes | GNU-patch diff applier; targets pre-validated against projectRoot | | diff | auto | no | Git diff against HEAD | | json | auto | no | jq-style JSON query |

Execution

| Tool | Permission | Mutating | Notes | |------|------------|----------|-------| | bash | confirm | yes | Sanitized child env; POSIX process-group kill on timeout | | exec | confirm | yes | Allowlist-only; validated cwd inside projectRoot | | git | confirm | yes (commits) | Typed subcommands only — no raw args (drops RCE via -c …) |

Network

| Tool | Permission | Mutating | Notes | |------|------------|----------|-------| | fetch | auto | no | SSRF-hardened (IPv4 + IPv6 private CIDR, redirect re-validation, http://-downgrade refused) | | search | auto | no | Web search via configured provider |

Browser

First-party browser_* tools lazily launch Playwright Chromium and use isolated per-agent contexts. Observation tools are automatic; navigation, interaction, screenshot persistence, upload, and evaluation require confirmation where appropriate. See browser automation for the lifecycle and security contract. Credential entry uses browser_type.secretEnv so audit records retain a placeholder rather than the secret value.

E2E discovery

| Tool | Permission | Mutating | Notes | |------|------------|----------|-------| | e2e_plan | auto | no | Statically discovers Playwright/Cypress configs, servers, specs, and exact argv without evaluating project code |

See the browser-aware E2E runner guide. Process startup and test execution remain separate permission-gated steps.

Project lifecycle

| Tool | Permission | Notes | |------|------------|-------| | lint | auto | Project-aware lint runner (eslint / biome / ruff / golangci-lint / …) | | format | confirm | Project-aware formatter | | typecheck | auto | Project-aware typechecker | | test | confirm | Project-aware test runner | | install | confirm | Package manager install | | audit | confirm | Dependency vulnerability audit | | outdated | auto | List outdated dependencies | | scaffold | confirm | Template-based scaffolding | | document | auto | Deprecated read-only documentation-candidate preview; use plugin tool auto_doc for generation | | logs | auto | Tail logs with rolling 100k-line window |

Agent control

| Tool | Notes | |------|-------| | todo | TodoWrite / TodoRead for session task tracking | | tool_search | Lazy-load deferred tool schemas | | tool_use | Generic single-tool call | | batch_tool_use | Parallel multi-tool dispatch | | tool_help | Show tool usage hint | | remember / forget | Memory-store mutations | | create_mode | Author a new agent mode |

Quick example

import { ToolRegistry } from '@wrongstack/core';
import { readTool, editTool, bashTool, builtinTools } from '@wrongstack/tools';

// Cherry-pick:
const tools = new ToolRegistry([readTool, editTool, bashTool]);

// Or take the whole built-in set:
const all = new ToolRegistry(builtinTools);

Security properties (0.1.6 hardening)

  • bash / exec child env sanitized to a fixed allowlist + secret-substring strip (TOKEN / SECRET / PASSWORD / AUTH / BEARER / COOKIE / PRIVATE / KEY). Opt-out via WRONGSTACK_BASH_ENV_PASSTHROUGH=1.
  • bash POSIX process-group kill with SIGTERM → 800 ms → SIGKILL. Runaway grandchildren can't survive the timeout.
  • fetch SSRF defenses: numeric CIDR checks for IPv4 (10/8, 127/8, 169.254/16, 100.64/10, 224/4, 240/4, …) and 8-group-expanded IPv6 (including Node's compressed ::ffff:7f00:1 form for v4-mapped addresses). Redirect target re-validated on every hop. http:// downgrade refused.
  • browser_* isolation and SSRF defenses: one context per agent/session, private-host and URL-credential rejection, guarded subrequests, disabled downloads, project-root-confined uploads, bounded/redacted evidence, and abort/run-disposal cleanup.
  • patch diff-target validation: every +++ target post-strip is resolved against projectRoot before GNU patch sees the diff. strip clamped to ≥1. Temp diff written to a 0700 mkdtemp directory. Run with LANG=C / LC_ALL=C.
  • replace / grep symlink-safe: lstat + realpath + projectRoot revalidation; symlinks skipped, not followed.
  • User-regex ReDoS guard (_regex.ts): 512-char cap, nested-quantifier rejection ((a+)+, (?:x+)*), 64 KB subject-line cap. Applied to grep, replace, logs.
  • git args raw string removed — the -c core.sshCommand=… RCE bypass is no longer reachable.
  • grep stdout buffer capped at 1 MB — pathological producers can't pin memory.
  • logs rolling window of 100k lines max; lines: 0 no longer means "buffer the whole file".

Full threat model: SECURITY.md at the repo root.

Writing a custom tool

import type { Tool } from '@wrongstack/core';

export const echoTool: Tool<{ text: string }, string> = {
  name: 'echo',
  description: 'Echo a string back.',
  inputSchema: {
    type: 'object',
    properties: { text: { type: 'string' } },
    required: ['text'],
  },
  permission: 'auto',
  mutating: false,
  // Tells permission policy which input field is the trust subject
  subjectKey: 'text',
  async execute(input, _ctx, { signal }) {
    if (signal.aborted) throw new Error('aborted');
    return input.text;
  },
};

See docs/tool-author-guide.md for the full contract.

License

MIT