Skip to content

feat(vibe): Add codex-fleet-monitor skill - #310

Merged
shafty023 merged 7 commits into
mainfrom
feat/vibe-codex-fleet-monitor
Oct 20, 2026
Merged

shafty023 merged 7 commits into
mainfrom
feat/vibe-codex-fleet-monitor

Conversation

@shafty023

@shafty023 shafty023 commented Oct 19, 2026 •

Copy link
Copy Markdown
Collaborator

Purpose

Adds a codex-fleet-monitor skill to the vibe plugin: one background command that polls a fleet of Codex App Server threads (local and one ssh host) plus the GitHub PRs they produce, and exits with a diff on the first change. It flags IDLE, STALLED, FAILED, merge conflicts, review and comment counts, settled check changes and new PRs.

A watcher that only checked turn ids missed a Codex usage-limit stall, because the turn stays open and silent. This one reads each thread's last turn (status, error, item count) and reports a turn whose item count has not grown for STALL_SECONDS as STALLED.

It also:

  • prints codex-usage <local|remote> <band>% <state> resets=<n> per machine from account/rateLimits/read (band is used percent floored to 10; state is ok, LIMIT, LIMIT-SPENDING-CREDITS or LIMIT-STOPPED). The skill tells the agent to warn the user when the band rises fast, and on LIMIT-SPENDING-CREDITS to tell the user at once and stop sending turns unless they approve paid credits.
  • with optional REQUESTS_DIR / REMOTE_REQUESTS_DIR, prints requests <where> <count> <newest file> so the watcher wakes when a Codex session drops a delegated-work request for a Claude worker.
  • compares each watcher run against the previous run's last-snapshot.txt, so a change between a watcher exit and its re-arm is still reported (resetting the base on every start hid a session switching to paid credits).
  • reports PR check counts only once settled; while checks are pending the last settled counts show with (running), so lines do not flap.

Everything stays inside the plugin: liveness.mjs talks to the managed App Server through codex app-server proxy with Node built-ins only, and ratelimit.mjs reuses its exported client. snapshot.sh copies both files to <REMOTE_STATE_DIR>/.fleet-monitor/ on the remote host. Both bound themselves with an unref'd in-process timer, since the repo's no-GNU-timeout contract rules out timeout wrappers.

Affected files

  • plugins/vibe/skills/codex-fleet-monitor/ (SKILL.md, agents/openai.yaml, scripts/liveness.mjs, liveness.test.mjs, ratelimit.mjs, ratelimit.test.mjs, classify.sh, snapshot.sh, watch.sh)
  • plugins/vibe/README.md, CHANGELOG.md
  • vibe version 1.0.58 to 1.0.59 in both plugin manifests

Commands run

  • node --test on every plugins/**/*.test.{mjs,cjs,js} (the CI step): 432 passed
  • uv run pytest plugins/vibe: 334 passed
  • uv run ruff check .: clean; uv run pyright: 0 errors
  • tools/plugin-manifests: npm test (pass)
  • Live: snapshot.sh against a scratch work dir printed codex-usage local and codex-usage remote lines over ssh, requests lines for local and remote dirs (and UNREADABLE for a missing one), and settled and (running) check counts on this PR through a gh shim; watch.sh reported a request file dropped before it was re-armed.

- Background watcher for a fleet of Codex App Server threads (local
  and one ssh host) plus their pull requests; exits with a diff on the
  first change
- Reads liveness from each thread's last turn and item count, so a
  turn left open by a silent usage limit shows as STALLED
- vibe 1.0.57, README and changelog entries

Testing: pytest plugins/ (2430 passed), ruff, plugin-manifests
typecheck and tests, node --check and zsh -n on the scripts
Risks: None identified, the skill only reads thread and PR state
- Describe when to reach for the skill and why a turn-only watcher misses a usage-limit stall
liveness.mjs no longer imports the app-server-orchestrator skill from
~/.codex/skills. It carries a small App Server client (WebSocket over
codex app-server proxy, initialize, thread/read) in one file so the ssh
copy to a remote host still works. sessions.txt takes
'local|remote <label> <threadId>' as well as the older '<name>' form that
reads a state file. Adds a node:test suite with a fake server.
- ratelimit.mjs reads account/rateLimits/read through the client liveness.mjs
  already exports and prints codex-usage <where> <band>% <state> resets=<n>.
  snapshot.sh runs it locally and on REMOTE_HOST, copying both scripts there.
- Optional REQUESTS_DIR and REMOTE_REQUESTS_DIR print a requests line so the
  watcher wakes when a session drops a delegated-work request.
- watch.sh keeps the previous run's last-snapshot.txt as its base, so a change
  between a watcher exit and its re-arm is still reported.
- PR check counts are only updated once settled; while checks are pending the
  last settled counts show with a (running) suffix.
- SKILL.md documents the new lines and what to do about each.
@shafty023
shafty023 merged commit 30283e8 into main Oct 20, 2026
10 checks passed
@shafty023
shafty023 deleted the feat/vibe-codex-fleet-monitor branch October 20, 2026 16:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant