caretline

caretline

caretline is a text-editing engine and a terminal text editor. The engine (the caretline crate, caretline-next in this repo) puts Helix’s editing model (a rope, multi-range selections, transactions, an undo tree, grapheme-correct motion and soft wrap) inside a strict Elm architecture. The whole editor is one serializable State. Every input is a Msg. A pure update function applies a message and returns Effects for the outside world, and a pure view function turns the state into a grid of cells. The engine does no I/O and has no terminal code, so you can drive it from a terminal, a test, a script or another program, and replay any session exactly. The caretline binary (caretline-app) is the interactive editor and a headless tool built on top.

$ caretline notes.md                                   # edit a file
$ caretline --new-state notes.md --size 40x6 > s.json  # capture a state
$ caretline --state s.json --keys '<d-down>Done.' --snapshot 40x6

What it covers

AreaStatusNotes
Grapheme-correct editingYesCarets never land inside an emoji, a ZWJ sequence, a flag or a combining accent
Wide charactersYesCJK and emoji take two cells, using Helix’s width table (unicode-width 0.1.12)
SelectionsYesAnchor and head per range, macOS text-field collapse rules
Multi-range selectionsEngine onlyupdate edits every range. No key creates extra ranges yet, but a state or a Msg sequence can
Transactions with position mappingYesEvery edit is a Helix Transaction; selections map through its changes
Undo and redoYesHelix’s revision tree. A typing run within 1.5 s is one step (up to 256 characters, breaking at a word past 128). Undo restores text and selection
Soft wrapYesVisual-line motion with a goal column, page up and down, Home/End per visual row
No-wrap modeYesconfig.soft_wrap = false scrolls sideways
ClipboardYes, as effectscopy/cut return clipboard_set; the runtime talks to the system clipboard
SavingYes, as effectssave returns write_file; the runtime writes and answers saved or save_failed
MouseYesClick, shift-click, drag and wheel, as click and scroll messages
Serializable stateYesState round-trips through JSON, history and goal column included
Deterministic replayYesA trace (state + messages) replays to the identical state and frame
Headless snapshotsYes--snapshot WxH as plain text or ANSI
State protocol (serve, --listen, send)YesDrive a headless engine or a live editor over JSON lines. See protocol.md
Syntax highlighting, search, multiple buffersNot yet
Keys that add cursorsNot yet
Markdown structure (lists, tasks, blocks)Yes, in outline documentsBlock identity that survives edits, list and task rules, Markdown in and out. See outline.md. Folds and several views per document included

The layers

flowchart TB
    rope["ropey: the text as a rope"]
    helix["Helix model (vendored, MPL-2.0)<br/>Selection · Transaction · History · graphemes · DocumentFormatter"]
    elm["caretline-next<br/>State · Msg · update → Effects · view → Frame · keymap"]
    rope --> helix --> elm
    elm --> tty["Interactive terminal<br/><code>caretline FILE</code>"]
    elm --> cli["Headless CLI<br/><code>--keys --msgs --snapshot --replay</code>"]
    elm --> proto["State protocol<br/><code>serve</code> · <code>--listen</code> · <code>send</code>"]
    elm --> lib["Your program<br/>(Rust library or child process)"]

The engine owns the editing rules. A runtime owns everything else: the clock, the terminal, files and the clipboard.

The crates

caretline is published on crates.io as caretline (cargo add caretline, imported as caretline::). In this repository its crate is still named caretline-next, until the older engine below is removed.

Crate in this repoWhat it isUsed by
caretline-nextcaretline: plain text on Helix’s model, in the Elm architecture. Published as caretline. This documentation is about it.caretline-app, and thc-tui with THC_EDITOR=next
caretline-appThe caretline binary: the interactive editor and the headless tools
crates/caretlineAn older block editor, internal to thought-central’s TUI and going away. Not the published cratethc-tui (by default, for now)

caretline now has a block model (outline documents), folds and multiple views per document, and is replacing the older engine in thc’s TUI: with THC_EDITOR=next the TUI opens each page or journal day as one caretline outline document, behind the same editor API (crates/thc-tui/src/editor): thc’s per-note save state is keyed by each block’s mark, changes from the vault arrive as external changes, and saving makes the same block operations as before.

Where to go next

You want toRead
Understand how it worksarchitecture.md
Call it from Rustapi.md
Look up a message, an effect or a keymessages.md
Edit lists, tasks and blocksoutline.md
Use the caretline commandcli.md
Drive it over JSON linesprotocol.md
Put it inside your own appembedding.md
Write or debug a testtesting.md
Know how fast it is, and its limitsperformance.md

License

caretline (caretline-next here) is MIT, except src/helix/, which is vendored from Helix and stays under the Mozilla Public License 2.0 file by file. caretline-app is MIT. See embedding.md for what that means for you.

This page on GitHub: docs/caretline/README.md