Skip to content

Latest commit

 

History

History
144 lines (102 loc) · 4.64 KB

File metadata and controls

144 lines (102 loc) · 4.64 KB

Note Versioning

All notes retain history on update. Previous versions are archived automatically.

Strings

Every note is a string — a linear chain of versions that grows each time you update it. Your working context (now) accumulates a string of intentions as you work. When a string of work is complete, keep move extracts matching versions by tag and strings them into a named note.

This isn't version control (no branches, no merges) and it isn't an append-only log (you can reorganize). It's the temporal dimension of how knowledge evolved — and unlike other memory stores, you can re-string it by meaning.

Version identifiers

Append @V{N} to any ID to specify a version:

  • ID@V{0} — current version
  • ID@V{1} — previous version
  • ID@V{2} — two versions ago
  • ID@V{-1} — oldest archived version
  • ID@V{-2} — second-oldest archived version
keep get "%a1b2c3d4@V{1}"        # Previous version
keep get "now@V{2}"              # Two versions ago of nowdoc
keep get "now@V{-1}"             # Oldest archived nowdoc

Accessing versions

keep get ID -V 1                 # Previous version (equivalent to @V{1})
keep get ID -V -1                # Oldest archived (equivalent to @V{-1})
keep get ID --history            # List all versions
keep now -V 1                   # Previous intentions
keep now --history              # List all nowdoc versions

History output

--history shows versions as summary lines with version identifiers:

now           2026-01-16 Current summary...
now@V{1}      2026-01-15 Previous summary...
now@V{2}      2026-01-14 Older summary...

With --ids, outputs version identifiers for piping:

keep --ids now --history
# now@V{0}
# now@V{1}
# now@V{2}

Version navigation in output

When viewing a single item (keep get, keep now), the output includes prev: and next: navigation:

---
id: %a1b2c3d4
prev:
  - @V{1} 2026-01-14 Previous summary text...
---
Current summary here...

Content-addressed IDs

Text-mode updates use content-addressed IDs for versioning:

keep put "my note"              # Creates %a1b2c3d4e5f6
keep put "my note" -t done      # Same ID, new version (tag change)
keep put "different note"       # Different ID (new document)

Same content = same ID = enables versioning via tag changes.

Restoring known content

If a note returns to content that already exists in its archived history, keep does not create a branch. It still appends a new head state to the same linear version string:

  • A -> B -> A archives A, then B, then makes A current again
  • the later B is still present in history
  • the restored A is treated as known content for that same note

When this happens, keep restores previously-known derived outputs for that content when available, including:

  • summary
  • auto-tagging results
  • embeddings

This avoids unnecessary re-summarization during checkouts and branch switches. Analysis parts are not version-restored. If parts from a later state are still attached to the note, they remain until keep analyze runs again. The tradeoff is that restored derived outputs may still be slightly stale if prompt selection or surrounding context changed while the content stayed the same.

Deleting and reverting

keep del has revert semantics when versions exist:

keep del ID                     # If versions exist: reverts to previous version
                                # If no versions: removes item entirely

Pipe composition

keep --ids now --history | xargs -I{} keep get "{}"   # Get all versions
diff <(keep get doc:1) <(keep get "doc:1@V{1}")       # Diff current vs previous

Python API

kp.get_version(id, offset=1)    # Previous version
kp.get_version(id, offset=2)    # Two versions ago
kp.list_versions(id, limit=10)  # Archived versions (newest first)

See PYTHON-API.md for complete Python API reference.

Parts vs versions

Versions and parts are complementary dimensions:

  • Versions (@V{N}) are temporal — each put adds a version
  • Parts (@P{N}) are structural — analyze decomposes content into sections

Versions accumulate (each one happened). Parts replace (each analyze produces a fresh decomposition). Both use tag-based metadata and appear in search results.

See KEEP-ANALYZE.md for details on structural decomposition.

See Also