This is the long version of the README.
Tilde is three small pieces:
- The keyboard (
InlineGhostIME) handles your keystrokes and draws the ghost as marked text inside the app you are typing in. It never inserts text through Accessibility, overlays, or fake paste events. - The app in the menu bar takes a bounded slice of what you typed, adds what it can see on screen, asks the model, filters the answer, and sends back a short suggestion over a private local socket.
- The model is a signed copy of
llama-serverrunning as a child of the app, with one of two pinned open-weight models downloaded on first run and verified byte for byte:- Gemma 4 E2B (default, 3.4 GB) — lighter, measured.
- Qwen 3.5 9B (optional, 5.6 GB) — stronger, needs more memory, still under study.
Typed text, screen text, and model output stay in memory and are gone when the request is done. If you turn on Personal History, what you write is stored on your Mac in an encrypted log whose size you can see, that you can exclude apps from, and that you can delete with one click. PRIVACY.md has the full boundary.
Every change to what Tilde shows goes through a research harness in this repository called Tilde Lab. Experiments are registered with a kill rule before they run, results are written down whether they won or lost, and nothing reaches the default build without a measured comparison against the build it replaces.
- Experiment records — Q11 to Q14 are the chain that took wrong-when-shown on the tuned stack from the forties into the teens. Q13 is the one that killed my own favourite idea, longer ghosts.
- The lab log — every attempt: what was tried, what was learned, what failed, written the same day.
- The learning ledger — the reusable lessons and the ordered queue of what may run next.
- The live outcome ledger — a text-free record of every ghost shown and every silence, with its reason, kept on your Mac and never uploaded.
| Name | Purpose | Ships to users? |
|---|---|---|
| Tilde | The macOS input method and its local runtime | Yes |
| Tilde Lab | The app and command-line tools used to test and improve Tilde | No |
The boundary is enforced by Swift package dependencies: Tilde Lab may use
TildeCore, but the app and keyboard never import anything from Tilde Lab.
See the repository boundary map.
The picker offers exactly two immutable files and needs no Hugging Face login:
https://huggingface.co/mradermacher/gemma-4-E2B-GGUF/resolve/3762686d74ff8db6c98f8d3c389f56fbdf994d5a/gemma-4-E2B.Q4_K_M.gguf— 3,427,861,984 bytes; SHA-256389c868898bffed97fd178646f88562cafecc6f60983a636bac53b131fd068a2https://huggingface.co/mradermacher/Qwen3.5-9B-Base-GGUF/resolve/ec5c6b42ca313fc71afe4a40b068d3f7026bf4f6/Qwen3.5-9B-Base.Q4_K_M.gguf— 5,629,109,312 bytes; SHA-2564171d5fec62a373744ca4f01ec9e2378c092a65f480c039e9c679d910351fda2
The first-run download is the only network request Tilde ever makes. It sends no typed text, screen text, prompt, history, or model output.
The project is a Swift 6.2 package with no Xcode project file.
./script/proof.sh fast
./script/build_and_run.sh
./script/build_ime.shThe two build scripts create development bundles; they do not contain the
release model or helper. By default, both require the one eligible Apple
Development identity in the keychain, so the app and IME receive matching,
non-empty Team IDs. If multiple identities exist, pass the same exact SHA-1 to
both with --sign-identity. Explicit --sign-identity - builds ad hoc bundles,
which cannot exercise the authenticated app-to-IME runtime.
script/proof.sh fast is the pre-merge gate.
script/package_app.sh is the single manual release driver. It requires the
helper hash and explicitly named Gemma and Qwen proof-model preseeds. Both are
checked against their revisions, byte counts, and SHA-256 pins above, copied
only into isolated external proof storage, and never into the signed app. The
driver exercises both selections and then blocks on bundle shape, helper/IME signatures, runtime health,
steady-state open-socket observation, notarization, Gatekeeper checks, and a
32 MiB hard cap on the signed app artifact. Run
./script/package_app.sh --help for the full command. The pins must come from
human review: matching bytes and valid file shapes do not prove provenance.
For private, aggregate-only model comparisons, see the evaluation guide.
Tilde Lab is the separate local regression studio for reply quality, judgment,
Scene Memory, synthetic personalization, real text-system interaction, and
performance experiments. It runs reproducible multi-arm suites through the
pinned loopback-only Gemma runtime, includes deterministic policy audits and an
instrumented AppKit Scene Host, and persists aggregate-only reports for
baseline/candidate comparison. Its locked headline is Net Keystrokes Saved,
with safety, bad-suggestion, temporal-integrity, privacy, interaction, and
latency gates outside the number. The tilde-lab CLI adds durable
work-item resume, interleaved paired blocks, a hard development/validation/
holdout firewall, root-clustered uncertainty, risk–coverage, chronological
personalization, local dogfood/attention-tax and confidence calibration,
real-host evidence, soak gates, and immutable permanent regressions. It
includes a 300-case protected curated
Slack pack with prefix replay/context ablations, the 400-case synthetic quiz,
and a read-only development-only importer for private accepted/typed-instead
history:
./script/build_and_run.sh --tilde-lab
swift build --product tilde-lab
.build/debug/tilde-lab init --name qwen-factorial --hypothesis-id QWEN-GEN-01 --hypothesis "The registered treatment improves expected utility without increasing harm." --class generator --suite certified-v2 --output campaign.json
.build/debug/tilde-lab run campaign.json --resume
.build/debug/tilde-lab review --campaign campaign.json --status supported --conclusion "The preregistered criteria passed; see the experiment record."
.build/debug/tilde-lab compare --campaign campaign.json
swift run tilde-lab-runner --workers 1 --slots 8 --repetitions 10
swift run tilde-lab-runner --built-in-suite slack-reply-gold-v1
swift run tilde-lab-runner --manifest ./candidate-matrix.tilde-lab.jsonSee the Tilde Lab guide for the complete knob manifest, score and privacy contracts, scenario format, matrix runner, and the boundary between high-throughput model evidence and foreground real-IME proof. The Tilde Learning Ledger preserves what experiments taught us, why candidates were kept or rejected, and what should be tested next. The research roadmap sequences the longer-term hypotheses behind that queue, while experiment records define the public pre-registration and result format.
The code follows the same two-part boundary:
- Tilde:
Sources/TildeCore,Sources/TildeApp, andSources/InlineGhostIME. - Tilde Lab:
Sources/TildeLabKit,Sources/TildeLab,Sources/TildeLabCLI, andSources/TildeLabRunner.
The names inside each group describe implementation components, not additional products.
Read AGENTS.md before changing behavior.