@moontrain/pi-py-exec
pi extension: persistent Python kernel with an isolated uv-managed venv and automatic dependency installation
Package details
Install @moontrain/pi-py-exec from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:@moontrain/pi-py-exec- Package
@moontrain/pi-py-exec- Version
0.1.0- Published
- Aug 18, 2026
- Downloads
- 165/mo · 17/wk
- Author
- moontrain
- License
- MIT
- Types
- extension
- Size
- 39.8 KB
- Dependencies
- 0 dependencies · 4 peers
Pi manifest JSON
{
"extensions": [
"./extensions/py-exec.ts"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
@moontrain/pi-py-exec
A pi extension that gives the agent a persistent Python kernel. Variables, imports, and function definitions survive between calls, the last expression comes back automatically like a REPL, and missing packages install themselves.
The kernel lives in a virtualenv that pi owns. It never touches your system Python and never touches your project's venv.
Install
pi install npm:@moontrain/pi-py-exec
Or try it for one run: pi -e npm:@moontrain/pi-py-exec
Why
The default move for an agent doing quick Python is bash python3 -c "...". Every call
is a fresh interpreter: the 400 MB dataframe you just parsed is gone, the import cost is
paid again, and any intermediate state has to be re-derived or serialized to disk.
With a persistent kernel the agent loads data once and keeps querying it:
# call 1
import pandas as pd
df = pd.read_csv("sales.csv")
len(df)
# [result] 128394
# call 2 — df is still there
df.groupby("region")["revenue"].sum().sort_values(ascending=False).head()
The py_exec tool
| Action | Purpose |
|---|---|
run (default) |
Execute code in the kernel |
install |
Install packages into the kernel environment |
reset |
Clear kernel state without restarting the process |
status |
Report interpreter, version, PID, and kernel health |
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
action |
"run" | "install" | "reset" | "status" |
"run" |
What to do. |
code |
string |
— | Python source, for action: "run". |
packages |
string[] |
— | Specs for action: "install", e.g. ["pandas", "requests>=2"]. |
auto_install |
boolean |
true |
On ModuleNotFoundError, install the missing package and retry once. |
timeout |
number |
30 |
Seconds. Maximum 300. |
REPL semantics
The value of the final expression is returned as [result] and bound to _. Use
print() for anything else. Output is capped at 50,000 characters.
The /py command
/py status interpreter, version, PID, kernel health
/py reset clear kernel state, keep the process
/py restart kill and respawn the kernel
/py install <pkgs...> install into the kernel environment
/py guard [on|off] toggle the inline-python bash guard
The Python environment
On first use the extension creates a virtualenv at ~/.pi/agent/py_exec/venv with
uv, based on a uv-downloaded standalone interpreter.
Nothing is installed into your system Python and nothing leaks in from it.
| Variable | Default | Effect |
|---|---|---|
PI_PYTHON |
— | Force a specific interpreter path. Skips uv entirely. |
PI_PYTHON_VERSION |
3.12 |
Python version uv provisions for the venv. |
PI_PYTHON_PREFERENCE |
only-managed |
Passed to uv --python-preference. |
PI_PY_EXEC_GUARD |
on | Set to 0, off, or false to disable the bash guard. |
If uv is not installed at all, the extension falls back to the first working
python3 / python / py on PATH. Everything still works; you just lose the
isolation guarantee and get whatever version that interpreter is.
Auto-install maps common import names to their PyPI package names, so import cv2
installs opencv-python, import PIL installs pillow, import sklearn installs
scikit-learn, and so on.
The inline-python bash guard
The extension watches bash tool calls and blocks bare inline Python — a whole-command
python -c '...' or python <<EOF — with a message pointing the agent at py_exec.
It is deliberately narrow. It only fires on a self-contained inline script with a bare
interpreter name, optionally prefixed by cd X &&. These stay unblocked:
- Project venv —
./.venv/bin/python -c '...'(path interpreter, not a bare name) - Long jobs over the 300 s cap
- Existing scripts —
python script.pyis never blocked - Shell integration — anything with pipes,
&&chains, or redirection
The block is a nudge, not a wall: re-running the same command succeeds. Turn it off
permanently with /py guard off or PI_PY_EXEC_GUARD=0.
How it works
The kernel is a stdlib-only Python script embedded in the extension, written to a
temp file and spawned as python -u -X utf8. It speaks NDJSON over stdin/stdout with
requests matched by id. There are no Python dependencies to install before the kernel
can start.
A timeout or cancellation kills and respawns the kernel — state is lost, and the error
message says so explicitly rather than silently returning stale results. Windows kills
via taskkill /T /F.
The kernel's working directory is fixed at first use. Call os.chdir() inside your code
to move it.
Security
py_exec executes arbitrary Python with your user's permissions, the same as the bash
tool. The venv isolates dependencies, not capabilities — code in the kernel can read
and write any file you can. Review what you run.
License
MIT © Moontrain Technologies