Typing a Prompt
The input line is where you spend the session. It behaves like a small editor
with the keys a readline user expects, and a few things of its own.
Editing
A line longer than the window wraps onto the next row between words (a word too
long for a row is split where it must be), and the input grows to eight rows as
you type and scrolls after that. Up and Down move by line of the prompt, not
by row on screen.
| Key | Does |
|---|---|
Enter | Send |
Shift+Enter, Alt+Enter, Ctrl-J | New line |
Left, Right, Home, End | Move; Ctrl-B, Ctrl-F, and Ctrl-A do the same as in a shell |
Ctrl-Left, Ctrl-Right, Alt-B, Alt-F | Move by word |
Up, Down | Move between lines of a multi-line prompt |
Backspace, Delete | Delete a character (Ctrl-H is backspace) |
Ctrl-W, Ctrl-Backspace | Delete the word before the cursor |
Ctrl-K | Delete to the end of the line |
Ctrl-U | Clear the input (or withdraw the newest queued message) |
Ctrl-C | Clear the input, when no turn is running |
Whether Shift+Enter is distinguishable from Enter depends on the terminal.
Heph asks the terminal to report modified keys (the kitty keyboard protocol);
terminals that support it, such as kitty, foot, WezTerm, and Ghostty, send
Shift+Enter as itself. In others, use Alt+Enter or Ctrl-J.
A paste arrives whole, newlines included, as one edit. The first newline does not send.
Editing in your editor
Ctrl-E opens what you have typed in $VISUAL, or $EDITOR, or vi. Heph
suspends its screen while the editor runs; save and quit, and the file's
contents become the input. Quit without saving and the input is unchanged. A
variable that is set but empty counts as unset.
Attaching files: @path
Type @ followed by a path anywhere in a prompt and the file goes to the model
with your message, saving a tool call and a round:
> the parser in @src/parse.rs rejects @tests/fixtures/odd.toml; why?
Tab completes the path. The first Tab lists files under the worktree that
match what you have typed, fuzzily and case-insensitively, like fzf: every
character in order, closer matches and matches on the file name first. It fills
in the best match; each further Tab cycles to the next. Hidden directories,
target, and node_modules are skipped.
What the model receives depends on the file:
| Attached | Becomes |
|---|---|
| A text file | A document block, titled with the path |
| A PNG, JPEG, GIF, or WebP | An image block the model can see |
| A directory | A listing of its entries |
| A file over 64 KB | A note with the path and size; the model reads the part it needs with view |
The size limit is [input] max_attach. The path may be anywhere, not only in
the project: @~/notes/design.md works. Attaching a file gives the model that
file and nothing else; it still cannot read a second file outside the worktree.
An @word that names nothing on disk is left as text, since @ is also how
people write handles. In the conversation, attachments show as chips under your
message: [src/parse.rs (2.1 KB)].
Images from the clipboard
Ctrl-V with an image on the clipboard saves it to a temporary PNG and puts
@that-path in the input, so it goes with the next message. Heph reads the
clipboard with wl-paste or xclip, whichever is on PATH, or the command in
[input] clipboard_image. With text on the clipboard, Ctrl-V does nothing;
paste text with your terminal's paste key as usual.
History
Up on an empty input recalls your previous prompt on this conversation, and
each further Up goes one further back; Down comes forward again, ending at
whatever you had typed before you started. The history is the conversation's own
record of your prompts, so it is there across sessions too.
Ctrl-R, prompt search, is not here yet; it arrives with /search.
Drafts
Whatever is in the input is saved as you type, and comes back when you next open
the conversation: after Ctrl-D, after a crash, after a reboot. Sending clears
it.
Sending while the model works
Enter while a turn is running does not interrupt it. Each message joins a
first-in, first-out queue instead of replacing earlier feedback. Messages drain
one at a time, each starting its own turn after the previous turn and any review
or publication pause finish. You can keep submitting small pieces of feedback
while reading a document.
The status bar shows the number waiting, such as 3 queued. A Queued messages
preview above the input shows the count and submitted text in queue order,
including while you scroll the conversation or view only user prompts. It wraps
at the terminal width and uses at most four content rows; overflow shows ....
Up recalls the newest queued message into the input to edit; Ctrl-U
withdraws only the newest message. Earlier messages stay queued. Resubmitting
recalled text appends it at the back. The queue is session-local; draft recovery
does not restore the entire queue after quitting or restarting.
The title's color says what the session is waiting for at a glance: green
message when it is ready for you, blue while a turn runs and a message would
queue, yellow commit pending while publication is busy and new prompts cannot
start, and red when a prompt above needs you (approve or deny the call above,
answer the question above, review the changes above).
This is deliberate: a message injected into a running turn would land between two of the model's steps with no way to know which. If you want the model to stop and do something else, interrupt first.
Slash commands
A prompt beginning / is a command to heph, not a message. /help, /clear,
/quit, /exit, /plan, /design, /code, and /commit exist today; see
Slash Commands.