Vault Format

The on-disk format TR-2 reads and writes — folders, files, frontmatter, task tokens, and the round-trip guarantee that makes the format safe to edit by hand or by AI.

Section: Vault Format

A TR-2 vault is just a folder. Everything below is what TR-2 expects to find there — and what it promises not to mangle. The full grammar lives in SPEC.md; this page is the working summary.

Vault layout

<vault>/
  .tr2                 # format-version marker (see "Versioning")
  README.md            # orientation; humans/agents read this first
  inbox.md             # the capture list
  Work/                # a folder = a GTD "area"
    website.md         # a file = a project
    Subarea/           # areas nest arbitrarily
      launch.md
  • A folder is a GTD area. Areas nest to any depth.
  • A file (*.md) is a project, or the special inbox.md.
  • A file lives in exactly one folder.
  • README.md at the vault root is orientation only and is never rewritten by TR-2.

Project file anatomy

Optional YAML frontmatter, then a GFM task checklist, then any markdown you like.

---
id: 7f3a2b
type: project
title: Website redesign
---

- [ ] Redesign homepage @next due:2026-05-25
  - [x] Audit current layout
  - [ ] Wireframe v2
- [x] Fix nav bug done:2026-05-18

## Done
- [x] Decommission old CMS done:2026-05-12

Any free prose, headings, code fences, links — preserved verbatim.

Frontmatter

KeyMeaning
idshort stable identifier (survives renames). Optional but recommended.
type: projectreserved; identifies a project file.
titleoptional display title. Falls back to the file name.
archived: trueparks the project — hidden from the default sidebar and lists; still on disk, accessible from the Archived view.

Any other keys are preserved untouched. Unknown keys, comments, blank lines, and key order all round-trip exactly. Reserved-for-later keys (don’t repurpose): area, tags, recurring, created.

Task lines

A task is a GFM checklist item. Three checkbox states:

BoxStateNotes
- [ ]open
- [*]in progress- [/] accepted; TR-2 writes *
- [x]done[X] accepted; TR-2 writes x and adds done:

* and + list bullets are accepted and preserved. Indentation makes subtasks.

Tokens

Lightweight, human-readable, position-independent within the line:

TokenMeaning
@todaybelongs in Today
@nexta next action; surfaced in Next + a per-task badge
@somedayparked “maybe later”; appears in Someday, excluded from Today / Scheduled
@waitingreserved (parsed & preserved; surfaced later)
#taga free-form tag; each tag gets a derived cross-vault view
due:YYYY-MM-DDdue date. On/before today → Today. In the future → Scheduled.
done:YYYY-MM-DDcompletion date. Written by the app on completion, cleared on un-complete.

Grammar: @word = @ + [A-Za-z][A-Za-z0-9_-]* (a context). #word = # + [A-Za-z][A-Za-z0-9_/-]* (a tag). key:value = key: + non-space value. Tokens are whitespace- or line-start delimited. Unrecognised @words, #tags, and key:values are left alone — adding meaning to one later cannot break an older file.

Sections

An ATX heading (## Name) inside a project body groups the tasks that follow it. Headings are preserved verbatim. You can drag-reorder sections in the app; you can also rename or delete the heading directly in the file.

Notes on a task

Prose lines indented deeper than the task, placed directly beneath it, are the task’s note. The note travels with the task on reorder/move.

- [ ] Redesign homepage @next due:2026-05-25
    Pick a direction with the team first.
    Longform is fine.
  - [ ] Wireframe v2

The optional ^id

A task line may end with an opaque block id: - [ ] Email Bob ^ab12 (^ + 1–16 of [0-9A-Za-z]). TR-2 adds one only when it must disambiguate two tasks with identical text. Editors should leave them alone but can delete one safely — TR-2 falls back to content/position matching with no data loss. A freshly hand-authored vault contains zero ^ids.

The ## Done section

A trailing ## Done heading collects completed top-level tasks. When you check a task off, TR-2 sweeps its whole subtree under this heading; un-checking moves it back.

  • The heading is optional. A file without one round-trips unchanged.
  • The text is exactly Done; any heading level is recognised. TR-2 writes ## Done.
  • The sweep is idempotent and only fires on a real status change — opening a file never silently rewrites it.
  • Subtasks travel with their root subtree; a checked child of an open parent is not archived in isolation.
  • You can delete or rename the heading freely; the next done-state change recreates it.

The round-trip guarantee

serialize(parse(bytes)) == bytes, byte-for-byte, for any input — including content TR-2 does not model.

TR-2 only rewrites the specific lines a user edits in-app. Everything else (prose, headings, code fences, unknown frontmatter, CRLF line endings, a missing final newline) is emitted verbatim. This is enforced by a blocking test suite. TR-2 will never destroy content it doesn’t understand — so hand-editing the file or letting an AI rewrite parts of it is safe.

Editing by hand / by AI / by git

The files are the source of truth, so:

  • Add a task — append a - [ ] something line to a project file or inbox.md.
  • Complete a task — change [ ] to [x] (TR-2 will add done:YYYY-MM-DD on its next write).
  • Move a task — cut from one file, paste into another. The task is wherever it lives on disk.
  • Rename an area — rename the folder. Everything beneath follows.
  • Diff history — every change is an ordinary text diff. git log is your audit trail.

Versioning

A vault carries a tiny .tr2 marker file at its root. It declares the format version (currently v1) so future TR-2 builds can opt into changes without surprising older files. The file format described on this page is v1 and the round-trip guarantee applies in full.

See also