# mori
git for cognition
mori keeps local history for documents, chats, and notes. You stage files, commit them onto branches, and later look them up with log, recall, and find. STTP is the structured memory format Locus uses; mori compiles files into it so you don't write it by hand. The history is stored in a SurrealKV file inside the repo.
mori is the cognition VCS. [Locus](https://github.com/EntasisLabs/locus) is the engine.
## Status
Apache-2.0. 0.2.0 is a local CLI for now: no remote and no forge. Install from crates.io or GitHub Releases.
## Install
`cargo install mori-cli` is the usual path. The crates.io package is `mori-cli`; the binary it installs is still `mori`. You need a recent stable Rust toolchain.
```bash
cargo install mori-cli
```
The install script downloads the matching GitHub Release archive and puts `mori` in `~/.local/bin`.
```bash
`~/.local/bin` needs to be on `PATH`. Set `MORI_INSTALL_DIR` to choose another directory. `/usr/local/bin` is the other common choice:
```bash
`MORI_VERSION=v0.2.0` installs that tag instead of the latest release. The script supports Linux x86_64, macOS (Apple Silicon and Intel), and Windows x86_64 from Git Bash. The Linux archive is built on Ubuntu 24.04; on an older glibc, use `cargo install mori-cli`.
To build from a clone:
```bash
git clone https://github.com/EntasisLabs/mori
cd mori
cargo install --path .
```
`cargo build --release` writes `target/release/mori` and does not install it. `rust-toolchain.toml` selects the stable channel.
There is no daemon. Each command opens the store, does one thing, and disconnects.
## Usage
```bash
mori init
mori add notes.md
mori add thread.json --kind chat
mori status
mori compile notes.md
mori commit -m "save the notes"
mori log
mori recall "notes"
mori find --contains notes
mori show <commit> --raw
```
`add` detects the kind from the file. Set `--kind` to `document`, `chat`, `note`, `context`, or `sttp` to override detection. `auto` is the default. Pass `-` to read stdin.
`compile` prints STTP and does not store it. With no paths, it compiles whatever is staged.
`commit` requires `-m`. `log` lists commits on the current branch, newest first, 20 by default (`-n` changes the limit). `show` takes a commit id or a unique prefix.
`recall` ranks stored context against the query (8 hits by default). `find` filters without ranking. `log`, `status`, `recall`, and `find` print the summary. The STTP text stays in the store until you ask for it with `compile`, `show --raw`, or `recall --raw`.
## Notes
`note` stages a freeform thought with no file. Each note is one index entry (`kind` `note`) and stays there until `commit`. Later notes append.
```bash
mori note -m "remember to check on-call docs before asking for escalation" --tag oncall
mori note -m "also verify pagerduty routing" --session procedures --tag oncall
mori status
mori commit -m "oncall reminders"
```
`--session` and `--tag` work the same way as `add`. Omit `-m` and pipe the text, or pass `-` to read stdin.
```bash
```
## Tags
`--tag` is a facet on the context, separate from `--session`. Repeat it, or pass a comma-separated list. Tags are stored with the `document` and `source:` tags mori already writes. `recall` and `find` require every tag you pass.
```bash
mori add notes.md --tag homelab --tag pxe --tag jellyfin
mori add notes.md --tag homelab,pxe,jellyfin
mori commit -m "homelab notes"
mori recall --tag jellyfin
mori recall "boot" --tag pxe --tag homelab
mori find --tag homelab
```
`status`, `log`, and `show` list the tags you added. A one-word `recall` query filters on that word. A query with two or more content words is ranked as before.
## Excerpts
Summary lines stay the default. `--excerpt` prints the matching section of each hit, with the file path and heading. Plain text is cut on blank lines. `--match` is a case-insensitive regular expression: it filters hits, and with `--excerpt` it chooses the sections. `-C` keeps that many lines around each match. `--full` prints the stored text of each hit. `--raw` still prints STTP.
```bash
mori recall "pagerduty escalation" --excerpt
mori recall "pagerduty" --excerpt -C 2
mori recall "pagerduty escalation" --full
```
## Branches
A branch is a name pointing at a commit. `log`, `recall`, and `find` follow every parent from that commit. A merge makes both sides visible. Context committed only on another branch stays out of view. Shared history stays visible on both. Nodes are not copied.
```bash
mori branch
mori branch design
mori checkout -b design
mori checkout main
```
`branch` with no name lists branches and marks the current one with `*`. `branch <name>` creates a branch at the current tip. `checkout -b` creates that branch and switches to it. `checkout` refuses when context is staged and you are switching branches.
`stash` parks the index so you can check out another branch. `stash pop` restores the newest entry onto an empty index. `stash drop` discards the newest entry.
```bash
mori stash -m "hold the design notes"
mori stash list
mori stash pop
mori stash drop
```
`reset` unstages. With no paths it clears the index and leaves stored memory and the stash alone.
```bash
mori reset
mori reset notes.md
```
`merge` brings another branch into the current one. If the current tip already contains the other branch, mori leaves the pointer where it is. If the other branch contains the current tip, mori moves the pointer forward. Otherwise it writes a merge commit with both parents and no new context. Stored context is additive, so both sides stay visible and there is no content-conflict step.
`rebase` replays the commits that belong only to the current branch onto another tip. The branch you rebase onto stays where it is. `rebase` refuses a merge commit, because replaying one would drop a parent.
`merge` and `rebase` refuse when context is staged. This history is local to the repo.
```bash
mori merge design
mori merge design -m "bring the design notes back"
mori rebase main
```
## Sessions
`--session` is a label Locus stores on the context. `checkout` is what changes the branch. The default session is `main`.
```bash
mori init --session design
mori add design.md --session design
mori recall "layout" --session design
mori find --session design
```
`init --session` sets the repo default. `add --session` labels the files in that command. `recall` and `find` take `--session` to limit the search to that label.
## Layout
```text
.mori/
config.json repo settings, including the default session
index.json staged context that is not stored yet
stash.json parked index entries, written on the first stash
kv/ embedded SurrealKV directory
```
`add` and `compile` never open `kv/`. Commands that read or write memory open it and disconnect before they return.
## What gets stored
| document, note, context | Locus `build_content_from_text`, then a canonical STTP document |
| chat (JSON messages, or `user:` / `assistant:` lines) | same compiler, with each turn nested under a conversation |
| raw STTP | validated and parsed, then stored as-is |
## License
Apache-2.0. See [LICENSE](LICENSE).