Expand description
Core of the Kimün note-taking app: all file operations, indexing, and note manipulation, with no presentation concerns.
The public surface is the NoteVault facade. A vault is a directory of
Markdown notes on disk; NoteVault owns the operations over it (create,
read, write, rename, search, browse) and is cheap to clone.
A few conventions shape this crate:
VaultPathfor vault-internal paths. Everything addressed inside the vault usesVaultPath, a case-insensitive,/-separated, OS-agnostic path. OS path types are reserved for configuration values (the workspace root) and for converting back to a real filesystem location when a caller needs one.- The index is a cache. Search, backlinks, suggestions, and listings are served from a SQLite index that mirrors the notes on disk. It can be rebuilt at any time from the files, which remain the source of truth.
nfsandsystemown the filesystem. Every directstd::fs/tokio::fscall lives in one of them:nfsfor vault-scoped work (notes, addressed byVaultPath) andsystemfor host-scoped work (the app’s own directories, cross-volume moves). The rest of the crate goes through them.
§Example
Create a vault in a temporary directory, write a note, and read it back:
use kimun_core::{NoteVault, SystemPath, VaultConfig};
use kimun_core::nfs::VaultPath;
let dir = tempfile::tempdir().unwrap();
let root = SystemPath::try_absolute(dir.path()).unwrap();
let rt = tokio::runtime::Runtime::new().unwrap();
rt.block_on(async {
let vault = NoteVault::new(VaultConfig::new(root)).await.unwrap();
let path = VaultPath::new("/hello.md");
vault.create_note(&path, "# Hello\n").await.unwrap();
let text = vault.get_note_text(&path).await.unwrap();
assert_eq!(text, "# Hello\n");
});Re-exports§
pub use nfs::saved_searches::saved_search_name_matches;pub use nfs::saved_searches::SavedSearch;pub use nfs::vault_id::VaultId;pub use nfs::EntryKind;pub use system::Host;pub use system::SystemPath;
Modules§
- error
- Error types returned across the crate’s public API.
- nfs
- Vault-scoped filesystem layer: notes, attachments and backups inside one
workspace, addressed by the
VaultPathvault-internal path type. Paired withsystem, which owns host-scoped paths and operations. - note
- Note model: parsing Markdown into details, chunks, links, and tags.
- system
- Host-scoped paths and file operations: the machine kimün runs on, its directories, and the file operations carrying OS-specific knowledge. Host-scoped paths and file operations: the machine kimün runs on.
Structs§
- Attachment
Details - Read-only details of an attachment, for the attachment view: its identity, size, last-modified time, extension, and previewable content.
- Directory
Details - A directory entry within the vault.
- Index
Diff - The diff a vault sync walk produces and
NoteIndex::applyconsumes in one atomic operation — the currency crossing the index’s interface. The order ofto_addandto_modifyis non-deterministic: they are populated by parallel walker threads and entries land in the order each thread completes its file read. - Index
File - A workspace’s index file on this machine — the whole artifact, sidecars included.
- Index
Report - Timing summary of an indexing pass.
- Note
Suggestion - A note suggestion for the autocomplete popup.
- Note
Vault - Facade over a vault: a directory of Markdown notes plus its searchable index. Cheap to clone — clones share the index pool and per-note locks.
- Query
Token Span - One classified span of a query string.
rangeindexes the original string (byte offsets), so spans can be styled in place. - Replace
Preview - Result of a dry-run replace (
NoteVault::preview_replace): how many matches would be replaced, and the note’s content after the replacement. Nothing is written to disk. - Search
Result - A single entry produced by browsing the vault: a note, directory, or attachment, identified by its path.
- Search
Terms - A search query string decomposed into the typed buckets the index turns
into an FTS query. Each prefix in the DSL routes a token into one of these
fields; bare tokens are full-text terms. This is the boundary the TUI
builds (often via
with_order_directive/quote_query_term) and the index consumes, so the DSL syntax lives entirely in core. - TagSuggestion
- A tag suggestion for the autocomplete popup.
usage_countis computed per-query viaCOUNT(*) GROUP BY nameover thelabelstable. - Vault
Browse Options - Options to traverse the Notes You need a sync::mpsc::Sender to use a channel to receive the entries
- Vault
Browse Options Builder - Builder for
VaultBrowseOptions; seeNoteVault::browse_vault. - Vault
Config - Configuration passed to
NoteVault::new.
Enums§
- Attachment
Content - The previewable content of an attachment.
- Note
Change - A note change reported by the
NoteIndexthe moment it is recorded, for consumers outside core (the RAG client). Thin by design — it carries a path, a content hash, and the kind of change, never chunk text. - Notes
Validation - How thoroughly a sync pass checks whether each note has changed before updating its index entry.
- OrderBy
- A parsed
or:/^order directive: the column to sort by together with its direction. Produced by the query parser when it encounters an order token;OrderFieldis the direction-free counterpart used by callers that carry the asc/desc choice separately. - Order
Field - The field a query can be ordered by. The asc/desc choice is carried separately by callers; this names only the column.
- Query
Token Class - Token class of a span in a query string, for syntax highlighting. Mirrors
the grammar
QueryTermExtractor::extract_and_consumeconsumes — the two must stay in step (see thelexer_agrees_with_parser_*tests). - Result
Type - Kind of a
SearchResult.
Constants§
- DEFAULT_
ASSETS_ PATH - Default directory for attachments (see
NoteVault::default_attachments_path). - DEFAULT_
INBOX_ PATH - Default directory for quick-capture notes (see
NoteVault::quick_note). - DEFAULT_
JOURNAL_ PATH - Default directory for journal entries, one note per day.
- MAX_
CONFLICT_ ATTEMPTS - How many incremented names (
VaultPath::get_name_on_conflict) a conflict-avoiding create tries before giving up. High enough that no real vault reaches it, low enough to bound the work when something pathological (a name every increment collides with) would otherwise spin forever. Shared byNoteVault::free_note_pathandNoteVault::create_note_avoiding_conflictsso the name they pick agrees.
Traits§
- Index
Observer - Observer of index mutations, registered zero-or-one on a vault via
NoteVault::set_index_observer. The index callson_changesynchronously right after a write commits, so an implementation must be cheap and non-blocking — no network, noawait; fold the event into a queue and drain it elsewhere.
Functions§
- expand_
bare_ note_ prefixes - Return
querywith every bare note-targeting prefix —</>/=, their long formslk:/fwd:/name:, and the-exclusion variants — expanded to<prefix><target>. A prefix is bare when the whole token is exactly the prefix. Tokenization follows the parser’s grammar: an unquoted token ends at an ASCII space (only — a tab or NBSP is part of the token, exactly as the parser reads it), a quote is honored only at a value start (the start of a token or right after a prefix), and a quoted value may span spaces. Everything else, including whitespace, is preserved verbatim, so the result is the same query with only the bare prefixes rewritten. - query_
has_ unterminated_ quote - True if
queryends in an unterminated quoted value — the only real parse error the lenient grammar produces (the parser silently drops the rest of the string). - query_
token_ spans - Lex
queryinto classified spans for syntax highlighting. Whitespace is not covered by any span. The lexer follows the parser’s grammar exactly: tokens split on ASCII space, a prefix is recognized at a token start, a quote is honored only at a value start, and an unterminated quote swallows the rest of the string (classifiedQueryTokenClass::Unterminated). - quote_
query_ term - Wrap
termin the search DSL’s quote characters when it contains whitespace, so a multi-word value (e.g. a note name with spaces) is parsed as a single token instead of being split across terms. Values without whitespace are returned unchanged. Note names can never contain"(invalid on Windows/macOS/Linux filesystems alike), so no escaping is needed. - strip_
order_ directive - Return
querywith any order directive (or:/-or:/^/-^, in any position) removed. Other tokens keep their order; whitespace is normalised to single spaces. The DSL knowledge lives here in core so the TUI never hardcodes the directive syntax. - with_
order_ directive - Return
querywith its order directive replaced byfield/asc.