Documentation
¶
Overview ¶
Package memory implements OK's persistent memory. It mirrors Claude Code's two-layer model while honoring OK's cache-first architecture:
- Hierarchical doc memory: AGENTS.md / OK.md files discovered from the user config dir and up the project tree, with "@path" imports. This is the analog of CLAUDE.md.
- Auto-memory store: per-project fact files with frontmatter plus a MEMORY.md index, which the model maintains via the `remember` tool (see store.go).
All of it folds into the durable system-prompt prefix exactly once at boot (see Compose), so it rides DeepSeek's automatic prefix cache at zero per-turn cost. Mid-session changes never mutate that prefix; they take effect through the controller's transient tail-injection and fold into the prefix on the next session.
Index ¶
Constants ¶
const MaxMemoryEntries = 80
MaxMemoryEntries caps the number of auto-memory files per project. Beyond this limit the oldest entries are pruned on each Save AND at load time to keep the system-prompt prefix lean and prevent unbounded disk growth.
const MaxQuickNotes = 30
MaxQuickNotes caps the number of bullet entries under ## Notes in a doc-memory file. Older entries are trimmed when new ones are added beyond this limit, preventing unbounded prefix bloat.
MaxSharedMemoryEntries caps shared memory files. Shared memories load into every project's system prefix, so they must stay much leaner than per-project memories. Beyond this limit the oldest entries are pruned on each Save.
Variables ¶
This section is empty.
Functions ¶
func AppendDoc ¶
AppendDoc appends a one-line note as a bullet under a "## Notes" section in the doc-memory file at path, creating the file (and section) when absent. The note is normalised to a single line so it can't corrupt the section. This is the write side of the "#" quick-add: a plain file edit the user can later reorganise by hand.
Uses a temp-file + rename to avoid TOCTOU: concurrent quick-adds or external edits between read and write are visible as a rename failure instead of a silent overwrite.
func Compose ¶
Compose folds the memory block onto the base system prompt and returns the durable cached-prefix string. Base stays first (it is the most stable text, so it remains a valid cache prefix even when memory changes between sessions); memory follows. With no memory, base is returned unchanged.
func NewRememberTool ¶
NewRememberTool returns the `remember` tool bound to store. A zero/disabled store yields a tool that reports the store is unavailable rather than silently dropping saves.
Types ¶
type Memory ¶
type Memory struct {
Name string // kebab-case slug; also the file stem (<name>.md)
Description string // one-line summary used for the index and recall
Type Type
Body string // the fact itself (Markdown)
}
Memory is one stored fact.
type Options ¶
type Options struct {
CWD string
UserDir string
Store Store // optional: reuse an existing store instead of creating a new one
}
Options configures discovery. CWD defaults to "." and UserDir is the user config root (config.MemoryUserDir()); a "" UserDir disables user-global docs and the auto-memory store. Store, when non-zero, reuses an existing store instead of creating a new one — use this to keep the `remember` tool's handle consistent across memory refreshes.
type Scope ¶
type Scope string
Scope labels where a doc source was discovered, so the assembled block can attribute each chunk and callers (e.g. the `#` quick-add picker) can offer meaningful targets.
type Set ¶
type Set struct {
Docs []Source // memory docs, ascending precedence
Store Store // auto-memory store (may be a zero/disabled Store)
Index string // MEMORY.md contents at load time
CWD string // project working dir used for discovery
UserDir string // user config root (may be "")
}
Set is everything memory loaded for one session: the hierarchical docs and a handle to the auto-memory store (whose index is captured at load time). It is assembled once at boot and folded into the system prompt by Compose. CWD and UserDir are retained so the controller can resolve quick-add targets without re-deriving discovery context.
func Load ¶
Load discovers all memory for a session: the hierarchical docs and the auto-memory index. It is best-effort and never errors — missing files just mean less memory — so boot can call it unconditionally.
On every load, the auto-memory store is compacted: oldest entries beyond MaxMemoryEntries are deleted and the index is rebuilt. This prevents unbounded growth from auto-learned entries and keeps the disk footprint small. Runs inside the ok process — not subject to sandbox file-access restrictions.
func (*Set) Block ¶
Block renders the memory as a single Markdown section, or "" when empty. It is deterministic given the same files, which is what keeps it a stable cache prefix across sessions that don't change their memory.
func (*Set) DocPath ¶
DocPath returns the doc-memory file a given scope writes to. To avoid splitting a project's memory across conventions, it prefers a file that already exists (AGENTS.md / CLAUDE.md, in that order); when none exists it creates the universal default (AGENTS.md / AGENTS.local.md). ScopeUser → <userDir>, ScopeLocal → <cwd> with the *.local.md names, anything else → <cwd>. Returns "" for ScopeUser when no user dir is configured.
func (*Set) Empty ¶
Empty reports whether the set carries nothing to inject, so Compose can leave the base prompt byte-for-byte untouched (and the cache prefix maximal) when there is no memory at all.
func (*Set) WriteDoc ¶
WriteDoc overwrites a doc-memory file with body, after checking path is a recognized memory file (see allowedDocPaths). It is the save side of the desktop panel's in-place editor. The write lands on disk immediately but does NOT mutate the cache-stable system prefix — the edit folds into the prefix on the next session; to make it apply this session, the controller separately queues a turn-tail note. Returns the path written.
type Store ¶
type Store struct {
Dir string // ...ok/projects/<slug>/memory
// contains filtered or unexported fields
}
Store is the per-project auto-memory: a directory of one-fact-per-file Markdown notes with frontmatter, plus a MEMORY.md index of one line per fact. The model maintains it through the `remember` tool; the index loads into the cached system-prompt prefix at boot so the model always knows what it has saved, and reads individual facts on demand with read_file. The whole thing is plain files the user can edit by hand.
func SharedStoreFor ¶
SharedStoreFor returns a Store that is NOT scoped to a specific project. Facts saved here load for every project the user runs. Use sparingly — only for truly cross-cutting knowledge (e.g. "user prefers tab indentation in every project", "global coding conventions across all projects", etc.).
Shared memories appear in the system prompt alongside project-specific memories, but are stored under ~/.config/ok/shared/memory/.
func StoreFor ¶
StoreFor resolves the auto-memory directory for a project working dir under the user config root, e.g. ~/.config/ok/projects/-Users-me-proj/memory. A "" userDir (config dir unresolvable) yields a zero Store, which all methods treat as a disabled no-op.
func (Store) Compact ¶
func (s Store) Compact()
Compact prunes oldest entries beyond MaxMemoryEntries. When files are actually deleted, it also rebuilds the index so MEMORY.md never references missing entries. When nothing is pruned, the index is left untouched — this preserves cache stability (byte-identical system prefix) and any hand-edits the user made to MEMORY.md. Idempotent; nil store or empty dir is a no-op.
func (Store) Index ¶
Index returns the MEMORY.md contents (the per-line index of saved memories), or "" if there are none yet. This is what loads into the cached prefix.
func (Store) List ¶
List returns the saved memories parsed from their files, sorted by name. Used by `/memory` and the desktop memory panel. Files that fail to parse are skipped so one bad file never hides the rest.
type Type ¶
type Type string
Type classifies a memory, mirroring the auto-memory taxonomy.
const ( TypeUser Type = "user" // who the user is: role, preferences, expertise TypeFeedback Type = "feedback" // guidance on how to work (with why + how-to-apply) TypeProject Type = "project" // ongoing work / goals / constraints not in the code TypeReference Type = "reference" // pointers to external resources (URLs, tickets) )
func NormalizeType ¶
NormalizeType coerces an arbitrary string to a known Type, defaulting to TypeProject so a sloppy tool argument never blocks a save.