Inline AI completion. In VibeCoder, it appears on its own as you pause typing, or immediately on ⌥\. In VS Code, it is still explicit-trigger only — press ⌥\ at the cursor. Either way: read the grey suggestion, press Tab to accept or Esc to dismiss.
Ghost text is VibeCody’s short-form AI completion. It renders inline at the cursor and accepts with Tab — the ergonomics people expect from a modern editor. VibeCoder answers both a debounced pause in typing and an explicit ask (reverted 2026-09-11, below); VS Code remains explicit-trigger only: nothing is requested there, and nothing appears, while you type.
For a larger change you want to review hunk-by-hunk, use Diffcomplete (⌘.) instead.
Quick start
- Open a file in VibeCoder, or any file in VS Code with the VibeCLI extension installed.
- Put the cursor where the code should go.
- Press ⌥\ (Alt-Backslash on every platform). Or run AI: Inline Completion at Cursor from the command palette.
- A grey suggestion appears inline.
- Tab accepts it. Esc dismisses it. Typing anything else dismisses it too.
If nothing appears, the model decided nothing belonged at that cursor — that is a normal answer, not an error.
Why it looks like other tools, and why VibeCoder and VS Code now differ
VibeCody removed its original keystroke-driven ghost-text implementation (SupercompleteEngine) in 5a7eef7c: that one ran on a debounce timer after every keystroke, kept a rolling buffer of your recent edits, and used them to predict the next one. It was flagged HIGH severity in an internal patent audit and removed with “no kill-switch, no opt-in path” — a deliberate call, not an oversight. What replaced it was explicit-trigger only, specifically to avoid that flagged pattern.
On 2026-09-11, VibeCoder’s copy of this was reverted back to also answering typing, at the repo owner’s explicit request, made after being told this reinstates a keystroke-driven pattern from that same flagged category — reusing the existing FIM completion backend (vibe_ai::ghost) rather than resurrecting SupercompleteEngine’s edit-history/next-edit-prediction machinery, which stays removed. VS Code’s implementation was not changed and remains explicit-trigger only. The two hosts intentionally diverge now:
| VS Code (explicit-trigger) | VibeCoder (since 2026-09-11) | |
|---|---|---|
| Trigger | ⌥\ only | typing (debounced) or ⌥\ |
| Sees your edit history | no — nothing retained between requests | no — nothing retained between requests |
| Auto-retrieval of other files | no | no |
| Requests while you type | zero | one per debounced pause (AUTOMATIC_DEBOUNCE_MS, currently 350ms), cancelled by the next keystroke |
| Accept | Tab | Tab |
VibeCoder’s gate is in vibecoder/src/lib/ghostText.ts; VS Code’s is unchanged in vscode-extension/src/ghost-text.ts. Both still key off the named trigger-kind member, not a literal — see the box below, which still applies to VS Code and to VibeCoder’s explicit path.
For contributors: the enum is inverted between the two hosts. Monaco has
InlineCompletionTriggerKind = { Automatic: 0, Explicit: 1 }; VS Code has{ Invoke: 0, Automatic: 1 }. The same names carry opposite numbers, so a literal comparison copied from one host to the other gates on exactly the wrong half. Always compare against the named member.The patent-audit document this all refers to (
notes/PATENT_AUDIT_INLINE.md) is gitignored and was not consulted when VibeCoder’s gate was reverted — if it draws a narrower line than “any keystroke-driven ghost text,” that revert should be checked against it.
What gets sent
Per request — one ⌥\ press, or one debounced pause in typing on VibeCoder — carrying:
- Prefix — up to 160 lines before the cursor.
- Suffix — up to 60 lines after the cursor.
- File path and language, for the prompt header.
- Project memory — your author-written
VIBECLI.md/AGENTS.md/CLAUDE.md, the same audit-restricted source diffcomplete uses. Never auto-extracted state.
Nothing else. No edit history, no telemetry about what you accepted or rejected, no embedding search — the request shape did not change in the 2026-09-11 revert, only how often it’s sent.
The response is capped at 12 lines (vibe_ai::ghost::MAX_COMPLETION_LINES). When the cap clips a suggestion the editor says so — accept what you have and trigger again to continue.
Provider and model
Ghost text is provider-agnostic and never defaults to a single vendor.
- VibeCoder uses the provider selected in the toolbar, with that provider’s registry default model. On an explicit ⌥\, no provider selected means a toast telling you to pick one. On an automatic (typing) trigger, the same case is silent rather than a toast on every debounced pause — either way, nothing is called.
- VS Code uses the
vibecli.providerandvibecli.modelsettings. The daemon only honours the override when both are set — leavevibecli.modelempty and the daemon uses whichever provider and model it was started with.
Architecture
VS Code: [ ⌥\ press ] ─────────────────────────────────────┐
VibeCoder: [ ⌥\ press ] or [ pause after typing ] ──────────┤
▼
editor.action.inlineSuggest.trigger
(⌥\ path only — typing calls the
provider directly) │
▼
inline-completion provider
VS Code: trigger kind Automatic? ──► return nothing
VibeCoder: trigger kind Automatic? ──► debounce, then continue
│
▼
VibeCoder: ghost_complete (Tauri command)
VS Code: POST /v1/ghost/complete (daemon, bearer auth)
│
▼
vibe_ai::ghost::generate()
│
├─► system prompt demanding bare insertion text
├─► prefix / cursor / suffix as labeled regions
├─► project memory as a separate system message
▼
sanitize_completion() — unwraps stray code fences, caps at 12 lines,
preserves leading indentation
Leading whitespace is deliberately preserved: at a cursor sitting at column 0 of an indented block, the indentation is the first thing that belongs there.
What ghost text is NOT
- Not FIM. The model receives prefix and suffix as discrete labeled regions, not a single fill-in-middle template.
- Not next-edit prediction. Each request is independent; nothing about your previous edits or previous suggestions is carried forward —
SupercompleteEngine’s rolling edit-history buffer stays removed even in VibeCoder’s reverted, keystroke-driven path. - Not auto-retrieval. No embedding search, no call-graph walk, no symbol-server probe.
- On VS Code, still not keystroke-driven — that host was not touched by the 2026-09-11 revert and remains explicit-trigger only.
Related
- Source:
vibecoder/crates/vibe-ai/src/ghost.rs·vibecoder/src/lib/ghostText.ts·vscode-extension/src/ghost-text.ts - Route:
POST /v1/ghost/complete(requires the daemon bearer token) - Companion surface: Diffcomplete (⌘.)