| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
…ys which one wants you
Implements PRD 0009. `moshcode start claude -d` now runs the engine in a
runtime that outlives the pit and hands the prompt straight back, so the
pit stops being a one-thing-at-a-time shell: `/ps` shows what is running
and what state each session is in, `/attach` steps into one, detaching
leaves it running.
Two substrates behind one interface, because "requires tmux" was the wart
worth removing rather than documenting:
tmux a single named server (socket `moshcode`, not tabs.mjs's per-pid
one). Full fidelity — resizing, scrollback, native attach.
pty no tmux: script(1) allocates the pty, the child is detached with
its stdin on a FIFO held O_RDWR so it never sees EOF when the pit
exits, and attach replays the transcript and relays keystrokes.
Sized from inside via stty; a later resize cannot reach it.
none foreground passthrough, exactly as today, said once.
Semantic state (working/blocked/done/idle/unknown) with herdr's rule that
each session has ONE authority: a live hook report suppresses screen
classification entirely, and expires so a crashed agent cannot read
`working` forever. Screen rules ship beside each engine's install spec,
are anchored to things a terminal draws rather than English words, and
are overridable in ~/.moshcode/herd/rules.json when they rot.
`blocked` can page the operator through the existing notify()/ask()
fan-out, with the reply typed back into the session that was waiting —
the part herdr structurally cannot do. Only transitions notify, so a
session sitting blocked does not page every five seconds.
One surface for humans and agents: every verb takes --json, `wait` exits
0/2/3 so scripts can branch, and moshscript gets herdStart/herdPrompt/
herdWait/herdRead/herdList/herdKill as values rather than exit codes.
Two bugs the survival test caught, both of which would have shipped as
"finished agents report gone": tmux's remain-on-exit was set in a second
call that a fast command could beat, now one invocation via tmux's `;`;
and the pty substrate could not tell a finished agent from a rebooted
box, now the session's own shell records its exit.
Named `herd`, not the `runtime`/`agent <verb>` the PRD first proposed —
`agent` is already an alias of `agents` and a test pins that, and
`runtime` is what src/runtime.mjs already means. PRD updated to match.
Deferred and stated in the PRD: auto-installing the status hook into each
engine (the protocol ships and works), pointing ttyd at a real session,
and scrollback replay across reboots.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
ThreatCrush Security Scan91 finding(s) HIGH/CRITICAL: 2 | MEDIUM: 41 | LOW: 48
…and 41 more. Full results in the Security tab. Snippets are redacted; ThreatCrush never prints matched credential material. |
Sorry, something went wrong.
…node exit under it CI caught this; a green local suite did not. Thirteen tests in herd-cli.test.mjs came back `cancelledByParent`, which was the test runner's way of reporting that the file's process had died mid-run. The cause is a real bug in shipped behaviour, not a test artifact. The poll timer in waitFor() was unref'd, copying the instinct from mirror.mjs where a background nicety must never hold the process open. Here that is exactly backwards: `wait` and `watch` exist to keep the process alive. An unref'd timer means node finds nothing scheduled between polls and exits. It does not hang — it is worse. `moshcode wait api --timeout 1h` returned in a millisecond, exit 0, having waited for nothing, and any script branching on it would have read that as "the agent is ready". Measured before: waitFor resolved never and the process exited after 1ms. After: it waits the full duration and settles. End to end, `moshcode wait` now blocks the whole timeout and exits 2, exits 0 the moment the state matches, and exits 3 for a session that does not exist. Also un-unref's the liveness poller in the pty substrate's attach, which was the same trap one step from being sprung: the follow timer beside it is already unref'd, so an attach whose stdin did not hold the loop open would have exited the instant it started. It is cleared on detach, so it never outlives the attach either. The regression test runs waitFor in its own process with nothing else pending, because the test runner itself keeps the event loop alive and hides the bug completely. Verified it fails against the old code before keeping it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Bump to v0.33.0, releasing the herd (#342) — agent sessions that outlive the terminal that started them — along with the PRD behind it (#341) and the moshpit pinned-TLS proxy fix (#343), all of which have been sitting on main unreleased. Minor rather than patch: #342 adds six commands (herd, ps, attach, kill, wait, restore) and six moshscript verbs, and changes none of the existing ones. `moshcode start claude` with no -d behaves exactly as it did. This release is what makes any of it reachable. install.sh serves the latest release tarball rather than main, so until a release carries it every installed machine answers `unknown command "ps"` — and the npm channel only moves when publish.yml sees a published GitHub release. No plugin bumps: stocks and crypto are untouched, and neither names a command that moved. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
| Back | FazBrowse Home | New Git URL |
Implements PRD 0009.
The change
moshcode start claude -d runs the engine in a runtime that outlives the pit and hands your prompt straight back. The pit stops being a one-thing-at-a-time shell:
Close the terminal, drop the SSH link, come back tomorrow — moshcode ps still answers. In the pit: /ps, /attach, /kill, and the roster prints on the way in.
Opt-in throughout. moshcode start claude with no -d behaves exactly as it does today.
Two substrates, because "requires tmux" was worth removing rather than documenting
MOSHCODE_HERD=pty forces the fallback, which is how it gets tested on a box that has tmux.
Semantic state
working / blocked / done / idle / unknown, with herdr's rule that each session has exactly one authority: a live hook report suppresses screen classification entirely (and expires, so a crashed agent cannot read working forever). Screen rules ship beside each engine's install spec, are anchored to things a terminal draws rather than English words — a test enforces that — and are overridable in ~/.moshcode/herd/rules.json when they rot.
blocked can page you through the existing notify()/ask() fan-out, with your reply typed back into the session that was waiting. Only transitions notify, so a session sitting blocked doesn't page every five seconds.
One surface for humans and agents
Every verb takes --json. wait exits 0 matched / 2 timed out / 3 gone so scripts can branch. moshscript gets herdStart / herdPrompt / herdWait / herdRead / herdList / herdKill as values rather than exit codes, which is what makes fan-out practical:
Two bugs the survival test caught
Both would have shipped as "finished agents report gone":
Naming
herd, not the runtime / agent <verb> the PRD first proposed. agent is already a registered alias of agents and test/help.test.mjs pins suggest("agent") === "agents"; runtime is what src/runtime.mjs already means. The five most-used verbs are top-level anyway. PRD updated to record the change and why.
Verification
Deferred, and stated in the PRD
Auto-installing the status hook into each engine's config (the protocol ships and works, so tier 1 is opt-in for now); pointing console.mjs's ttyd at a real session; scrollback replay across reboots (P2, opt-in by design).
🤖 Generated with Claude Code