1<p align="center"><img src="docs/icon.png" width="128" height="128" alt="fold"></p>
5One outline of notes and tasks, stored as plain Markdown, in the terminal.
7Everything you write — projects, notes, tasks, an inbox — is one tree. Headings and
8bullets are its nodes; you read and edit any subtree on its own, move subtrees around,
9and check tasks off. The files stay ordinary Markdown that `rg`, your editor and your
10phone can read, and they sync with Syncthing.
13 fold › Homelab › NAS ⌕ Filter + Capture ↶ Undo ↷ Redo ☰ Commands ? Help
14╭ Outline ───────────────────────╮╭ ZFS layout ▤ ─────────────────────────── ✎ Edit ─ ⋯ ─╮
15│▾ Homelab 2/4 ││ # ZFS layout │
16│ ▾ NAS 1/2 ││ ⚑ since 2024-03 │
17│ ▾ ZFS layout ▤ 1/2 ⋯││ │
18│ ▾ ☐ Snapshot policy ││ Mirrored pairs, no raidz. Snapshots hourly. │
19│ ▸ Networking 1/2 ││ ## ☐ Snapshot policy │
20│▾ Inbox ││ - hourly, keep 24 │
21╰────────────────────────────────╯╰───────────────────────────────────────────────────────╯
29nix run github:iko-soy/fold # the TUI on your vault
30nix run github:iko-soy/fold -- --keys vim
33With Cargo (a recent stable Rust, and a C compiler for the syntax-highlighting grammars):
36cargo install --path crates/fold-cli
40The vault is `--vault PATH`, else `$FOLD_VAULT`, else the nearest directory above the
41current one that contains `root.md`, else `~/fold`. Pointed at an empty directory, the TUI
42starts a new vault with an `# Inbox`.
46The TUI is mouse-first, and every action also has a key.
48- **Click** a row to select it. Each row shows the first line of its node's text; click
49 `◨` in the top bar (or press `zp`) for the reading pane, which shows the whole selected
50 node beside the outline. Click `▸`/`▾` to
51 fold, `☐` to check a task off, a breadcrumb in the top bar to zoom out.
52- **Double-click** a row to zoom into it. Double-click a line of text to edit it there.
53- **Right-click** a row (or click its `⋯`) for everything you can do to a node: edit, new
54 sibling or child, done, properties, move, indent, make a block, copy, paste, delete.
55- **Drag** a row onto another row's title to nest it there, or to the left of a title to
57- **Filter** (`/`) finds nodes by title and text; **Commands** (`:`) lists every action by
58 name; **Capture** (`c`) drops a note into today's inbox.
60Keys, in the outline: `j`/`k` move, `h`/`l` fold, `Enter` zooms, `e` edits, `x` checks a
61task, `n`/`N` add a sibling or child, `J`/`K` move a node, `>`/`<` indent, `r` moves a
62subtree elsewhere, `u`/`U` undo and redo, `?` (or `F1`) shows everything. The status bar
63says what a key did, then which keys come next where you are. Everything is saved as you
64go; `q` quits. The view — the pane, folds, zoom, wrapping, the editor's keys — is remembered
65per vault for next time.
69`e` edits the selected subtree's Markdown in the reading pane. It saves on its own — when
70you pause, when you leave a part of the tree that lives in another file, and when you're
71done, or when fold is closed some other way (the window closed, the ssh session dropped,
72a crash). Text it cannot save because the file changed under it goes to the trash, and
73fold says where; `fold trash restore` prints it and leaves it there. Pick a keymap with
74`--keys` or `$FOLD_KEYS`, or click `⌨` in the editor's border:
76- **normal** (default) — a conventional editor like micro: Shift+arrows select,
77 `Ctrl-C`/`X`/`V`, `Ctrl-Z`/`Y`, `Ctrl-S`, `Ctrl-F`.
78- **vim** — modes, counts, motions, operators, text objects, `.`, `/`, `:w`/`:q`.
79- **helix** — selection first: `w`/`x` select, `d`/`c`/`y` act on the selection.
81Long lines wrap (`zw` toggles), fenced code is syntax-highlighted in about 140 languages,
82and pasting from the terminal and copying to the system clipboard both work.
86A vault is a directory with `root.md` and, optionally, one file per **block**:
91Two boxes in the closet, one at Hetzner.
95### ![[dozzod-binwes-talsun-worbec]]
99- [ ] Replace the flaky switch
100![[racfer-hattes-mislup-nodrys]]
103- A heading or a bullet is a node; nesting is the tree. Headings can sit under bullets,
104 and levels go past six.
105- A checkbox after the marker makes any node a task: `- [ ]`, `## [x]`.
106- A node that gets a property (a due date, say) becomes a **block**: its own file,
107 `racfer~order-new-switch.md`, with YAML frontmatter and an `id`, stitched into its parent
108 by `![[id]]`. That's how a single task gets a due date, and how the inbox becomes a small
109 file you can append to from a phone.
111Nothing else is special. Deleting goes to a trash (`$XDG_STATE_HOME/fold/trash`), and
112Syncthing conflict copies are merged node by node, with anything that differs kept as a
113`conflict:` block to resolve in the app: it is marked `⚠` in the outline, and a click on the
120fold capture "call the plumber" # append to today's inbox (stdin if no text)
121fold capture --task --to Homelab/NAS "check the scrub"
122fold check [--fix] # diagnostics; --fix rewrites in canonical form
123fold merge [--dry-run] # fold Syncthing conflict files in
124fold trash list | fold trash restore ID
130[android/](android/README.md) is fold for the phone: the same vault, opened from the
131folder Syncthing syncs it to, read and written by the same `fold-core`. The outline with
132folds and checkboxes, zoom, the node menu, capture (also from the share sheet), the
133subtree editor, properties with a date picker, find, move to, undo, and the conflict view
134for sync-conflict copies. Build it with `./gradlew assembleDebug` in `android/`; see its
135README for what it needs.
140nix develop # cargo, rustc, clippy, rustfmt, rust-analyzer
141cargo test --workspace
142nix flake check # the same tests, in the Nix sandbox
145The code is four crates: `fold-core` (parsing, rendering, the operations, merge),
146`fold-tui` (the ratatui app), `fold-cli` (the `fold` binary) and `fold-ffi` (a session
147over `fold-core` for other languages, through UniFFI, which the Android app calls).
148[SPEC.md](SPEC.md) is the design: the data model, the file format, every operation and
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list