Getting it into your agent
One page per mod, every tool's command on it. A separate URL per tool would split the same page into five that compete with each other.
npx agentmods add agents/multiplex-term/multiplex/input-and-windowsgit clone --depth 1 https://github.com/multiplex-term/MultiplexWhat it costs to keep this loaded
Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.
| Model | Per session | Once invoked |
|---|---|---|
| Fable 5 | $0.00000 | $0.10243 |
| Opus 5 | $0.00000 | $0.05122 |
| Sonnet 5 | $0.00000 | $0.02049 |
| Haiku 4.5 | $0.00000 | $0.01024 |
Grade A, and why
input-and-windows scanned grade A with 0 findings against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured 2d ago.
A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.
Nothing flagged
None of the 26 patterns this scan looks for appear in this file: no shell pipes, no recursive deletes, no credential paths, no hidden text, no instruction-override or anti-refusal phrasing, no agent-config snooping. That is not a guarantee, it is the absence of the things that are checkable.
How it starts
The opening of the file, as written. The whole thing — 602 lines — stays where its author put it; the contents beside it link to each section on GitHub.
Terminal input, windows & scenes
Load-bearing decisions split from AGENTS.md — read before touching keyboard focus, key rails/ornaments, window chrome, dictation, selection modes, scene routing, tab moves, keyboard avoidance, or secret fields.
- Keyboard focus goes through
TerminalFocusArbiter, never per-view: every visionOS window is its own always-key scene, so per-view responders leave input stuck on the first session; claiming resigns the previous owner and activates the claimed scene. Its visibility tracking must ride the frame-change notifications (KeyboardAvoidance.isPresented, pure): floating keyboards never post didShow/didHide, and stuck-false visibility makes a terminal tap tear down the input session. Stage Manager's zero-height frame while a floating keyboard stays active is ambiguous, not a hide — preserve the previous state. Stage Manager also transiently clears a moving window'sisKeyWindow: an already-owned claim must stay a no-op, nevermakeKey(). The compact shell's deck is a focus-exclusion surface: restoration passes stage visibility throughTerminalFocusArbiter.restoreand refuses/resigns a hidden responder. - The shell spends the safe areas; its panes hand back the clearance
(
SingleWindowShell). The GeometryReader stays inside the safe area (ignoring an edge zeroes that edge's inset), the pane stack spans the bands, and each pane restores its own: FleetWall as wall padding (shellSafeArea), the terminal as content insets (contentSafeArea, down toKeyBarRow's own padding inside the ViewThatFits proposal). Traps: a landscape Dynamic Island sits mid-edge and iOS reports BOTH landscape edges unsafe without saying which holds it — no band is safe to read in; heights areheight + safeArea.bottom(this reader is inset by whichever bottom region applies, so adding it back lands on the window edge, keyboard or not). The key rail takes the bottom strip at compact vertical size class and on every iPad stage (shell or classic window) — the rail IS the window's bottom edge there, so a reserved strip would only park a dead band under the row. Where it does,SwiftTermView.railOwnsBottomSafeAreamovesrestingBottomwith it — a static fact per pane, never read from the live frame (the strip's padding would feed back) — and the rail buys its own daylight back below the key faces (TerminalKeyBar.keyBottomInset(isIOSAppOnMac:spendsBottomStrip:): 3 → 8, which is also the iPhone-landscape padding fix, so the bar's height moves with the fact). The auxiliary panes' rails instead paint through the strip and lift their controls by the classic window'scontentSafeArea .bottom, which is why a classic window now hands that inset down. Panes are placed with.offset(claims no width): align the frame.topLeadingor SwiftUI centers the lot. - iPhone's left-edge right-swipe arbitrates above SwiftTerm
(
ShellBackSwipeRecognizer, oneUIScreenEdgePanGestureRecognizeron the shell window): at the edge, horizontal movement gets first refusal; vertical intent fails immediately back to SwiftTerm (remote scrolling preserved); an active local selection rejects the touch before tracking and re-checks at begin. A SwiftUI gesture does not reliably receive drags begun insideTerminalView. - The iPad/iPhone key rail is app-owned chrome, never an
inputAccessoryView(TerminalKeyBar): ESC / latching CTRL / TAB, the shell symbols~ | / -, DECCKM-aware autorepeat arrows, RET (iPad, and iPhone while locked), autorepeating PgUp/PgDn (CSI 5~/6~), and one slot that is the keyboard toggle or — with a physical keyboard — the dictation key. KeepTerminalView.inputAccessoryView = nil: a physical-iPad A/B proved TextInputUI rehosts even a custom accessory during Stage Manager moves, stalling the UI. The keyboard key holds (~0.5 s) into the keyboard lock (TerminalFocusArbiter.lock— a zero-size custominputView, so the input session, rail, and hardware keys stay live while taps stop summoning); a KEYBOARD LOCKED tip top-center carries the dictation action, latching while permissions resolve then yielding to the LISTENING bar (it shares the dictation bar's slot — the top-trailing slot belongs to window chrome the tip used to cover). Without a physical keyboard, the lock is also a named action in the⋯menu at every width (toggleKeyboardLock; wide chrome passesdisplacesDirectActions: falseso it never duplicates chips).HardwareKeyboardMonitorhides the redundant LOCK action while a keyboard is connected (an already-held lock keeps UNLOCK reachable). State is app-wide (KeyboardLock.shared, arbiter-written, never persisted);claimre-applies it to whichever terminal takes focus. Narrow tiers drop page keys, then symbols;SingleWindowShellLayout's 390/420 pt cutoffs must stay in lockstep with the measuredKeyBarRowtiers (375 pt locked floor keeps RET; narrow locked phones move TMUX to a top-right button, and the overflow deliberately has no duplicate tmux entry). "TMUX" names the shortcut-key SLOT: a herdr tab fills it with HRDR — four mono characters, so every tier and cutoff holds unchanged — and both open the sharedShortcutPanelViewController, whose content (ShortcutPanelContent.tmux/.herdr) is the ONE place a backend's shortcut set lives. Pane cycling (both backends) and herdr tab cycling are deliberately absent because those targets are already directly tappable; tmux Last Window is absent because the live switch list targets a window directly. The panel root scrolls when a phone popover clamps its height — never clip rows. The top popover opens downward; while presented, the arbiter resigns the terminal (a docked keyboard would clip the grid) and restores only if that tab still owns focus. Every key sends throughTerminalView.send→ delegate → ordered pump — never a side channel; CTRL ridescontrolModifier, latch released on.terminalViewControlModifierReset. Hold CTRL (0.3 s,KeyCommandPanelViewController.controlHoldDuration; a tap still latches and never fires the hold) opens KEY COMMANDS — the recognized hold cancels the control's tap at source, and opening it first retires any already-raised C / B quick slab, so the two CTRL surfaces never coexist. The panel is anchored to the CTRL key on both platforms (KeyCommandPanelViewControllerinKeyCommandPanel.swift; ONEKeyCommandPanelPresenterowns present / dismiss / focus-resume / popover delegate for both hosts —TerminalKeyBarand the visionOSTerminalKeyClusterGroupViewsupply only the anchor and their appearance step, the ornament carrying the C / B popover's appearance and glass mirroring). The panel stands on the shortcut panel's now-shared grammar (ShortcutPanelRootView,ShortcutPressControl,TallyHairlineGrid,TallyPanelHeader,UIKitChassisMonoLabel) and the agent editor's shared controls inDesign/TallyEditorControls.swift(TallyEditorSwitch,TallyEditorRowActionButton,TallyEditorRowActions,TallyEditorLegend,TallyEditorFooter). Two tabs: COMMANDS is a two-column hairline grid of saved rows (tap sends; a row with CLOSE ON PRESS off keeps the panel up; a 0.5 s hold jumps to that row's setup); CUSTOM SETUP is the agent editor's numbered list with an inline composer (TYPE KEYS | TEXT, ⌃ ⇧ ⌥ + one key from ↩ ⇥ ⎋ ⌫ ␣ ↑ ↓ ← → or a one-character field, or one line of text with SUBMIT = CR ~160 ms later, REPEAT count + gap under the guard ×5 · 50–500 ms · burst ≤ 2 s, PANEL, SENDS readout of the live bytes) — a draft transaction, DONE normalizes once, CANCEL/outside dismissal discards. The model (KeyCommand,KeyChord,KeyTextSnippet,KeyCommandSetwith the three shipped defaults ⇧↩ · ⌃C×2 · ⌥⌫-stays,KeyCommandRepeatGuard) is pure; chords are never bytes —KeyCommandDispatcherasks the fork (TerminalView.bytes(for:), fourteenth patch group) at press time, so a chord sends exactly what a hardware press would in the terminal's current mode (kitty flags, DECCKM, backspace mode), and text rows ridesend(txt:)+ a delayed CR like slash chips. Every send isTerminalView.send, i.e. the ordered pump. Storage is app-wide (KeyCommandStore.shared:keycommands.jsonbesidehosts.jsonplus one synchronizable Keychain item;KeyCommandSync.mergeis the pure last-writer-wins rule; refreshed at launch and when the panel opens, at most once a minute — no CloudKit/KVS entitlement exists). Tier: free keepsEntitlementStore.freeKeyCommandLimit(5) commands, Pro the model's cap (12) — the same rule as hosts: a set that already holds more (synced from a Pro device) is never trimmed and every row keeps sending; only ADD COMMAND is gated, turning into the prominent "ADD COMMAND · PRO" chip that opens the paywall (a legend line says why the cap is 5). The rail and cluster never learn about Pro: the terminal window builds aKeyCommandPlan(limit + paywall route) from itsEntitlementStoreand hands it down — iPad throughTerminalPaneConfiguration→TerminalSurfaceView.Configuration→TerminalKeyBar.keyCommandPlan, visionOS onto bothTerminalKeyClusterContexts (shell + ornament) — and the presenter wraps the route so the popover is down before the paywall sheet presents (presentPaywallrefuses while anything is presented).entitlements.isProis in the window's observation set, so a purchase re-renders with the lifted plan. The terminal GUIDE carries a HOLD CTRL card (figure 12) and a MESSAGE BOX card (figure 13). Focus: the panel never suspends the terminal; only if one of its own fields took the keyboard does dismissalresumeAfterPresentation. Design record + grill:local-plan/key-commands-bakeoff/. visionOS:TerminalKeyCluster(same keys + latch + DEBUG hook) flanks the UMD on ONE console line in the bottom ornament. ViewThatFits compacts key faces first; when even compact can't fit, afixedSizefloor lets the row overflow the window edges symmetrically. Never re-add a keys-under-UMD restack (the system CLIPS ornament content hanging below the anchor) and never let the UMD compress (its title truncates).UIHostingOrnamentcenters the root's geometric bounds; a descendant alignment guide does not cross that host.TerminalVisionConsoleLayouttherefore makes the console row's top the root's actual midpoint, with the helper in the upper half. Do not regress it to a plain VStack/alignment guide: helper-less keys will straddle the window until an agent grows the stack. Re-verify visually when touching it. DECK and the text-size chips live in the UMD title row. ⚠ SwiftTerm still builds its stock accessory on visionOS andcommitTextInputprefers itscontrolModifier—SwiftTermViewnilsinputAccessoryViewthere; don't remove that. - Arrange Keys (2026-08-27) —
⋯→ Arrange Keys… (a menu row: every key hold is taken and a held key is unfindable); per tab, never persisted (TerminalSessionController.keyBarArranging). The ORDER is a slot permutation (KeyBarOrder; a slot names a position — keyboard/mic share.keyboard, TMUX/HRDR.shortcuts), device-local inKeyBarOrderStore; gaps and widths never move (rail groups are counted at layout, the ornament's ten keys split 3 lead / 7 trail, CTRL's slab follows the key). The move is the tab strip's drag and drop: each key is aUIDragInteractionsource (TerminalChromeDragItem, the item recipe tabs share — the pane's file gate refuses anyTerminalChromeDragPayload), oneKeyBarDropCoordinatoris the drop delegate for the rail and the cluster (KeyBarDropSurface); target = nearest other key by centre (RowDropGeometry), rightward lands after it, leftward before (KeyBarOrder.movingmoves only the dragged key in the full order). Never a custom recognizer drag: the keys stay live and hoverable (visionOS gaze targets interactive elements) and the system preview is the one thing that floats over the UMD's glass. Rails reconcile the order in layout, never in the render signature, so nothing re-creates a key mid-mode. iPad: the ARRANGE KEYS bar (RESET · DONE) hangs over the rail like the C / B slab (mountOverRail); leaving the window ends the mode. visionOS: drop hosts are both slabs plus the UMD and bar slabs (a release over the title lands beside the nearer key); the bar is ornament role.arrangebelow the console row, oneArrangeKeysBarViewControllerper tab that watches the store for RESET; a tab switch ends the mode; GUIDE rides the⋯(guideIsDirectChip). Proofs:debug.arrangekeys,debug.arrangekeysmove,build.sh uitest ipad(the visionOS sim lifts nothing; fakeUIDropSessiontests cover the coordinator). - Auxiliary tabs wear their whole bottom chrome in the ornament
(2026-08-10) — on classic visionOS windows the in-window ▤/⌗ rails are
not mounted (
showsInWindowRail: false); their end chips collided with the system resize corners. The ▤ file viewer stacks its file row above the verbatim UMD row in ONE slab (ViewportUMDRootView .installStackedDeck; the rail's duplicate CLOSE is deleted — the window row's CLOSE is the only one). The ⌗ viewport replaces rail + UMD with three content-sized slabs (ViewportSwitchboardViewController: navigate DECK ◂ ⟳ / locate address+reach / act SYSTEM ⋯ CLOSE; the caps⌗ port · hosttitle is retired — the address readout is the identity, and MERGE folds into ⋯). Both mount.fixedSize()— NEVER window-width: a slab that tracks the window permanently covers the system resize bar (shipped and caught same day).TerminalVisionStackedDeckGeometrybiases the deck so its top edge sits half a window row above the anchor and the extra file row hangs BELOW it, off the pane's last lines; auxiliary slab content below the anchor does render — the CLIPS trap above is about restacking keys under the UMD console line. Shell/iPad keep the in-window rails unchanged; re-verify placement visually when touching any of this. - The side panel never participates in terminal layout or focus. iPad
mounts the card over the pane container's inset rectangle, reuses the
pane's
keyboardObstruction, and the address field borrows the host terminal throughTerminalFocusArbiter.lend. Its action row is a header on iPad and a bottom bar on visionOS (SidePanelRowEdge) and surfaces chips in measured priority order —⋯only for what did not fit. Classic visionOS hangs it from a third trailing ornament whose content is ONE static mount: a transparent strip twice the window's width, centred on the glass edge (SidePanelWidth.visionStripWidth(windowWidth:)); the card lives inside it as (width,overhang= right edge past the GLASS) with a handle on each edge above the row, and the strip's empty part passes hits through (SidePanelStripView). Decisions that cost device rounds — don't re-open without new facts: geometry persists GLASS-relative, never strip-relative (a strip-relative inset outlived a strip-width change and pinned the card); a drag FREEZES the card into one blurred bitmap until RELEASE (no mid-drag settle thaw — gaze-and-pinch events arrive with gaps), moves only frames, and under GLASS the system platter steps out for the drag; nothing about the ornament changes per tick (a SwiftUI-driven drag and a per-tick UIKit relayout were both unusable on device) and its content carries no animation/transition. ⚠ visionOS 27 sim only: after ↗ TAB on a ▤ panel the glass keeps the old frame 3–6 s (CPU idle; ⌗, iPad and the shell present in ≤ 1 s) — judge on device, don't chase it. - A terminal window's title bar is app-owned, and its scene asks for
.minimalwindow controls (TerminalClassicRailInsets;MultiplexSceneDelegate.preferredWindowingControlStyle(for:)). Two system pieces had to go. The navigation bar: iPadOS 26+ sizes it for system controls and it CANNOT be shortened — measured 54 pt above a 10 pt scene inset (64 pt of chrome for 21 pt faces), wheresizeThatFitsis consulted and ignored, aframeclamp never lands (constraint-driven layout), and aboundsclamp shrinks the bar but leaves UIKit centring it in the band it still reserves, pushing the content inset to 74.5 pt. Don't retry those; the classic window mounts the sameUMDBarViewController.shellrail a full-screen iPad wears, and the navigation controller stays only as the hosting plan with its bar hidden. The window-control pill: iPadOS 26's default.unifiedStyleparks it INSIDE the scene's content, 21–43 pt below the window's top edge, and nothing app-side moves it (hidden status bar, no navigation controller, rail heights 54/41/31 all left it exactly there)..minimalStyle— "occupy as little of the scene's space as possible" — lifts it to 6–27.5 pt, in line with the rail's own chips. It is scoped to terminal scenes: the deck and shell still host system navigation bars, and.unifiedis what insets THOSE bars around the pill. Total chrome: 44 pt in a window — the rail matchesTerminalKeyBar.barHeightat the pane's other end (minimumContentHeight; the faces keep their size and centre in it, and the padding becomes a floor) — pill contained, versus the old 64 pt. The rail spends a top strip ONLY where the scene reaches the display's top chrome, and never on the Mac (its scene already sits below a real title bar). Both halves are caught regressions: spending it always paints the row below a floating window's pill and under a second, empty Mac title bar; spending it never paints the rail UNDER the status bar when the window is maximised. ⚠ Under iPadOS 26 windowing NONE of the obvious signals answer this (all measured 2026-08-04):safeAreaInsets.topreports the display's 32 pt status bar even for a 711x941 window floating in the middle of a 1032x1376 display,statusBarManagerlikewise answers for the display, andUIWindowScene.isFullScreenis Mac Catalyst's property — it stays false even when the window is maximised. ⚠ Nothing reports a window MOVE either:UIWindowSceneGeometryon iOS carries no origin (coordinate space, orientation,isInteractivelyResizing;systemFrameis Mac Catalyst only), sowindowScene(_:didUpdateEffectiveGeometry:)— iOS 26's replacement for the deprecateddidUpdateCoordinateSpace, adopted here — covers resizes and screen moves but NOT a drag, and the rail kept stale insets (user-reported as "doesn't always expand or collapse when the window is moved"). A 0.5 s position watch closes it: one rect conversion per tick while the scene is active, layout invalidated only on a real change — watching is polling, the deck's way. Geometry is what's left, and a window's own frame is scene-relative (origin always zero) — the position comes fromwindow.convert(window.bounds, to: screen.coordinateSpace), which DOES report where a scene sits on the display (measured: a floating window at y 217.5 on a 1376 pt display).meetsSystemTopChrome(spans the display) compares the dimensions UNORDERED —UIScreen .boundsdoes not follow the scene's orientation, so a maximised landscape window is 1376x1032 against a 1032x1376 screen. Same trap for anything else asking "am I full screen" — the shell-mode decision's ownisFullScreenread is worth re-checking. TMUX/HRDR names one road and exactly one rail may draw it: the pane's key rail owns the chip wherever it fits, and the rail above takes it over only at the widths where the key rail drops it. The rail therefore measures the KEY RAIL's content width (keyRailContentWidth), never its own — a classic window's rail clears the window-control pill and is ~90 pt narrower than the pane below it, while the shell's wide row stays above the cutoff on any landscape phone (drawing a second chip there was a shipped bug, 2026-08-06). No key rail at all (visionOS) means the rail owns the chip outright. MERGE rides the wide row beside DETACH (the overflow carries it only when it displaces the direct actions). ⚠ The clearances are the RAIL's (umdSafeArea), never a pane's (contentSafeArea): the leading inset reachingTerminalPaneConfigurationshoves the terminal and key rail off their own window (shipped-and-caught, 2026-08-04;paneAndRailInsetsForTestingpins them apart).umdAvailableWidthmust likewise stay non-nil or the rail never chooses its compact row. There is still NO way to touch the Mac's own title bar from a Designed-for-iPad binary (UITitlebaris Mac Catalyst-only and absent from the iOS SDK).
What this file has done since we first saw it
Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.
- 2d ago First seen · 602 lines · 0 tokens per session scan A 63ded570a062
input-and-windows is an agent published in the GitHub repository multiplex-term/Multiplex (10 stars, last pushed 5d ago), licensed Apache-2.0. It costs nothing until one of its globs matches a file; then it loads 10,243 tokens. A static security scan graded it A with 0 findings. No closer match exists in the catalogue, so it is treated as the original; first seen 2026-08-31.
Other agents, from other repositories
i18n
Hermex ships one String Catalog, HermesMobile/Resources/Localizable.xcstrings, included in the app, widget, and share-extension targets. Every user-facing literal is already externalized (String(localized:) / LocalizedStringKey), so adding a language is normally translation-only — no Swift edits.
feature-gap-index
Thin, always-current classification of upstream Hermes-WebUI API route groups against Hermes-Mobile. This file replaces an earlier 1,400-line per-endpoint catalog, which mixed durable judgment (priority, defer/skip decisions, safety notes) with volatile detail (exact JSON shapes, handler names) that rotted between…
issue-tracker
Issues and PRDs for this repo live as GitHub issues. Use the gh CLI for issue operations.
layer3-issue-detection
Layer 3 systematically scans ALL entry points from Layer 1 and applies issue detection rules. Unlike Layer 2 (which traces specific flows in depth), Layer 3 does a breadth-first scan to categorize issues across the entire codebase.
layer5-data-wiring
Layer 5 verifies that features use real user data instead of mock/hardcoded values, and that model capabilities are fully wired into the features that need them. While Layers 1-4 audit navigation and UX, Layer 5 audits whether the data flowing through those workflows is genuine.
layer2-methodology
Layer 2 takes entry points from Layer 1 and traces the complete user journey.