skip to content

Terminal notes: Markdown files with folders, #tags, [[links]] and a mouse-first TUI.

Fast, minimal note-taking that never leaves your terminal. Plain .md on disk, live Markdown highlighting while you type, emacs or vim keys, and a headless JSON CLI so scripts and AI agents work the same vault.

installread the docsgithub ↗v1.3.0 · MIT · macOS & Linux

Interface preview

Left: folders, tags and the note list. Right: tabs and the editor. Everything is clickable; everything has a key.

Why tnotes

01 Files, not a database

One .md per note, folders are directories, tags live in the text. Atomic saves, conflict copies instead of silent overwrites, live reload. Sync with anything.

02 A real editor

Live highlighting, list continuation, checkbox toggling, word wrap, link and tag completion, backlinks. Emacs or vim keys. Mouse works everywhere.

03 Scriptable by design

tnotes ls --json gives every note with tags, links, backlinks and timestamps. Agents and cron jobs write; your open TUI updates live.

# Features

Most of what tnotes does is on screen at once. The numbers point at it; the manual below lists the rest.

  1. 1Folders are directoriesEvery root and subfolder in the tree is a real directory on disk.
  2. 2#tags, parsed from the textNested ones like #work/project too. Click one to filter.
  3. 3Fuzzy search/ searches titles and bodies (nucleo), combined with tag and folder filters.
  4. 4Tabs with a preview tabSelecting a note previews it; typing or enter pins it. 1–9 jumps.
  5. 5Tags live in the noteNo frontmatter, no sidecar file: the tag line is the tag.
  6. 6Lists that behaveenter continues, an empty item ends, tab nests, alt+x or a click toggles the box.
  7. 7[[Links]] with completionPopup after [[, alt+enter follows, a missing target is created, links are rewritten on rename.
  8. 8Live Markdown highlightingHeadings, emphasis, code, quotes, links and tags styled as you type; colour or mono.
  9. 9Autosave, atomic, never lostWritten after 500 ms idle to a temp file then renamed; a conflict copy instead of an overwrite; a failed save keeps the text under the state dir.
  10. 10BacklinksCount in the status bar, overlay on alt+enter, and a backlinks field in the CLI's JSON.
  11. 11Emacs or vim keysedtui underneath. Switch on the settings page (F2).

$ man tnotes

FILES

.md on disk
One file per note, named after its title. Atomic saves, name (conflict <time>).md instead of a silent overwrite, live reload when a file changes outside the app.
folders
Real directories. Every root has its own .Trash/ mirroring the layout, so u undoes and r restores.
#tags
Parsed from the text, nested #work/project included. Nothing else is written next to your notes.
sync
Any file sync: git, Syncthing, iCloud, Dropbox. Syncer conflict files are listed as ordinary notes.

EDITOR

[[links]]
Completion popup after [[, alt+enter or ctrl+click to follow, backlinks overlay, rewritten when a title changes.
- [ ] lists
enter continues, empty item ends, tab / shift+tab nest, alt+x toggles a checkbox.
highlighting
Headings, lists, checkboxes, code, links, emphasis, quotes, tags as you type. Colour or monochrome; the theme follows your terminal palette.
emacs | vim
edtui keys. Vim has normal and insert modes, . repeat and / search.
wrap, width
Word wrap at a configurable column, left or centred, drawn or terminal cursor.

NAVIGATION

tabs
One preview tab; editing pins it. 1–9 jumps, alt+. / alt+, cycle, ctrl+w closes.
/ search
Fuzzy over titles and bodies, combined with the tag and folder filter. s changes the sort.
mouse
Click selects, double-click pins, right-click opens a context menu, wheel scrolls, drag selects text and copies on release.
session
Open tabs, filter, sort, focus and folded tree sections come back on the next launch.
narrow
A single-panel layout on small terminals; ctrl+b toggles the sidebar.
F2
An in-app settings page that writes config.toml for you.

CLI

tnotes ls --json
Every note with id, path, title, folder, tags, links, backlinks, created, modified, preview. --tag, --folder, --limit.
search · cat
Fuzzy search, best first; cat prints a note, --json adds the text.
new · append · write
Create, add a line, replace the text; all take --stdin. A changed title renames the file and updates links.
trash · restore
To the root's .Trash/ and back. Nothing is deleted outright.
live
A running TUI picks CLI changes up; a tab with unsaved edits is never overwritten. No daemon, no API: files and JSON, which is all an agent needs.

# How it feels

Capture

ctrl+t, type a title, keep typing. Autosave after 500 ms of idle.

# Groceries#home- [ ] milk- [ ] coffee⏎- [ ] ▌

Link

Type [[, pick from the popup, alt+enter to jump. Rename a note and every link follows.

- [ ] Prep [[Meet▌         ┌────────────────┐         │ Meeting notes  │         │ Meetup ideas   │         └────────────────┘

Automate

Pipe text in from anywhere. The open TUI shows it the moment the file lands.

$ echo "- [ ] call Ann" \  | tnotes append weekly-plan --stdin$ tnotes search "berlin" --json \  | jq '.[0].path'"vault/weekly-plan.md"

# Built for AI agents

The CLI is the agent interface: no daemon, no API keys, no plugin, just files and JSON. Point an agent at your vault and let it read, search and write notes while you keep the TUI open. Edits show up live in both directions; a note with unsaved edits in the TUI is never overwritten.

links and backlinks in the JSON let an agent walk the note graph. Ids (root/sub/stem) are the same in every command.

agent recipes →
$ tnotes ls --json | jq '.[0]'{  "id": "vault/weekly-plan",  "path": "/home/me/notes/vault/weekly-plan.md",  "title": "Weekly plan",  "folder": "vault",  "tags": ["work", "planning"],  "links": ["tnotes roadmap", "Meeting notes"],  "backlinks": ["tnotes roadmap"],  "created": "2026-09-21T09:12:04Z",  "modified": "2026-09-22T08:40:11Z",  "preview": "#work #planning - [x] Review pull requests …"}

# Install

One binary, no account, no daemon. v1.3.0 · macOS and Linux · MIT. Four steps, about a minute.

  1. Get the binary

    Operating system

    ▸ Static binary, any distro

    recommended
    $ V=1.3.0; T=x86_64-unknown-linux-musl$ curl -sL https://github.com/0x1ocean/tnotes/releases/download/v$V/tnotes-$V-$T.tar.gz | tar xz$ install tnotes-$V-$T/tnotes ~/.local/bin/

    musl build: no glibc version to match, works on Debian, Arch, Alpine, NixOS, a fresh container. On aarch64 (Raspberry Pi, Graviton): T=aarch64-unknown-linux-gnu.

    upgrade: re-run with the new version number

    ▸ other ways on Linux (Homebrew on Linux, cargo)

    Homebrew on Linux

    $ brew install 0x1ocean/tnotes/tnotes

    x86_64 and aarch64. Prebuilt, no Rust needed.

    upgrade: brew upgrade tnotes

    cargo

    $ cargo install tnotes

    Builds from crates.io. Rust ≥ 1.98.

    upgrade: cargo install tnotes --force

    No AUR, deb or rpm packages yet; the static tarball is the portable answer until then.

    ▸ Homebrew

    recommended
    $ brew install 0x1ocean/tnotes/tnotes

    Apple Silicon and Intel. Prebuilt bottle, no Rust needed.

    upgrade: brew upgrade tnotes

    ▸ other ways on macOS (Prebuilt tarball, cargo)

    Prebuilt tarball, Apple Silicon

    $ V=1.3.0; T=aarch64-apple-darwin$ curl -sL https://github.com/0x1ocean/tnotes/releases/download/v$V/tnotes-$V-$T.tar.gz | tar xz$ install tnotes-$V-$T/tnotes ~/.local/bin/

    Intel: T=x86_64-apple-darwin. A .sha256 sits next to every tarball.

    upgrade: re-run with the new version number

    cargo

    $ cargo install tnotes

    Builds from crates.io. Rust ≥ 1.98.

    upgrade: cargo install tnotes --force

    Binaries are not signed. Homebrew and curl downloads run as-is; a tarball saved through the browser is quarantined by Gatekeeper: xattr -d com.apple.quarantine tnotes clears it.

    ▸ cargo, from crates.io

    recommended
    $ cargo install tnotes

    Any platform with Rust ≥ 1.98. Windows is untested.

    upgrade: cargo install tnotes --force

    ▸ other ways on From source (Current main branch)

    Current main branch

    $ cargo install --git https://github.com/0x1ocean/tnotes

    Includes the vendored word-wrap fork of edtui. May be ahead of the changelog.

    upgrade: re-run

  2. Check it runs

    $ tnotes --versiontnotes 1.3.0

    If the shell says command not found, ~/.local/bin is not on your PATH yet; open a new shell or add it.

  3. Open your notes

    $ tnotes ~/notes

    Any folder of .md files works, including an existing Obsidian vault. The folder is saved as a root and opened next time by plain tnotes. Without an argument, the first launch asks where notes live (default ~/Documents/notes). --dir opens a folder for one session only.

  4. Learn five keys

    • ctrl+t new note
    • / search
    • [[ link a note
    • alt+enter follow the link
    • ? everything else

    Then: getting started · all keys · config · use with AI agents.

# Sync and encryption are the file system's job

Put a root inside Syncthing, iCloud Drive, Dropbox or a git repo. Changes from another device show up live; saves are atomic so a syncer never sees a half-written note; concurrent edits become a conflict copy, never a lost one.

Encrypt the folder, not the notes: FileVault, an encrypted .dmg, gocryptfs or fscrypt. Point roots at the mounted path and everything keeps working.

sync recipes →
~/.config/tnotes/config.tomlroots = ["~/Sync/notes", "~/work/wiki"][editor]keys = "vim"autosave_ms = 500width = 72[theme]accent = "cyan"tag = "green"

# Read more

# FAQ

? Where are my notes stored?
As plain .md files in the folders you choose (default ~/Documents/notes). One file per note, named after its title. Nothing else is written next to them, so the folder is safe to sync with git, Syncthing, iCloud Drive or Dropbox.
? Does tnotes work with Obsidian or other Markdown apps?
Yes. Notes are ordinary Markdown with [[wikilinks]] and #tags in the text, so the same folder can be opened by any Markdown editor. tnotes reloads live when a file changes outside the app.
? Can I use vim keys?
Yes. Set editor.keys = "vim" in the config or in the in-app settings page (F2). The default is emacs-style keys.
? How do AI agents use tnotes?
Through the headless CLI: tnotes ls, search, cat, new, append, write, trash and restore, all with --json. No daemon, no API, just files. A running TUI picks the changes up live.
? Is it free?
Yes. tnotes is open source under the MIT license.
? Does it run on Windows?
Untested. Prebuilt binaries ship for macOS and Linux; cargo install may work on Windows but is not supported.