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-permission-layers

v1.1.0

Published

Pi extension to handle permissions using a layered approach

Downloads

172

Readme

pi-permission-layers

A Pi Coding Agent extension that implements a layered permission control extension to protect users from unintended operations. It classifies shell commands into 5 security levels and enforces them at runtime, with configurable overrides and two permission modes (ask / block).

Note: This project is a refactored fork. See the Acknowledgements section for lineage and credits. The goal of this fork is to have a more maintainable codebase while preserving the same core idea, and to adjust a few things deemed useful to me.

Key Features

  • Command classification — Automatically classifies shell commands by required permission level
  • Dangerous command detection — Special handling for rm -rf, sudo, chmod 777, etc.
  • MCP tool permissioning — Controls access to MCP tools (search, connect, etc.)
  • Shell trick detection — Prevents bypass via $(cmd), backticks, process substitution, eval, etc.
  • Configurable overrides — Users can customize classification in ~/.pi/agent/settings.json
  • Two permission modesask (prompt) or block (deny without asking)
  • Prefix mappings — Normalize version-manager commands (fvm flutter, nvm exec, etc.) to their base tools
  • Terminal awareness — Detects tmux/screen for appropriate notifications

Levels

| Level | Description | Allowed Operations | |-------|-------------|-------------------| | minimal | Read-only (default) | cat, ls, grep, git status/log/diff, npm list, etc. | | low | File operations | Output redirection (>, >>), write/edit tool calls, known read-only MCP tools | | medium | Development operations | Create/edit files (mkdir, cp, mv, ln), npm install, builds, tests, git commit/pull, linters, package managers | | high | Full operations | git push, deployments, curl, docker push, shell execution (eval, exec, source, env, etc.) | | bypassed | All checks disabled | Everything (dangerous — CI/containers only) |

Dangerous commands (always require confirmation in interactive mode, always blocked in print mode): sudo, rm -rf, chmod 777, dd of=/dev/*, mkfs*, fdisk, parted, format, shutdown, reboot, halt, poweroff, init, fork bombs

Shell tricks (always classified as high): $(cmd), backticks, <(cmd), >(cmd), ${VAR:-$(cmd)}

See docs/command-classification.md for the complete classification reference.

Installation

This package is a Pi extension. Install it with

npm install pi-permission-layers

or

pi install https://github.com/gsanhueza/pi-permission-layers

Usage

Interactive Mode

Interactive mode enables the usage of the following commands:

Commands:

  • /permission — Show selector to change level
  • /permission medium — Set level directly (asks session/global)
  • /permission-mode — Switch between ask/block when permission is required
  • /permission-mode block — Block instead of prompting
  • /permission config show — Display current configuration
  • /permission config reset — Reset to default (empty)
  • /permission settings — Interactive UI to toggle quietStartup / forceUI / systemNotifications

Autocomplete: All commands support argument autocomplete. After typing the command name, press Space to see available values. Nested subcommands also autocomplete — e.g. /permission config <space> shows show/reset.

When a command needs higher permission:

[Requires Medium]: $ npm install lodash

  Allow once                  → Execute this command once
  Allow all Medium (session)  → Update the session's permissions and execute
  Cancel                      → Don't execute

If permission mode is set to block, commands requiring higher permission are blocked without prompting. Use /permission-mode ask to restore prompts.

Print Mode

Permission mode is ignored in print mode; insufficient permissions always block.

# Set level via environment variable
PI_PERMISSION_LEVEL=medium pi -p "install deps and run tests"

# Bypass all permission checks (CI/containers — dangerous!)
PI_PERMISSION_LEVEL=bypassed pi -p "do anything"

If permission is insufficient: The command is blocked but execution continues. The agent receives:

$ npm install lodash
Blocked by permission (minimal). Allowed at this level: Read-only
User can re-run with: PI_PERMISSION_LEVEL=medium pi -p "..."

If a dangerous command is used:

Dangerous command requires confirmation: sudo rm -rf /tmp/foo
User can re-run with: PI_PERMISSION_LEVEL=bypassed pi -p "..."

The agent can then work around the limitation or inform the user.

Environment Variables

| Variable | Values | Description | |----------|--------|-------------| | PI_PERMISSION_LEVEL | minimal, low, medium, high, bypassed | Set permission level | | PI_QUIET | 1, true, yes | Suppress startup notifications | | PI_FORCEUI | 1, true, yes | Force interactive UI mode |

Settings

Global settings are stored in ~/.pi/agent/settings.json:

{
  "permissionLevel": "medium",
  "permissionMode": "ask",
  "permissionConfig": {
    "overrides": {
      "minimal": ["tmux list-*", "tmux show-*"],
      "medium": ["tmux attach*", "tmux new*"],
      "high": ["rm -rf *"],
      "dangerous": ["dd if=* of=/dev/*"]
    },
    "prefixMappings": [
      { "from": "fvm flutter", "to": "flutter" },
      { "from": "nvm exec", "to": "" },
      { "from": "rbenv exec", "to": "" },
      { "from": "pyenv exec", "to": "" }
    ],
    "quietStartup": true,
    "forceUI": true,
    "systemNotifications": "unfocused"
  }
}

permissionMode accepts ask (prompt) or block (deny without prompting).

permissionConfig Options

| Option | Type | Default | Description | |--------|------|---------|-------------| | quietStartup | boolean | false | Suppress the startup notification message | | forceUI | boolean | false | Force interactive UI mode regardless of context (e.g., in print mode) | | systemNotifications | "off" \| "on" \| "unfocused" \| "persistent" | "unfocused" | Control OS notifications ("off" = fully disabled, "unfocused" = only when terminal is not focused, "on" = always show, "persistent" = always show with critical/persistent priority) |

Note on Linux: Terminal focus detection is not supported on Linux, so the "unfocused" option behaves the same as "on" (notifications are always shown).

Override Patterns

Glob patterns are matched against the full command:

  • * matches any characters
  • ? matches single character
  • Patterns are case-insensitive

Override priority (highest to lowest):

  1. dangerous — Always prompt, even at high level
  2. high — Require high permission
  3. medium — Require medium permission
  4. low — Require low permission
  5. minimal — Allow at minimal (read-only)

Note: When a command matches patterns in multiple levels, the most restrictive level wins. Avoid overlapping patterns across levels. For example, don't put tmux * in medium if you want tmux list-* to be minimal.

Note on the low level: low is not a standalone command classification level (there is no isLowLevel() classifier). Instead, it serves as a permission threshold used for output redirections, write/edit tool calls, known read-only MCP tools, and as an override target. Commands like mkdir, cp, mv, ln, and touch are classified as medium, not low.

Examples:

{
  "overrides": {
    "minimal": [
      "tmux list-*",      // tmux list-sessions, tmux list-windows, etc.
      "tmux show-*",      // tmux show-options, tmux show-messages, etc.
      "screen -list"      // List screen sessions
    ],
    "medium": [
      "tmux attach*",     // Attach to sessions
      "tmux new*",        // Create new sessions
      "screen -r *"       // Reattach to screen
    ],
    "high": [
      "rm -rf *",         // Force rm with any arguments
      "dd of=/dev/*"      // dd writing to any device
    ],
    "dangerous": [
      "dd if=* of=/dev/*" // dd writing to device from any source
    ]
  }
}

Prefix Mappings

Normalize version manager commands to their base tools:

  • fvm flutter build → treated as flutter build (classified normally)
  • nvm exec node → treated as node (classified normally)
  • rbenv exec ruby → treated as ruby (classified normally)

How it works:

  1. Commands are checked against prefix mappings first
  2. If a prefix matches, it's replaced with the mapped value
  3. The normalized command is then classified

Testing

Run tests with:

npm run test

Test Structure

  • permission.test.ts — Tests classifyCommand() directly

    • Covers all 5 permission levels
    • Tests command parsing, pipelines, redirections
    • Tests shell tricks ($(), backticks, eval)
    • Tests config overrides and prefix mappings
  • permission-prompt.test.ts — Tests UI handler functions

    • Tests prompt messages and options
    • Tests Allow/Cancel/Block behavior
    • Tests block mode vs ask mode
  • interactive-ui.test.ts — Tests hasInteractiveUI(), isQuietMode(), notifySystem(), terminal detection, systemNotifications handling

New features MUST be covered by tests. All command classification changes require test updates. Run npm run test before committing.

Architecture

See docs/architecture.md for a complete breakdown of the codebase structure, module responsibilities, and design decisions.

Acknowledgements

This project is a fork of:

  1. pi-permission — the starting point of this fork, which added MCP tool permissioning and expanded classification (archived project).
  2. permission-pi — the original extension that established the layered permission control concept (the starting point of the fork above).