This guide takes a completely fresh macOS machine — no developer tools, no Homebrew, no Go, no git — to a fully working vimango with spell checking (hunspell), inline images in the terminal (including HEIC), the native WebKit preview window, and full-text search.
Every step includes a verification command so you can confirm it worked before moving on. Follow the steps in order — later steps assume earlier ones.
Time estimate: 30–60 minutes, most of it waiting for downloads and compiles.
Already have a partially set-up machine? Skim each step's verify command; skip steps that already pass. The build-from-source details live in INSTALL.md — this guide covers the same ground plus the from-zero bootstrapping around it.
macOS ships with stubs for git and clang that prompt you to install the
real tools. Kick that off directly:
xcode-select --installA dialog appears — click Install and wait (several minutes; it's a ~1 GB download). You do not need full Xcode.
Verify:
git --version # e.g. git version 2.x
clang --version # e.g. Apple clang ...Both should print versions instead of prompting to install.
Install per https://brew.sh:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"Important: at the end, the installer prints two eval lines under
"Next steps" — run them, then also add them to your shell profile so brew
is on PATH in every new terminal. On Apple Silicon that is:
echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.zprofile
eval "$(/opt/homebrew/bin/brew shellenv)"Verify:
brew --version
brew --prefixbrew --prefix matters for later steps:
/opt/homebrew→ Apple Silicon (M1/M2/M3/M4). All paths in this guide match as written./usr/local→ Intel Mac. Two files hardcode Apple Silicon paths and need a one-line edit each — flagged inline below at steps 7 and 9.
vimango renders images inside the terminal using the kitty graphics protocol (unicode placeholders), and its markdown headings use kitty's text-sizing protocol. The built-in Terminal.app does not support either — notes will work but images won't render.
Install one of:
brew install --cask kitty # reference implementation of the protocol
# or
brew install --cask ghostty # also supports kitty graphics; what the author usesOpen the one you installed (Cmd-Space, type its name) and do the rest of this guide inside it — the final smoke test displays an image.
First launch of an unsigned-by-App-Store app may show a Gatekeeper prompt; approve it in System Settings → Privacy & Security if needed.
brew install goVerify:
go version # needs 1.26 or later (the workspace file pins go 1.26.1)Homebrew installs the current release, which satisfies this.
vimango depends on a personal fork of the glamour markdown renderer (it
carries kitty text-sizing helpers that upstream doesn't have). The fork must
sit next to vimango, wired in by a go.work file that is deliberately not
checked in. A fresh clone will not compile without this step.
mkdir -p ~/code && cd ~/code # or wherever you keep source
git clone https://github.com/slzatz/vimango.git
git clone https://github.com/slzatz/glamour.gitCreate the workspace file inside vimango:
cd vimango
cat > go.work <<'EOF'
go 1.26.1
use (
.
../glamour
)
EOFVerify:
ls ../glamour/go.mod go.work # both files must existIf you later see
undefined: ansi.DecodeKittyTextSizeMarkersorundefined: makeRawwhen building, this step was skipped orgo.workpoints at the wrong path.
brew install pkg-config hunspell ncurses gettext libheifWhat each is for:
| Package | Used by |
|---|---|
pkg-config |
locating libheif when building the HEIC worker |
hunspell |
spell checking (the library; dictionaries are step 7) |
ncurses, gettext |
linking libvim and the vimango binary |
libheif |
decoding HEIC/HEIF images (iPhone photos) |
Verify:
pkg-config --modversion libheif # prints a version, e.g. 1.23.x
brew list hunspell >/dev/null && echo hunspell OKHomebrew installs the hunspell library but no dictionaries, and vimango
looks for them at a fixed path: /usr/share/hunspell/en_US.aff and
/usr/share/hunspell/en_US.dic. Fetch the standard US-English dictionary from
the LibreOffice project and put it there:
sudo mkdir -p /usr/share/hunspell
sudo curl -fsSL -o /usr/share/hunspell/en_US.aff \
https://raw.githubusercontent.com/LibreOffice/dictionaries/master/en/en_US.aff
sudo curl -fsSL -o /usr/share/hunspell/en_US.dic \
https://raw.githubusercontent.com/LibreOffice/dictionaries/master/en/en_US.dicVerify:
ls -la /usr/share/hunspell/ # both files present and non-trivial in sizeIf the dictionaries are absent vimango still builds and runs — spell check just silently reports every word as correct.
Intel Macs only: the Go binding hardcodes Apple Silicon include/lib paths. Edit
hunspell/hunspell.goand change/opt/homebrew/include→/usr/local/includeand/opt/homebrew/lib→/usr/local/libin the two#cgo darwinlines.
vimango's editor is vim, provided by a static library built from onivim/libvim. It's architecture-specific, so each machine builds its own copy. A script does everything (detects your Homebrew prefix, clones libvim next to vimango, builds, and copies the result into the vimango root):
cd ~/code/vimango # adjust if you cloned elsewhere
./scripts/build-libvim.shThis takes a few minutes of C compilation.
Verify:
ls -la libvim.a # sits in the vimango root, next to go.modIf the script fails partway, the manual recipe and an explanation of the
-Wno-errorworkaround for newer clang versions are in INSTALL.md §4.
These run as subprocesses so that crashes in native image/WebKit libraries can't take down vimango. Both are optional-but-recommended; both land in the vimango root.
cd cmd/heic_worker
CGO_ENABLED=1 go build -o ../../heic_worker
cd ../..If you get cgo type errors like
cannot use uint32(compression) ... as _Ctype_heif_compression_format: the Go binding version must match the libheif Homebrew installed. Fix withgo get github.com/strukturag/libheif@v<version>where<version>is whatpkg-config --modversion libheifprints, then rebuild. A warning aboutduplicate libraries: '-lheif'is harmless.
cd cmd/webview_worker
CGO_ENABLED=1 go build -o ../../webview_worker
cd ../..Verify:
ls -la heic_worker webview_workerIf either is missing vimango still works: HEIC images fall back to a Python path (step 10) or don't render; the web preview opens in your browser instead of its own window.
A second, pure-Python HEIC decode path used when heic_worker can't handle a
file. macOS's python3 (installed with the Command Line Tools) is fine:
python3 -m venv .venv
.venv/bin/pip install Pillow pillow-heifSkip freely — it degrades gracefully.
From the vimango root:
CGO_ENABLED=1 go build --tags="fts5,cgo"The tags are not optional. fts5 compiles SQLite's full-text-search
module into the binary — without it vimango starts but fails on every note
save with no such module: fts5. CGO is required because libvim is the only
vim engine.
Verify:
ls -la vimango
./vimango --help | head -5Generate the config file and local databases:
./vimango --initThis writes config.json and creates vimango.db (notes) and
fts5_vimango.db (search index). Then, inside kitty or Ghostty, from the
vimango directory:
./vimangoYou should see the organizer (note list) on the left and a note pane on the right. Basics to try:
a— create a new note title, type it, press Enter, then Enter again to edit the note body in vim;Escthen:xsaves and returns.:help— command list./— search.:q— quit.
Image smoke test: create a note containing
 (that file ships in the repo)
and view it — the image should render inline in the terminal.
Always run vimango from its own directory. It resolves
config.json, the style files, both databases,.venv, and the worker binaries relative to the current directory. A shell alias keeps that convenient:echo 'alias vimango="cd ~/code/vimango && ./vimango"' >> ~/.zshrc
Configured in config.json (created by --init; it's .gitignored because
it can hold secrets):
- Google Drive images — render
markdown from your Drive. Needs a Google Cloud OAuth credential; full walkthrough in README.md → Google Drive Setup. - Remote sync (PostgreSQL) — sync notes across machines. Fill in the
postgresblock; leave it empty to stay local-only. vimango works fully offline; connectivity is only checked when you run a sync. - Claude deep research — stores research results as notes. Add
"claude": { "api_key": "..." }or setVIMANGO_CLAUDE_API_KEY.
cd ~/code/vimango
git pull
git -C ../glamour pull # keep the fork in step
CGO_ENABLED=1 go build --tags="fts5,cgo" # ALWAYS with the tagslibvim.a and the workers only need rebuilding if libvim or their
dependencies change (e.g. after brew upgrade libheif, rebuild
heic_worker; bump the binding version first if cgo type errors appear —
see step 9).
| Symptom | Cause | Fix |
|---|---|---|
xcrun: error: invalid active developer path |
Command Line Tools missing | step 1 |
brew: command not found in a new terminal |
shellenv not in ~/.zprofile |
step 2 |
undefined: ansi.DecodeKittyTextSizeMarkers / undefined: makeRaw |
glamour fork or go.work missing |
step 5 |
hunspell/hunspell.h: file not found |
hunspell not installed (or Intel paths) | steps 6–7 |
| Spell check accepts everything | dictionaries missing from /usr/share/hunspell |
step 7 |
linker can't find libvim.a |
not built, or go build not run from vimango root |
step 8 |
exec: "pkg-config": executable file not found |
pkg-config missing | step 6 |
cannot use uint32(...) as _Ctype_heif_* |
libheif binding/library version mismatch | step 9 note |
no such module: fts5 when saving a note |
built without --tags="fts5,cgo" |
step 11 |
| Images don't render, notes otherwise fine | terminal lacks kitty graphics (e.g. Terminal.app) | step 3 |
| HEIC images specifically don't render | heic_worker missing/wrong arch |
step 9 (non-fatal) |
| Web preview opens in browser, not a window | webview_worker missing |
step 9 (non-fatal) |
config.json / database errors at startup |
first-run init never done, or wrong CWD | step 12 |