sapphire-journal
Unified binary for sapphire-journal — a Markdown-based task and note manager. Provides both the CLI for humans and an MCP server for AI agents.
Installation
Install script (Linux / macOS)
|
Install script (Windows)
irm https://raw.githubusercontent.com/fluo10/sapphire-journal/main/install.ps1 | iex
From crates.io
From source
CLI usage
Initialize a journal
Creates .sapphire-journal/config.toml with the detected local timezone and .sapphire-journal/.gitignore.
Global options
# Override journal root (also settable via SAPPHIRE_JOURNAL_DIR env var)
Entry commands
Create a new entry
Options:
--slug SLUG— override the filename slug--tags tag1,tag2— set tags--task-due DATETIME— set task due date--task-status STATUS— set task status (open|in_progress|done|cancelled|archived)--event-start DATETIME,--event-end DATETIME
The filename is auto-generated as {year}/{grain-id}_{slug}.md.
Create and edit in $EDITOR
Opens $EDITOR ($VISUAL → $EDITOR → vi) with a pre-filled frontmatter template. On save, the filename is adjusted to match the title.
List entries
Timestamp filters (OR'd across fields):
PERIOD formats: today | yesterday | this_week | last_week | this_month | last_month | YYYY-MM-DD | YYYY-MM-DD,YYYY-MM-DD | YYYY-MM-DDTHH:MM,YYYY-MM-DDTHH:MM
Task state filters:
Other filters (AND'd on top):
Sort:
Output:
Display entries as a tree
Displays entries in a parent-child hierarchy based on parent_id in frontmatter.
Supports the same filter and sort options as entry list.
Show an entry
Edit an entry
Opens the entry in $EDITOR.
Update frontmatter fields
When --task-status is set to done, cancelled, or archived, closed_at is set automatically.
Check and fix filename
Remove an entry
Cache commands
DATETIME format
YYYY-MM-DD or YYYY-MM-DDTHH:MM.
For deadline/end timestamps (--task-due, --event-end), date-only input is interpreted as 23:59.
For start/close timestamps (--event-start, --task-closed-at), date-only input is interpreted as 00:00.
Journal configuration
.sapphire-journal/config.toml:
[]
= "Asia/Tokyo" # IANA timezone name
# week_start is deprecated — ISO weeks (Monday start) are always used
MCP server
The MCP (Model Context Protocol) server now ships as a separate sapphire-journal-mcp binary in the sapphire-journal-mcp crate. Install it alongside the CLI to let AI agents (Claude, etc.) read and write journal entries.
Start the server
# Open the journal found by walking up from the current directory
# Open an explicit journal path
# Create the journal (and the directory itself) if it doesn't exist, then open it
The server fails to start when the target directory is not a sapphire-journal — pass --init to have the server create one in place (no-op when one already exists there).
Flags and environment variables
| Flag / Variable | Description |
|---|---|
--journal-dir <DIR> / SAPPHIRE_JOURNAL_DIR |
Path to the journal root. If not set, the server walks up from the current directory to find .sapphire-journal/. |
--init |
Initialize the target directory as a sapphire-journal if it isn't one already (and create the directory itself if missing). |
Example: Claude Desktop
Available tools
| Tool | Description |
|---|---|
entry_list |
List entries as JSON with filtering and sorting |
entry_tree |
List entries as a nested JSON tree (parent-child hierarchy) |
entry_show |
Show the contents of an entry by ID prefix or file path |
entry_new |
Create a new journal entry |
entry_modify |
Update frontmatter fields of an existing entry |
entry_check |
Validate an entry's frontmatter and filename |
entry_fix |
Rename an entry file to match its frontmatter |
entry_remove |
Delete an entry file |
entry_search |
Search entries (vector when embeddings are enabled, FTS otherwise) |
cache_info |
Show cache status and statistics |
cache_sync |
Incrementally update the SQLite cache |
cache_rebuild |
Drop and rebuild the cache from scratch |
git_sync |
Commit, fetch, merge, and push if a sync backend is configured |
entry_list parameters
Timestamp filters are OR'd across fields; task_status and tags are AND'd on top.
| Parameter | Description |
|---|---|
period |
Shorthand: applies to all timestamp fields |
task_due |
Filter by task due date |
event_span |
Filter by event span overlap: matches entries whose event [start, end] overlaps the period |
created_at |
Filter by created_at |
updated_at |
Filter by updated_at |
task_overdue |
Include tasks whose due date is past and not closed |
task_in_progress |
Include tasks currently in_progress |
task_unstarted |
Include tasks with status open and no started_at |
active |
Composite: overdue OR in-progress |
task_status |
Array of statuses to include, e.g. ["open", "in_progress"] |
tags |
Array of tags; entry must have ALL specified tags |
sort_by |
Field to sort by: id | title | task_status | created_at | updated_at | task_due | event_start | event_end |
sort_order |
"asc" (default) or "desc" |
PERIOD format: today | this_week | this_month | yesterday | last_week | last_month | YYYY-MM-DD | YYYY-MM-DD,YYYY-MM-DD | YYYY-MM-DDTHH:MM,YYYY-MM-DDTHH:MM
License
MIT OR Apache-2.0