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

pi-sandbox

v0.6.4

Published

OS-level sandboxing for pi with interactive permission prompts

Readme

pi-sandbox

Sandbox for pi.

Sandboxes pi like this:

  • read/write/edit: direct control using allow/deny lists
  • bash: uses @carderne/sandbox-runtime to control network and file system access

When a blocked action is attempted, the user is prompted to allow it temporarily or permanently rather than silently failing.

demo

Notes

There is an example config at sandbox.json. It was quite a few things added to get this extension to work with agent-browser and other common tools.

These open significant security loopholes, so shouldn't be used in a sensitive context or when you don't need browser support.

You may need to trial and error to find additional things you need to allow.

Quickstart

Prerequisites

pi-sandbox delegates the OS-level bash sandbox to @carderne/sandbox-runtime, published from the fork at https://github.com/carderne/sandbox-runtime, which is forked from Anthropic's anthropic-experimental/sandbox-runtime. The sandbox runtime checks for ripgrep (the rg binary) on both macOS and Linux at sandbox-init time. If rg is not on the PATH that pi was launched with, sandbox initialization fails with:

Sandbox initialization failed: Sandbox dependencies not available: ripgrep (rg) not found

Install ripgrep before enabling the extension:

| Platform | Install | |---|---| | macOS (Homebrew) | brew install ripgrep | | macOS (MacPorts) | sudo port install ripgrep | | Linux (Debian/Ubuntu) | sudo apt install ripgrep | | Linux (Fedora/RHEL) | sudo dnf install ripgrep | | Linux (Arch) | sudo pacman -S ripgrep | | From source / other | https://github.com/BurntSushi/ripgrep#installation |

If which rg succeeds in your shell but pi still reports rg not found, pi is being launched from a parent process whose PATH does not include the directory containing rg (common when GUI launchers inherit a minimal non-login PATH). On macOS, /opt/homebrew/bin and /usr/local/bin are the usual culprits — make sure your launcher's environment includes whichever one your install uses.

Install

pi install npm:pi-sandbox

Configure

Add a config like this either to ~/.pi/agent/sandbox.json (global) or to .pi/sandbox.json (local). Scalar settings in the local config take precedence over global settings. The path and domain arrays from both files are combined and deduplicated, so a project can add permissions without repeating the global configuration. Built-in defaults are used for an array only when neither file configures it.

Note below that the order of precedence for filesystem read and write are opposite.

{
  "enabled": true,
  "permissionPromptTimeoutSeconds": 600, // Defaults to 10 minutes; 0 waits indefinitely
  "allowBrowserProcess": true,     // If you want to use agent-browser or similar Chrome setup
  "network": {
    "allowLocalBinding": true,     // ditto
    "allowAllUnixSockets": true,   // ditto
    "allowUnauthenticatedSocksProxy": true, // Enables Git-over-SSH on macOS
    "allowedDomains": ["github.com", "*.github.com"],
    "deniedDomains": []
  },
  "filesystem": {
    // For READS:
    // - ANY read is prompted unless the path is in allowRead or allowWrite
    // - Granting a prompt adds to allowRead, which overrides denyRead
    // - denyRead is not a hard-block; it just marks regions as denied by default
    "denyRead": ["/Users", "/home"],
    "allowRead": [".", "~/.config", "~/.local", "Library"],

    // For WRITES:
    // - allowWrite also grants read access to the same paths
    // - empty ALLOW means no write access at all
    // - DENY takes precedence and is never prompted
    "allowWrite": [".", "/tmp"],
    "denyWrite": [".env", ".env.*", "*.pem", "*.key"]
  }
}

Usage

pi --no-sandbox                  disable sandboxing for the session
Alt+S                            toggle sandboxing on/off for the session
/sandbox                         show current configuration and session allowances
/sandbox-enable                  enable the sandbox for this session
/sandbox-disable                 disable the sandbox for this session
/sandbox-allow domain <url>      prompt to add a domain to allowedDomains
/sandbox-allow read <path>       prompt to add a path to allowRead
/sandbox-allow write <path>      prompt to add a path to allowWrite

What it does

Bash commands are wrapped with sandbox-exec (macOS) or bubblewrap (Linux) to enforce network and filesystem restrictions at the OS level.

Read, write, and edit tool calls are intercepted before execution and checked against the same filesystem policy. The OS-level sandbox cannot cover these tools because they run directly in the Node.js process rather than in a subprocess.

When a block is triggered, a prompt appears with four options. Permission prompts automatically select Abort (keep blocked) after 10 minutes by default. Set permissionPromptTimeoutSeconds to a positive number to use a different timeout, or set it to 0 to wait indefinitely. A timeout never grants permission.

  • Abort (keep blocked)
  • Allow for this session only
  • Allow for this project — written to .pi/sandbox.json
  • Allow for all projects — written to ~/.pi/agent/sandbox.json

Session allowances are held in memory only. They are never written to disk and the agent has no way to read or modify them. They are reset when the extension reloads or pi restarts.

What is prompted vs. hard-blocked

| Rule | Behaviour | |------|-----------| | Domain not in allowedDomains | Prompted (bash and !cmd) | | Path not in allowRead or allowWrite | Prompted (read tool); granting adds to allowRead | | Path not in allowWrite | Prompted (write/edit tools and bash write failures) | | Path in denyWrite | Hard-blocked, no prompt | | Domain in deniedDomains | Hard-blocked at OS level, no prompt |

If a path is added to allowWrite via a prompt but is also present in denyWrite, it remains blocked. A warning is shown explaining which config files to check.

allowedDomains supports *.example.com wildcards. It also supports "*" to allow all domains; pi-sandbox shows a warning when this is configured because it removes per-domain prompts and can be easy to add accidentally. allowWrite uses prefix matching, so . covers the entire current working directory. Write access also implies read access; paths do not need to be repeated in allowRead.

allowUnauthenticatedSocksProxy is enabled by default on macOS so Git-over-SSH works with the built-in nc. Domain filtering still applies, but another local process that discovers the temporary proxy port can use it while the sandbox is running.

⚠️ Read and write have different precedence rules:

  • Read: Every read is prompted unless the path is in allowRead or allowWrite. denyRead is not a hard-block — it marks regions as denied by default, but granting a prompt adds the path to allowRead, overriding denyRead.
  • Write: denyWrite takes precedence over allowWrite and is never prompted. A path in denyWrite is always blocked, even if it matches allowWrite.

If neither file configures an array, its built-in defaults apply (see above for the defaults). Once an array is configured, only its combined global and local entries are used, so an explicit empty array disables that default.

The footer shows a lock indicator while the sandbox is active.

Ackowledgements

Based on code from badlogic/pi-mono by Mario Zechner, used under the MIT License.