npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@geraschenko/pictl

v0.1.4

Published

Spawn, observe, control, and attach to a fleet of pi coding-agent instances

Readme

pictl: a pi agent orchestration CLI

npm

pictl aims to let humans, agents, scripts, and code interact with live pi instances simultaneously, each on their own terms. Humans can attach with the stock pi TUI, and agents/scripts get ergonomic (but unfettered) access to the RPC interface. You don't have to give up your /tree, and they aren't forced to tmux capture-pane.

Like pi, pictl is meant to be minimal and composable. Its main components and associated subcommands are:

  • Lifecycle management (spawn/archive/list/status/…). Each agent runs as a background process, automatically resumed when needed. There is no central orchestrator; each agent's daemon manages its own entry in an on-disk registry.
  • CLI wrappers for all RPC commands (prompt/set-model/abort/compact/…). prompt streams the response; everything else returns the RPC response as JSON.
  • Monitoring with tail and wait. prompt and tail can emit formatted messages (default), session entries, or the RPC event stream — human-readable by default, --json for machines. See Getting fancy.
  • TUI access with attach. You get pi's stock interface, including any custom UI extensions.

Installation

npm install -g @geraschenko/pictl
pictl --version

pictl bundles its own lightly modified pi, so you don't need pi installed. See docs/pi-modifications.md for what's changed.

[!NOTE] pictl runs on Linux and macOS only; it uses Unix domain sockets and has no native Windows support. Node 22.18 or newer is required.

On Linux, pictl's node-pty dependency has no prebuilt binary and compiles a native addon during install, so you need a C/C++ toolchain and Python: build-essential and python3 on Debian/Ubuntu, or the equivalent.

Quickstart

Start an agent and make it the default target for subsequent commands:

export PICTL_TARGET="$(pictl spawn)"
echo "$PICTL_TARGET"
  • If you don't set $PICTL_TARGET, commands that require a target need --target PREFIX or -t PREFIX. Any unique prefix of the agent id is accepted.
  • If you want to pass extra args to pi, put them after -- when you spawn the agent, like this: pictl spawn -- -e my_extension.ts. To "wrap" an existing pi session, exit the session and run pictl spawn -- --resume <session-id> (NOTE: the agent id is different from the session id).

Attach to the TUI in another terminal if you want to follow along in "regular pi view" (recommended).

pictl attach --target <PREFIX_OF_PICTL_TARGET>
  • You can detach with ctrl+]. Detaching does not stop the agent.
  • You can also exit with ctrl+d as usual, which does stop the agent since it forwards the exit command to the pi process. But it'll be automatically revived when any commands are sent to it. When it's revived, the same cwd and arguments to pi are used that were used when it was first created.

Send commands to the agent with prompt and pi's other RPC commands. Do this from the first terminal (or wherever you've set PICTL_TARGET):

pictl prompt "Say hello. Keep it short"
pictl set-model openai-codex gpt-5.5

# Note: compaction will fail if the session is already tiny.
pictl compact --custom-instructions "Next we're going to say goodbye. Only keep context relevant to that task."

# RPC pass-through commands (except for `prompt`) return json. `pictl format`
# can prettify the responses from `get-messages`, `get-entries`, and `get-tree`.
pictl get-entries | pictl format entries

# Note: you have to use a real entry id from your actual session here;
# see the output from `get-entries` above.
pictl navigate-tree 8c5cb595

[!NOTE]

  • For all available RPC commands, see pi's rpc-types.ts, or run pictl -H. The tweaked version of pi used by pictl also includes the command navigate-tree, which stock pi does not.
  • The help also includes details about subcommand arguments, e.g. pictl set-model -H to learn about arguments of set-model.

Manage your agents

pictl list [--all] [--cwd PATH]

# Non-destructive. Shuts down processes and removes from default `pictl list`.
pictl archive -t <PREFIX_OF_PICTL_TARGET>

# Destructive. Deletes file from registry.
pictl purge -t <PREFIX_OF_PICTL_TARGET>

[!NOTE]

  • The actual session messages live in your ~/.pi as usual.
  • pictl's agent registry lives in your per-OS user data dir (~/.local/share/pictl on Linux), or wherever $PICTL_DIR points if you set it.

Setup tab completion with pictl completion install (bash only).

Getting fancy with pictl [prompt|tail|format]

pictl prompt and pictl tail both show a live agent's activity. prompt sends a message and streams until the end of the assistant turn. tail doesn't send anything; it prints the agent's current context and then keeps streaming new activity indefinitely. Use tail --until turn-end to return once the current turn (if any) finishes, or tail --timeout 0 to print the current context and return immediately.

Machine-readable output

Both prompt and tail print human-readable, formatted output by default, but add --json to get machine-readable output. If you want finer control over the formatting use --json and pipe to pictl format.

Async prompting

Send a prompt without waiting for the reply with pictl prompt --detach. Then check back with tail --until turn-end, which returns once the current turn (if any) finishes. The output of prompt/tail --until ends with a "cursor" that identifies the entry id of the last message returned, and pictl tail --since <entry-id> will return all the messages after that. For example:

$ pictl tail -t c8b --until turn-end
...
== assistant ==
You are so smart.

[cursor: 6be9380a]

Then you can send an async message with

$ pictl prompt -t c8b -d "Stop being such a boot-licker and write a compiler. No mistakes."

The -d causes the prompt command to return immediately with no output, but then when you're ready to check back in on this agent, you can see what's happened since last you checked with

$ pictl tail -t c8b --since 6be9380a --until turn-end
== user ==
Stop being such a boot-licker and write a compiler. No mistakes.

== assistant ==
[thinking]
Yes sir. I'll get right on it.
[tool: bash ...]
...

[!NOTE]

  • If no --since is provided, tail will give you all the messages in the agent's current context.
  • If --since is provided, you get all messages from all activity since that entry, which can cross compaction boundaries and tree navitation. If you used /tree to navigate back and forth between branches of the conversation, sending messages here and there, what you'll get is the messages in the order they were inserted into the session file (i.e. chronological order).
  • If the underlying session file has changed (e.g. you typed /new or /fork into the interactive TUI, or used the switch-session command), then you'll only get the new activity on the current session file, and you'll get an error if the current file doesn't contain the given entry id. You can use pictl status to see what session files have been associated with a given agent.

Messages vs Entries (vs RPC events)

pi distinguishes between messages (the agent/LLM-facing conversation units) and entries (durable, branchable session history). Messages are derived from entries. If you need the greater fidelity of entries, you can get it. You can even stream the RPC socket events if you really need to, but watch out because that includes a bunch of stuff that doesn't get written to the session file, like incremental message updates.

You can control what you get from prompt/tail with --type:

  • --type messages (default): one block per message (and per control event like compaction), the same rendering as pictl format messages. --json for no formatting.
  • --type entries: one line per session entry (<id> <role> <summary>), the same rendering as pictl format entries. --json for no formatting.
  • --type events: pi socket events, one line per event, the same rendering as pictl format events. --json for no formatting. Since events aren't persisted, you can only get events that appear after you run the command; there is no historical output, so -n and --since don't apply.

If the reason you're after entries is to recover the tree structure from the parentId field, you may want to get the tree structure directly with get-tree. The output of get-tree is json (like pretty much all subcommands other than prompt and tail), but you can pretty print it like this:

pictl get-tree -t c8b | pictl format tree

Further reading

  • How does pictl work? See docs/architecture.md for details about the agent registry, command and tty sockets, daemon processes, and how I expect pictl to interact with other languages.

  • Tweaks to pi. See docs/pi-modifications.md for details about the tweaked version of pi pictl depends on, especially --rpc-socket mode.

  • For all available subcommands, run pictl --help-all. Subcommands have their own help info; e.g. pictl format entries --help.