LaTeX Squiggly

You can't paste LaTeX into Slack. So type it anyway — and get real characters instead.

A menu bar app on macOS, a tray app on Windows. Type \alpha, press space, and the letters you just typed become α — in place, in whatever app you were already in.

macOS 13+ Windows 10+ 202 symbols
Converting as you type

This box behaves the way the app does. Space or tab finishes a command; return never does.

Try:

What comes out

Characters, not markup

Every result below is what the app's own engine produced, not a mock-up. It is ordinary Unicode text: it survives a copy, a paste, a chat message and an email subject line, because there is nothing left to render.

\alpha
→
α
\Rightarrow
→
⇒
\int
→
∫
\subseteq
→
⊆
\mathbb{R}
→
ℝ
$x^2$
→
x²
$a_1$
→
a₁
$\int_0^1$
→
∫₀¹
\sin
→
sin
\infty
→
∞

When it can't

It tells you, in words about your maths

Some LaTeX has no honest one-line form. The app leaves your text exactly as you typed it and says why — naming the constraint rather than reporting a syntax error, because \vec is not a typo.

\vec{v}
→
An accent cannot be drawn over other characters in plain text.
\overbrace
→
An overbrace cannot be drawn over other characters in plain text.
\matrix
→
A matrix needs two-dimensional layout, which has no inline Unicode form.
\mathbf{x}
→
Bold, script and fraktur alphabets are not supported yet.
$e^{i\pi}$
→
There is no Unicode superscript for “π”.

Where an approximation is defensible, it takes it and tells you it did. A fraction with an exact character becomes that character; one that composes legibly out of scripts is composed; everything else goes on one line with a slash.

\frac{1}{2}
→
½
\frac{3}{7}
→
³⁄₇
\frac{a}{b}
→
a∕bA fraction cannot be stacked in plain text, so it was written on one line with a slash.
\sqrt{2}
→
√2A radical sign cannot extend over what is under it, so the root was written as √(…).
\sqrt[3]{x}
→
∛xA radical sign cannot extend over what is under it, so the root was written as ∛(…).
\binom{n}{k}
→
C(n, k)A binomial coefficient cannot be stacked in plain text, so it was written as C(n, k).

Staying quiet

The hard part isn't converting. It's knowing when not to.

An always-on replacement with no exceptions rewrites your LaTeX source as you write it. So the app watches which app is in front, and in a TeX editor it does nothing at all — no buffer is even kept, which makes a replacement there structurally impossible rather than merely declined.

Excluded on sight

These ship excluded, and the list is re-checked at every launch, so an editor you install next month is covered without you thinking about it. Anything you delete stays deleted.

Overleaf, in any browser

A browser is one app with a thousand documents in it, so the page matters as much as the app. These hosts are excluded wherever they are open — and so is every subdomain.

  • Cursor
  • RStudio
  • Terminal
  • Visual Studio Code
  • TeXShop
  • TeXstudio
  • Texifier
  • LyX
  • BBEdit
  • overleaf.com
  • sharelatex.com
  • papeeria.com
  • cocalc.com
  • latexbase.com

What each browser will actually tell you

Measured on macOS 15.6 against Safari 26 and Chrome 152 — not assumed, because the received wisdom here is wrong in both directions.

BrowserGives the page URLCost of a readHow
Chrome, Chromium familyYes2.8 ms avgAXDocument on the focused window, and an AXWebArea under the caret
SafariYes12 ms avg · 109 ms worstAXWebArea six levels down; it does not answer AXDocument, contrary to the usual claim
Firefox familyNo—Window title only, so site rules fall back to matching it

Two consequences are baked in. Safari's descent is skipped on the path inside the keystroke callback, where 109 ms would be felt as a stuck key. And a browser that will say nothing at all is treated as suppressed — a setting you can turn off if you never open Overleaf.

Coverage

202 symbols, and a way to find them

Every character is resolved from its official Unicode name by the table generator, never transcribed by hand. Search runs over the command, the Unicode name and the category at once — so greek capital narrows to eleven rows, and double-struck finds the blackboard bold letters without knowing they are called that.

The dollar rule

It knows the difference between maths and money

Superscripts are the dangerous feature. x^2 cannot convert on its own, because 2^3 in a sentence and a_b in a variable name would rewrite themselves the moment you hit space. So bare scripts are unreachable, and $x^2$ — which nobody types by accident — is what turns them on.

That is not enough by itself. I have $5$ left is a pair of dollar signs around a number, and rewriting it would be worse than useless. So a span only converts when it contains a backslash, a caret or an underscore: an actual mathematical signal. Currency has none, and is left alone.

I have $5$ left
→
left exactly as typed
that costs $20 and $30 more
→
left exactly as typed
$a$
→
left exactly as typed
x^2
→
left exactly as typed
2^3
→
left exactly as typed
$x^2$
→
x²
$5x^2$
→
5x²

Capped at 48 characters

So a stray dollar sign earlier in the sentence cannot reach forward and swallow half a line on its way to the one you just typed.

Failure here is always reported

Unlike the backslash path, where staying quiet is polite, wrapping something in $…$ is a clear statement of intent — so if it cannot be converted, the app says so rather than doing nothing.

What it costs you

Nothing you can measure

Measured on the running app over a five-minute idle window, using the same energy metric Activity Monitor shows. macOS starts calling an app an energy problem at around 150 idle wakeups per second.

0.01%of one CPU core, idle
0.0energy impact, every sample
0.28/sidle wakeups
15 MBresident memory

Nothing is stored or sent

The app keeps a short in-memory buffer of what you just typed and discards it the moment a command completes, or the moment you move the caret, switch app or change tab. There is no network code in it.

Two permissions, and why

Input Monitoring to notice when you type a command; Accessibility to replace the text. Having only the first would give you an app that watches you type and can do nothing about it.

It reads a page only while running

Reaching into a browser's accessibility tree happens only while conversion is actually on. Switched off, every app looks like a non-browser.

Getting it

Download it, or build it

Both platforms run the same engine. Not a similar one: the Windows tables are generated from the tables the macOS engine uses at runtime, and the two are diffed against each other over 2,030 LaTeX fragments before anything is published, with both required to give the identical answer down to the number of backspaces. Only the parts that touch the operating system differ, and the Windows README says exactly which and why.

macOS 13+. Download the disk image, open it, and drag LaTeX Squiggly onto Applications. It is signed but not notarized — that needs a paid Apple Developer account — so the first time you open it macOS will refuse. Go to System Settings → Privacy & Security, scroll down, and click Open Anyway.

Windows 10+. Download the .exe and double-click it. No installer, no admin rights, and Windows asks for no permission at all. It is not code-signed, so SmartScreen will say Windows protected your PC: click More info, then Run anyway. Your antivirus may also take an interest, because the app installs a low-level keyboard hook, which is the same mechanism a keylogger uses.

Chrome. Add it from the Chrome Web Store. It also works in Edge, Brave and other Chromium browsers, and needs nothing installed outside the browser.

You should be sceptical of any app that asks you to click past a security warning, particularly one that can see your keystrokes. So, plainly: nothing you type is stored, logged, or sent anywhere. The app holds the last 64 characters in memory only long enough to recognise a command, then forgets them — the instant one completes, and also whenever you click, press return, move the cursor, switch app, or change browser tab. There is no networking code in the project at all: it never opens a connection, so there is nowhere for anything you type to go. Nothing is written to disk except your own settings. You do not have to take that on trust; the source is right there, and on a Mac you can build it yourself in about a minute.

Installed it? The guide walks through the first steps on each platform, and how to turn an equation into an image.

Building it on a Mac

This is the primary path, not a fallback. An app built on the machine it runs on is never downloaded, so it never carries com.apple.quarantine and Gatekeeper never blocks it — no System Settings detour, and nobody has to weaken a security setting to run something that reads their keystrokes. It needs the Command Line Tools; Xcode's 15 GB is not required, which is why the bundle is assembled by hand rather than by an .xcodeproj.

# 1. Apple's command line tools (not Xcode)
xcode-select --install

# 2. get the source
git clone https://github.com/SuperWalrus01/LaTeX-Squiggly.git
cd LaTeX-Squiggly

# 3. a stable signing identity — once, BEFORE the first install
scripts/setup-mac-signing.sh

# 4. build and install
scripts/install-mac-app.sh
open "/Applications/LaTeX Squiggly.app"

Order matters: macOS ties the Accessibility grant to the code signature, so signing after you have granted permission invalidates the grant. Ad-hoc signatures key on a hash that changes with every build, which is how you end up re-granting Accessibility forever and blaming the app.

# ask the app what it currently sees
"/Applications/LaTeX Squiggly.app/Contents/MacOS/LaTeX Squiggly" --diagnose

It prints every rule and, for each running browser, what it can read and what it would do. Hosts are printed rather than whole URLs — an Overleaf link carries a share token, and a diagnostic somebody pastes into a bug report should not carry it too.

Building the Windows app

From a Mac or a Linux box, which is how it is actually built: the .NET SDK cross-compiles, so no Windows machine is needed to produce the binary. The pipeline generates the C# tables from the Swift engine, records what the Swift engine answers, checks the port against it, and only then publishes. If any of that disagrees, nothing is published.

# needs the .NET 8 SDK; nothing else
scripts/build-windows.sh
#   1/6  building the Swift engine
#   2/6  generating the C# tables from it
#   3/6  generating the icons
#   4/6  recording Swift's answers
#   5/6  checking the port against them
#   6/6  publishing for win-x64

The Windows app cannot be run on the machine it is built on, so agreement with the macOS engine is the only evidence available that the port is faithful. That is why it is checked before publishing rather than after shipping.