Independent AI intelligence Two editions daily · ET
FervorAI

Analysis · August 10, 2026 · repo

Pi agent harnessearendil-worksGondolinNVIDIA OpenShellagent-harnessagent-securityagent-infrastructureai-skills

Pi Pins Every npm Dependency And Ships No Permission System At All

The Pi agent harness treats a dependency bump like a code review and treats your filesystem like your problem. Here is how to run it without handing an LLM your shell.

The README for earendil-works/pi has a section called "Permissions & Containerization." Its first sentence is that there is no permission system.

The exact wording: "Pi does not include a built-in permission system for restricting filesystem, process, network, or credential access. By default, it runs with the permissions of the user and process that launched it."

Two sections further down is a heading called "Supply-chain hardening," and it runs to nine bullets covering pinned versions, a release quarantine window, lifecycle-script allowlists, and a pre-commit hook that blocks accidental lockfile changes. One threat model got engineering. The other got a paragraph telling you it is yours.

That is not sloppiness. It is a split that the rest of the harness ecosystem mostly papers over, and it is worth understanding before you install anything.

The position: an honest gap beats a permission system that half works

I would rather run a tool that tells me it has no boundary than one that ships an approval prompt with holes in it.

We have spent the past few months watching those holes. A sandbox deny path written with a trailing slash was silently ignored. A permission system that was switched on still let a coding agent delete tracked files. Approval dialogs get clicked through by people who have seen four hundred of them that week. A permission layer that is 90 percent effective produces a user who behaves as though it is 100 percent effective, and the missing 10 percent is where the incident lives.

Pi's posture removes that ambiguity. There is no prompt to trust, so you do not trust one. You put the process somewhere it cannot hurt you, or you accept that it can.

The cost of that honesty is that Pi is not a drop-in replacement for a harness with a permission model. If your team's safety story is "the tool asks before it writes," installing Pi on a laptop with production credentials in the environment deletes your safety story and does not tell you.

What Pi actually locks down

The supply-chain section is specific enough to audit, which is more than most projects manage. The stated practice is to treat npm dependency changes as reviewed code changes.

Direct external dependencies are pinned to exact versions; internal workspace packages stay range-versioned. .npmrc sets save-exact=true and, more interestingly, min-release-age=2, which refuses to resolve a dependency release published in the last two days. package-lock.json is the ground truth, and a pre-commit hook blocks accidental lockfile commits unless you set PI_ALLOW_LOCKFILE_CHANGE=1 on purpose. The published CLI package ships its own npm-shrinkwrap.json generated from the root lockfile so transitive deps are pinned for npm installers too. Shrinkwrap generation carries an explicit allowlist for dependency lifecycle scripts, and any new dependency that wants a lifecycle script fails checks until someone reviews it. CI installs with npm ci --ignore-scripts, documented installs and pi update --self use --ignore-scripts where supported, and a scheduled workflow runs npm audit --omit=dev plus npm audit signatures.

The two-day quarantine is the one to notice. Most npm compromises this year have followed the same shape: a maintainer account gets taken over, a malicious version publishes, and the window between publish and detection is measured in hours. min-release-age=2 does not detect anything. It just declines to be first, which is a cheap and effective way to let someone else be the canary. You can set the same flag in your own .npmrc today whether or not you ever run Pi.

If you build from a release source archive, the archive is covered by the release's SHA256SUMS file and there is a documented offline build path that will not refresh model data from live provider catalogs. That is a real reproducibility story.

Where the boundary leaks

The containerization doc offers three patterns, and it is candid about what each one misses. Read the caveats column before the pattern names.

OpenShell runs the whole pi process inside NVIDIA OpenShell, a policy-controlled sandbox with filesystem, process, network, credential, and inference controls. This is the only pattern with a credential story: OpenShell providers can keep raw model API keys outside the sandbox, and code inside can call https://inference.local while the gateway injects credentials upstream. It requires an active gateway backed by Docker, Podman, a VM runtime, or remote Kubernetes. If the gateway is remote, your project files are not bind-mounted, so writes inside do not reach your machine unless you upload and download explicitly.

Gondolin keeps pi and your provider auth on the host and routes built-in tools into a local Linux micro-VM. The extension overrides read, write, edit, bash, grep, find, and ls, and routes your ! commands into the VM as well. It needs Node 23.6.0 or newer plus QEMU.

Plain Docker puts the whole process in a container and is the simplest thing that works.

Now the sentence that decides whether any of this holds, straight from the doc: "Extensions run wherever the pi process runs. If you run host pi with a tool-routing extension, other custom extension tools still run on the host unless they also delegate their operations."

Pi's entire design philosophy is that you extend it. The harness ships a small set of built-in tools and pushes everything else into TypeScript extensions that register their own tools for the model to call. So the most likely configuration in practice is host Pi plus Gondolin plus two or three extensions you wrote yourself. In that setup the seven built-in tools are isolated in a micro-VM and your own tools are running on your laptop with your credentials. The boundary is exactly as strong as the extension you forgot about.

Two more caveats the doc names and people will skip. Under plain Docker, "provider API keys enter the container," so a container escape or a malicious dependency inside it reaches your keys. And "mounting your host ~/.pi/agent exposes host auth and session files to the container," which is the convenient thing to do and the wrong thing to do. Gondolin also writes through: the host working directory mounts at /workspace and changes there hit your real files, by design.

One governance detail worth knowing before you open an issue. The README states that new issues and pull requests from new contributors are auto-closed by default, with maintainers reviewing auto-closed items daily. For a project this size that is a defensible triage policy and it will surprise you the first time.

Put this into practice

  1. Do not install Pi globally on your daily-driver machine first. Start with the plain Docker recipe in the containerization doc, mount only the project directory, and use a named volume for /root/.pi/agent rather than mounting your host one.
  2. Use a scoped, revocable provider key for the container, not the key sitting in your shell profile. Assume anything inside the container can read it, because the doc says it can.
  3. Pick your pattern from what you need isolated, not from what installs fastest. Filesystem and process only, and Gondolin is enough. Credentials and network egress too, and OpenShell is the only one of the three that covers it.
  4. Inventory your extensions before you trust a boundary. For each one, ask where its tool actually executes. If it shells out on the host while your built-ins route into a VM, you have a sandbox with a door in it.
  5. Steal the .npmrc settings regardless. save-exact=true and min-release-age=2 cost nothing and apply to every Node project you own, including the ones with no agent in them.

Honest limitations

The star count is not reportable with confidence. Loading the repository twice in one session returned 86.4k stars with 10.7k forks on the repository page and 60.4k with 7.3k forks on a file page served from cache, and the two loads carried different repository descriptions. Secondary coverage put it above sixty-two thousand in June 2026. GitHub's caching has been unreliable on fast-moving repos all summer, so treat any single figure as directional. The commit count read 5,584 on the freshest load. The license is MIT, and MIT means no warranty on any of the hardening described above.

The supply-chain claims are self-described. Everything in that section is a policy the maintainers say they follow, verifiable by reading the repo and not audited by a third party. The policies are checkable, which is better than most, and checking them is still your job.

The isolation options each carry a dependency. OpenShell is NVIDIA infrastructure and needs a gateway you run. Gondolin needs a Node version newer than many teams are on plus a QEMU install through your package manager. Plain Docker is the easy one and it is also the one with your API keys inside it.

And the structural limit stands whatever you configure: no permission system means no per-action policy, no audit trail of denied operations, and nothing that distinguishes a read of your source tree from a read of your SSH directory. Containment is all-or-nothing at the process boundary.

Where this leaves you

Pi is a useful thing to study even if you never run it, because it separates two problems that most agent tooling blends into one word. Supply-chain integrity is about what code gets to be part of your agent. Runtime permissions are about what your agent gets to do once it is running. Pi solved the first carefully and declined the second explicitly, and it wrote both decisions down.

Most harnesses you are evaluating have made the same split without telling you which half they solved. Go read their equivalent of that paragraph. If you cannot find one, that is the finding.

Sources: earendil-works/pi README; pi containerization doc; NVIDIA OpenShell overview; Gondolin. Repository metrics were read directly from GitHub this week and varied between page loads; figures are directional.