Twinned from https://github.com/cfsh/ninefold/issues/835 by tools/beads/import_github.py's reconcile pass.
Unclaimed. Prescriptive — MVP scope, not the design. Part of the fleet project (#832). Depends on #834 landing first (sequencing per Aedan on #832: delete the board before building fleet).
CLI only. No webserver, no remote-control-session visibility — both are real follow-ups (#832 notes them) but not this issue; adding either here is scope creep on an MVP.
./dev.py fleet — prints a table of every session on this box, derived live, no caching, no writes.
``` SESSION BRANCH LIVE LAST COMMIT CHUNK ISSUES PRS bork feat/fleet-mvp yes 12m ago Fleet project 832 - sg feat/probe-gate yes 3h ago Probe gate 728 841* tonapse feat/rename-fix no 2d ago - - 839✓ ```
Exact columns and formatting are the implementer's call — this is a shape, not a spec. * / ✓ markers for PR review state, or a second PR sub-table, whichever reads cleaner in a terminal.
nflib.sessions, don't re-derive ittools/nflib/sessions.py already computes almost everything a session row needs, and its whole existence is "one implementation, two entry points" (#640/#641) so a fleet-specific reader would be a *third*. Use it:
sessions.survey(git, agents=sessions.read_agents(), tmux=sessions.tmux_sessions()) returns list[Session] — one per topic on this box, each already carrying worktree, branch, tmux (liveness), last_active, tracked (PR numbers from tracked-prs.txt), agents (sids).Session, and where to get it/triage output, not persisted state). For the MVP, derive what *is* derivable and skip the rest: gh issue list --label active --label session:<topic> gives the issue numbers a session holds; that's enough for a useful row. Don't invent a chunk-name store to fill in a "Chunk" column — leave it blank or synthesize it from the issue titles if you want something there, but don't add persistence for it.rev:pass at head / mergeable) — Session.tracked only has PR *numbers*. One gh pr list --json number,reviewDecision,mergeable,statusCheckRollup call (or per-number gh pr view) resolves the rest. Batch it — one gh call for all tracked PRs across all sessions, not one per session, or fleet gets slow as the fleet grows.tools/fleet/ (Aedan on #832, item 4 — chosen so a webserver can sit alongside the CLI pieces later without a directory move). Put the rendering logic there as a module with tests, same shape as everything else in tools/; dev.py fleet calls into it the way dev.py check/wrap call into tools/nflib/devcli.py.
Wire the verb into tools/nflib/devcli.py's subparsers (subs.add_parser("fleet", ...), next to check and wrap) — that's where dev.py's dispatch already lives, and test_nflib_devcli.py walks every subparser, so a bare add_parser call with no options is enough to pass that test.
nf-dev-sg; YAGNI until a second box runs sessions).Run it against the live fleet on nf-dev-sg while other sessions are active and confirm the table matches what claude agents --json / tmux ls / gh pr list actually show by hand for at least one session — this is a read tool with no test fixture that can stand in for "does it agree with reality."
None.
No comments.