Capture a thought before it's gone.
A fast, minimal, card-based memo app for macOS (Apple Silicon).
Where a human hits Option twice and a coding agent reads the same vault over a CLI — with parity, no cloud, and plain-text files as the source of truth.
oximemo is optimized for the speed of catching a thought. Every memo is a card; cards live on a grid. The capture path has no AI summary, no auto-tagging, no chatbot — those trade away the capture speed and reliability this project exists to protect. Agentic help exists only as an optional, closable panel that delegates to a terminal-agent CLI you explicitly activate (see Copilot panel below); it can never touch the overlay.
Two core scenarios, one vault:
- A human double-taps
Optionanywhere on macOS, types one line, and disappears back into their work. - An agent (coding agent, local script) reads and writes those same notes over the
oximemoCLI — safely, with no duplicates.
- Files are the source of truth. Notes are plain
.mdfiles with TOML frontmatter.grepandcatwork. The index is just a cache — rebuildable at any time withoximemo reindex. - Three-tier storage, pure Rust. Plain files + a
redbmetadata index + atantivyBM25 full-text index. No SQLite, no C dependencies in the index layer. - Capture that doesn't make you wait. The overlay window is warmed up off-screen so it appears in a single frame (target ≤ 16 ms) on trigger.
- Human/agent parity. Every GUI operation is a CLI operation. Agent-facing commands default to JSON / NDJSON for clean streaming and scripting.
- Hash-based sync.
oximemo exportemits a body-less manifest of{id, hash, updated_at, deleted}; diff the hashes, fetch only what changed, advance your cursor. HandlesARG_MAXwith--ids-file/--ids-stdin. - OKLCH colors. Perceptually uniform, CSS-native color labels that look right in both light and dark mode.
- Hardened against external writes. The file watcher debounces, retries partial writes (editors, iCloud), and never crashes the indexer.
- HTML notes (
.html)..htmlfiles are first-class notes alongside.md— frontmatter lives in a leading HTML comment, the title is derived from the first<h1>/<title>, and the same TEMPLATE rule applies (TEMPLATE.htmlfor HTML notes,TEMPLATE.mdfor markdown). The CLI creates HTML notes withoximemo new --html. - oxibrain context panel. A read-only panel in
MemoDetailgathers recall layers from oxibrain ≥ 0.10 (no cloud). There is no daemon: each interaction spawns a short-livedoxibrain admin serve --stdiochild, the binary resolves via PATH ([brain].executableoverrides), and the space is derived from the vault directory name. Ingestion is oximemo-triggered: the active vault is ensured as adocuments.tomlroot andoxibrain admin index --documentsruns on boot and after settled saves. - Copilot panel. A floating window (
⌘⇧C/ bottom-right FAB) that delegates vault work — write a note, tidy up, suggest tags — to a terminal-agent CLI you explicitly activate (adapters:oxios,omp,claude,codex,oxicode). oximemo contains no model, no prompt, no embedding: it hands the agent a declarative context block and the bundledoximemoCLI +SKILL.mdcontract, one subprocess per turn. The composer supports@note references (attached as context chips),/commands (요약·태그 제안·정리·찾기·새 노트), and IME-safe input; responses render as markdown with copy actions. Approvals, sandboxing, and providers stay with the agent; the panel header always discloses the active agent and provider, and vault changes observed during a turn are linked without claiming causality. Hidden entirely when no agent is activated.
- System requirements
- Install
- Quick start
- The vault
- Architecture
- Project structure
- Oxi ecosystem
- Agent synchronization
- Development
- Roadmap
- Contributing
- License
- macOS 14+ on Apple Silicon (
aarch64-apple-darwin). - Rust 1.89+ (edition 2024) to build from source.
Windows, Linux, and mobile are intentionally out of scope for the MVP. See the design doc.
curl -fsSL https://github.com/project-oxi/oximemo/releases/latest/download/install.sh | shDownloads the latest release, verifies the sha256, installs the CLI to
/usr/local/bin (sudo when needed). VERSION=v0.10.0 / PREFIX=~/bin
pin or relocate.
curl -fsSL https://github.com/project-oxi/oximemo/releases/latest/download/install.sh | sh -s -- --appAlso installs/updates /Applications/OxiMemo.app from the signed dmg
(checksum-verified; the running app is refused replacement — quit it
first, or let its in-app updater handle upgrades).
Download the prebuilt oximemo binary and .dmg from the
latest release, then:
tar -xzf oximemo-aarch64-apple-darwin.tar.gz
sudo install -m 0755 oximemo /usr/local/bin/oximemo
oximemo --versioncargo install oximemo-cligit clone https://github.com/project-oxi/oximemo.git
cd oximemo
cargo build --release -p oximemo-cli
# binary: target/release/oximemoA Homebrew tap (
brew install) is planned. For now, use the one-liner, a release tarball, crates.io, or build from source.
The CLI is the authoritative interface — the same oximemo-core the desktop app uses.
# Capture a thought (text arg, or omit to read stdin)
oximemo new "Ship the redb bump before the freeze" --tag backlog --category todo
# Create an HTML note (frontmatter lives in a leading <!-- +++ ... +++ --> comment)
oximemo new "Knowledge distillation draft" --html
# List recent notes — table for humans (default), JSON/NDJSON for agents
oximemo list --limit 10
oximemo list --favorites --format ndjson
# Read one memo (JSON by default; --md for the raw file)
oximemo get 019fa927-a897-7e12-9102-8a8c7ebbb594 --md
# Full-text search (BM25 over body + tags)
oximemo search "redb upgrade" --limit 5 --format ndjson
# Edit a memo (favorite / category / body) and manage categories
oximemo update 019fa927-a897-7e12-9102-8a8c7ebbb594 --favorite --category idea
oximemo category list
oximemo category new research --color "oklch(0.72 0.15 310)"
# Where does my vault live?
oximemo vault pathFull command reference
oximemo new [TEXT] [--tag TAG]… [--category ID] [--html] # --html creates a .html note (frontmatter in a leading HTML comment) oximemo list [--limit N] [--tag T] [--category ID] [--favorites] [--format table|json|ndjson] oximemo list --where status=stub --sort status_changed --offset 40 # property query (offset path) oximemo list --where domain=TECH,MATH --where subdomain~AI # comma = any-of; ~ = list membership oximemo update --set status=understood --unset draft # property set/remove oximemo get [--md] oximemo export [--since RFC3339] [--ids a,b,c | --ids-file PATH | --ids-stdin] [--full] [--format ndjson|json] oximemo delete # soft-delete → .trash/ oximemo restore # un-delete a trashed memo oximemo purge [--older-than 30d] oximemo category list [--format table|json|ndjson] oximemo category new [--color "oklch(...)"] oximemo category recolor | --none # set or clear a category's color oximemo category rename # moves memos; prints count oximemo category delete # inbox cannot be deleted oximemo reindex # rebuild indexes from files oximemo doctor [--fix] # audit / safe-repair oximemo vault path # print the vault root oximemo upgrade [--check] # self-update from GitHub Releases
Global: `--vault <PATH>` (or `OXIMEMO_VAULT`) selects a non-default vault. Output formats: `table` (human), `json` (single array), `ndjson` (one value per line, the default for `export`/`search`). Timestamps are RFC 3339.
</details>
<details>
<summary><strong>Global capture & desktop app</strong></summary>
- **Capture overlay:** double-tap `Option` (needs Accessibility / Input Monitoring permission), or the always-available `Cmd+Shift+N`, or the menu-bar icon. `Enter` saves & dismisses, `Shift+Enter` newline, `Esc` cancels.
- **Card grid:** search, tag/favorite filters, OKLCH color labels, virtualized for large vaults.
- Light/dark follows the macOS system appearance.
</details>
## The vault
Notes are plain text — humans and agents can read them with anything.
The default vault is the active space's vault, `~/.oxi/spaces/<space>/vault/`
(`personal` by default; `OXI_HOME` relocates the whole `~/.oxi` tree):
```plain
~/.oxi/
├── spaces/
│ └── personal/
│ └── vault/ # the default vault
│ ├── <folder>/<title-slug>.md
│ ├── _assets/ # images, referenced as oximg://
│ ├── .trash/ # soft-deleted notes
│ └── oximemo.toml # optional vault settings
├── oximemo/ # oximemo-private state (settings, index)
└── brain/ # oxibrain's data plane (never written by oximemo)
Older installs keep working: the pre-unification vaults (macOS
Application Support, the flat ~/.oxi/vault) are migrated into the
spaces layout automatically — journaled, resumable, and for
cross-volume moves the source is kept as a verified backup. Run
oximemo migrate-home --dry-run to see what would happen, or
oximemo doctor for the current layout.
oximemo.toml also carries an optional [brain] section (enabled/executable, defaults true/"" — empty means spawn oxibrain from PATH) for the read-only oxibrain context panel in MemoDetail; the panel hides itself when enabled = false. oxibrain ≥ 0.10.1 is required. Retired socket/space keys in existing files are ignored.
Each memo is one file with TOML frontmatter delimited by +++:
+++
id = "01991a2e-7c3f-7c91-9f3e-6b1a2e8f9c10"
created_at = "2026-07-28T10:15:03+09:00"
updated_at = "2026-07-28T10:15:03+09:00"
hash = "b3:6f2a9e1d4c7b8a90f1e2d3c4b5a6978…"
favorite = false
category = "inbox"
tags = ["idea", "oximemo"]
+++
The capture overlay must appear in under one frame.The id is a time-sortable UUIDv7; the hash is b3: + BLAKE3 over the normalized body, tags, favorite flag, and category — so a pure metadata edit (add a tag, change a category) bumps the hash and is detected by sync. Full parsing rules and the safe-writing guide are in doc/DESIGN.md §5 and skills/oximemo/SKILL.md.
A persistent sidebar calendar (DAILY section) opens — or creates — one note per day in the [daily] folder (oximemo.toml: enabled, folder, default daily). Notes are titled by ISO date (2026-08-21.md), so they are ordinary notes: searchable, taggable, movable. A TEMPLATE.md in the daily folder seeds new entries ({{date}}, {{weekday}}, … are filled with the local date); if the template's heading isn't the date, the date heading is prepended so filenames stay deterministic. Days with a note show a dot; past and future days can be created (backfilling and planning). Set enabled = false to hide the sidebar section and Today button.
Every frontmatter key beyond the core five (id, created, updated,
favorite, deleted) is a property — indexed, searchable through
aliases, covered by the sync digest, and editable in the app's property
panel or over the CLI (--set / --unset). Files stay plain
Obsidian-compatible markdown.
A folder that carries a SCHEMA.toml declares its property system:
types and allowed values, card badges with color tokens, state
transitions (e.g. the knowledge preset's peak_status max-merge that
preserves the all-time high through decay/re-learn cycles), and an
optional [review] block that turns the folder's header into a review
queue ("설명 가능함" reasserts, "막힘" decays). The ⌘K action 지식 관리
폴더 만들기 installs the full knowledge-state preset (stub → vague →
understood → mastered, decayed) as two editable files. TEMPLATE.md
frontmatter seeds new notes' properties — a quick capture into a schema
folder starts at status: stub.
[[wiki links]] resolve through titles and aliases, and links
inside property values (e.g. related) count for backlinks, the graph,
and rename propagation — so an empty stub stays connected.
oximemo-core is a pure-Rust library that owns the file store, indexes, file-watching, and sync. The desktop app (Tauri) and the CLI are thin adapters over oximemo_core::Vault — so the GUI and CLI always behave identically and can share one live vault (guarded by an fs2 advisory lock).
flowchart TB
subgraph Native["macOS native"]
CAP["oximemo-capture\nobjc2 global flagsChanged monitor\n(Option double-tap)"]
MENU["Menu-bar NSStatusItem"]
end
subgraph App["Tauri desktop app (apps/desktop)"]
RUST["Tauri Rust backend"]
UI["React 19 frontend\ncard grid + overlay"]
end
subgraph CLI["oximemo-cli"]
BIN["clap subcommands\nnew / list / search / export …"]
end
subgraph Core["oximemo-core (pure Rust)"]
FILES[("Files (*.md)\nsource of truth")]
LOCK["fs2 advisory lock"]
REDB[("redb metadata\nindex")]
TANT[("tantivy\nBM25 search")]
WATCH["notify watcher"]
SYNC["hash dedup / export"]
end
AGENT["External agent\n(coding agent / script)"]
CAP --> RUST
MENU --> RUST
RUST <--> UI
RUST --> Core
BIN --> Core
FILES --> WATCH --> REDB
WATCH --> TANT
LOCK -. guards .-> REDB
REDB --> SYNC
AGENT -- "CLI call" --> BIN
| Layer | Role | Tech |
|---|---|---|
| Source of truth | Human-readable memo bodies | .md files + TOML frontmatter |
| Metadata index | Fast pagination, filters, sync cursor | redb |
| Full-text index | BM25 keyword search | tantivy |
The index layers are 100% derivable from the files — corrupt or stale? One oximemo reindex restores them.
oximemo/
├── crates/
│ ├── oximemo-core/ # Pure-Rust core: store, index, search, watcher, sync
│ ├── oximemo-cli/ # `oximemo` binary — clap adapter over oximemo-core
│ └── oximemo-capture/ # macOS global Option double-tap monitor (objc2)
├── apps/desktop/ # Tauri 2 + React 19 desktop app
│ ├── src-tauri/ # Rust backend
│ └── src/ # React frontend (Tailwind v4, Base UI, TanStack)
├── skills/oximemo/ # SKILL.md — agent-facing CLI guide
└── doc/DESIGN.md # Full design document
oximemo owns the local note vault and capture experience. It reads contextual recall from oxibrain, while terminal agents such as oxicode and oxios work with the same plain-text vault through the oximemo CLI. Each product keeps its own boundaries: oximemo never embeds a model or writes agent-managed memory itself.
The manifest is cheap on purpose — bodies are omitted, so it stays light for tens of thousands of notes.
- Fetch the manifest since your cursor:
oximemo export --since "$CURSOR" --format ndjson > manifest.ndjson
- Diff against your local
id → hashcache (in your code):idunseen → fetchhashdiffers → fetch (covers tag/favorite/color edits too)deleted: true→ drop
- Fetch changed bodies in bulk (use
--ids-file/--ids-stdinpastARG_MAX):oximemo export --ids-file ids.txt --full --format ndjson - Advance your cursor to the max
updated_atseen. Repeat.
The full procedure, output schemas, and the safe direct-write rules are in skills/oximemo/SKILL.md.
# Rust
cargo fmt --all -- --check
cargo clippy -p oximemo-core -p oximemo-cli -p oximemo-capture --all-targets -- -D warnings
cargo test -p oximemo-core -p oximemo-cli -p oximemo-capture
# Desktop frontend
cd apps/desktop
bun install --frozen-lockfile
bun run buildA scratch vault is handy for manual testing:
cargo run -p oximemo-cli -- --vault /tmp/oximemo-test new "hello" --tag dev
cargo run -p oximemo-cli -- --vault /tmp/oximemo-test listSee CONTRIBUTING.md for the full workflow, and doc/DESIGN.md for the design authority.
- Next — MCP server mode (
oximemo mcp serve), iCloud-Drive vault auto-detection. - Deferred by design — AI summaries, auto-tagging, chatbot, and embedding-based semantic search. BM25 keeps the capture loop fast; an offline embedding path (Rust
candle, Metal-accelerated) stays a possibility if real demand appears.
Contributions are welcome! Please read CONTRIBUTING.md first.
By contributing, you agree your contributions will be licensed under the MIT License.
Licensed under the MIT License.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this project by you shall be licensed under the MIT License, without any additional terms or conditions.