@mjakl/pi-processes
**Manage long-running commands from Pi without blocking the conversation.**
Package details
Install @mjakl/pi-processes from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:@mjakl/pi-processes- Package
@mjakl/pi-processes- Version
2.5.0- Published
- Oct 2, 2026
- Downloads
- not available
- Author
- mjakl
- License
- MIT
- Types
- extension
- Size
- 229.4 KB
- Dependencies
- 1 dependency · 4 peers
Pi manifest JSON
{
"extensions": [
"./src/index.ts"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
Pi Processes
Manage long-running commands from Pi without blocking the conversation.
User Guide
Why Pi Processes
Coding agents often need to start dev servers, watch-mode tests, log tails, port forwards, and other commands that should keep running while the conversation continues. pi-processes gives Pi a safe, visible way to manage those commands.
Features
- Agent-facing process tool — the agent can start, inspect, kill, and clear managed processes.
- Responsive by default — in TUI and RPC modes, managed work continues across agent turns instead of blocking the conversation.
- Event-driven readiness and completion — in TUI and RPC modes,
readyPatterncan wake the agent when output marks a process ready, and managed processes wake it when they end. - Explicit wait in every mode — block for an exit, output pattern, or timeout when results are required before the run ends. Long-lived TUI and RPC sessions remain asynchronous by default.
- Incremental output —
process outputreturns only what was printed since the agent last looked. /psoverlay — users can monitor processes and logs without asking the agent to poll.- Native process status — Pi's status area shows
N procswhile processes are active;/psremains the complete process view. - File-backed logs — recent process output is retained outside the agent context window.
- Detached-command interception — commands that escape the session are blocked and routed to the
processtool, and unbounded bash calls get a timeout so a long command cannot hang the agent.
Install
Requires Pi 0.85.0 or newer.
Install from npm:
pi install npm:@mjakl/pi-processes
Install from git:
pi install git:github.com/mjakl/pi-processes
Or install from a local checkout:
pi install /path/to/pi-processes
Using Pi Processes
The process tool is for the agent, not for direct user input. Ask the agent to start or inspect long-running work, then use /ps to watch it.
Example user prompts:
Start the dev server with pnpm dev and call it backend-dev.
Run the test watcher as tests.
Show me the latest output from backend-dev.
Stop the backend-dev process.
The agent should start managed processes through the process tool instead of running shell backgrounding such as command &, nohup, disown, or setsid.
/ps overlay
Run:
/ps
Inside the overlay:
up/down— move the highlighted process.left/right— scroll older/newer log output for the highlighted process.g/G— jump to the top or back to the live tail.x— terminate the highlighted process; pressxagain when it showsneeds killto force-kill it.c— clear finished processes.qorEsc— close the overlay.
The right side always shows logs for the currently highlighted process.
Configuration
Global config lives in:
~/.pi/agent/extensions/process.json
Example:
{
"output": {
"defaultTailLines": 100,
"maxOutputLines": 200
},
"execution": {
"shellPath": "/absolute/path/to/bash"
},
"interception": {
"blockBackgroundCommands": true,
"bashTimeoutSeconds": 300
}
}
Options:
output.defaultTailLines— default number of lines returned byprocess output(positive integer, capped bymaxOutputLines).output.maxOutputLines— hard cap forprocess output(positive integer, at most 2,000).execution.shellPath— absolute shell path override used for process startup.interception.blockBackgroundCommands— block bash commands that detach from the session (&,setsid,disown,gunicorn --daemon,ssh -f, …) and guide the agent to theprocesstool instead.interception.bashTimeoutSeconds— timeout applied to bash calls that set none, so a command that turns out to be long-running cannot hang the agent. A timeout tells the agent to restart the work as a process. Set0to disable, at most 3,600.
Technical Reference
These sections document the agent-facing tool contract and runtime behavior.
Tool API
The tool is named process.
Actions:
start— start a managed process, optionally with one-shot readiness monitoring.wait— in every mode, block until exit, matching output, or timeout.list— list all retained process records (at most 32), newest first.output— return the output printed since the agent last looked.logs— return file paths for stdout, stderr, and combined logs.kill— terminate or force-kill a process.clear— remove finished processes from the manager.
Agent tool-call examples (not shell commands):
process start "pnpm dev" name="backend-dev" readyPattern="listening on" readyTimeoutSeconds=30
process start "pnpm test --watch" name="tests"
process start "pnpm test" name="test-run" completionSummaryFile="artifacts/test-summary.txt"
process wait id="test-run" timeoutSeconds=60
process list
process output id="backend-dev"
process logs id="proc_1"
process kill id="backend-dev"
process kill id="proc_1" force=true
process clear
Field rules:
startrequirescommandandname. A live process name must be unique, ignoring case. Names whose trimmed value matchesproc_<digits>are reserved for IDs, ignoring case (for example,proc_1andPROC_999). Choose a different friendly name; invalid names are rejected before spawning or creating logs.- A started command must remain in the foreground. Do not include
&,setsid,coproc, detached container flags, or daemon-mode options; the manager supervises the foreground process group. Validation also applies through package executors such aspnpm exec,npm exec, andnpx. Package scripts are not inspected. This validation is mandatory even when bash interception is disabled. - In every mode,
startacceptsreadyPatternand optionalreadyTimeoutSeconds(default 60, at most 1,800).readyTimeoutSecondsrequiresreadyPattern. Matching is a case-insensitive substring across stdout and stderr. A match or timeout wakes the agent without stopping the process. - In every mode,
startalso acceptscompletionSummaryFile. Relative paths resolve from the process working directory. The process must create and manage this UTF-8 file. Completion notifications and completed waits use the same substantive report: process identity, command, success/failure/termination outcome, and summary or recent output. Each report reads the file once after the process ends; the file is not cached or managed by the extension. - Summary reports contain up to 128 sanitized lines, with each line limited to 512 UTF-8 bytes. When content is omitted, the last line is an omission marker. An unavailable, invalid, or empty summary produces an explicit fallback report with recent output. Both delivery paths use the same summary extraction and sanitization; wait results also apply the total content cap below. Wait timeouts and readiness results for a still-running process do not read the summary.
output,logs,kill, andwaitrequireid.waitacceptsuntil("exit"by default, or"output"with a case-insensitive substringpattern) andtimeoutSeconds(default 60, at most 1,800). A timeout or cancelled wait does not stop the process. A successful wait operation can report a failed or terminated command; inspect the command outcome.- Wait content is capped at 50 KiB, including truncation notices. Structured message and matching-line previews are separately UTF-8 byte-bounded. The outcome remains visible, including command failure or termination. Truncated results point to process logs only while the record is retained; waiting does not extend log lifetime.
killacceptsforce=trueto sendSIGKILLinstead ofSIGTERM.
Matching processes
For actions that accept id, it must be either:
- the exact process ID, such as
proc_1 - the exact friendly process name, such as
backend-dev
IDs take precedence over friendly names. Friendly names match case-insensitively. Reusing a finished process's name can make a name lookup ambiguous; use an exact ID in that case. Records and output cursors live only in memory and are not restored from session history; historical tool results still render.
A failed lookup names the known processes, so a mistyped id does not cost an extra list call.
Event-driven continuation instead of polling
By default, in long-lived TUI and RPC sessions:
- Call
process start; it returns immediately and the process continues across agent turns. - Do independent work if any remains. Otherwise, report that work is running and end the turn so the user remains in control.
- Pi automatically resumes the agent when the process ends.
- For a server or watcher, set
readyPatternonstart. Pi resumes the agent when the pattern matches, when the readiness timeout expires, or when the process exits first.
Readiness monitoring is one-shot. A timeout expires only the monitor; it does not stop the process. Normally, a process that becomes ready and later exits produces both a readiness notification and an end notification.
For explicit run-to-completion work, or whenever required results must be obtained before the run ends, use process wait instead. Print and JSON runs should wait for required results rather than rely on a future turn. If a wait times out and the result is still required, wait again. Keep each wait within the available execution time, including any caller inactivity limit; a longer tool timeout cannot extend the caller's lifetime.
An active wait suppresses the automatic completion notification. For readiness, only an output wait that actually delivers the same case-insensitive marker replaces the automatic readiness notification. Different markers and exit-only waits leave readiness independent. If a matching wait times out or is cancelled before readiness, the monitor remains armed until its own deadline or the process ends. If a matching result cannot be delivered, readiness is notified instead. A notification already sent before a wait starts cannot be retracted.
Wait for required results, not every process's natural exit. For a temporary dev server, start it, wait for readiness, run and wait for tests, then stop the server. A user-facing service intended to keep running needs a long-lived owning session; session shutdown still stops managed processes.
Repeated process list, process output, or process logs calls just to check progress are an anti-pattern. Use output for one-off inspection or diagnosis, not polling.
Logs and output
process outputreturns what was printed since the agent's previousoutputcall, and reports "no new output" instead of resending known lines.process logsreturns log file paths for deeper inspection and for the/psoverlay.- Each stdout, stderr, and combined log file keeps the latest output, up to 5 MiB. On overflow it trims to roughly 4 MiB so runaway output cannot grow without bound. Incremental reads and output waits track logical byte positions through rotations rather than relying on file size. Consumed complete lines are not replayed.
- If rotation discards unread bytes, output resumes at retained content and reports a coverage gap. Output waits still scan retained unread bytes, but cannot rule out a pattern in discarded output. Logs are bounded tails, not a complete output archive.
- A session retains at most 16 live processes and 32 total process records. At the total limit, a successful start evicts the oldest finished record and its logs; live records are never evicted. Use
process clearto remove all finished records explicitly. - Use
outputandlogswhen the user asks, when debugging, or when investigating a specific problem.
Bash interception
Whether a command runs for a long time cannot be decided from its name, so this extension does not try. Two mechanisms cover it instead:
- Commands that detach from the session (
&,setsid,disown,gunicorn --daemon,ssh -f, and the same through wrappers, package executors, shells, and command substitution) are blocked and routed toprocess start. Remove the detaching syntax before starting a managed process. Package option values and ordinary command arguments are not treated as executables. Bash's existing allowance for detached container commands such asdocker compose up -dis unchanged;process startrejects them because the managed command must remain in the foreground. - Every other bash command runs normally, but a bash call that sets no
timeoutof its own getsinterception.bashTimeoutSeconds. If it is hit, the timeout message tells the agent to restart the work with theprocesstool. A timeout the agent chose itself is never overridden.
Routing long work to the tool in the first place is the job of the tool description and the prompt guidelines, which the extension re-adds to the system prompt when a custom prompt would otherwise drop them.
Killing processes
process kill id="..."sendsSIGTERM.process kill id="..." force=truesendsSIGKILL.- Tool-triggered kills never notify the agent.
Runtime notes
- Log files live in a temporary directory managed by the extension.
- Background processes are cleaned up when the session shuts down.
- Pi's native extension status area shows only the active-process count as
N procsand clears at zero. Finished records and logs remain available through/psand the process tool. - The
/psoverlay reads from file-backed logs, so process output remains available without stuffing the full log into the agent context.
Development
There are no Git hooks installed by this repository. Before committing or opening a PR, consider running:
pnpm typecheck
pnpm lint
pnpm test
After dependency changes, also verify the lockfile with:
pnpm install --frozen-lockfile --ignore-scripts
Releasing
- Update
versioninpackage.jsonand add the release toCHANGELOG.md. - Check what would ship:
npm pack --dry-run(source only; no test files). - Publish from
mainwith a clean tree:pnpm publish --access public.prepublishOnlyruns lint, typecheck, and tests first. - Tag the release:
git tag v<version> && git push origin v<version>.
License
MIT