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

@agentick/sandbox-local

v0.14.35

Published

Local sandbox provider for Agentick — OS-level process isolation via macOS seatbelt and Linux bubblewrap

Readme

@agentick/sandbox-local

Local sandbox provider for Agentick. Executes commands on the host machine with OS-level security rails.

Quick Start

import { localProvider } from "@agentick/sandbox-local";

const provider = localProvider();
const sandbox = await provider.create({ workspace: true });

const result = await sandbox.exec("echo hello");
console.log(result.stdout); // "hello\n"

await sandbox.writeFile("test.txt", "content");
const content = await sandbox.readFile("test.txt");

await sandbox.destroy();

Sandbox Strategies

The provider automatically selects the best available isolation strategy:

| Strategy | Platform | Isolation | | ---------- | -------- | ------------------------------------------------------------- | | seatbelt | macOS | Apple Sandbox (sandbox-exec) with SBPL profiles | | bwrap | Linux | Bubblewrap with namespace isolation | | unshare | Linux | unshare with user namespaces | | none | Any | No OS sandboxing (workspace isolation + path validation only) |

// Auto-detect (default)
const provider = localProvider();

// Force a specific strategy
const provider = localProvider({ strategy: "seatbelt" });
const provider = localProvider({ strategy: "none" }); // For testing

Platform Detection

import { detectCapabilities } from "@agentick/sandbox-local";

const caps = await detectCapabilities();
// {
//   platform: "darwin",
//   arch: "arm64",
//   hasSandboxExec: true,
//   recommended: "seatbelt",
//   ...
// }

Network Rules

Control sandbox network access with fine-grained rules.

const sandbox = await provider.create({
  workspace: true,
  permissions: {
    net: [
      { action: "allow", domain: "api.github.com" },
      { action: "allow", domain: "*.npmjs.org" },
      { action: "deny", domain: "*.evil.com" },
      { action: "allow", port: 443, methods: ["GET"] },
    ],
  },
});

Rules are evaluated in order. First match wins. Default action is deny.

When NetworkRule[] is provided, a transparent HTTP proxy is started. HTTPS connections are filtered at the CONNECT level (domain allow/block without TLS termination).

Permissions

const sandbox = await provider.create({
  workspace: true,
  permissions: {
    fs: true, // Filesystem access (default: true)
    net: false, // Network access (default: false)
    childProcess: true, // Fork processes (default: true)
    inheritEnv: false, // Inherit host env vars (default: false)
  },
});

Mounts

Map host directories into the sandbox.

const sandbox = await provider.create({
  workspace: true,
  mounts: [
    { host: "/data/shared", sandbox: "/mnt/shared", mode: "ro" },
    { host: "/data/output", sandbox: "/mnt/output", mode: "rw" },
  ],
});

Resource Limits

const sandbox = await provider.create({
  workspace: true,
  limits: {
    memory: 512 * 1024 * 1024, // 512MB
    cpu: 0.5, // Half a core
    timeout: 30000, // 30s global timeout
    disk: 100 * 1024 * 1024, // 100MB workspace
    maxProcesses: 10,
  },
});

Resource limits use cgroups v2 on Linux. On macOS, timeout and disk limits are enforced; memory/CPU are advisory.

Streaming Output

const result = await sandbox.exec("npm install", {
  onOutput: (chunk) => {
    process.stdout.write(`[${chunk.stream}] ${chunk.data}`);
  },
});

With Agentick Components

import { Sandbox, Shell, ReadFile, WriteFile } from "@agentick/sandbox";
import { localProvider } from "@agentick/sandbox-local";

const MyAgent = () => (
  <Sandbox provider={localProvider()} workspace={true}>
    <Shell />
    <ReadFile />
    <WriteFile />
  </Sandbox>
);

Testing

import { createTestProvider, isDarwin } from "@agentick/sandbox-local/testing";

const provider = createTestProvider(); // strategy: "none"
const sandbox = await provider.create({ workspace: true });

// Platform-gated tests
describe.skipIf(!isDarwin)("seatbelt tests", () => { ... });

Security Model

Safe by default. The sandbox denies access to sensitive resources unless explicitly allowed.

macOS Seatbelt (reads)

Sandboxed processes can read system libraries and executables (required for bash/node), but cannot read:

| Denied Path | Contains | | ------------------------- | ------------------------------------------------------------------ | | /Users | Home directories — SSH keys, .env, browser profiles, credentials | | /private/var/root | Root's home directory | | /Volumes | Mounted drives, encrypted volumes, network shares | | /Network | Network-mounted resources | | /Library/Keychains | System-level keychains and certificates | | /private/var/db/dslocal | Local directory service (user account data) |

The workspace and any configured mounts are re-allowed via SBPL specificity rules (more-specific subpath allows override broader denies).

Write restrictions

All strategies restrict writes to:

  • The workspace directory
  • Configured read-write mounts
  • /tmp and /dev

Additional protections

| Threat | Mitigation | | ------------------- | -------------------------------------------------------------- | | Path traversal | realpath() + bounds check | | Symlink escape | Follow symlinks before validation | | Null byte injection | Reject null bytes in all paths | | Output OOM | 10MB cap per stream | | Env var injection | Blocklist for LD_PRELOAD, DYLD_* | | Process orphans | Kill process group (detached + -pid), SIGTERM then SIGKILL | | Zombie sandbox | destroyed flag prevents use-after-destroy | | Disk bomb | Polling monitor kills processes on exceed |

Platform requirements

macOS: /usr/bin/sandbox-exec (ships with macOS, no install needed).

Linux: One of:

  • bwrap (bubblewrap) — install via apt install bubblewrap or equivalent
  • unshare with unprivileged user namespaces enabled (sysctl kernel.unprivileged_userns_clone=1)
  • cgroups v2 for memory/CPU/process limits (writable /sys/fs/cgroup)

All platforms: Falls back to strategy: "none" (workspace isolation + path validation only, no OS-level sandboxing) when no sandbox tooling is available.