A note-taking system built on Typst instead of Markdown.
Notes are plain .typ files with built-in support for typed metadata, cross-references, backlinks, and knowledge graphs — all powered by Typst's own type system.
Instead of reinventing frontmatter parsers, Dataview-style query languages, and custom renderers, typos lets Typst do what it already does: functions, types, and content transformations. The tooling layer (Rust) handles AST extraction and indexing, while the Typst framework handles rendering.

Editor with Typst syntax highlighting and live HTML preview

Programmable type system — define your note types in vault.typ

Interactive knowledge graph visualization
typos/
├── notes-app/ Tauri desktop app (Svelte + CodeMirror)
├── notes-core/ Rust library (AST parsing, indexing, compilation)
├── notes-cli/ CLI binary wrapping notes-core
└── notes-framework/ @local/notes Typst package
Data flow:
1. You write .typ notes with typed constructors and cross-references
2. The indexer parses all files via typst-syntax AST and builds notes-index.json
3. When Typst compiles a note, the framework reads the index to resolve links and render backlinks
A native desktop app built with Tauri 2, Svelte 5, and CodeMirror 6. Editor with Typst syntax highlighting, live HTML preview, full-text search, and note management. Typst compiler and framework are bundled — no external dependencies needed for end users.
| Platform | Download |
|---|---|
| macOS (Apple Silicon) | typos_0.2.4_aarch64.dmg |
| macOS (Intel) | typos_0.2.4_x64.dmg |
| Linux (Debian/Ubuntu) | typos_0.2.4_amd64.deb |
| Linux (AppImage) | typos_0.2.4_amd64.AppImage |
| Windows | typos_0.2.4_x64-setup.exe |
macOS note: The app is not yet code-signed. On first launch macOS may show "app is damaged" or "unidentified developer". To fix, run in Terminal:
xattr -d com.apple.quarantine /Applications/typos.appOr: System Settings → Privacy & Security → scroll down → click "Open Anyway".
Place both binaries in notes-app/src-tauri/binaries/:
notes-app/src-tauri/binaries/
├── typst-aarch64-apple-darwin # macOS ARM
├── typst-x86_64-apple-darwin # macOS Intel
├── typst-x86_64-unknown-linux-gnu # Linux
├── typst-x86_64-pc-windows-msvc.exe # Windows
├── tinymist-aarch64-apple-darwin # macOS ARM
├── tinymist-x86_64-apple-darwin # macOS Intel
├── tinymist-x86_64-unknown-linux-gnu # Linux
└── tinymist-x86_64-pc-windows-msvc.exe # Windows
You only need the binaries for your current platform. The notes framework is bundled automatically from notes-framework/.
cd notes-app
npm install
npx tauri dev
cd notes-app
npx tauri build
The compiled app bundle will be in notes-app/src-tauri/target/release/bundle/.
| Shortcut | Action |
|---|---|
Cmd+S |
Save current note |
Cmd+K |
Search notes |
Cmd+O |
Open vault |
Cmd+N |
New note |
# Requires Rust toolchain
cargo install --path notes-cli
# Install the Typst framework as a local package
# macOS:
cp -r notes-framework/src/ ~/Library/Application\ Support/typst/packages/local/notes/0.1.0/src/
cp notes-framework/typst.toml ~/Library/Application\ Support/typst/packages/local/notes/0.1.0/
# Linux:
cp -r notes-framework/src/ ~/.local/share/typst/packages/local/notes/0.1.0/src/
cp notes-framework/typst.toml ~/.local/share/typst/packages/local/notes/0.1.0/
notes init my-vault
cd my-vault
This generates:
- vault.typ — vault configuration with note type definitions
- note-paths.csv — registry of all note files
- notes-index.json — metadata index
- notes/welcome.typ — your first note
notes new "Build MVP" --type task
notes new "programming/rust" --type note
notes new "programming/rust/closures" --type note
The path syntax (/) creates a hierarchy. Parent notes are auto-created if they don't exist:
notes/build-mvp.typ → id: "build-mvp"
notes/programming--rust.typ → id: "programming/rust"
notes/programming--rust--closures.typ → id: "programming/rust/closures"
notes index # rebuild index
notes list # list all notes
notes list --type task # filter by type
notes search "rust" # full-text search
notes backlinks "programming/rust" # show incoming links
notes graph # knowledge graph
notes compile programming/rust # compile to HTML
notes compile programming/rust --format pdf
notes watch welcome # live recompilation
notes rename old-id new-id # rename with reference updates
notes delete note-id # delete note
notes sync # sync after external changes (e.g. git pull)
A note is a regular .typ file. The title heading is rendered automatically:
#import "../vault.typ": *
#show: card.with(
title: "closures",
tags: ("rust", "fp", "@programming/python"),
difficulty: "hard",
)
Closures capture variables from their environment.
See also #xlink("programming/rust/traits").
#show: type.with(title: "...") — registers the note with typed metadata. The id and parent are derived from the filename automatically.
"@id" string: tags: ("rust", "@programming/python"). Rendered as a clickable link, indexed automatically.#xlink("id"): See #xlink("programming/rust"). Rendered as an inline link.Both appear in backlinks of the target note. Backlinks are rendered automatically at the bottom of each note.
The Typst framework (@local/notes) provides:
| Module | Purpose |
|---|---|
vault.typ |
new-vault() — initializes vault object from index data |
note-type.typ |
Creates typed constructors for #show: rules |
xlink.typ |
Cross-reference resolution via index lookup |
backlinks.typ |
Renders incoming links at the end of each note |
graph.typ |
Text-based graph + DOT output for Graphviz |
index.typ |
Index reading and query helpers |
The user's vault.typ ties it together:
#import "@local/notes:0.1.0": new-vault, as-branch
#let vault = new-vault(
index: json("notes-index.json"),
)
#let tag = (vault.note-type)("tag")
#let note = (vault.note-type)("note", fields: (tags: (), links: ()))
#let task = (vault.note-type)("task", fields: (tags: (), priority: ""))
#let xlink = vault.xlink
notes compile and notes watch via typst subprocess--type against vault.typ definitionsnotes rename with automatic reference updates@ references and #xlink():w, :q, :wqtypst Rust crate (World trait)$ claude mcp add typos \
-- python -m otcore.mcp_server <graph>