https://github.com/oxyaxion/clef-note
A Lightweight, fast, queryable, keyboard-oriented note-taking personnal web app with a minimal footprint.
https://github.com/oxyaxion/clef-note
freebsd lightweight markdown-editor note-taking notes-app queries requests rust self-hosted
Last synced: 13 days ago
JSON representation
A Lightweight, fast, queryable, keyboard-oriented note-taking personnal web app with a minimal footprint.
- Host: GitHub
- URL: https://github.com/oxyaxion/clef-note
- Owner: Oxyaxion
- Created: 2026-05-03T10:10:08.000Z (about 1 month ago)
- Default Branch: main
- Last Pushed: 2026-05-11T20:54:12.000Z (25 days ago)
- Last Synced: 2026-05-11T22:28:01.098Z (24 days ago)
- Topics: freebsd, lightweight, markdown-editor, note-taking, notes-app, queries, requests, rust, self-hosted
- Language: Svelte
- Homepage:
- Size: 3.48 MB
- Stars: 1
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
Clef Note
A lightweight, fast, queryable, keyboard-oriented markdown note-taking app with a minimal footprint.
- Self-hosted, WYSIWYG editor, note-taking backed by plain `.md` files with frontmatter, no database, no lock-in.
- Move your `storage/` folder anywhere, open notes in any editor.
- Clean and minimal UI.
- Minimal footprint : one binary, ~15 MB on disk and just a few dozen megabytes of RAM for 5000 notes.
- Fast search even with thousands of notes.
- Keyboard-first: `/` for blocks, `Ctrl+K` for commands.
- Write live query blocks directly in your notes: `{area:pro status:active order by priority}`, `{path:Work/ depth:2 order by name and not project print name}` : Results update in real time.
- All the modern features : Export notes / Copy Paste images / Excalidraw ...
- Responsive for smartphone.
- Read only mode.
- API to queries from the CLI (`scripts/an`).
- OpenAI compatible endpoint to plug with an LLM.
## Try the demo
**[clef-note.fly.dev](https://clef-note.fly.dev)** · password: `clef-note`
## Road map
- OpenID Authentication
- Dashboard system
- git synchronisation
- Any ideas ?
---
## Stack
| Layer | Technology |
|----------|------------------------------------|
| Backend | Rust + Axum |
| Frontend | SvelteKit (vanilla CSS) |
| Editor | TipTap (ProseMirror) |
| Storage | Flat `.md` files (in-memory index) |
---
## Getting Started
### Download pre-built binary
The easiest way to get started — no Rust or Node.js required.
Download the latest binary for your platform from the [Releases page](https://github.com/Oxyaxion/clef-note/releases):
- `clef-note-linux-x86_64` — Linux
- `clef-note-freebsd-x86_64` — FreeBSD
```bash
chmod +x clef-note-linux-x86_64
./clef-note-linux-x86_64 --config clef-note.toml
```
### Build from source
#### Prerequisites
- [Rust toolchain](https://rustup.rs) — for the backend
- Node.js ≥ 20 — only needed to build the frontend
### Production build
The backend embeds the entire frontend at compile time into a single binary.
```bash
# 1. Build the frontend
cd frontend && npm install && npm run build
# 2. Compile the backend (embeds frontend/build/ automatically)
cd ../backend && cargo build --release
# 3. Run — serves UI + API on http://localhost:3000
./target/release/clef-note --config /path/clef-note.toml
```
No Node.js needed at runtime — `clef-note` is self-contained.
### Development
Run the backend and frontend in two separate terminals:
```bash
# backend (API on http://localhost:3000)
cd backend && cargo run -- --config /path/clef-note.toml --storage /path/storage
# frontend (UI on http://localhost:5173, proxies API to :3000)
cd frontend && npm install && npm run dev
```
Open `http://localhost:5173`.
### Run as a systemd service
Create `/etc/systemd/system/clef-note.service`:
```ini
[Unit]
Description=Clef Note
After=network.target
[Service]
User=clef-note
WorkingDirectory=/opt/clef-note
ExecStart=/opt/clef-note/clef-note
Restart=on-failure
[Install]
WantedBy=multi-user.target
```
```bash
sudo systemctl daemon-reload
sudo systemctl enable --now clef-note
sudo journalctl -u clef-note -f # follow logs
```
The `clef-note` binary serves both the frontend and the API on port `3000` — no nginx, no Node.js required in production.
### FreeBSD rc.d service
Create `/usr/local/etc/rc.d/clef-note`:
```sh
#!/bin/sh
# PROVIDE: clef-note
# REQUIRE: NETWORKING
# KEYWORD: shutdown
. /etc/rc.subr
name="clef-note"
rcvar="clef-note_enable"
command="/opt/clef-note/clef-note"
pidfile="/var/run/${name}.pid"
load_rc_config $name
run_rc_command "$1"
```
```bash
chmod +x /usr/local/etc/rc.d/clef-note
echo 'clef-note_enable="YES"' >> /etc/rc.conf
service clef-note start
```
---
## Configuration
All configuration lives in `clef-note.toml`, looked up next to the binary by default. A template is provided at [`clef-note.toml.example`](clef-note.toml.example).
```toml
# Required — hash with: ./clef-note --hash-password "yourpassword"
password = "$argon2id$v=19$..."
# Optional
# storage = "/mnt/notes" # default: ../storage relative to the binary
# api_key = "" # CLI/REST access — openssl rand -hex 32
```
**CLI flags** (override the config file):
```
--storage Override the notes storage directory
--port Listening port (default: 3000)
--config Path to clef-note.toml
--hash-password Print Argon2 hash and exit
```
### Storage layout
Data lives under the storage directory:
```
storage/
notes/ ← Markdown files (sub-directories supported)
assets/ ← uploaded images
drawings/ ← Excalidraw diagrams (.excalidraw)
```
A note named `work/meeting` is stored as `storage/notes/work/meeting.md`. The folder can be moved freely — no database, no lock-in.
To import existing notes, copy your `.md` files into `storage/notes/` — they will appear automatically on next startup.
### Authentication
| Client | Mechanism |
|--------|-----------|
| Web UI | Password → session token (localStorage, 30-day TTL) |
| CLI (`scripts/an`) | `AN_KEY` env var = `api_key` from config |
The web UI shows a login page on first visit. Sessions expire after 30 days or on sign out.
---
## API Reference
All endpoints are served by the Rust backend on port `3000`.
| Method | Path | Description |
|----------|-----------------------|--------------------------------------|
| `GET` | `/notes` | List all notes |
| `GET` | `/notes/{*name}` | Read note (`{name, content, frontmatter}`) |
| `PUT` | `/notes/{*name}` | Create or overwrite note (`{content}`) |
| `PATCH` | `/notes/{*name}` | Rename note (`{new_name}`) |
| `DELETE` | `/notes/{*name}` | Delete note |
| `GET` | `/backlinks/{*name}` | Backlinks for a note |
| `POST` | `/assets` | Upload image (multipart), returns `{url}` |
| `GET` | `/api/search?q=` | Full-text search |
| `GET` | `/api/query?q=` | DSL metadata query |
### Query DSL examples
Filters are combined with implicit AND. Tokens are whitespace-separated.
```
#work status:active → tagged "work" AND status "active"
#work OR #perso → tagged "work" or "perso"
NOT status:archived → all notes except archived
recent:10 → 10 most recently modified notes
oldest:5 → 5 least recently modified notes
date:2025-04 type:meeting → meetings from April 2025
#journal order by date desc → journal notes, newest frontmatter date first
recent:10 order by title → 10 freshest notes, sorted alphabetically
status:active order by due → active tasks sorted by due date
area:pro type:meeting print title date → meetings with only title and date columns
```
**Filters:** bare word, `#tag`, `tag:`, `title:`, `path:`, `name:`, `depth:`, `status:`, `type:`, `area:`, `author:`, `rating:`, `date:`, `due:`, `lastModified:`, `url:`, `alias:`, `pinned:`, `priority:`, `project:`
**Limiters:** `recent:n`, `oldest:n` — by filesystem modification date
**Sort:** `order by [asc|desc]` — fields: `name`, `title`, `date`, `modified`, `due`, `status`, `rating`, `area`, `author`, `priority`, `project`, `lastModified`
**Columns:** `print [field2 …]` — fields: `name`, `title`, `tags`, `date`, `status`, `area`, `author`, `due`, `rating`, `url`, `priority`, `project`
---
## Keyboard Shortcuts
### Navigation
| Shortcut | Action |
|----------------|-----------------------------------------------------|
| `Ctrl+K` | Open command palette |
| `Ctrl+Shift+H` | Go to home page (set in Settings → General) |
| `Ctrl+Shift+P` | Navigate back in history |
| `Ctrl+Shift+N` | Navigate forward in history |
### Editor
| Shortcut | Action |
|----------------|-------------------------------|
| `/` | Open slash-command menu |
| `[[` | Start a WikiLink |
| `:shortcode:` | Insert emoji (`:smile:` → 😊) |
| `Ctrl+S` | Save (auto-save also active) |
| `Ctrl+B/I` | Bold / Italic |
| `Ctrl+Z` | Undo |
---
## License
MIT