Repository navigation
Release v0.18.0: Context Engine, Managed Agents & Workspaces - #345
Open
raiseCatError wants to merge 56 commits into
Open
raiseCatError wants to merge 56 commits into
raiseCatError wants to merge 56 commits into
Conversation
…rubber The mods panel cycles tabs with the shared PanelShell helpers, so Tab has one rule across panels. Agent and mod display text uses the shared terminal control scrubber line by line, so unterminated, C1, DCS and APC sequences leave no debris (the local scrubber kept ]0;... from an unterminated OSC).
The model comes only from the provider's structured events (system/init model, assistant message.model; <synthetic> placeholders ignored). A failed turn's reason comes from the assistant error code, an error_* subtype or terminal_reason: Claude reported an authentication failure as is_error with subtype "success", which read "Run failed: success". Interrupted turns read Interrupted; a denied tool fails only that tool.
…e import /claude, /claude new and /ai -> Claude open one launcher: targets grouped under the launch profile that started them, a + New target per profile, factual states and resumability. Selection never activates; Enter, N, / and Esc are explicit; configured profiles are never bypassed for the default identity. Up from an idle composer focuses an already visible shelf (Left/Right select, Enter opens, Down/Esc return) with a non-color focus marker. The agent view opens on an NMSh-native provider welcome and keeps a compact header with the reported model; implementation names are gone. Simple CLAUDE_CONFIG_DIR launch aliases are found by a text-only match and imported only on explicit confirmation.
One porcelain -z list call plus bounded concurrent status probes. Hooks, fsmonitor and transport are disabled per invocation; repositories with content filters or includes fail closed to unknown status. Proven on an armed fixture.
…ced removal Removal is offered only for clean, unlocked, present linked worktrees and aborts when branch, HEAD, directory identity or cleanliness change after the preview.
Selection by identity, explicit refresh with a visibly stale snapshot, local search, typed navigation/diff intents and fact-driven action availability. Safe/ASCII, NO_COLOR and narrow layouts fit display cells.
…g status there git -C follows the worktree's own .git pointer; a pointer leading to another repository with content filters could otherwise run its filter.
Read-only foundation for #338: GitHub-compatible PR/issue search through the authenticated gh CLI, lazy PR/issue detail, a bounded diff review model, merge planning with exact head SHA (never execution), a keyboard-first controller, a pure renderer for 30-200 columns with Safe glyph and NO_COLOR paths, and a development-only interactive preview with offline fixtures. Not wired into TerminalApp; no remote writes exist.
The launch command stays on screen after detach. A base-36 socket suffix ending in e.g. "5d" matched the stray-'d' assertion (~2% of runs; CI run 37743508082, reproduced on master with the same suffix). Use a digit-only suffix; the assertion is unchanged.
inspectFile resolved the target through symlinks but compared it with the roots as given, so a home folder or project reached through a symlink (/tmp and /var on macOS) refused its own files. The roots are now resolved too; a symlink leading out of them is still refused. The cursor native-setup test failed this way on any Mac whose temp directory is under /private.
…nto release/v0.18.0
…nto release/v0.18.0
…ersation The managed agent view fills the screen below its frame instead of sitting under the shell's welcome with an empty band. The header leads with the target's state and gives way in a fixed order at narrow widths. User turns carry a marker, agent prose is indented and word-wrapped, tools and outcomes are quiet rows, and the composer shows the draft as edited with a caret. Copy, routing, identity and drafts are unchanged.
Under NO_COLOR the active tab rested on bold alone. Use the same reverse-video fallback as the selected row band; colored output is unchanged.
The shared tab strip, a search and provider row, grouped rows (kind, and provider with launch profile) on the shared selected band, and a contextual footer. Browsing shows name, factual state and scope; the selected entry's execution facts stay visible below the list and wrap rather than truncate. Enter opens the full record: execution first, then provenance. Nothing implies an NMSh sandbox. Discovery, broker and controller are unchanged.
The worktree manager and GitHub workspace cores now run inside NMSh: - /worktrees lists this repository's worktrees. Enter stages cd -- <path> in an empty composer (never runs it, never replaces a draft); n asks for a branch name and plans a sibling worktree, created only after Enter on the reviewed plan; x previews removal, which is also refused while a managed agent works inside that worktree. - /github and /prs open pull requests, /issues opens issues, for the github.com origin remote, read-only through the person's gh. o opens only github.com URLs; w hands the PR branch to /worktrees (forks excluded). - Keys map onto each controller's own keyboard model; the panels use the existing panel slot, frame and glyph/color settings.
…notes and known limitations
A tag sharing the branch's name would otherwise win when Git resolves the start point. The plan still shows the resolved commit before confirmation.
…ase build Three VHS tapes in the existing pipeline (disposable demo home, 1440x960). github.tape is the one networked recording: it reads this public repository through the recorder's gh login, passed as GH_TOKEN in the environment and never written to a file. The gallery gains a Context and repositories chapter and their stills.
…) and reverse-video active tabs without color
…sation that meets the composer Physical QA found no visible caret in the /claude draft and a fresh session's welcome far above the composer. - The draft uses the shell composer's layoutInput geometry and reports its caret; TerminalApp shows the terminal cursor there through the frame cursor and CursorPresenter, so /cursor shape, color and effects apply. No painted caret glyph. Up and Down move between draft rows at the drawn width. No caret while approvals, questions or transcript focus own the keys. - The conversation is a stream that meets the composer: the compact welcome rests on the composer rule and gives way to turns; the state rides the rule. Scrollback reaches the first turn and a scrolled-back view does not move when rows arrive. Normal and Chat follow the transcript presentation setting; Composer Top is honoured. - Tests for the caret geometry and ownership, both composer positions, Normal and Chat order, scroll anchoring, resume, Safe glyphs and NO_COLOR; #344's layout tests updated to the new contract. Before/after VHS captures.
…an NMSh command /Volumes/tools/adb devices was parsed as an unknown slash command and refused, and path input lost shell completion and suggestions. One text-only rule now decides: when the first word has a / after the leading one it is a path. No NMSh command name contains one, so /zsh is still the handoff while /bin/zsh runs. Unknown single-word input (/stauts) remains an NMSh typo; a leading space still sends anything to the shell.
… the real composer Types each line into a real NMSh frontend and waits for the shell's output and the journal record: arguments, quoted arguments with spaces, a backslash-escaped path, /usr/bin/env and /bin/echo. A directory used as a command gets the shell's own behavior, never "Unknown NMSh command"; /help still opens NMSh's help.
Cherry-picked from 95bd7ff (feature/agent-workspace) for v0.18.0; the changelog line is filed under 0.18.0 Fixed instead of Unreleased. The completed-command record keeps the command's PTY output (output) apart from NMSh's lifecycle row (lifecycleText), but serializeCopyPayload appended the row, so /copy after an extraction included "✔ Completed · 21.6s · 15:42". The payload is now the output field alone, the same source the block actions and the pager use; the row stays recorded and displayed. Output that merely looks like a status line is the command's and is kept. A command that printed nothing no longer replaces the clipboard with the status row: /copy says so and leaves the clipboard alone.
A clear (clear, tmux, ESC[2J/3J) emptied the stored lines but left every completed record with its old line ids. Commands after the clear reused those ids, so a stale record drew its fold row inside another command's output and Ctrl+O folded unrelated lines, /copy rows included. Records now leave with their lines, fold toggles and the output filter reset, and a running command that clears owns what it writes afterwards (its /copy payload included). Restored transcripts drop records that cannot be placed on their lines.
A bounds check alone kept stale records that happened to fit: a pre-clear record could sit on NMSh notice lines or on another command's output. A restored record now also needs command header lines (NMSh's own line for an Ask block) and lines that read as its recorded output, compared without trailing blanks. The first record that fails marks an unrecorded clear, so it and every older record are dropped, never attributed to other lines. A reattached running command whose journaled start predates the clear rule is treated as having cleared: it owns the stored lines and older records go.
Fish 4's line editor (its prompt and its read builtin) queries the terminal each time it starts and drops keys that arrive while it waits for the device-attributes answer. At the prompt NMSh answered fish itself; during read the queries went through the session service, the frontend and the host terminal and back, tens of milliseconds per round, and keys typed meanwhile reached fish first: type-ahead during a fish read was lost 8 of 8 times under load. ShellSession now answers fish's editor queries wherever the editor runs (the foreground process is fish itself), and QueryOrder keeps any program's input behind the answer to its device-attributes query, with a bounded fallback for hosts that never answer. Native fish still drops type-ahead already queued when its reader asks; that remaining limit is documented with measurements in docs/development/fish-typeahead.md.
…head, ESC[3J Lists what still needs a person at a real terminal, keeps the residual Fish type-ahead limit on the list, and records the lone ESC[3J behavior with its cause, impact and planned follow-up.
A security review of the Fish fix found two ways the hold could change what reaches the program: - interrupt() wrote Ctrl+C directly, so keys held behind a terminal answer were delivered after it and a cancelled line could still run. Held input is now discarded first, as a terminal's Ctrl+C discards pending input; Ctrl+D keeps its place in order. - answer-like bytes inside a bracketed paste were moved before it and could end the hold. Paste spans are now opaque: never searched for the answer, never split or reordered.
…edrawn Fish asks again as soon as it is answered and redraws its prompt. Keys from the frontend could reach fish after that next question but before the session service had read it from the PTY, and fish dropped them: in the full suite under load, an answer typed after fish showed its read prompt was lost. After NMSh answers fish's editor, input now waits for the editor's prompt-drawn mark (OSC 133;B), answering further rounds on the way, with the same bounded fallback.
The fish read test removed fish's temporary home while fish was still writing its history on exit (ENOTEMPTY under full-suite load).
This was referenced Oct 10, 2026
…ip is used NMSh picks a Linux clipboard tool only when DISPLAY or WAYLAND_DISPLAY is set; CI has neither, so the test timed out on Ubuntu before reaching its stand-in. No real display or clipboard is involved.
Fake agent processes can still be writing into it when the suite ends; on a busy Linux runner the removal raced them (ENOTEMPTY).
…are not its output A /copy that finished after the next command started added its confirmation inside that command's block, and the line became part of the command's recorded output: the next /copy copied NMSh's own text (found by CI on Linux). A finished command's output now leaves out the lines NMSh added while it ran; they stay where they were shown. The transcript repair accepts records saved either way.
This was referenced Oct 10, 2026
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Release candidate for v0.18.0. No tag or GitHub Release exists yet; both follow only after this PR's full CI and the master merge commit's CI pass.
What this brings together
/modules, terminal title ownership, tmux/passthrough/cursor fixes (Context Engine platform, declarative Context Packs, agent context and Theme Bridge completion #326, Status Strip 2.0, module manager UX, and Ghostty physical-QA fixes #328; tap-native Homebrew automation chore: finalize Homebrew distribution and README diagrams #325).164ec48: managed Claude Code targets (/claude,/claude new,/ai) and/mods.a0291da: worktree manager core.06df151: read-only GitHub workspace core.9096532: managed agent view as a full-height workspace.60f8487:/modsas a native NMSh menu; reverse-video active tabs without color.Merging this PR marks #329, #342, #343, #344 and #346 merged.
Integration done here
The worktree and GitHub cores shipped without live routing. This PR wires them into the existing panel slot (no new dispatcher):
/worktrees: Enter stagescd -- '<path>'in an empty composer and never replaces a draft.ntakes a branch name and plans a sibling worktree, created only on Enter at the reviewed plan.xpreviews non-forced removal, which is also refused while a live managed agent works inside that worktree./github,/prs,/issues: read-only over the user'sgh, for a github.comorigin.oopens only github.com URLs;wopens/worktreeson the PR branch (same-repository PRs only).Fixes found during release checks
/tmp,/var); roots are now compared in resolved form. This was the cause of a cursor native-setup test failing on any Mac.refs/heads/...ref, so a same-named tag can't win.Docs and media
CHANGELOG
[0.18.0](features vs fixes, upgrade notes, known limitations), README, ROADMAP, architecture/design docs, version 0.18.0 in package and lockfile. New VHS captures from this build: Status Strip, worktrees, GitHub (docs/demos.md).Verification
npm run verify:releaselocally on the combined candidate (with Managed agent view: full-height workspace, compact header, readable conversation #344 and /mods: a native NMSh menu (tabs, grouped rows, browse vs. details) #346): 2062/2062 tests, 8/8 timing budgets.Fixes added after this PR was opened
Found during release checks and physical use; each has regression tests.
/bin/zsh -c …,/usr/bin/env …) run in the shell instead of being refused as unknown NMSh commands. One text rule: a first word with a/after the leading one is a path./zshstill switches shells./copycopies only the command's own output, never NMSh's completion row (✔ Completed · 21.6s · 15:42).clear, tmux, or anything writingESC[2J/ESC[3Jemptied the stored lines but kept the earlier commands' records, whose line numbers the next commands reused. A fold row such as15 lines shown · Ctrl+Othen appeared inside another command's output, and Ctrl+O folded unrelated lines together with/copyrows. Records now go with their lines. Saved transcripts are repaired when opened: a record is kept only if its range fits, its header lines are command lines and its lines read as the output it recorded. The first record that fails is dropped together with everything older, never attributed to the wrong command.read) queries the terminal and drops keys that arrive while it waits for the answer. Duringread, those queries made a round trip through the session service, the frontend and the host terminal, and keys typed meanwhile were lost (8 of 8 under load). NMSh now answers fish's editor itself, as it already did at the prompt, and holds input until fish has redrawn its prompt. For any program, keys never overtake the answer to a device-attributes query. Ctrl+C discards held input, and bracketed pastes are never reordered (both found by a security review of the first version). Remaining limit: type-ahead typed while a fishreadis still running can be dropped by fish itself, in any terminal (docs/development/fish-typeahead.md).docs/testing/v018-physical-qa.md. It includes the Fish residual and a known issue: a loneESC[3J(scrollback clear) empties NMSh's transcript. That behavior is pre-existing since the first release and is not a release blocker; the planned fix is to ignore a loneESC[3J, after v0.18.Dependent PRs (merge after this one)
release/v0.18.0and independent of each other; they merge cleanly in either order.Local verification of this head:
npm run verify:releasepassed (2108/2108 tests, 8/8 timing budgets).