Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 4 additions & 5 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@

## Unreleased: agent monitor

- Add `/pstack:monitor` and `pstack-monitor`, a read-only local server with a live node canvas of the agents on this machine: Claude Code and Codex sessions, the subagents they spawn, and each agent's model. Any agent opens into a panel that streams its prompts, replies, thinking, and tool calls. The theme follows the session's harness: warm for Claude Code, blue for Codex.
- The monitor reads the transcripts each harness already writes and adds no hook, so it costs nothing in sessions that never open it. Status comes from process records, lifecycle events, and parent tool results, never file times; what cannot be known shows as unknown. Unrecognized transcript records are counted and surfaced instead of dropped, and `pstack-monitor doctor` reports them without printing content.
- Messages between agents appear as dashed, arrowed arcs with a count, from Codex's agent messages and Claude Code's `SendMessage` calls. Each new message sends a spark from sender to recipient.
- External lanes become visible while they run. `pstack-runner` writes an opt-in journal (start record, stdout as it arrives, receipt copy) under `~/.pstack-flex/lanes/` whenever that directory exists; `pstack-monitor start` creates it and `pstack-monitor journal off` deletes it. The new `--label` flag names a lane by its role, such as `arena cross-judge`, and routes nothing. A journal failure never changes a lane's receipt, exit status, or output.
- The server binds `127.0.0.1`, accepts no writes, rejects foreign `Host` and `Origin` headers, and requires a per-start token. It runs until `pstack-monitor stop`. Tracked in [pstack-flex #23](https://github.com/thisguymartin/pstack-flex/issues/23).
- Add `/pstack:monitor` and `pstack-monitor`, a read-only local server that draws pstack work on this machine as a live node canvas: each session that runs pstack, every subagent it spawns, and external Codex, Grok, DeepSeek, and MiniMax lanes, with each agent's model and messages. `--all` or **Show all** shows every session. Tracked in [pstack-flex #23](https://github.com/thisguymartin/pstack-flex/issues/23).
- Status comes from process records, turn boundaries, parent results, and lane receipts, never file times. The page separates working, waiting for input, stalled, and finished, and shows each agent's task, the tool call it waits on, and its latest step.
- The agent panel resizes by dragging its edge or with a widen button, and remembers its width.
- `pstack-runner` writes an opt-in lane journal (start record with the head of the prompt, stdout as it arrives, receipt copy) under `~/.pstack-flex/lanes/` while that directory exists. `--label` names a lane. A journal failure never changes a lane's receipt, exit status, or output.

## Unreleased: merge open-pstack 1.5.0 (Cursor pstack 0.15.5)

Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ The monitor does not start by itself. Start it when you want to watch a run:
/pstack:monitor
```

In Codex, ask for `pstack:monitor`. It prints a link to a local page that draws every session, the agents it spawned, the external lanes pstack launched, and the messages between them, live. It keeps running in the background until you say "pstack, kill the monitor" or restart the machine. See [Watching your agents](docs/USAGE.md#watching-your-agents-the-monitor) for the terminal commands and troubleshooting.
In Codex, ask for `pstack:monitor`. It prints a link to a local page that draws each session running pstack, the agents it spawned, the external lanes pstack launched, and what each one is doing now, live. It keeps running in the background until you say "pstack, kill the monitor" or restart the machine. See [Watching your agents](docs/USAGE.md#watching-your-agents-the-monitor) for the terminal commands and troubleshooting.

## Useful skills

Expand All @@ -167,7 +167,7 @@ In Codex, ask for `pstack:monitor`. It prints a link to a local page that draws
| `maintain-verification-skill` | The project's verification instructions no longer match the product. |
| `babysit` | A pull request needs CI failures and review comments handled until it is ready. |
| `reflect` | A hard task is finished and its lessons should improve the next run. |
| `monitor` | You want to watch your agents work: a live graph of every session, subagent, and model lane, with each agent's activity a click away. |
| `monitor` | You want to watch your agents work: a live graph of each pstack session, its subagents and model lanes, and what each is doing now. |

Plugin skills include `pstack:` in their name. In Claude Code, invoke a native skill such as `/pstack:architect`. In Codex, ask for the skill, such as `Use pstack:architect for this design.` See the [technical reference](docs/reference.md) for the full list.

Expand Down
75 changes: 31 additions & 44 deletions docs/USAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -220,75 +220,62 @@ Every external lane writes a JSON receipt next to its output. The fields that ma

## Watching your agents: the monitor

The monitor is a local web page that draws every Claude Code and Codex session on this machine as a live graph. It shows the agents each session spawned, the external lanes pstack launched, and the messages they sent each other. Click any agent to read what it is doing.
The monitor is a local web page that shows pstack work on this machine as a live graph. Each session that runs pstack appears with every agent it spawned: native Claude and Codex subagents, and external Codex, Grok, DeepSeek, and MiniMax lanes. Click an agent to see its task, what it is doing now, and its full activity.

### It does not start by itself
A session counts as pstack work once it runs a `/pstack:` command, a pstack skill, or a pstack agent (in Codex, a prompt that names pstack or a call into pstack's skills or runner). **Show all** in the session list, or `start --all`, shows every session instead.

Nothing launches the monitor when a session starts or when you log in. Start it once. It then runs in the background, outside any session, until you stop it or restart the machine. Starting it while it already runs prints the same link again. After a plugin update, the next start replaces the old server with the new build.
Status comes from evidence:

### Start it

In Claude Code:
| Shown | Meaning |
| --- | --- |
| working | the process is busy, or the agent is mid-turn |
| waiting for input | the session's process is open and idle |
| stalled | a turn started and has been silent for 15 minutes with no live process behind it |
| quiet | still working, but nothing new for 90 seconds |
| done, failed, cancelled | the agent or lane recorded an outcome |
| ended · process gone | the process exited without an outcome |

```text
/pstack:monitor
```
### Start and stop

In Codex:
Nothing starts the monitor for you. Start it once; it runs in the background until you stop it or restart the machine.

```text
Use pstack:monitor.
/pstack:monitor # Claude Code
Use pstack:monitor. # Codex
```

Either one prints a link such as `http://127.0.0.1:47317/?token=…`. Open it in your browser. The link carries an access token that is new each time the monitor starts, so an old link stops working after a restart.

From a terminal, run the launcher inside the installed plugin. It needs Bun, which pstack's runner already uses.
Either prints a link such as `http://127.0.0.1:47317/?token=…`. The token changes on every start. From a terminal, run the launcher inside the installed plugin (it needs Bun):

```shell
# Claude Code install
~/.claude/plugins/cache/open-pstack/pstack/<version>/skills/poteto-mode/scripts/monitor/pstack-monitor start --parent claude

# Codex install
~/.codex/plugins/cache/open-pstack/pstack/<version>/skills/poteto-mode/scripts/monitor/pstack-monitor start --parent codex

# a checkout of this repository
plugins/pstack/skills/poteto-mode/scripts/monitor/pstack-monitor start
```

`--parent` picks the page's starting theme, orange for Claude Code and blue for Codex, and selects that harness's current session first. Other options: `--port <n>` (default 47317), `--hours <n>` for how far back the session list reaches (default 24), and `--focus <session id>`.

### Stop it and other commands
Options: `--all`, `--port <n>` (default 47317), `--hours <n>` (default 24), `--focus <session id>`.

| Ask pstack | Or run | What happens |
| --- | --- | --- |
| "pstack, kill the monitor" | `pstack-monitor stop` | Stops the server. Your agents keep running; the monitor never stops an agent. |
| "is the monitor running?" | `pstack-monitor status` | Prints agent counts and the link. |
| | `pstack-monitor doctor` | Reports how well recent transcripts parsed, as counts only. |
| | `pstack-monitor journal off` | Stops recording external lanes and deletes what was recorded. `on` and `status` also work. |

To stop an agent itself, interrupt it in its own session, or cancel a pstack lane through the background task that launched it. The runner then writes a `cancelled` receipt.
| "pstack, kill the monitor" | `pstack-monitor stop` | Stops the server. Agents keep running. |
| "is the monitor running?" | `pstack-monitor status` | Prints counts and the link. |
| | `pstack-monitor doctor` | Reports how well recent transcripts parsed. |
| | `pstack-monitor journal off` | Stops recording lanes and deletes the records. |

### External lanes

pstack runs some lanes outside the harness, such as a Codex cross-judge launched from Claude Code. Those lanes normally leave nothing on disk until they finish. The first `start` turns on the lane journal, which records each lane in `~/.pstack-flex/lanes/` as it runs, so the monitor can show it live. The journal keeps each lane for 7 days, readable only by you. Lanes that started before the journal was on do not appear.

Codex and Grok lanes stream while they work. Claude, DeepSeek, and MiniMax lanes appear as soon as they start, but their reply arrives only when they finish, because those CLIs print one result at exit.

### What it reads and writes
The first `start` turns on the lane journal in `~/.pstack-flex/lanes/`, kept for 7 days, so lanes show while they run. Codex and Grok lanes stream. Claude, DeepSeek, and MiniMax lanes show their reply when they exit. Lanes started while the journal was off do not appear.

It reads the transcripts Claude Code and Codex already keep in `~/.claude` and `~/.codex` (or `CLAUDE_CONFIG_DIR` and `CODEX_HOME`). It writes only its own record and log in `~/.pstack-flex/monitor/` and the lane journal. It adds no hook and changes no harness setting. It listens on `127.0.0.1` only and accepts no writes. `PSTACK_FLEX_MONITOR_DIR` and `PSTACK_FLEX_LANES_DIR` move its two directories.
The monitor reads the transcripts in `~/.claude` and `~/.codex` (or `CLAUDE_CONFIG_DIR` and `CODEX_HOME`), writes only `~/.pstack-flex/monitor/` and the journal, listens on `127.0.0.1` only, and accepts no writes.

### When something looks wrong

| Symptom | Meaning | Fix |
| --- | --- | --- |
| `port 47317 is unavailable` | another program uses the port | `pstack-monitor start --port 47400` |
| The page says "This link has expired" | the monitor restarted, after an update or a reboot | run start again and open the new link |
| Start fails inside a sandboxed session | the sandbox blocked the local port or `~/.pstack-flex` | run the start command in your own terminal; in Claude Code, type it after `!` |
| A session says "status unknown" | Claude Desktop and SDK sessions keep no process record | nothing to fix; its activity still streams |
| A banner says a source is degraded or newer than checked | a CLI update changed its transcript format | run `pstack-monitor doctor` and open an issue with its output |
| An external lane never appears | the journal was off when the lane started | `pstack-monitor journal status`, then `pstack-monitor journal on` |
| A Codex thread stays "in turn" | Codex was killed mid-turn and wrote no ending | nothing to fix |
| Symptom | Fix |
| --- | --- |
| `port 47317 is unavailable` | `pstack-monitor start --port 47400` |
| "Link expired" | the monitor restarted; run start again and open the new link |
| Start fails in a sandboxed session | run the start command in your own terminal (in Claude Code, after `!`) |
| A session is missing | it has not run pstack yet; click **Show all** |
| A banner says a source is degraded | run `pstack-monitor doctor` and open an issue with its output |
| An external lane never appears | `pstack-monitor journal status`, then `journal on` |

## Cost playbook

Expand Down
19 changes: 10 additions & 9 deletions docs/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,15 +155,16 @@ The table uses the short upstream names. Claude Code exposes each native skill w

## Agent monitor

`/monitor` starts `skills/poteto-mode/scripts/monitor/pstack-monitor`, a read-only server on `127.0.0.1` (default port 47317), and prints a link that carries a per-start access token. The page draws the selected session's agents as a node canvas, themed by the session's harness, and streams any agent's timeline in a side panel.

- **Sources.** It reads what each harness already writes: Claude Code session transcripts, subagent transcripts and their `.meta.json` sidecars, and `~/.claude/sessions/<pid>.json` process records; Codex rollouts under `~/.codex/sessions/`, where a child thread names its parent. It adds no hook and changes no harness setting. `CLAUDE_CONFIG_DIR` and `CODEX_HOME` move the sources; `PSTACK_FLEX_MONITOR_DIR` moves the server record and log.
- **Status comes from evidence, never file times.** A Claude Code terminal session is live while its process record names a running process with the recorded start time. A subagent finishes on its parent's tool result or background-task notification. A Codex thread is in a turn between `task_started` and `task_complete` or `turn_aborted`. Claude Desktop and SDK sessions keep no process record, so their status shows as unknown rather than guessed.
- **External lanes.** `pstack-runner` keeps a lane's output in memory until it exits, so the runner also writes an opt-in journal: one directory per lane under `~/.pstack-flex/lanes/` (or `PSTACK_FLEX_LANES_DIR`) with `lane.json` (provider, model, effort, label, runner pid, parent session), `stream.jsonl` (the CLI's stdout as it arrives), and `receipt.json` (a copy of the receipt). The journal is on only while that directory exists: `pstack-monitor start` creates it, `pstack-monitor journal off` deletes it with everything recorded, and the server prunes lanes older than 7 days. A lane hangs under the session that launched it, read from that harness's own session variable. Codex and Grok lanes stream; Claude, DeepSeek, and MiniMax lanes print one result when they exit. A journal failure never changes a lane's receipt, exit status, or output.
- **Messages between agents.** Dashed, arrowed arcs show who messaged whom, with a count; each new message sends a spark along its arc, and an agent's panel totals what it sent and received. Codex records each message once, in the recipient's rollout, addressed by agent path (`/root`, `/root/<agent>`), and the monitor resolves the path within that tree. Claude Code messages come from `SendMessage` calls, addressed by agent id, name, or `main`. A message to another session's socket is left off the canvas, since that session is drawn separately.
- **Format drift is visible.** These transcript formats are undocumented. Unrecognized record types and malformed records are counted per source; the page shows a banner and `pstack-monitor doctor` prints the counts, record types, and CLI versions, never content.
- **Lifecycle.** `start` reuses a running server of the same build and replaces one from another build. `status`, `stop`, `doctor`, and `journal on|off|status` complete the CLI. Nothing times the server out.
- **Security.** The server binds loopback only, rejects foreign `Host` and `Origin` headers, accepts no writes, and requires the token (exchanged for an `HttpOnly`, `SameSite=Strict` cookie) on every route except a health check that reveals no data. The page runs under a same-origin content security policy and renders transcript text only as text.
`/monitor` starts `skills/poteto-mode/scripts/monitor/pstack-monitor`, a read-only server on `127.0.0.1` (default port 47317), and prints a link with a per-start access token. The page draws one session's agents as a node canvas and streams any agent's timeline in a resizable side panel.

- **Scope.** The server indexes every Claude Code and Codex session and marks a spawn tree as pstack work when any member shows pstack evidence: `attributionPlugin`/`attributionSkill`/`attributionAgent` on Claude records, a `Skill` or `Agent` call naming `pstack:`, a `/pstack:` command, a `pstack:` subagent sidecar, a Codex root prompt naming pstack or a call into `pstack-runner` or pstack's skills, or any runner lane. The page shows marked trees by default; **Show all** or `?all=1` (`start --all`) shows everything.
- **Sources.** Claude Code session and subagent transcripts, `.meta.json` sidecars, and `~/.claude/sessions/<pid>.json` process records; Codex rollouts under `~/.codex/sessions/`. No hook, no harness setting. `CLAUDE_CONFIG_DIR`, `CODEX_HOME`, and `PSTACK_FLEX_MONITOR_DIR` move them.
- **Status comes from evidence, never file times.** A terminal session follows its live process record (`busy` is working, `idle` is waiting for input). Sessions without one, and Claude subagents, follow turn boundaries: a human prompt opens a turn and an `end_turn` reply closes it. A subagent is done when its own turn ends or its parent records the result, whichever comes first. A Codex thread follows `task_started` and `task_complete`. The page adds two qualifiers: quiet after 90 s without stamped activity, and stalled once a turn-only run has been silent for 15 minutes.
- **Activity.** Each agent carries its latest prompt, the tool call still awaiting a result, and its latest step. Cards, the session list, and the panel's Task and Now lines show them.
- **External lanes.** `pstack-runner` writes an opt-in journal under `~/.pstack-flex/lanes/` (or `PSTACK_FLEX_LANES_DIR`) while that directory exists: `lane.json` (provider, model, effort, label, the first 300 characters of the prompt, runner pid, parent session), `stream.jsonl` (stdout as it arrives), and `receipt.json`. `pstack-monitor start` creates it, `journal off` deletes it, and the server prunes lanes older than 7 days. Codex and Grok lanes stream; Claude, DeepSeek, and MiniMax lanes print one result at exit. A journal failure never changes a lane's receipt, exit status, or output.
- **Messages between agents.** Arrowed arcs with a count, from Codex agent messages (addressed by agent path) and Claude Code `SendMessage` calls. Messages to another session's socket are left off.
- **Format drift is visible.** Unrecognized and malformed records are counted per source; the page shows a banner and `pstack-monitor doctor` prints counts and CLI versions, never content.
- **Lifecycle and security.** `start` reuses a running server of the same build and replaces another build. The server binds loopback, rejects foreign `Host` and `Origin` headers, accepts no writes, requires the token (exchanged for an `HttpOnly`, `SameSite=Strict` cookie) everywhere except a data-free health check, and renders transcript text only as text. Nothing times it out.

## Subagents

Expand Down
Loading
Loading