Research: what is the best industry approach to add autocomplete to DropTerm’s terminal?

Date: 2026-10-17 Question: Warp-style autocomplete and its peers come in three architectural families — shell-side ghost text (fish), terminal-side overlays over a PTY grid (VS Code, iTerm2, Windows Terminal), and replacing the input surface entirely (Warp, Fig). Which of these should DropTerm adopt, given a custom iced widget over alacritty_terminal and the standing no-shell-injection verdict of terminal-de-integration?

TL;DR

DropTerm should ship fish-style inline ghost-text autosuggestions computed entirely terminal-side — history-prefix suggestions rendered as a dim overlay after the cursor, accepted by writing the remaining suffix to the existing PTY writer on Right (full) and Alt+Right (one word) — because it is the only design that every living peer converges on, needs zero shell cooperation, zero OSC engine work, and zero new dependencies. The prompt state DropTerm needs is already in the engine: the tcgetpgrp foreground check that powers close-confirmation and the status band (src/terminal/engine.rs:244-265) reads “the shell itself holds the terminal foreground” — which is precisely “the user is sitting at a prompt” — for any shell, with no injection and no OSC 133. Suggestions come from per-tab command history scraped out of the grid at command-finish, the same screen-scraping the URL highlighter already does; the ghost text draws as an overlay in the widget’s draw() (the cursor quad and IME preedit are the existing not-in-the-grid precedents), never written into the grid; and acceptance synthesizes plain bytes through Terminal::input_no_scroll (src/terminal/engine.rs:647-649), the exact path every keystroke already takes. A popup menu and any OSC 133 prompt-mark engine work stay out of phase 1.

Three premises from the task landscape itself were corrected by primary sources and are load-bearing for the verdict:

  1. Ghostty does not have a terminal-side completions feature. As of Ghostty 1.3.1 (the current release, Oct 2026) there is no completions-* config key anywhere in src/config/Config.zig, the shell-integration feature list is exactly cursor/sudo/title/ssh-env/ssh-terminfo/path, the 1.2.0 release notes’ shell-integration headline is SSH compatibility (not completions), and the only “completions” in the 1.3.0 notes is “fish: Add descriptions to fish shell completions for Ghostty” — argument completion for the ghostty CLI binary itself. The “Ghostty 1.2 shipped Warp-style completions” claim that circulates in AI-generated surveys does not exist. DropTerm therefore cannot cite Ghostty as precedent; the live terminal-side precedents are VS Code, iTerm2, and Windows Terminal.
  2. kitty’s no-complete shell-integration feature is also CLI completion for kitty itself — “Turn off completion for the kitty command.” (kitty shell-integration docs) — not prompt autosuggestions.
  3. No shipping terminal has the shell send completion candidates. Not even VS Code: its OSC 633 scripts report prompt/command-line/cwd state only (633;E is the command line, not candidates); the suggest popup’s items come from VS Code’s own providers and a built-in spec library. The “shell-emits-candidates protocol” is an experiment, not an industry approach.

The recommendation works strictly within the standing verdict of terminal-de-integration (2026-10-02), which rejected shipping and injecting shell scripts; nothing here needs that verdict revisited, so this record extends rather than supersedes it.

What DropTerm has today

Grounded in the working tree (~29k lines src/):

Findings

1. fish autosuggestions — the UX everything else copies

fish is the origin of the interaction every later implementation imitates (fishshell.com, “Autosuggestions”, read 2026-10-17):

The terminal’s entire role is rendering dim text after the cursor correctly. Everything else — knowing the prompt, the input, the history — lives in the shell. Any terminal-side clone is re-implementing this UX over a PTY it cannot natively understand, which is the central difficulty of family 2.

2. zsh-autosuggestions — proof the UX is shell-agnostic and that terminals need do nothing

zsh-users/zsh-autosuggestions (MIT; README @ master, read 2026-10-17) ports the fish UX to zsh: “you will see a completion offered after the cursor in a muted gray color”, default style fg=8 from the 256-color palette. Strategies feed the suggestion — history (“Chooses the most recent match from history.”), completion, match_prev_cmd — tried in order until one yields. Acceptance is →/End at buffer end; “If you invoke the forward-word widget, it will partially accept the suggestion up to the point that the cursor moves to.” The plugin works by hooking zle widgets, and needs no terminal support at all beyond 8/256 colors — the one documented rendering caveat is an iTerm2 color-scheme issue where “Bright Black” equals “Background”, making ghost text invisible.

Two lessons for DropTerm: (a) the fish UX is what users expect regardless of shell — zsh users install a plugin to get it; (b) any DropTerm-side ghost text must be visually distinguishable from the background by construction (theme-derived dim color, not a hardcoded 8), or it will reproduce the exact bug zsh-autosuggestions documents.

3. Ghostty — the claimed precedent does not exist (corrected result)

The claim “Ghostty 1.2 (Sept 2025) shipped terminal-side fish-style Completions” fails at every primary source, checked 2026-10-17:

What Ghostty actually demonstrates is the adjacent pattern: OSC 133 prompt marks enable jump_to_prompt and 1.3’s click-to-move-cursor, and notify-on-command-finish builds on marks — command awareness without command completion. A completions feature may yet arrive (Mitchell Hashimoto has publicly admired fish’s UX), but as of this record it is not a shipped precedent anyone can grade against. The correct reading for DropTerm is that even the most actively developed new terminal has shipped prompt marks, search, and notifications — but not autocomplete — which says something about the difficulty-to-value ratio of terminal-side completion.

4. VS Code terminal suggest — the richest terminal-side implementation, and it does not have the shell send candidates

VS Code is the deepest terminal-side implementation shipping today (code.visualstudio.com/docs/terminal/shell-integration, read 2026-10-17; source @ microsoft/vscode main, read 2026-10-17):

5. iTerm2 — shell integration for state, a popup for completion

(iterm2.com/documentation-one-page.html, read 2026-10-17.) iTerm2’s Cmd+; Autocomplete is a popup over the PTY grid: “Any text that exists in a tab or its scrollback buffer can be autocompleted in that tab” — type the beginning of a word, press Cmd+;, “An autocomplete window opens showing the top 20 choices”; Return enters the choice, Tab extends it. The candidate source is striking in its simplicity: everything on screen (scrollback included), not history files. Separately, Shell Integration (a script iTerm2 can auto-load — “available for zsh, bash, and fish” — that “modifies your prompt so iTerm2 knows where it is”) provides the state layer: navigate between prompts, “record your command history, suggest most used directories, helps you re-run commands”. iTerm2’s AI composer has inline suggestion of a different kind (“what you have entered and relevant files or commands are sent to AI so it can make suggested completions”) — explicitly off by default for privacy. iTerm2 therefore demonstrates the two-layer split — shell integration for prompt/command state, terminal UI for the completion surface — with the least sophisticated candidate engine (screen text) and a manual-invocation popup rather than always-on ghost text.

6. Windows Terminal — a suggestions flyout, deliberately not ghost text

Windows Terminal’s Suggestions UI (introduced Preview 1.19, expanded 1.21/1.22) is an extension point, not an autocomplete engine (learn.microsoft.com — Terminal actions, “Suggestions”, updated 2025-08-21; 1.22 preview release post, read 2026-10-17):

For DropTerm the precedent is: a terminal can ship completion-adjacent UX with zero prompt heuristics by being explicitly on-demand — but WT’s recentCommands still leans on shell integration for its data, which is the part DropTerm’s verdict rules out.

7. kitty’s complete — CLI completion for kitty itself (corrected result)

kitty’s shell-integration feature list includes no-complete, verified against sw.kovidgoyal.net/kitty/shell-integration (read 2026-10-17): “Turn off completion for the kitty command.” — the feature registers “Sophisticated completion for the kitty command in the shell” (kitty/kitten/clone-in-kitty; “for the fish shell this does not take effect, since fish already comes with a kitty completion script”). It is argument completion for kitty’s own binary, identical in kind to Ghostty’s fish/zsh completions. kitty has no prompt autosuggestion or completion overlay feature; like WezTerm it leaves that entirely to the shell (fish, or plugins). Any survey that lists kitty’s complete among “terminal autocomplete integrations” is misreading it.

8. Alacritty — the engine DropTerm embeds has a stated position, and it is not “add terminal features”

Alacritty remains at v0.17.0 (2026-04-06) with no autocomplete feature; its one “Add Support for AI Autocomplete” issue is closed unanswered. The maintainer position on the shell-integration family is on record in alacritty/alacritty#5554 (closed): “Many of these things are just patches to the shell which has nothing to do with Alacritty. The whole concept of ‘shell integration’ is pretty vague. Alacritty communicates with the program running inside it through escape sequences and those are either supported or they aren’t. If there is a specific escape sequence you’re missing, please mention that one specifically. Though some are just out of scope for the project.”

Two implications for DropTerm. Upstream will not add OSC 133 support for DropTerm to inherit (no specific-sequence request for it has been accepted), and DropTerm should not expect the vendored parser to grow an unknown-OSC hook. And philosophically, DropTerm’s standing verdict — escape sequences either supported or not, no script shipping — is the same line Alacritty’s maintainer draws; DropTerm diverges only in choosing to detect shell state out-of-band (tcgetpgrp, /proc) rather than not at all.

9. Warp — replacing the input surface buys the best completions at the cost of no longer being a terminal-first terminal

(docs.warp.dev, read 2026-10-17.) Warp’s input line is a native text editor — the “modern text editing” feature set (multi-cursor selection, alias expansion, command inspector, syntax and error highlighting, Vim keybindings) exists because typing does not go through a PTY grid at all; commands run on Execute and render as blocks (“Blocks group your command and command output”, per the docs’ Block basics cited in status-bar-ux). On that editor sit two completion systems:

Correction to the circulating claim: Warp’s current docs make no AI, local-model, or cloud claims on the autosuggestions page — the “AI Autocomplete (local ML model, cloud fallback)” description dates from 2023-24 marketing and does not match today’s documented behavior (history + completions). Warp’s AI surfaces now live in its agent features, which do involve cloud models (and community pushback about session data leaving the machine). The costs of the paradigm are structural: because the editor is native, TUI apps, SSH sessions, and non-Warp-aware shells all need accommodation machinery Warp has spent years building (per-shell integration, shells wired into the editor model), and Warp 2.0 (2025) repositioned the product around agents — the input-surface bet was a product pivot, not a feature. DropTerm, a drop-down for quick shell access on COSMIC, has no reason to pay that price.

10. Fig / Amazon Q — the TTY-interception approach is a dead project

Fig’s architecture was the third way: intercept keystrokes at the TTY level, render an out-of-process GUI overlay, drive completions from a TypeScript spec format. The approach is now doubly dead: the withfig/fig repository is archived (description now “Public issue tracker for Fig.”), the client stopped working 2024-09-01 after the AWS acquisition, and AWS’s successor amazon-q-developer-cli README (read 2026-10-17) states: “This open source project is no longer being actively maintained and will only receive critical security fixes. Amazon Q Developer CLI is now available as Kiro CLI, a closed-source product.” AWS’s end-of-support notice dates the IDE-plugin family’s discontinuation at 2027-04-30. The Fig spec format lives on only as an input vocabulary (VS Code’s terminal-suggest extension ships Fig-style specs), not as a runtime. For DropTerm this is the cautionary precedent: an architecture that fights the terminal (separate overlay process, TTY wrappers) died even with a company behind it.

11. The negative peers — and one proprietary positive

The three families, graded

Family Members Prompt knowledge Candidate source UI Cost profile
Shell-side ghost text fish, zsh-autosuggestions, Clink shell’s own shell (history/completions/paths) inline dim text zero terminal work; per-shell plugins; DropTerm would ship none of it
Terminal-side overlay VS Code, iTerm2, Windows Terminal, Termius shell scripts (OSC 633/133) or screen heuristics terminal-computed (PATH/files/specs/screen text/history) popup (all four) + inline passthrough (VS Code) prompt detection is the hard problem; every member either ships shell scripts or accepts degraded detection
Input-surface replacement Warp (alive), Fig/Amazon Q (dead) owns the editor history + specs + AI inline + menu in a native editor rebuild the terminal around it; TUI/SSH accommodation forever; product-pivot scale

Every surviving terminal-side implementer converges on the same division of labor: the state layer (where is the prompt, what is typed) comes from either shell cooperation or out-of-band detection, and the suggestion layer is computed terminal-side, accepted by synthesizing keystrokes. None has the shell send candidates. DropTerm’s unusual advantage is that its engine already owns an out-of-band state signal — tcgetpgrp — that the others don’t use for this purpose (VS Code/iTerm2/WT run on OSes where a terminal-side tcgetpgrp against the child shell is less straightforward, and they want exact command lines anyway).

Recommendation

Phase 1 — fish-style history ghost text, terminal-side, opt-out. Graded against precedent: the interaction model is fish/zsh-autosuggestions/Warp’s autosuggestions (inline, dim, inert until accepted); the detection model is DropTerm-specific and stronger than any heuristic peer (kernel truth, any shell, SSH-transparent); the acceptance model is VS Code’s (synthesize keystrokes into the PTY); the rollout model is fish/Warp default-on with a kill switch (VS Code’s eighteen-month opt-in was about a popup over unknown shells — DropTerm’s inline text has a smaller blast radius, and fish_autosuggestion_enabled defaults on).

  1. Prompt state — no OSC, no injection. A suggestion may show only when !terminal.foreground_child_running() (src/terminal/engine.rs:669-679) and the cursor sits on the bottom grid line at display offset 0. The tcgetpgrp check is exactly “the shell owns the foreground,” which is the idle-prompt state; it already drives close-confirmation and the status band, is Linux-native, and follows SSH transparently (the remote shell still holds the pgrp locally through the ssh client). This strengthens the standing verdict rather than testing it: detection without injection, no TERM_PROGRAM gating, no scripts shipped. Fail-closed by construction — a shell without job control degrades to “no suggestions,” never to wrong suggestions.
  2. Input tracking — read the grid, don’t intercept keys. On each Wakeup-driven needs_update cycle, scrape the cursor line from term.grid() (the display_iter walk update() already performs, src/terminal/engine.rs:1081-1082) from the line start to the cursor column; that string is the typed input for prefix matching. Cells left of the first non-prompt character is a heuristic phase 1 accepts: a suggestion that is wrong about the prompt prefix is still accepted as “append this suffix,” so only the suffix must be exact. Multi-line and right prompts degrade to no-suggestion, the honest failure.
  3. History source — scrape at command-finish, per tab. When the foreground returns to the shell (the same transition the engine’s test pins, src/terminal/engine.rs:1600-1646), record the just-typed line into a bounded per-tab ring (fish and zsh both cap effective history; Warp indexes history; VS Code caches shell-history globals). This is the iTerm2 observation (screen text is a legitimate candidate source) without its popup, and the Warp autosuggestion source (history + completions → phase 1 keeps only history) without its editor. No history files are read; ~/.bash_history parsing is a non-goal (VS Code does it; it buys cross-session coverage DropTerm’s per-tab ring already covers for the drop-down’s own usage pattern — session persistence already restores tabs).
  4. Match policy — prefix, most-recent-first. Fish’s backbone and zsh-autosuggestions’ default history strategy: the most recent history entry with the typed line as a strict prefix. One suggestion, inline — the graded precedent is unanimous that inline is the always-on surface (fish, zsh-autosuggestions, Warp autosuggestions); every popup implementation (VS Code, iTerm2, WT) makes it on-demand because a persistent popup over an uncertain prompt is hostile. A menu is a later, separate decision with zero regression risk to the inline path.
  5. Rendering — overlay in draw(), never the grid. After the fill_raw text pass (src/terminal/widget.rs:895-900), lay the suggestion’s glyphs starting at the cell after the cursor, clipped at the line end, in a theme-derived dim foreground (composited from the scheme’s foreground/background — never palette index 8, the zsh-autosuggestions invisible-text lesson). The cursor quad (src/terminal/widget.rs:988-1065) and IME preedit are the two existing overlays proving the pattern; the grid and the cosmic-text buffer stay untouched, so selection, search, copy, and scrollback see nothing. Wrapping: clip, don’t wrap (a suggestion that would wrap is dropped — showing wrong-cell ghost text is worse than none).
  6. Acceptance — synthesize into the existing PTY funnel. While a suggestion is displayed: Right (and only then — Right is otherwise forwarded verbatim, src/terminal/widget.rs:1195-1200) writes the remaining suffix through terminal.input_no_scroll(suffix) (src/terminal/engine.rs:647-649), the identical path paste and every keypress use; Alt+Right accepts one shell-word of it (fish’s alt-right/ctrl-right family, zsh’s forward-word, Warp’s Ctrl+→). Any other key, focus loss, resize, or foreground change dismisses the suggestion first and then processes the key normally — fish’s “it won’t execute unless you accept it” invariant. No bracketed-paste wrapping on the suffix: it is typed characters, not a paste, matching how VS Code’s addon emits raw suffix bytes.
  7. Config — autosuggestions_enabled (default true), pinned to the docs contract. One serialized key, documented in docs/configuration.md (the every_config_key_is_documented gate), a Behavior-card toggle beside bell_notification_enabled (src/config.rs:262). Keybind surface: none in phase 1 — the accept keys are soft (only meaningful while a suggestion shows, never swallowed otherwise), which avoids spending action_id stability on keys whose default no peer customizes. If users ask, Right/Alt-Right can join the overlay later as the customization layer already models (src/keybinds.rs:319-339).
  8. Privacy — local-only, by construction. No network, no model, no telemetry; suggestions are a prefix search over the tab’s own visible past. The contrast is the survey’s own negative space: Warp’s agent features send session data to cloud models, iTerm2’s AI composer is off by default for privacy, and Fig’s spec network died with the product. DropTerm’s stance costs nothing because phase 1’s source (history) is the one thing that never needed a model.

Phase 2 (conditional, not scheduled): prompt marks via OSC 133 — only if phase 1’s heuristics demonstrably fail. The honest trigger would be widespread wrong-suffix suggestions from multi-line/right prompts that the prefix heuristic cannot see. The work is real and nameable: the vendored vte 0.15.0 parser drops unknown OSCs at src/ansi.rs:1523 with no extension hook, and alacritty_terminal’s event loop owns the parser (src/event_loop.rs:154), so DropTerm would carry a [patch]-pinned fork of vte (add an unknown-OSC callback to osc_dispatch) or of alacritty_terminal — plus mark storage in/alongside the grid. That is engine work the standing verdict already priced as high, for marginal gain over the tcgetpgrp signal; it should not be pre-paid. If it ever lands, the no-injection verdict still holds: marks are accepted, never injected — the docs would carry a copy-paste OSC 133 snippet (the same sequences WezTerm ships as wezterm.sh and VS Code as 633), detection-only, for users who opt in. No shipped scripts, no env injection, no supersession of the 2026-10-02 record.

Rejected, and why

Sources