~11 min · terminal-profile, coding-agents, safety, bracketed-paste
Level 0Unlit
0 XP0/48 lessons0/13 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
What ships: the terminal list and the Enter guard (FirekeeperKit + DictationController)·swift
// FirekeeperKit AppCategory.classify(bundleID:) — the terminal list
private static let terminalIDs: Set<String> = [
"com.apple.terminal", "com.googlecode.iterm2", "dev.warp.warp-stable", "dev.warp.warp",
"com.mitchellh.ghostty", "com.github.wez.wezterm", "net.kovidgoyal.kitty", "co.zeit.hyper",
"com.cwk.smolder", // the family terminal, missing until the 2026-09-27 review
]
// VS Code, Cursor, Xcode, Obsidian are .editor: an integrated terminal reports its editor's id.
// DictationController — Enter in a terminal is withheld while the guard is on (the default).
var pressEnter = EnterCommand.detect(in: raw) || EnterCommand.detect(in: output.text)
let text = EnterCommand.strip(from: output.text)
if pressEnter, settings.terminalGuardEnabled, snapshot?.category == .terminal {
// Terminals execute on Enter; a mis-heard "press enter" in a shell is a live command.
pressEnter = false
guardNote = " (terminal guard: Enter suppressed)"
}
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.