# heph.nvim The primary surface for [hephaestus](../README.md) — an obsidian.nvim replacement that is a thin client of the local `hephd` daemon over its unix-socket JSON-RPC (tech-spec §8). Notes, journals, and tasks are edited as ordinary Neovim buffers; saving routes through the daemon. > **Status:** built in checkpointed slices. **11a (this slice)** delivers the > RPC client, buffer-backed editing, `[[wiki-link]]` following, and the daily > journal. Task/agenda views (`:Heph next`/`list`/capture), the per-task log, > and promotion arrive in 11b/11c. See tech-spec §14. ## How it works - **Buffer-backed nodes.** A node is edited in a buffer named `heph://node/`. Opening it loads the markdown body via `node.get`; `:w` saves the whole buffer back via `node.update` (the backend diffs it into a text CRDT, so sending the full buffer is correct). `buftype=acwrite`. - **Links.** Press `` on a `[[wiki-link]]` to jump to its node (resolved exactly via `node.resolve`). Unresolved links are allowed — they just notify. - **Journal.** `:Heph today` (or `:Heph journal YYYY-MM-DD`) opens a dated journal note; the id is deterministic so reopening is idempotent. ## Setup Requires Neovim ≥ 0.10 and `hephd` on `PATH` (e.g. `cargo install`ed). By default the plugin is **plug-and-play** — it starts and manages its own `hephd`: ```lua require("heph").setup({}) -- spawns a local hephd against the default XDG paths ``` - **`autostart = true`** (default): if nothing is serving the socket, the plugin spawns a local `hephd`, kills only what *it* spawned on exit, and **self-heals** (respawns + reconnects if the daemon dies mid-session). - **Running your own daemon** (a `server`/`client` architecture, or a launchd service)? Set `autostart = false` and point at its socket — the plugin then **connects only**, never spawning over your daemon, and warns if it's unreachable. A daemon already serving the socket is always respected, even with `autostart = true` (the plugin only spawns when nothing is there). ```lua require("heph").setup({ -- socket = "...", -- default: $HEPH_SOCKET, else hephd's XDG path -- db = "...", -- DB for an autostarted daemon ($HEPH_DB, else default) -- autostart = true, -- false = connect-only (you run hephd yourself) -- bin = "hephd", -- daemon binary for autostart -- keymaps = true, -- h* maps }) ``` **Dev isolation:** set `$HEPH_SOCKET` / `$HEPH_DB` (or run `mise run dev`) so a development Neovim drives a separate daemon + DB and never touches real data. ## Commands | Command | Action | |---|---| | `:Heph today` | Open today's journal | | `:Heph journal ` | Open a dated journal | | `:Heph follow` | Follow the `[[link]]` under the cursor (also ``) | | `:Heph open ` | Open a node buffer by id | ## Tests The e2e suite drives the plugin in headless Neovim against a real daemon: ```bash mise run test-nvim # builds hephd, runs the headless e2e suite ``` The suite uses a small self-contained busted-style runner (`tests/e2e/runner.lua`) — no external plugins and no network, so it is deterministic. Dev runs use system-installed Neovim (≥ 0.10) + rustc; CI runs the same suite inside a Dagger container that provides them (slice 11c).