C.W.K.
Stream
Lesson 04 of 05 · published

Terminals Are First-Class Targets

~11 min · terminal-profile, coding-agents, safety, bracketed-paste

Level 0Unlit
0 XP0/36 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
"In a text field, a wrong paste is embarrassing. In a terminal, a wrong paste runs."

Why Terminals Are Special

Dictating into Terminal, iTerm, a VS Code or Cursor integrated terminal, or a coding-agent CLI like Codex or Claude Code is a first-class use case — Dad lives in those all day. But a terminal is not a generic text field. Text pasted there can execute. A big hidden paste block you can't read before it runs is hostile at best and dangerous at worst. So Firekeeper gives terminals their own insertion profile with different rules from a Mail compose window.

The Terminal Profile Rules

Detect the target as a terminal (by bundle id — Terminal, iTerm2, Ghostty, editor-embedded terminals, agent CLIs) and switch behavior:

  • Short single-line dictation: paste normally.
  • Long or multi-line dictation: keep it visible and editable — a preview overlay with an explicit "send to terminal," or slow/line-by-line insertion, or bracketed-paste-aware insertion if the target supports it.
  • Never auto-press Enter after a long terminal dictation unless the user explicitly spoke "press enter" and enabled that behavior.

The Enter rule is the load-bearing one: a dictation that auto-executes is a dictation that can run a command you didn't finish thinking about.

Generic text field:  paste text -> done
Terminal profile:    detect terminal
                     -> short? paste
                     -> long?  preview / chunk / bracketed-paste, stay editable
                     -> Enter ONLY if spoken "press enter" AND enabled

Respecting the Working Loop

The deeper idea is respect for the user's actual workflow. A developer dictating a long prompt into a coding agent wants to see and edit it before sending — that's how the tool fits their loop instead of fighting it. Wispr Flow figured this out; Firekeeper treats it as a design requirement, not a nice-to-have. The terminal profile is what turns "I can dictate" into "I can dictate into my actual dev environment safely."

Never synthesize Enter into a terminal on the app's own initiative. Auto-pressing Enter after a terminal dictation can execute a half-formed command. The only path to a synthesized Enter is the user explicitly speaking a 'press enter' phrase with the setting enabled — two deliberate signals, never an inference. When in doubt, leave the cursor at the end of the text and let the human press it.
Detect target category by bundle id, then specialize. The frontmost app's bundle identifier is a reliable, cheap signal for choosing an insertion profile. Maintain a set of known terminal and coding-agent bundle ids, and when the target matches, switch to the cautious profile. Unknown apps get the safe generic path, not the terminal one.

Code

Terminals get a cautious profile, and Enter is never inferred·swift
let terminalBundles: Set<String> = [
    "com.apple.Terminal", "com.googlecode.iterm2", "com.mitchellh.ghostty",
    "com.microsoft.VSCode", "com.todesktop.230313mzl4w4u92" /* Cursor */,
    // ...plus coding-agent CLIs where detectable
]

func insertInto(_ t: TargetSnapshot, text: String, spokeEnter: Bool, enterEnabled: Bool) async {
    if terminalBundles.contains(t.appBundleID) {
        if text.isMultiline { await previewThenSend(text, into: t) }  // stay visible/editable
        else { await pasteInsert(text, into: t) }
        // Enter requires BOTH an explicit spoken command AND the setting on.
        if spokeEnter && enterEnabled { await synthesizeReturn() }
    } else {
        await insertAtomic(text, into: t)   // generic safe path
    }
}

External links

Exercise

List three targets where inserting text has different consequences than a plain text field (a terminal, a spreadsheet formula bar, a chat input that sends on Enter). For each, what's the dangerous default behavior, and what specialized rule would you add to make dictation safe there?
Hint
The pattern is: identify what the target does with inserted text beyond just holding it — execute (terminal), evaluate (formula bar), transmit (chat-on-Enter). The specialized rule always constrains the most irreversible consequence: don't auto-run, don't auto-evaluate, don't auto-send. Detect the target category and withhold the dangerous final step until the human takes it.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.