Pretype — Your Mac finishes your sentences

pre·type /ˈpriː.taɪp/ · n.
text that exists before you type it.
52 ms · local
The best interface is invisible — it lives at your caret.
Tabword ⇧Tabsentence Escdismiss typed 0 chars · uploaded 0 bytes
what this is

Your code editor finishes lines for you. Pretype does it for everything you write on your Mac.

You type the dark half — a model on your own chip types the gray half.

The best interface is invisible — it lives at your caret.

ink = you blue = the caret, where they meet gray = the model
and the rest of it

Ghost text is the whole idea, not the whole app. Everything below is the same local model at the same caret — on keys your hands are already on.

  • Tab

    Fixes the typo

    The macOS dictionary, floated over the word — in whichever language it reads around the caret. Esc drops it, and it never asks twice about the same word.

  • Tab

    Spells the emoji

    macOS already knows every Unicode name, so thousands of shortcodes are offered in that same pill without a table being shipped.

  • ⌥Tab

    Rewrites the mess

    Grammar and phrasing repaired in place, in your own tone — or the word you just typed, when nothing is selected. Always previewed, never applied behind your back.

  • ⌥⇧Tab

    Writes the whole reply

    In front of an empty chat box it reads the conversation on screen and drafts your next message as one ghost. Opt-in, OCR’d on-device, only ever on this chord.

  • on its own

    Learns your words

    Your names, your slang, the sentence you type ten times a day — from a model of your own writing, built on this Mac, answering before the LLM has started. Clearable, and off if you want.

  • on its own

    Knows when to stay quiet

    Never in terminals or password managers, never while macOS reports secure input. In an app where you keep ignoring it, it stops offering — and says so in the menu, with a one-click resume.

everywhere

Tab works here. And in every other text field on your Mac — no plugin per app.

Mail
Messages
Slack
Notes
Safari
VS Code
Telegram
Obsidian
Claude
Xcode
Linear
every field
It hooks the text field itself — native apps, Electron, web views. Deliberately silent in terminals, password managers, and during secure input.
how it works

Still your words. Just already typed.

1

Install

Drag it to Applications. No account, no wizard — a menu-bar icon, one Accessibility prompt, and a model downloaded once (≈2 GB).

Applications
2

Type

Write the way you always do. Ghost text appears at the caret, matched to the field’s own font. Wrong guess? Just keep typing.

Mail
To: legal@ — Re: Q3 numbers
Thanks for the quick turnaround — the numbers look right, sending to legal today.
3

Tab

Tab takes a word, ⇧Tab the sentence. The part the next Tab will take reads a step darker. With nothing showing, Tab is just Tab.

Slack — #eng
Message #eng
can someone review #4821? it’s small — two files, mostly tests.
models

Completions, fixes and replies are each measured on their own eval — and the default is sized to your Mac's memory. You can just not care.

The ghost text Tab finishes. Eleven models against the same held-out sentences, ranked for any language you actually type in.

The selection repaired in place. This chord doesn't run on the model you picked — it runs on that model's instruct sibling, so these six rows are the siblings, and each one says which picks land on it.

A whole message drafted from the conversation on screen. Same six siblings as the fix chord — and almost the opposite ranking.

First-word accuracy, % of all cases coverage Latency, p50
1 Gemma 4 E4B 8-bit 8.6 GB 23% 82% 145 ms
2 Gemma 4 E2B 8-bit 5.7 GB default · 24 GB 22% 82% 75 ms
3 Gemma 4 E4B 6-bit 6.8 GB default · 32 GB + 22% 81% 129 ms
4 Gemma 4 E2B 4-bit 3.5 GB default · 16–18 GB 20% 81% 127 ms
5 Qwen3.5 2B 1.6 GB default · 8 GB 15% 74% 93 ms
6 MiniCPM5 1B 2.2 GB 13% 72% 49 ms
7 Qwen2.5 0.5B 1.0 GB 12% 74% 79 ms
8 Ternary Bonsai 4B 1.1 GB 12% 72% 102 ms
9 LFM2.5 1.2B 2.2 GB 11% 67% 59 ms
10 Gemma 4 E4B 4-bit 5.0 GB 10% 72% 151 ms
11 Apple Intelligence 0 GB 9% 75% 430 ms

Dot size = resident memory (hollow = built into macOS) · coverage = share of cases answered · ± = this language vs the model's 17-language average

First-word accuracy with silence counted as a miss, matched cells (OpenSubtitles · Tatoeba · Leipzig) · per-language cells are thin (±5–10 pp) — compare models within a language, not numbers across languages · 07-2026

Exact restore, % of 510 typo lines offered Latency, p50
1 Gemma E4B-it 4-bit 5.0 GB · used by Gemma E4B tiers · E2B 8-bit 65% 89% 1523 ms
2 Gemma E2B-it 4-bit 3.5 GB · used by Gemma E2B 4-bit 50% 90% 378 ms
3 Qwen3.5 2B 1.6 GB · corrects with itself 32% 74% 255 ms
4 Ternary Bonsai 4B 1.1 GB · corrects with itself 21% 43% 324 ms
5 Qwen2.5 0.5B-it 0.4 GB · used by Qwen2.5 0.5B 11% 41% 185 ms
6 MiniCPM5 1B-it 2.2 GB · used by MiniCPM5 1B 4% 28% 668 ms

Whisker = 95% interval · red tick = how often it rewrites a line that was already correct (170 clean controls) · offered = share of lines it proposed anything on · dot size = resident memory

One real typo per line, 17 languages, through the shipped pipeline with the minimal-edit gate already inside the numbers. A correct fix phrased differently counts as a miss, so real usefulness sits above this bar. Per-language cells are 30 rows — read the whisker, not the number. The E4B 8-bit and 6-bit tiers run the 6-bit sibling, which the sweep didn't cover; the 4-bit row is its measured floor. Apple Intelligence isn't in this sweep · 07-2026

Usable draft, % of 570 conversations answered Latency, p50
1 MiniCPM5 1B-it 2.2 GB · used by MiniCPM5 1B 56% 94% 1801 ms
2 Qwen3.5 2B 1.6 GB · corrects with itself 46% 100% 448 ms
3 Qwen2.5 0.5B-it 0.4 GB · used by Qwen2.5 0.5B 38% 94% 345 ms
4 Gemma E4B-it 4-bit 5.0 GB · used by Gemma E4B tiers · E2B 8-bit 33% 100% 532 ms
5 Gemma E2B-it 4-bit 3.5 GB · used by Gemma E2B 4-bit 32% 100% 356 ms
6 Ternary Bonsai 4B 1.1 GB · corrects with itself 21% 91% 324 ms

Whisker = 95% interval · answered = share it drafted anything on · dot size = resident memory · ± = this language vs the model's 19-language total

A draft counts as usable when it is in the conversation's language and doesn't parrot the screen back — a floor on usability, not a quality score; reference similarity was too noisy to book. 19 languages, 30 conversations each, so per-language cells are wide — read the whisker. Apple Intelligence isn't in this sweep · 07-2026

the app

Every setting shows its measured cost.

Three panes — presentation, model, personalization. Hover any control and Pretype shows exactly what it improves or costs, from real measurements.

Inline ghost or floating panel, accept hotkey, ghost visibility with a live preview — and per-app off switches.

Pretype settings, General pane: suggestion display modes, accept hotkey, ghost visibility slider and per-app exclusions.
the ideology

Your words are yours.

the cloud way
you type » their server » their model » their logs
a subscription, an account, an API key
a privacy policy you skim and hope for the best
autocomplete that stops working on a plane
the pretype way
you type » your chip » ghost text
$0 — free, MIT-licensed, no account
a privacy policy you can compile
works in airplane mode, forever
everything pretype ever puts on the wire
your text, your keystrokes
» nowhere
0 bytes, ever — by architecture
model weights ≈1.6–2.2 GB
« Hugging Face
once, on first launch
version check, no payload
» GitHub Releases
daily · off in Settings
honest by default — it needs the Accessibility permission, the same grant a keylogger would ask for. That’s exactly why the input path is open — and short enough to read on a coffee break:
the code

Don’t take privacy on faith — the entire input path is three files. Read them before you trust them.

AXText.swift 570 lines · reads the field
/// Fallback for apps whose focus
/// notifications never fire (some
/// Electron builds): ask the system-
/// wide element who has focus now.
static func
systemFocusedTextElement()
    -> AXUIElement? {
  let sys =
    AXUIElementCreateSystemWide()
  guard CopyAttributeValue(sys,
    kAXFocusedUIElementAttribute,
    &ref) == .success
  else { return nil }
  return isEditableTextElement(el)
    ? el : nil
}
KeyTap.swift 83 lines · catches Tab
/// CGEvent tap on key-down events.
/// The handler returns `true` to
/// swallow the event — used to eat
/// Tab while a suggestion is shown.
final class KeyTap {
  func start() {
    let mask = CGEventMask(
      1 << CGEventType
        .keyDown.rawValue)
    tapPort = CGEvent.tapCreate(
      tap: .cgSessionEventTap,
      place: .headInsertEventTap,
      options: .defaultTap,
      eventsOfInterest: mask,
      ...)
  }
}
TextInjector.swift 63 lines · types it back
/// Inserts text by posting synthetic
/// keyboard events — the most app-
/// agnostic path (AppKit, Electron,
/// web views, terminals alike).
enum TextInjector {
  /// Tags our synthetic events so
  /// the key tap ignores them.
  static let magicTag: Int64 =
    0x5052_5459 // "PRTY"

  static func insert(_ t: String) {
    for c in utf16Chunks(t.utf16) {
      post(chunk: c, keyDown: true)
      post(chunk: c, keyDown: false)
    }
  }
}
Fig. 1 — verbatim from the repo. 716 lines between your keys and the ghost text. free · MIT · no account github.com/nikiomori/Pretype

One key between you and the end of the sentence.

macOS · Apple Silicon≈1.6–2.2 GB model, downloaded oncefree · MIT · no account