Skip to content
← Back
Anotadinho icon

case study · since 2026-08

Anotadinho

"I like it this way."

A native, offline-first Markdown note editor inspired by Obsidian and Logseq. A personal project I use to really learn Rust: crate-based architecture, tests, a CLI, a TUI and an MCP server for AI agents.

lines of Rust
55,328
automated tests
851
commits
345
crates
6

Decisions

Why Rust?

I wanted to leave my Python/TypeScript comfort zone and truly understand memory, ownership and concurrency. A note editor has a parser, I/O, an index and a UI — it covers almost everything.

Why Tauri + Yew?

~1 MB bundle vs ~100 MB for Electron, and the UI is Rust too (compiled to WASM), with React-like components and hooks. I evaluated Dioxus, Leptos and Svelte before deciding.

Why .md files?

Offline-first with no lock-in: the vault is a plain folder, syncable by USB stick or any copy, readable in another editor ten years from now.

Architecture

A Cargo workspace of isolated crates. The Yew UI talks to the core only through Tauri IPC commands; the CLI and TUI reuse the same core.

ui · Yew/WASM
cli · MCP
tui · Ratatui

↓ tauri::command / direct calls ↓

ipc

↓

core

block model, Markdown parser, embeds, index, queries

vault

file I/O, watcher, locks

search

full-text search with FTS5

Embeds that stay Markdown

Everything lives in .md files with YAML frontmatter. The 9 interactive embed types use a {{ type: "X" }} syntax that never collides with CommonMark, so files stay readable in any editor.

  • kanban
  • calendar
  • table
  • callout
  • columns
  • gallery
  • query
  • timeline
  • actions
{{ type: "kanban" }}
columns:
  - name: A fazer
    cards:
      - title: Revisar parser de embeds
        checklist: [testes, docs]
  - name: Feito
    cards:
      - title: Servidor MCP
{{ /kanban }}

AI proposes, human decides

The MCP server (JSON-RPC over stdio) gives agents like Claude Code direct read access to the vault — but the only write tool is "propose". Changes land on a review screen and only hit disk after a human click.

//! As ferramentas de LEITURA são diretas. A de ESCRITA é `propor`,
//! não `escrever`: o agente não tem como gravar uma página, só
//! sugerir. O que ele propõe aparece na tela de revisão e só vira
//! arquivo depois de um clique humano.
//!
//! JSON-RPC 2.0 em linhas, sobre stdin/stdout: uma requisição por
//! linha, uma resposta por linha. É o transporte stdio do MCP.

use serde_json::{json, Value};
use std::io::{BufRead, Write};

/// Versão do protocolo que este servidor fala.
const VERSAO_PROTOCOLO: &str = "2024-11-05";

crates/cli/src/mcp.rs

Cycle-driven development

The project evolves in cycles, not loose commits: each cycle reads a task, implements it, runs tests, checks acceptance criteria and records status. That keeps 800+ tests green across 55k lines.

One core, three interfaces

The same Rust core powers the desktop app (Tauri + Yew/WASM, ~1 MB vs ~100 MB for Electron), the CLI and the terminal TUI.