piocloop
A Python TUI that orchestrates the PI coding agent
to execute tasks from a PLAN.md file iteratively, one session at a time.
piocloop is a port of pyocloop — same
concept, but it drives pi --mode rpc over stdin/stdout JSONL instead of an
OpenCode HTTP server plus SSE stream. That change, plus a real watchdog, fixes
the hangs documented in ANALYSIS.md.
How it works
- piocloop starts a
pi --mode rpcsubprocess - On each iteration it starts a fresh session, sends your loop prompt (with the
plan file path injected), and waits for
agent_settled - PI reads the plan, executes the next task, marks it
[x], and appends<plan-complete>when everything is done - The TUI shows live progress: task counter, progress bar, current task, token count, cost, and elapsed/average time per iteration
- The loop stops when PI writes
<plan-complete>— or when the watchdog, an error streak, a stall, or--max-iterationsintervenes
Requirements
- Python 3.11+
pion your PATH, configured with a provider (developed against pi 0.82.1)
npm install -g @earendil-works/pi-coding-agent
Installation
git clone https://github.com/rbarzic/piocloop
cd piocloop
pip install .
Usage
piloop doctor # check pi is installed and reachable
piloop bootstrap . # create starter PLAN.md and .loop-prompt.md
piloop run --model zai/glm-5.2
Using an OpenRouter model
Set your OpenRouter API key, then prefix the OpenRouter model ID with
openrouter/. For example, Kimi K3 is moonshotai/kimi-k3 on OpenRouter:
export OPENROUTER_API_KEY="your-openrouter-api-key"
piloop run --model openrouter/moonshotai/kimi-k3
You can check that PI's model catalog contains it with:
pi --list-models openrouter | grep kimi-k3
piloop run
| Option | Default | Meaning |
|---|---|---|
-m, --model |
pi's default | Model pattern or provider/id |
--thinking |
pi's default | off|minimal|low|medium|high|xhigh|max |
--plan |
PLAN.md |
Plan file |
--prompt |
.loop-prompt.md |
Loop prompt file |
-r, --run |
off | Start iterating immediately |
--max-iterations |
100 | Hard stop |
--iteration-timeout |
1800 | Seconds before an iteration is aborted |
--max-stalls |
3 | Stop after N iterations with no plan progress (0 disables) |
--dialog-policy |
cancel |
How to answer blocking extension dialogs |
--session-dir, --no-session |
— | Passed through to pi |
--tools, --exclude-tools |
— | Passed through to pi |
--append-system-prompt, --skill |
— | Passed through to pi (repeatable) |
--approve / --no-approve |
pi's default | Project-local file trust |
--verbose, --log, --debug |
— | Diagnostics |
Keys: S start · Space pause · A abort current iteration · R retry ·
Q quit.
Plan format
- [ ] a task to do
- [x] a completed task
- [MANUAL] something a human must do — never attempted, excluded from progress
- [BLOCKED: reason] something the agent could not finish
The run ends when the agent appends, at the start of a line:
<plan-complete>summary of what was done</plan-complete>
Agent skill (optional)
skills/piocloop-setup/ is an Agent Skills
package you can copy into your own agent so it can set up piocloop runs for you —
turning "for each of these 40 items, do X" into a correctly formatted PLAN.md
and .loop-prompt.md. It is not loaded automatically; install it only if you
want it:
cp -r skills/piocloop-setup ~/.pi/agent/skills/ # PI
cp -r skills/piocloop-setup ~/.claude/skills/ # Claude Code
See skills/README.md for other harnesses and for pointing
pi at this checkout without copying.
Differences from pyocloop
| pyocloop | piocloop | |
|---|---|---|
| Agent | OpenCode | PI |
| Transport | HTTP + SSE on port 4096 | stdin/stdout JSONL |
| "Iteration done" signal | session.idle SSE event |
agent_settled RPC event |
| Idle fallback | polled a field that does not exist | polls get_state().isStreaming |
| Iteration timeout | none | --iteration-timeout, then abort, then respawn |
| Iteration cap | none | --max-iterations |
| Progress stalls | undetected | STALLED state |
| Repeated errors | looped forever | error-streak circuit breaker |
| Blocking agent dialogs | n/a | auto-answered (--dialog-policy) |
| Tests | none | 119 |
-a/--agent and -p/--port are gone: PI has no named-agent concept (use
--append-system-prompt / --skill) and no server to bind.
Why the rewrite is more reliable
ANALYSIS.md documents the pyocloop defects that motivated this
port — verified against a live OpenCode server, not inferred. The two that
caused silent hangs:
- the server's stdout pipe was never drained after startup, so the OS pipe
eventually filled and the server blocked in
write()and stopped serving; - the loop's idle wait had no deadline, and its polling fallback tested a
session.idlefield that OpenCode does not return — so a single missed SSE event hung the run forever.
piocloop's design rules (DESIGN.md §4) are the direct response:
every pipe gets a drainer, every wait gets a deadline, and lack of progress is
a first-class state. The test suite mutation-checks the first two — removing
either fix makes the corresponding regression test hang.
Development
python -m venv .venv && .venv/bin/pip install -e ".[dev]"
.venv/bin/python -m pytest tests/ -q
Tests run against tests/fake_pi.py, a stub agent — no network, no API key and
no LLM required.
License
MIT
Metadata
Release files for piocloop 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| piocloop-0.1.1.tar.gz | 53.4 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| piocloop-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 79.9 kB
Release files / piocloop-0.1.1.tar.gz
| Download URL | piocloop-0.1.1.tar.gz |
|---|---|
| Size | 53.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
2ff611ba6a7df72e91e400c0c759b2e8798fee9906e9b30a6741ec86b742587e
|
|
BLAKE2b-256 checksum How to use checksums |
a5c32bfa8462ec50bbb0a971ca608f15c004a6236d08897b524b8ff7147f9aba
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 20, 2026.
Transparency logRelease files / piocloop-0.1.1-py3-none-any.whl
| Download URL | piocloop-0.1.1-py3-none-any.whl |
|---|---|
| Size | 26.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
64c8d8a85a5d57bdee1106539f3dffa1d8b57bafa2a4e397f4ca93e34aa04de7
|
|
BLAKE2b-256 checksum How to use checksums |
ea74d0faaf81db0de7d065f6770cce71e6d0b3fdd48192093e3607b7e7db9803
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 20, 2026.
Transparency logSecurity for piocloop 0.1.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for piocloop-0.1.1.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 20, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.