Skip to content

Repository files navigation

oximemo

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.

CI Release License: MIT Rust Tauri macOS


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:

  1. A human double-taps Option anywhere on macOS, types one line, and disappears back into their work.
  2. An agent (coding agent, local script) reads and writes those same notes over the oximemo CLI — safely, with no duplicates.

Highlights

  • Files are the source of truth. Notes are plain .md files with TOML frontmatter. grep and cat work. The index is just a cache — rebuildable at any time with oximemo reindex.
  • Three-tier storage, pure Rust. Plain files + a redb metadata index + a tantivy BM25 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 export emits a body-less manifest of {id, hash, updated_at, deleted}; diff the hashes, fetch only what changed, advance your cursor. Handles ARG_MAX with --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). .html files 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.html for HTML notes, TEMPLATE.md for markdown). The CLI creates HTML notes with oximemo new --html.
  • oxibrain context panel. A read-only panel in MemoDetail gathers recall layers from oxibrain ≥ 0.10 (no cloud). There is no daemon: each interaction spawns a short-lived oxibrain admin serve --stdio child, the binary resolves via PATH ([brain].executable overrides), and the space is derived from the vault directory name. Ingestion is oximemo-triggered: the active vault is ensured as a documents.toml root and oxibrain admin index --documents runs 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 bundled oximemo CLI + SKILL.md contract, 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.

Table of contents

System requirements

  • 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.

Install

One-liner (CLI)

curl -fsSL https://github.com/project-oxi/oximemo/releases/latest/download/install.sh | sh

Downloads 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.

One-liner (CLI + desktop app)

curl -fsSL https://github.com/project-oxi/oximemo/releases/latest/download/install.sh | sh -s -- --app

Also 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).

From a release

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 --version

From crates.io (CLI)

cargo install oximemo-cli

From source

git clone https://github.com/project-oxi/oximemo.git
cd oximemo
cargo build --release -p oximemo-cli
# binary: target/release/oximemo

A Homebrew tap (brew install) is planned. For now, use the one-liner, a release tarball, crates.io, or build from source.

Quick start

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 path
Full 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.

Daily notes

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.

Note properties & folder schemas

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.

Architecture

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
Loading
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.

Project structure

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

Oxi ecosystem

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.

Agent synchronization

The manifest is cheap on purpose — bodies are omitted, so it stays light for tens of thousands of notes.

  1. Fetch the manifest since your cursor:
    oximemo export --since "$CURSOR" --format ndjson > manifest.ndjson
  2. Diff against your local id → hash cache (in your code):
    • id unseen → fetch
    • hash differs → fetch (covers tag/favorite/color edits too)
    • deleted: truedrop
  3. Fetch changed bodies in bulk (use --ids-file/--ids-stdin past ARG_MAX):
    oximemo export --ids-file ids.txt --full --format ndjson
  4. Advance your cursor to the max updated_at seen. Repeat.

The full procedure, output schemas, and the safe direct-write rules are in skills/oximemo/SKILL.md.

Development

# 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 build

A 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 list

See CONTRIBUTING.md for the full workflow, and doc/DESIGN.md for the design authority.

Roadmap

  • 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.

Contributing

Contributions are welcome! Please read CONTRIBUTING.md first.

By contributing, you agree your contributions will be licensed under the MIT License.

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.

About

Fast, minimal, card-based note capture for macOS (Apple Silicon). Rust + Tauri 2; plain .md files as the source of truth, CLI/agent parity.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages