glint
A modeless terminal markdown editor with live styling — a Bubble Tea
TUI built for a notes vault. Type in a centered iA-Writer-style writing canvas
with soft-wrapping and live markdown coloring, flip to a Glamour read
preview, fuzzy-find notes with a live preview pane, and theme it to match your
terminal (Flexoki light/dark + charm). Open any file, jump to today's daily
note, or start a fresh document from anywhere. Code files open with calm,
minimal syntax highlighting (strings, comments, and numbers only) so glint works
as a quick $EDITOR too. Prose gets light inline spellcheck — a red curly
underline under obvious typos, with one-key suggestions.
Install
brew tap humdrum/tap https://codex.humdrum.me/git/homebrew-tap.git
brew trust humdrum/tap # Homebrew gates third-party taps
brew install glint
Upgrade later:
brew update && brew upgrade glint
Usage
glint # fuzzy picker over the current directory
glint notes.md # open a file
glint -n [name] # new note in the current dir (-n -i → inbox, -n -v → vault)
glint -p [file] # open straight into the read preview (glow-style reader)
glint -e <file> # export a file to printable house-style HTML and open it
glint -t # today's daily note
glint -d # browse the daily-notes folder
glint -v # fuzzy picker over your vault, from anywhere
glint -i # fuzzy picker over your inbox
glint -c # interactive config walkthrough
glint -h # help: all commands and keys
glint --version # print version
Every command flag accepts a short letter or the full word, with one or two
dashes: -n / --n / -new / --new, -t / --today, -v / --vault, etc.
Keys
| Key | Action |
|---|---|
type / arrows / Enter / Backspace / Del |
edit and move (Up/Down move by visual line) |
Enter on a list item |
continue the list (-/*/+, N./N), - [ ] checkboxes; numbers increment); empty item exits the list |
Tab / Shift+Tab |
indent / outdent the current list item |
Alt+↑ / Alt+↓ |
move the current line up / down (reorder list items; the cursor follows, so repeats walk it; one undo step per move) |
Alt+x · click the box |
toggle the checkbox on the current line - [ ] ⟷ - [x], including checkboxes inside > blockquotes/callouts (no-op off a checkbox line; key works with the cursor anywhere on the line) |
| mouse click | move the cursor |
| mouse drag | select text (press to anchor, drag to extend, release to keep) |
| mouse wheel | scroll the view |
Home / End |
smart Home (first non-blank, then column 0) / end of line |
Ctrl+Home / Ctrl+End |
top / bottom of the document (Ctrl+↑ / Ctrl+↓ do the same, but macOS binds those to Mission Control — see below) |
type ( [ ` with no selection |
auto-closes the pair with the cursor inside; type the closer over it to step past |
Shift+arrows · Shift+Home/End |
select text (Ctrl+Shift+←/→ selects by word) |
Ctrl+C / Ctrl+X / Ctrl+V |
copy / cut / paste (system clipboard); pasting a URL over a selection makes a [selection](url) link |
Alt+s / Alt+i / Alt+c / Alt+k |
wrap the selection: bold ** · italic _ · code ` · link [sel]() (toggles off if already wrapped; no selection inserts the empty pair) |
type * _ ` [ ( { < " ' with a selection |
surround the selection with that punctuation (repeat to nest, e.g. *→** for bold) |
Alt+← / Alt+→ |
move by word (also Alt+b / Alt+f) |
Alt+Backspace / Ctrl+W |
delete the word before the cursor (Alt+d deletes the word after) |
Ctrl+U / Ctrl+K |
delete to start / end of line |
Ctrl+Z / Ctrl+Y |
undo / redo |
Ctrl+S |
save (an unnamed buffer prompts for a name → inbox) |
Ctrl+E |
export a printable HTML document and open it in the browser → Print → Save as PDF (see Export) |
Ctrl+P |
toggle the Glamour read preview |
Ctrl+F |
fuzzy file picker (with live preview); prefix the query with / to full-text search note contents — results show file:line text and open at the match |
Ctrl+G |
find in document (Enter/↓ next, Shift+Tab/↑ prev, Esc close) |
Ctrl+L |
go to line (type a number, Enter to jump, Esc to cancel) |
Ctrl+D |
today's daily note |
Ctrl+N |
new note in the current directory (a typed picker query becomes its name) |
Ctrl+B |
new note in the inbox |
Ctrl+T |
cycle theme (flexoki-light → flexoki-dark → charm) |
Alt+; · click |
proofing popup on the misspelled word or grammar span at the cursor (or click an underlined word): pick a suggestion / grammar fix 1–9, a add to dictionary, i ignore, t toggle spellcheck, g toggle grammar, Esc close |
Ctrl+/ |
toggle the in-editor help overlay (keys + commands) |
Ctrl+Q |
quit (press twice if there are unsaved changes) |
Esc |
clear the selection, or close find / back to the editor |
Using Cmd+arrows on macOS
Terminals speak ANSI escape sequences, which have no concept of a Cmd (Super)
key — a terminal app never sees Cmd+←, only whatever bytes the terminal chose
to send for it. glint therefore can't bind Cmd itself; your terminal has to
translate. Every key in the table above works out of the box with no config.
To get the macOS muscle memory (Cmd+←/→ for line edges, Cmd+↑/↓ for document
edges), map the four sequences glint listens for:
| Cmd key | Sequence to send | glint sees |
|---|---|---|
Cmd+← |
ESC [ H |
Home |
Cmd+→ |
ESC [ F |
End |
Cmd+↑ |
ESC [ 1;5H |
Ctrl+Home |
Cmd+↓ |
ESC [ 1;5F |
Ctrl+End |
Ghostty — in ~/.config/ghostty/config:
keybind = cmd+left=csi:H
keybind = cmd+right=csi:F
keybind = cmd+up=csi:1;5H
keybind = cmd+down=csi:1;5F
iTerm2 — Settings → Profiles → Keys → Key Mappings, add each as Send Escape
Sequence with the text after the ESC ([H, [F, [1;5H, [1;5F).
Apple Terminal — Settings → Profiles → Keyboard → +, same escape sequences.
On a Mac, Ctrl+↑ and Ctrl+↓ never reach any terminal app — macOS claims them
for Mission Control (System Settings → Keyboard → Keyboard Shortcuts → Mission
Control). Use Ctrl+Home/Ctrl+End, or the Cmd+↑/Cmd+↓ mapping above.
Unsure what your terminal actually sends? glint --keys prints the key glint
decodes for each press — press Cmd+↑ and see whether anything arrives.
Configuration
Run glint -c for an interactive walkthrough that writes the file for you
(no hand-editing, daily-format presets instead of raw Go layouts). The settings
live in ~/.config/glint/config.toml (all keys optional):
vault_dir = "" # the vault `glint -v` opens from anywhere (e.g. "~/Notes"); unset = current dir
inbox_dir = "" # where `glint -n -i` / save-as land; "" = working dir, relative = under it
daily_subdir = "Daily" # daily notes live in <vault>/<daily_subdir>/ (absolute path used as-is)
daily_format = "2006-01-02" # Go time layout for daily-note filenames
theme = "auto" # auto | flexoki-light | flexoki-dark | charm (auto detects macOS appearance)
glamour_style = "" # override the preview style; "" follows the theme
spellcheck = "auto" # auto | on | off (auto = on for prose/notes, off for code files)
grammar = "auto" # auto | on | off (Harper; auto = on when harper-ls is installed)
font_display = "" # PDF export heading/cover font stack; "" = Georgia serif
font_body = "" # PDF export body font stack; "" = system-ui sans
font_mono = "" # PDF export code font stack; "" = ui-monospace
Two roots. Bare glint, glint -n, and -d operate on the working
directory — the folder you launched from (or $GLINT_VAULT if set), so glint
works in whatever repo you're in. glint -v opens the picker on your
configured vault_dir from anywhere — set it to your notes vault to reach it
without cd-ing there.
Export (PDF)
Ctrl+E exports the current buffer to a clean, printable document in the Humdrum
house style and opens it in your default browser — there you hit Print → Save
as PDF. No external converter is required: the export is a single
self-contained .html file (the house stylesheet and your rendered Markdown are
baked in), written next to the source file (note.md → note.html; an unnamed
buffer lands in the temp dir). If the browser can't be opened automatically,
glint prints the file path so you can open it yourself — the export still
succeeds.
The print layout follows the kit's conventions: a leading # Title becomes a
centered cover page, headings start new pages, {.page-break} on a heading
forces a break, the page is US Letter with 1in margins, and printing collapses
to black-on-white.
The stylesheet (doc.css) is vendored into the
binary via go:embed, so a brew install glint on any machine has everything it
needs. The kit's licensed display/body/mono faces are not bundled — the
export ships portable open/system defaults (Georgia / system-ui / ui-monospace)
and lets you point the three font slots at any fonts you have via the
font_display / font_body / font_mono config keys above.
Fonts are embedded at export time. Set a custom font and glint finds it in
your font directories (~/Library/Fonts, /Library/Fonts), reads the matching
faces (regular + bold, roman + italic), and inlines them as base64 @font-face
in the exported HTML. This is required because WebKit browsers (Safari, Orion)
refuse to render locally-installed user fonts referenced only by name. A font
glint can't find on disk falls back to a plain name reference (which still works
in Chrome/Firefox), and nothing licensed is ever baked into the binary — it
embeds only the fonts you configured and have installed.
To refresh the embedded style after the kit changes, run
internal/export/assets/sync.sh.
Themes
Three palettes, every span explicitly colored so text stays readable on light
and dark terminals: flexoki-light, flexoki-dark, and charm. auto
picks light or dark from the macOS system appearance; Ctrl+T cycles live. The
read preview and the whole canvas background follow the active theme.
Spellcheck
Misspelled prose gets a calm red curly underline (undercurl). It's deliberately light — an embedded ~60k common-English dictionary catches obvious typos without the false positives of a heavy morphological checker. Code fences, inline code, URLs, wikilinks, link targets, and frontmatter are never flagged, and recognized code files are skipped entirely (same extension routing as syntax highlighting).
Alt+; (or clicking an underlined word) opens a popup with up to five
suggestions ranked by edit distance — pick one with 1–9 to replace in place,
a to add the word to your personal dictionary, i to ignore it for the
session, t to toggle spellcheck off and on, or g to toggle grammar checking
(Alt+; opens a toggle-only popup when no word is flagged). The personal
dictionary is a plain, hand-editable file at
~/.config/glint/dict.txt (one word per line). Set spellcheck = off to disable
it, or on to force it on.
Grammar (Harper)
Grammar checking is optional and off unless you opt in. glint speaks LSP to
Harper's harper-ls in a subprocess, so the
build stays pure-Go with no new linked dependency. Install it and glint picks it
up automatically:
brew install harper
Grammar issues get a green curly underline, distinct from spellcheck's red. When a word is both misspelled and inside a grammar span, the red spelling underline wins. Diagnostics refresh as you type (debounced) without blocking the UI.
Alt+; on a grammar span (or clicking it) opens the proofing popup with
Harper's fixes as the numbered rows — pick one to rewrite the text — plus
i Ignore, which hides that hint for the rest of the session. (Harper's own
ignore command is a no-op over LSP, so glint keeps the ignore list itself; it
resets on the next launch.) Toggle grammar at runtime with g in the same popup,
and control it with grammar = auto | on | off (auto = on when harper-ls is on
your PATH). With no harper-ls installed, grammar is silently inert and glint
behaves exactly as before.
TK markers
The journalism TK placeholder — "to come", the thing you'll fill in later —
renders as a bold filled badge so unfinished spots are impossible to miss. TK,
tk, or a TKTK run is matched as a whole word, case-insensitive, so real
words like catkin, Atkins, and outkast are never touched. Prose only —
code files, code spans, URLs, and frontmatter are skipped. Always on, no config.
The curly underline uses the 4:3 SGR underline-style and 58 underline-color
codes — supported by Ghostty, kitty, WezTerm, foot, and recent VTE terminals.
Terminals without them degrade to a straight underline or none. Inside tmux,
enable passthrough so the styles reach the terminal:
set -as terminal-features ',*:usstyle'
License
glint — Copyright (C) 2026 humdrum-tiv.
Free software under the GNU Affero General Public License v3.0 (or, at your option, any later version). You may use, study, share, and modify it; any distributed derivative — or modified version offered to users over a network — must also be AGPL-licensed with source available. It comes with no warranty. See LICENSE for the full terms.