Textracto_
The 90-second guide

Press a shortcut. Type a few characters. Press Enter.

That's the whole app. This page covers the two capture shortcuts, every key inside the palette, and — the part worth learning — how your query matches and what a copy actually copies.

Step one

Capture shortcuts

A capture takes what's on screen, runs on-device OCR, and opens the palette with every recognized line. Two flavors:

Shortcut (default)Action
⌥⌘OCapture the focused window and open the palette.
⌥⌘⇧OCapture all windows into one merged, searchable list — each line tagged with its source app.

Both are rebindable: menu-bar icon ▸ Settings… (the same window this guide opens from). Shortcuts must include , , or .

Step two

Keys in the palette

KeyAction
typeFilter and re-rank as you type.
/ Move the selection.
Copy the selection and dismiss.
⌘↩Copy and keep the palette open — grab several things from one capture.
⌘1⌘9Copy the Nth-ranked match and dismiss.
escDismiss without copying.
clickSelect a row; click the selected row again to copy.
Tip — linger to read the whole thing. Rows that are longer than they can show truncate with an ellipsis. Rest the pointer on one (or arrow onto it) for a second and it expands in place at a smaller font, so you can read the full line before you copy it.
The important part

How matching works

Matching is word-confined

A word is anything separated by whitespace. Your query fuzzy-matches inside a single word — the characters you type can be non-contiguous (inv matches Invoice, dcu matches document) — but a match never spans two words: it will not match Is there by borrowing one letter from each.

Spaces mean AND

inv 44 matches lines that have a word matching inv and a word matching 44 — in any order, anywhere on the line.

Ranking

Ranking favors matches at word starts, contiguous runs of your typed characters, and camelCase boundaries. The best match is always on top, so the fastest workflow is: type until the thing you want is #1, then .

The clever bit

What gets copied

The line you see is context; the copy is the payload — shown at full brightness while the rest of the line dims.

⌘1 Total due: $1,204.00 Preview — invoice.pdf
Query total → the bright payload is the word Total; copies just that. The dim remainder is context.
QueryCopies
Empty (browsing)The whole line.
Plain term(s)Just the matched word(s). total vs Total due: $1,204.00 copies Total. Attached punctuation comes along: 44 vs Invoice #4471 copies #4471. Multiple terms copy each matched word, space-separated.
.* chunksThe whole span — see below.
Power move

Selecting a span with .*

word1.*word2 selects a chunk: it matches when a word fuzzy-matches word1 and a later word on the same line fuzzy-matches word2, and the copy is everything from the first word through the last, verbatim.

line:   npm ERR! Could not resolve dependency
query:  err.*dep
copies: ERR! Could not resolve dependency

Rules of thumb

  • It crosses lines. A chunk can start on one line and end on a later one (within the same window; spans never mix windows). The copy keeps the line breaks, and the row shows a where each break is. Multi-line rows truncate in the middle so you see both ends; linger to expand the whole thing.
  • Order matters. Like a regex, .* reads left to right (and top to bottom). dep.*err does not match the line above.
  • Nearest end wins. Each place the first word matches starts a chunk, completed by the nearest following match of the last word. Overlapping chunks ending at the same word collapse to the tightest one.
  • The ends are two different words. A chunk needs a first word and a last word, so both terms landing in the same word doesn't count.
  • It chains. from.*via.*to works — middle terms must match words between the ends, in order.
  • It composes with spaces. err.*not npm requires the err…not chunk and a word matching npm within the chunk's lines; both end up in the copy.
  • While you're still typing. err. may momentarily match nothing (the dot is literal until the * arrives); err.* behaves like plain err.
Cheat sheet

Everyday recipes

You wantType
An ID, hash, or tracking numbera few of its characters
A whole error messagefirst word .* last word
The amount off an invoice$ or the first digits
A URL from a slidehttp (or htt.* for the full word)
The whole line, but found by keywordkeyword to find it, esc, then arrow to it with an empty query

That last one is the honest workaround for “I searched to find the line but want all of it” — with a query active, copies take the payload, not the line.

Want to try it live? The home page has a working, miniaturized palette — type inv, or err.*dep, and press .
Say hello

Feedback & bug reports

Textracto is a tiny tool made by one person, and real feedback shapes it. Found a bug, hit a window it couldn't read, or wish it did one more thing? Email armand.halbert+textracto@gmail.com — it goes straight to me.

  • Bugs: what you captured, what you expected, and what happened. A screenshot of the palette helps.
  • Ideas: the thing you wanted to grab and couldn't — those requests drive the roadmap.
  • Your setup: your macOS version, so I can reproduce it.