A text editor that looks like a printed page, not a terminal application.
curl -sSL https://raw.githubusercontent.com/davidemerson/issy/main/install.sh | shOne line. Drops issy at ~/.local/bin/issy, verifies an Ed25519 signature over the release manifest, seeds ~/.issyrc with commented defaults if you don't already have one, and wires up the opt-in auto-update path. Works on Linux (amd64/arm64) and OpenBSD amd64 with a prebuilt binary; macOS falls through to a zig build from source. Full install options →
Built in Zig with zero external dependencies. Single binary, around 470KB in ReleaseSafe. Gap-buffer text storage, syntax highlighting for 17 languages (including TeX/LaTeX), PDF export with real TTF/OTF font embedding, multi-cursors, undo/redo, incremental search, keyboard and mouse selection.
| Default | Paper |
|---|---|
![]() |
![]() |
Both follow the same rule: only a couple of token types get real chromatic contrast so the eye parses structure through gentle luminance shifts instead of a rainbow. See DESIGN.md for the full visual design notes.
Ctrl+P renders the current buffer to a real PDF 1.4 file with TTF/OTF font embedding, a separate ink-on-paper print theme, headers, and automatic page breaks. No external dependencies, no temporary PostScript — the PDF writer is hand-rolled in Zig.
Ctrl+D selects the word under the cursor and adds a cursor at the next occurrence. Press it again to keep adding. Every edit — typing, backspace, delete, paste — applies to all cursors simultaneously, and Ctrl+Z undoes the whole multi-cursor tick as a single step.
Ctrl+F enters search mode and each keystroke re-runs the search, jumping the cursor to the first live match. Ctrl+G walks to the next match; Escape cancels and returns the cursor to where it started.
Shift + arrow extends a selection one character at a time; Ctrl+Shift+Left/Ctrl+Shift+Right grow it a word at a time. Click, double-click (select word), and triple-click (select line) also work, as does shift+click to extend from the existing anchor. Drag past the viewport edge and the view autoscrolls.
Ctrl+O opens the file prompt seeded with the current directory. Type a partial directory or filename and press Tab to complete against what's on disk.
curl -sSL https://raw.githubusercontent.com/davidemerson/issy/main/install.sh | shFlags:
| Flag | Default | Purpose |
|---|---|---|
--prefix DIR |
$HOME/.local/bin |
Target install directory |
--version VER |
latest |
Pin to a specific release |
--no-rc |
off | Skip seeding ~/.issyrc |
--help, -h |
— | Show usage |
Prefer to inspect the script first?
curl -sSL https://raw.githubusercontent.com/davidemerson/issy/main/install.sh -o install.sh
less install.sh
sh install.shHow it decides what to do. On Linux amd64/arm64 and OpenBSD amd64 the installer downloads a prebuilt binary, verifies an Ed25519 signature over sha256sums.txt against a public key baked into the script, then verifies the binary's SHA-256 against that manifest, and finally installs with install -m 0755. On macOS (and any platform without a prebuilt) it falls through to a source build: clones the repo, runs zig build -Doptimize=ReleaseSafe, and installs the resulting binary. Source builds require Zig 0.15.2+ on PATH.
brew tap davidemerson/issy https://github.com/davidemerson/issy
brew install issyUpgrade: brew upgrade issy. The formula tracks tagged releases (vX.Y.Z), so this is the same one-liner you'd use for any Homebrew package — no --fetch-HEAD, no uninstall+reinstall dance. CI maintains the formula's url + sha256 automatically on every tag push (see .github/workflows/ci.yml → release-tag job).
Want the bleeding edge between releases?
brew install --HEAD issy # build from main
brew upgrade --fetch-HEAD issyThe curl installer also works on macOS — use whichever you prefer.
The curl installer downloads a prebuilt amd64 binary. Builds are verified on every push by a real OpenBSD 7.8 amd64 VM in CI (openbsd-test job, see .github/workflows/ci.yml) — full unit + integration suite must pass on OpenBSD before main accepts a merge. An editors/issy ports submission is in flight; when it lands, pkg_add issy will be the preferred path.
Building from source on OpenBSD: pkg_add zig then zig build -Doptimize=ReleaseSafe. bash and expect (also via pkg_add) are needed if you want to run the integration test suite.
Requires Zig 0.15.2+.
git clone https://github.com/davidemerson/issy
cd issy
zig build -Doptimize=ReleaseSafe
install -m 0755 zig-out/bin/issy ~/.local/bin/issyOther build.zig entry points:
zig build # debug build
zig build test # run all tests
zig build cross # build all cross-compile targetsCross-compile targets: x86_64-linux-gnu, aarch64-linux-gnu, x86_64-macos, aarch64-macos, x86_64-openbsd.
issy [options] [file[:line]]
issy main.zig
issy src/editor.zig:42 # open at line 42
issy newdoc.md # start a new file at that path
issy # empty buffer| Flag | Description |
|---|---|
--version, -v |
Print version and exit |
--help, -h |
Print usage and exit |
--config FILE |
Use a specific config file |
--theme NAME |
Override theme (default, paper) |
--font PATH |
TTF/OTF font for PDF output |
--no-config |
Skip loading config file |
--print FILE |
Export to PDF and exit (no TUI) |
--rollback |
Swap in the previous binary (if auto-update has run) and exit |
issy --font /path/to/font.ttf --print output.pdf source.c| Key | Action |
|---|---|
| Ctrl+S | Save |
| Ctrl+Q | Quit (on unsaved changes, press Enter or Ctrl+Q again to discard; Escape cancels) |
| Ctrl+Z | Undo (typing runs coalesce within 500ms — one step per word) |
| Ctrl+Y | Redo |
| Ctrl+C | Copy selection (also pushes to OS clipboard via OSC 52) |
| Ctrl+X | Cut selection (also pushes to OS clipboard via OSC 52) |
| Ctrl+V | Paste from internal clipboard (OS paste comes via terminal paste: Cmd+V / Ctrl+Shift+V) |
| Ctrl+A | Select all |
| Tab | Insert tab or spaces (per config) |
| Enter | Newline with auto-indent |
Typing, Tab, or Enter while a selection is active replaces the selection. Terminal pastes use bracketed paste (DECSET 2004): during a paste, auto-indent is suppressed and tabs land as literal \t, so already-indented content comes in verbatim instead of compounding.
| Key | Action |
|---|---|
| Arrow keys | Move cursor |
| Ctrl+Left / Ctrl+Right | Jump by word |
| Home / End | Start / end of line |
| Page Up / Down | Scroll by page |
| Ctrl+L | Go to line (prompt for a line number) |
| Mouse scroll | Scroll viewport (cursor stays) |
| Mouse click | Position cursor |
| Double-click | Select word |
| Triple-click | Select line |
| Key | Action |
|---|---|
| Shift + Arrow | Extend selection by character |
| Ctrl+Shift + Left/Right | Extend selection by word |
| Shift + Home / End | Extend to line start / end |
| Shift + Click | Extend selection to click position |
| Click + drag | Extend selection (drag past edge to autoscroll) |
| Escape | Clear selection and extra cursors |
| Key | Action |
|---|---|
| Ctrl+F | Incremental search (Escape cancels, Enter confirms) |
| Ctrl+G | Find next match |
| Ctrl+H | Search and replace (Tab switches fields, Enter replaces next, Ctrl+A replaces all) |
| Key | Action |
|---|---|
| Ctrl+O | Open file (on unsaved changes, prompts for confirmation) |
| Ctrl+N | New empty buffer (on unsaved changes, prompts for confirmation) |
| Ctrl+P | Export to PDF (requires font_file in config or --font) |
| Ctrl+R | Reload file from disk |
| Ctrl+W | Same as Ctrl+Q |
| Key | Action |
|---|---|
| Ctrl+D | Select word under cursor; press again to add cursor at next occurrence |
| Escape | Clear all extra cursors and selection |
All editing operations apply to every cursor simultaneously, and Ctrl+Z undoes the whole tick.
| Key | Action |
|---|---|
| Ctrl+/ | Show keybindings overlay |
| F1 | Same as Ctrl+/ |
The installer seeds ~/.issyrc on first run with every setting commented out, so you can see what's available and uncomment what you want. Unknown keys are ignored; missing keys fall back to compiled-in defaults.
See CONFIGURATION.md for the full reference, or copy examples/issyrc as a starting point. Quick taste:
tab_width = 4
expand_tabs = true
line_numbers = true
right_margin = 100
cursor_style = bar
font_file = "/path/to/font.ttf"
[theme.paper]
Quit a file and issy remembers the cursor position at ~/.cache/issy/positions.txt; reopening the same file restores the caret automatically. Positions are keyed by absolute path, capped at 300 entries with an LRU-ish "newest on top" layout, and lose gracefully (corrupt file or missing HOME is a silent no-op). Explicit file:line on the command line always wins over the saved position.
C, C++, Zig, Python, JavaScript, TypeScript, Rust, Go, Shell, HTML, CSS, JSON, YAML, TOML, Makefile, Markdown, TeX/LaTeX. Language is detected by file extension.
Ctrl+P exports the current buffer to a PDF 1.4 file alongside it (same directory, .pdf suffix). --print output.pdf source.c does the same headlessly without opening the TUI. Both require a TTF or OTF font file via font_file in config or --font on the command line. PDF output uses a print theme with colors tuned for ink on white paper — it never inherits the TUI theme.
Recommended fonts: Berkeley Mono, Iosevka, JetBrains Mono, Commit Mono.
Release builds check the latest GitHub release on startup via a detached background worker, so the editor itself never blocks on the network. If the release's commit SHA differs from the one the running binary was built from, the footer shows update available: <sha>.
Opt into automatic download and in-session re-exec by setting autoupdate = true in ~/.issyrc. With auto-apply on, the worker downloads the signed manifest, verifies the Ed25519 signature against src/update_key.zig, hashes the platform binary against the manifest, stages it at ~/.cache/issy/issy.staged, and atomically swaps it over the running binary the next time the buffer is clean and the editor has been idle for 60 seconds — then execve()s the new binary with a one-shot --resume record that restores the cursor position. Rollback any time with issy --rollback.
Dev builds skip the check entirely; only ReleaseSafe builds produced by CI participate. Root-owned installs silently fall back to notify-only (the worker refuses to overwrite root-owned binaries).
See ARCHITECTURE.md for the full flow, the cache layout, and the signing-key bootstrap procedure for forks.
- ARCHITECTURE.md — tour of the source code and the major subsystems
zig build test— 789-test unit suite (gap buffer, Unicode, tokenizer, editor operations, mouse/selection, etc.)bash tests/run_tests.sh— end-to-end integration suite viaexpect, launches the real binary in a PTYman ./issy.1— man page
BSD 3-Clause






