Input editor
The input editor is the rounded-box component at the bottom of the terminal: > prompt, multi-line editing, history and kill-ring, undo — the text-editing machinery comes from the underlying pi-tui Editor; Mayfly layers context and enhancements on top.
Slash-command context
Input starting with / turns the frame primary mayfly and enters command context:
- Fuzzy autocomplete — the query splits on whitespace into tokens, each matched as a subsequence, ranked by score; every dropdown entry shows a two-part
hint — description, Enter accepts the preselected entry and submits. - No-match notice — when the fuzzy filter matches nothing, the hint line says
no matching command: /…(command discovery lives in the autocomplete dropdown, which closes itself on an empty match; this notice is the only signal). - Argument ghost hints — shown at most one space after
/command(e.g./sessions [<session-id>]); a leading space is added before you type the separator.
All commands live in the Slash commands reference.
! bash mode
When the buffer is exactly !, bash mode engages (the ! never enters the buffer) with a triple cue: the ! prompt, the ! shell mode frame label, and the shellMode violet frame. Submitting returns to prompt mode automatically.
Commands run through Mayfly's own executor and echo as shell cards (sanitized, truncated per stream: 200 lines / 64KB each), failures keep an exit code N line — deliberately outside the session transcript, invisible to the model. Prompt and bash submissions share one history (Up recall is not mode-filtered).
@ file completion
@ triggers file-path completion: fd first (fuzzy-scored, top 20 suggestions), with a filesystem scan as fallback when fd is missing (2000 scanned entries, 50 suggestions). Completion covers file paths; command-argument completion is deferred.
# skill invocation
# triggers skill-name completion (the same fuzzy matching as slash completion; the /skills panel, grouped by source layer, is the full catalog). On submit, #name is rewritten to /name and routed through the harness's skill gesture path — the transcript echoes the rewritten /name, and the skill's injection renders zero lines per the injected-context rule.
Large-paste folding
Pasting more than 10 lines or 1000 characters folds into a [paste #N +M lines] marker (the full text lives in the editor and expands automatically before submit — the model receives everything); the transcript side folds the same message into a 3-line preview plus a hint row, with Ctrl-O expanding on equal terms. History recall (Up) brings back the expanded full text.
Ctrl-G external editor
Ctrl-G hands the current draft to an external editor (the mayfly.editorCommand setting wins, then $VISUAL, then $EDITOR) for full-screen editing: Mayfly suspends rendering and yields the terminal to the child process; on a normal editor exit the screen restores and the text is read back (paste markers survive the round trip). Quitting with :cq counts as cancellation — the draft stays as it was.
Ctrl-V image paste
Ctrl-V stores the clipboard image in the attachment library and inserts an [image #N] marker at the cursor; on submit the markers split into image content blocks. Markers survive theme switches.
Dependencies and limits: probes wl-paste then xclip on Linux (3s timeout); on Windows one PowerShell call saves the clipboard image or the copied files (10s budget); on macOS osascript reads the clipboard classes and converts TIFF-only copies through sips (5s budget). 10MB per image, 8 images / 30MB / 16M pixels per message; the model must accept image input (see the FAQ).
Copied files paste as one ordered batch on every platform: text/uri-list in Ubuntu Files, a FileDropList in Windows Explorer, a Finder copy on macOS. Only local regular PNG/JPEG/WebP/GIF files are accepted; remote URIs, directories, and symlinks are refused with a reason.
Editor-context keys
With the editor focused, a contextual key chain applies (see Key bindings): while a session flow is in progress (the selected Agent is running; a running subagent alone does not count), Escape interrupts that flow — safe retraction of the just-submitted message first when the buffer is empty and the message is eligible, which restores it into the editor — and never touches the draft; Ctrl-C empties the box while a flow runs and interrupts with an empty buffer. When the selected subtree is idle both keys clear a draft, and Ctrl-C with an empty buffer enters the double-press-within-1-second exit path. The interrupt answers on the same frame: the activity row switches to a static ■ interrupting... until the current step/tool drains and the turn truly ends (native drain semantics keep started tool calls running so replay stays valid). An interrupt stops only the selected Agent's current turn: subagents, jobs and the goal are left running, and queued and steering messages are kept and run as the next turn. Ctrl-Enter steers the non-empty draft into the current turn. ↑/↓ always belong to editor history (queued messages are rows of the conversation stream: Alt+↑ focuses them, then e edits, s sends now, d cancels), with ↑ history 2/4 on the notification row while you walk it, while PageUp/PageDown scroll the current transcript. Every side conversation keeps this editor: a live BTW/subagent uses the whole chain; in a read-only conversation a submitted draft stays in the editor with a notice; in a resumable (cold continuable) one the send wakes the child: Enter queues the draft for its next turn and Ctrl-Enter steers it. Slash commands always run. F7 returns to the previous conversation and F8 closes the displayed side conversation.
Draft survival
The unsubmitted draft, input mode (bash triple cue included), and hint history are mirrored into a draft stash — a /theme hot-switch rebuilds the editor fiber and restores everything, so a just-submitted /theme light won't vanish from Up history either.