summaryrefslogtreecommitdiff
path: root/README.md
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-08-02 23:43:08 -0300
committerGabriel Schneider <[email protected]>2026-08-03 09:54:39 -0300
commit5ec72f8723d795d0b02d7e9ebb9f555f0c7e6a2e (patch)
treef12f4b700fff4ff6f7e818d2a542672ba0b8d76e /README.md
parenta9263daee9413c5eff3c1f1bebcd224442fd8685 (diff)
downloadnotevi-5ec72f8723d795d0b02d7e9ebb9f555f0c7e6a2e.tar.gz
notevi-5ec72f8723d795d0b02d7e9ebb9f555f0c7e6a2e.zip
rebrand to notevi: one CLI over the jj sidecar
vr and vrsite become a single binary. vrsite/ folds into a web package in one module (0x4200.cafe/notevi); "notevi web" serves and exports exactly what vrsite did, and "notevi read/grep/note/query" is unchanged. The sidecar is renamed with it: notevi_log, notevi-log.jsonl, and the description "private: notevi log". The pre-rebrand names are still recognized, so an old repository opens and reads; it is renamed in place on the first write, or up front with "notevi migrate DIR...". That rename cannot be a single mv inside jj run. jj only auto-tracks a *new* file in the run working copy below a size limit it does not take from the command line, so writing a whole log under a name the change has never held is silently dropped while jj reports success. ensureLogFile creates the file empty first and lets every later byte be a modification of a tracked file, which snapshots at any size; that also fixes the same latent bug when importing a large legacy vr-log.jsonl. Adds a bem-te-vi mark (favicon and nav brand) and a README. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Diffstat (limited to 'README.md')
-rw-r--r--README.md125
1 files changed, 125 insertions, 0 deletions
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..3ca6eff
--- /dev/null
+++ b/README.md
@@ -0,0 +1,125 @@
+<img src="web/assets/bemtevi.svg" width="96" align="right" alt="">
+
+# notevi
+
+A code reader that remembers. Read files and grep through `notevi`, pin notes to
+line ranges, and every one of those calls is appended as a single JSON line to
+an **append-only JSONL log** kept in a **private jj commit**. Not your working
+copy. Not your history.
+
+Two front ends over that one log — a CLI and a local web app. Both read it, both
+write to it. Use either. Use only one.
+
+The bem-te-vi calls all day and keeps a bright crown patch hidden under a plain
+black cap. Same idea: the notes are always there, never in the way.
+
+## Install
+
+```sh
+go build -o ~/.local/bin/notevi .
+```
+
+Needs `jj` (the repo must be a jj workspace) and `rg` for working-copy greps.
+
+## From the shell
+
+```sh
+notevi read src/lib.rs # whole file, line-numbered
+notevi read src/lib.rs:120-180 # just the range
+notevi grep 'fn resolve' src/ # regex over the working copy
+
+notevi note -f src/lib.rs:143 -t invariant "holds only under the bank lock"
+notevi note -reply 12 "no — see the early return above"
+
+notevi query -op note # replay the log, oldest first
+notevi query -file accounts_db # everything touching a path
+```
+
+Add `-r REV` to any of them to work at another revision — any jj revset, default
+`@`. Every entry records the full change **and** commit id, so a note stays
+pinned to the exact bytes it was about even after the change is rewritten.
+Notes take an optional `-t KIND` (`fn`, `struct`, `invariant`, whatever you
+want) and can reply to each other by number.
+
+## From the browser
+
+```sh
+notevi web # dashboard: every sidecar under ~
+notevi web -repo . # one repo, http://127.0.0.1:4200
+```
+
+**This is not a viewer.** Click a line, type, and the note is appended to the
+same JSONL log `notevi note` writes to — same numbering, same permalinks, at the
+exact change and commit you are looking at, attributed to your username. Reply
+to notes, thread them, filter by file, text, kind, author, model, session,
+change or date range. Never open the CLI and you lose nothing.
+
+What it shows:
+
+- the repo tree with per-reader coverage, and sources highlighted by tree-sitter
+ with coverage-tinted line numbers — the colors mix where readers overlap
+- every note pinned to its lines, plus a notes-only mode across the whole repo
+- who is reading right now, refreshed every few seconds
+- ad-hoc jj queries over the repo
+- every Zed and Helix theme installed on the machine, previewed live as you
+ arrow through the picker
+
+The dashboard scans `~` for repositories, and can start a sidecar in a jj repo
+or add colocated jj to a Git one — so a project can begin in the browser too.
+It writes no registry and no scan cache.
+
+```sh
+notevi web -repo . -out site # static export: hand it to someone
+```
+
+The export is a plain directory of HTML. Tree, coverage, highlighting, notes,
+filters and the file finder all still work with no server; writing notes, live
+activity and jj queries do not, because there is nothing running.
+
+## The log
+
+One file, `notevi-log.jsonl`, only ever appended to. Lines are never edited and
+never deleted: a note you got wrong is superseded by a later note, not rewritten,
+so the trace stays a faithful record of what was believed when. Which also means
+you can skip the tooling entirely:
+
+```sh
+jj file show -r 'exactly(notevi_log, 1)' -- notevi-log.jsonl |
+ jq -c 'select(.op == "note") | {file, start, text}'
+```
+
+That file lives in one anonymous commit whose parent is `root()`, described
+`private: notevi log`. The repo-local revset alias `notevi_log` names it and
+`git.private-commits` keeps it from being pushed. Each append is a new revision
+of that commit, so the evolog is the log's own history:
+
+```sh
+jj evolog -r 'exactly(notevi_log, 1)' --reversed -p --git
+```
+
+Appends are serialized and go through an isolated `jj run`; your `@` is never
+snapshotted or moved. There is no bookmark and no push — **a fresh clone will
+not have your notes.** Back up the jj repo, or export the site.
+
+## If a coding agent is the one running it
+
+`notevi` notices. It reads the harness environment (Claude Code, Codex, Hermes),
+falling back to walking the process tree, and adds session id, model and
+reasoning effort to every entry it writes. Nothing to configure; a human at a
+shell just gets entries without those fields.
+
+That turns the trace into a record of what an agent actually looked at before it
+told you something. The web view colors coverage per reader, so overlapping
+work is visible, and each note links to the conversation turn it came from.
+
+`constrain/` goes further and makes `notevi` the *only* way to read: a Claude
+Code `PreToolUse` hook and a codex execpolicy ruleset that deny
+`cat`/`rg`/`sed`/`jj file show`/`git show`/… and point the agent at
+`notevi -doc`. Agents converge on it with zero instructions. See
+`constrain/README.txt`.
+
+## Coming from `vr` / `vrsite`
+
+Same tool, one binary. Old sidecars (`vr_log`, `vr-log.jsonl`) are still
+recognized and renamed in place on first write; `notevi migrate DIR...` does it
+up front.