@99percentpeople/pi-background-tasks
Background tasks, explicit waits, logs, signals, and PTY/TUI support for Pi
Package details
Install @99percentpeople/pi-background-tasks from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:@99percentpeople/pi-background-tasks- Package
@99percentpeople/pi-background-tasks- Version
1.2.1- Published
- Jul 28, 2026
- Downloads
- 1,631/mo · 991/wk
- Author
- 99percentpeople
- License
- MIT
- Types
- extension
- Size
- 116.4 KB
- Dependencies
- 3 dependencies · 4 peers
Pi manifest JSON
{
"extensions": [
"./index.ts"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
@99percentpeople/pi-background-tasks
Run long-lived commands alongside the Pi coding agent without blocking the current conversation. The extension supports ordinary background processes as well as full PTY-backed terminal applications, with live status, retained output, interactive attach, and completion-aware cleanup.
Features
- Run builds, servers, watchers, tests, and terminal applications in the background
- Choose lightweight
pipemode or a real pseudo-terminal withptymode - Keep consuming and retaining output even when no user is attached
- Attach without pausing or redirecting the child process
- Replay earlier output before switching seamlessly to live output
- Interact with PTY applications using keyboard, mouse, focus, and resize events
- Inspect separate stdout/stderr logs for pipe tasks or a parsed terminal screen for PTY tasks
- Wait explicitly for task completion without repeated polling
- Require unique task names while tasks remain retained, preventing ambiguous references
- Keep final output available long enough for both the user and model to inspect it
- Track task status, duration, and recent output in a compact expandable widget
- Send text, terminal keys, stdin data, and process signals to running tasks
- Use the same shell resolution and command syntax as Pi's built-in
bashtool
Install
pi install npm:@99percentpeople/pi-background-tasks
During local development:
pi -e ./extensions/background-tasks/index.ts
Typical workflow
Ask Pi to start a command in the background, then continue working while it runs. For example:
Run the development server in the background and tell me when it is ready.
Start lazygit in a background PTY so I can attach to it.
Run the test suite in the background and inspect the failures when it exits.
The model can start, wait for, inspect, signal, and stop tasks. Model-facing
tools have narrow responsibilities: bg_wait reports completion, bg_status
reports metadata, bg_logs reads output, and bg_kill reports termination.
Users normally only need the two interactive commands:
/bg-attach <task-id>
/bg-kill <task-id>
Omit the task ID to choose from an interactive list. Press Ctrl+] to leave an
attached console without stopping its task.
Tool ordering and parallelism
Background tool calls that target the same task ID in one model response execute strictly in source order. Calls for different task IDs remain independent and can execute in parallel. This supports composable workflows without making one tool perform another tool's job:
bg_wait(A) → bg_logs(A) # wait, then read final/current-at-timeout output
bg_send(A) → bg_wait(A) → bg_logs(A) # interact, wait, then read output
bg_kill(A) → bg_logs(A) # terminate, then read final output
The ordering is intentional. bg_logs(A) → bg_wait(A) reads the output that is
available first and only then begins waiting. Multiple chains such as
bg_wait(A) → bg_logs(A) and bg_wait(B) → bg_logs(B) can run concurrently.
A bg_status call without an ID is a global snapshot and is not part of any
single-task chain.
Pipe and PTY modes
| Pipe mode | PTY mode | |
|---|---|---|
| Best for | Builds, servers, scripts, tests, and watchers | TUIs, REPLs, debuggers, and terminal-aware programs |
| Output model | Separate stdout and stderr logs | One terminal screen with ANSI control sequences interpreted |
| Attached view | Combined stdout/stderr in arrival order | Live virtual terminal |
| Direct attached input | Read-only; send stdin through Pi | Keyboard and mouse input are forwarded |
| Resize behavior | Local console reflow only | Debounced terminal and child-process resize |
Pipe mode is the simpler default for commands that only need reliable logs. PTY mode sets up a real pseudo-terminal, so programs can detect terminal capabilities, redraw their screen, request mouse tracking, and respond to window size changes as they would in a standalone terminal.
Live attach and final snapshots
Each task owns a virtual console from the moment it starts. Output is processed
continuously whether attached or not. When /bg-attach opens the console, it
first renders the retained terminal buffer and buffers only the small amount of
output arriving during that replay. The child process is never paused and its
stdout or stderr is never reconnected to the physical terminal.
For PTY applications, attach forwards keyboard input and terminal resize events. Extended mouse encodings, including SGR and SGR pixel mode, are restored when the application enables them. Mouse tracking, encodings, and focus modes are reset on detach so terminal state does not leak back into Pi.
If a task exits while attached, the console stays open until Ctrl+]:
- pipe mode appends a completion message;
- PTY mode overlays the message in the bottom-right corner without changing the application's final screen.
The completion message exists only on the user's physical terminal. It is not
written into retained logs, bg_logs, or the final virtual-terminal snapshot.
A finished task can be attached again in read-only mode while its snapshot is
still retained.
Status widget
Pi displays background tasks below the editor with their status, duration, and
latest pipe output. The collapsed widget shows only the task totals so it stays
out of the way by default. Pi's standard tool expansion shortcut (Ctrl+O by
default) reveals the complete task list. Finished pipe tasks include their
latest output in the expanded view; finished PTY tasks keep the list compact
because their final screen remains available through attach or explicit logs.
The header uses separate colors for the total, running, and finished counts so active work stands out without making the whole widget look like a warning. Running durations and recent output refresh without repeatedly registering a new widget.
Output retention and cleanup
Within the current session, a running task continues across ordinary agent runs and remains available to the background tools. Reloading or shutting down the session terminates running tasks.
If a task finishes before the current agent run settles, its final status and retained output remain available only for the rest of that run and are normally removed before the next run starts. Only a task that is still running when the agent settles and then finishes while the agent is idle remains available throughout the next agent run. It can be inspected multiple times during that run and is normally removed before the following run.
Once removed, the old task ID is no longer available through attach, status, logs, or wait operations. Task names must be unique (case-insensitively) among all retained running and finished tasks; a name becomes available again when its old task is removed by this cleanup lifecycle. Completed snapshots are checkpointed as hidden Pi session entries, so reloading the extension or navigating the session tree does not clear them early. Cleanup writes a matching session event, so an expired snapshot cannot reappear after another reload.
Live pipe stdout and stderr remain in memory and are capped at 4 MiB each, with the oldest bytes discarded when that limit is reached. A persisted pipe snapshot keeps the latest 500 lines, capped at 256 KiB per stream. The attached console snapshot keeps 200 lines of scrollback and is capped at 512 KiB. No task output is written to a temporary disk directory. This is not persistent job management: reload restores only completed read-only snapshots, while session shutdown still terminates running processes and disposes live virtual terminals so it does not leave orphaned tasks.
Sending input and keys
Pi can send ordinary text, terminal keys, or signals without opening an attached
console. Text is exact and never implies Enter. Special keys use <...> tokens:
<C-o>filename.txt<Enter>
<Esc>iHello<Enter>
<Down*3><Enter>
The input syntax supports Ctrl+A-Z and Ctrl punctuation, Alt/Meta combinations,
arrows, navigation keys, Insert/Delete, F1-F12, Space, Enter, Escape, Tab, and
Backspace. Modifiers can be combined, such as <C-A-d> or <S-A-Left>, and
key repetition uses forms such as <Down*3>. Use \< for a literal < and
\\ for a literal backslash.
Pipe attachments do not forward keyboard input directly, but Pi can still send stdin through the background task interface. PTY attachments forward input interactively and the same key syntax remains available for model-driven input.
The signal input accepts every named signal exposed by Node.js for the current operating system and sends it to the task's process group on Unix. Signal availability and behavior remain platform-specific; Windows processes and Windows PTYs support a smaller set of effective signal behaviors. Use the dedicated kill operation when the goal is reliable process-tree termination.
Output inspection
bg_logs is the only model-facing tool that returns process output. Pipe tasks
retain stdout and stderr separately, while PTY tasks expose the parsed terminal
buffer rather than raw ANSI escape sequences. Omitting stream works in both
modes: pipe tasks return stdout and stderr, and PTY tasks return terminal output.
Use tail or from_line/max_lines to select the retained range.
bg_wait, bg_status, and bg_kill deliberately return no logs or terminal
screens. Emit them before bg_logs for the same task when output is needed
after completion, inspection, or termination.
Pi capabilities
The extension exposes a compact set of model-facing operations: start, wait, status, logs, send, and kill. Each operation has one responsibility, and same-task source ordering composes them without sacrificing parallel execution across tasks. Users can usually describe the desired outcome in natural language instead of calling these operations manually. While a tool call is streaming, fields appear only after the model writes them; missing arguments are omitted rather than rendered as placeholders.
Shell and platform behavior
Background commands follow Pi's configured Bash resolution and command prefix,
so they use the same syntax as the built-in bash tool. On Windows this means
Pi's configured shellPath, Git Bash, or a bash.exe found on PATH, rather
than cmd.exe.
Installing @99percentpeople/pi-pwsh-adapter explicitly switches both Pi's
built-in shell tool and background tasks to PowerShell syntax.
Pipe-task completion follows the tracked process's exit event rather than the
stdio close event. Launch failures are finalized by the pre-spawn error
event, while close is used only to persist any output drained after process
exit. This matters on Windows, where a descendant can keep a pipe handle open
after the shell PID has already exited; the task status still transitions out
of running, so later status or kill operations do not target a nonexistent
process.
Native dependency
PTY support uses node-pty. If a compatible prebuilt binary is unavailable,
installation may require Python and a native C/C++ build toolchain. On macOS
this generally means Xcode command-line tools; Windows builds may require Visual
Studio C++ and the Windows SDK. Pipe mode does not require a pseudo-terminal at
runtime, but node-pty is still installed as a package dependency.
License
MIT