sboxd 0.1.7

Policy-driven command runner for sandboxed dependency installation
Documentation
# Transparent Interception with Shims

Shims let you use sbox without changing your existing workflow. Once installed, running `npm install` in a project with `sbox.yaml` automatically delegates to `sbox run -- npm install`. In a project without `sbox.yaml`, the real npm runs unchanged.

## Installing shims

```bash
sbox shim                        # install to ~/.local/bin (default)
sbox shim --dir ~/bin            # custom directory
sbox shim --force                # overwrite existing shims
sbox shim --dry-run              # preview what would be created
```

After installing, add the shim directory before the real binaries in your PATH:

```bash
# Add to ~/.bashrc or ~/.zshrc
export PATH="$HOME/.local/bin:$PATH"
```

Verify the shim is active:

```bash
which npm          # should show ~/.local/bin/npm
npm --version      # calls the shim, which passes through to real npm (no sbox.yaml here)
```

## Supported package managers

| Shim | Intercepts |
|------|-----------|
| `npm` | All npm commands |
| `npx` | npx invocations |
| `pnpm` | All pnpm commands |
| `yarn` | All yarn commands |
| `bun` | All bun commands |
| `uv` | All uv commands |
| `pip` | All pip commands |
| `pip3` | All pip3 commands |
| `poetry` | All poetry commands |
| `cargo` | All cargo commands |
| `composer` | All composer commands |

## How shims work

Each shim is a small shell script:

```bash
#!/bin/sh
# sbox shim: npm
# Generated by `sbox shim`. Re-run `sbox shim --dir DIR` to regenerate.
_sbox_d="$PWD"
while true; do
  if [ -f "$_sbox_d/sbox.yaml" ]; then
    exec sbox run -- npm "$@"
  fi
  [ "$_sbox_d" = "/" ] && break
  _sbox_d="${_sbox_d%/*}"
  [ -z "$_sbox_d" ] && _sbox_d="/"
done
exec /usr/bin/npm "$@"
```

The shim walks up the directory tree from `$PWD`, checking each level for `sbox.yaml`. If found at any level, it delegates to sbox. If the root is reached without finding a config, the real binary is called with all original arguments.

The path to the real binary is hardcoded at shim-generation time (by `sbox shim`) to avoid PATH lookup loops. If the real binary moves, re-run `sbox shim` to regenerate.

Exit codes, stdin, stdout, and stderr are passed through unchanged. The shim is transparent to the calling process.

## Dispatch rules with shims

When a shim delegates to sbox, sbox applies the normal dispatch rules. For example, with:

```yaml
dispatch:
  npm-install:
    match:
      - "npm install*"
    profile: install
  npm-run:
    match:
      - "npm run*"
    profile: default
```

Running `npm install` uses the `install` profile (network on, registry allowlist, lockfile check).
Running `npm run build` uses the `default` profile (network off).

## Removing shims

```bash
rm ~/.local/bin/npm ~/.local/bin/npx  # remove individual shims
# or remove all at once:
sbox shim --dry-run                   # list shim paths
```

## Team setup

For a team where everyone should have sbox active:

```bash
# System-wide (requires sudo)
sudo sbox shim --dir /usr/local/bin

# Or document in the project README:
echo "Run: sbox shim && export PATH=\"\$HOME/.local/bin:\$PATH\""
```

Projects without `sbox.yaml` are unaffected.