Memory plugin (memory)

A local second brain gives one place to ask "what do we know about X?" with citations back to the source.

Command: /memory


Code discovery

See Markdown and shared discovery below for project-wide parsing/search.

Index one committed TypeScript project, then search symbol names, signatures, documentation, and structural relationships. No model, remote API, or database server is required. The project must contain committed package.json and tsconfig.json; inherited configuration and aliases are resolved by TypeScript. Project paths are relative to AppWeaver core's active workspace.

bun src/cli.ts memory code.parse '{"project":"plugins/nr"}'
bun src/cli.ts memory code.parse '{"project":"plugins/nr","fresh":true}'
bun src/cli.ts memory code.search '{"project":"plugins/nr","query":"NostrResolutionService"}'
bun src/cli.ts memory code.search '{"project":"plugins/nr","query":"NostrResolutionService","format":"json"}'
bun src/cli.ts memory code.inspect '{"project":"plugins/nr","id":"<returned-node-id>"}'
bun src/cli.ts memory code.expand '{"project":"plugins/nr","id":"<returned-node-id>","depth":2}'

Equivalent app commands use flags:

/memory code.parse --project plugins/nr
/memory code.search --project plugins/nr --query NostrResolutionService
/memory code.search --project plugins/nr --query NostrResolutionService --format json
/memory code.inspect --project plugins/nr --id <returned-node-id>
/memory code.expand --project plugins/nr --id <returned-node-id> --depth 2

All four code tools default to compact text. Use "format":"json" in tool arguments or --format json in app commands for the full typed result. Search text lists names, kinds, full callable IDs, locations and matching fields; use inspection for signatures/comments. Inspection and expansion use numbered node tables and --relation--> edges. Row numbers and F follow-up labels are local display references, not IDs. External navigation commands are shell-quoted and deduplicated. Truncation, pagination, revision drift, and indexing suggestions (which write the DB) remain visible. JSON includes all stored locations/evidence.

Indexed projects widget

Open /memory projects to view indexed projects within the active workspace as a regular timeline card, without adding a header/docked widget. Each expandable row shows files/nodes, short indexed and HEAD hashes, indexing timestamp, generation, edge/external-reference counts, hook state, last automatic run, and stored diagnostics. Current means hashes match; Outdated means they differ; Unknown means HEAD could not be read. Uncommitted code/config changes are shown separately. Dependency freshness remains unknown. Index diagnostics are collapsed and grouped by code, with readable source locations and messages on expansion. Old unresolved-call records remain readable until reindexing; raw stored diagnostics remain available in JSON output. The latest indexing attempt is tracked separately from the successful snapshot and automatic-hook log. A failed manual or automatic parse shows its reason, browser-local failure time, recovery advice, and expandable failure details even while the project row is collapsed. Refresh preserves this feedback. Successful or unchanged attempts clear the prior failure; unfinished attempts are identified as having no completed result. Compiler/cleanliness errors are separate from non-blocking graph coverage limitations. JSON includes lastAttempt. Displayed hashes use eight characters, with full values on hover and in JSON. Indexed-at and last-run timestamps use the browser's local date/time and timezone; JSON retains epoch milliseconds. CLI text uses its process-local timezone.

Refresh only reloads status. Reindex explicitly forces a rebuild (fresh: true) and refreshes the originating widget. Preview hook opens a modal with the exact command and proposed changes; its explicitly labeled Enable/Disable button calls the existing hook operation. Opening either view never changes Git settings or indexes a project. Missing project directories remain visible with disabled actions; paths outside the workspace (including symlink escapes) are excluded. Unindexed-project discovery is deferred.

bun src/cli.ts memory projects '{}'
bun src/cli.ts memory projects '{"format":"json"}'

Storage and implementation

db.sqlite lives beside the plugin. Versioned memory_code_* tables contain project snapshots, nodes, edges/evidence, compact metadata, and FTS5 search data. The input manifest records Git revisions, read hashes, and negative resolution lookups. Installed packages and ignored generated dependencies are explicitly hashed local environment inputs, not falsely labeled as Git-committed content. The additive memory_code_attempts table retains one latest attempt per project, with a monotonic ID, start/completion timestamps, outcome, and structured errors. Older concurrent completions cannot overwrite a newer attempt's outcome.

Index replacement is transactional and project-scoped. Generation checks reject stale concurrent publishers. The full AST and implementation bodies are not persisted. Root filesystem paths currently identify projects; moving a project requires a new index. Multiple referenced tsconfig projects are not yet supported.

Scaffold CRUD commands operate directly against SQLite without draft review. Draft commands and draft table creation have been removed. Indexed-project status and hook controls are available in the projects widget; broader settings and unindexed-project discovery remain later work. See the Memory design for the durable design/progress record.

Tool schemas and agent instructions are exported through aiDefinition in ai.ts. Regenerate tooling with bun run plugin:generate after changing that interface.

Opt-in post-commit indexing

Indexing never installs a Git hook. Each repository requires a separate explicit install action by the user or an agent acting on that specific user request:

bun src/cli.ts memory code.hook '{"project":"plugins/journal","operation":"preview"}'
bun src/cli.ts memory code.hook '{"project":"plugins/journal","operation":"install"}'
bun src/cli.ts memory code.hook '{"project":"plugins/journal","operation":"status"}'
bun src/cli.ts memory code.hook '{"project":"plugins/journal","operation":"remove"}'

Equivalent app commands use --project and --operation; all operations support format: "json". Preview shows the generated wrapper, exact executable command, managed directory, and delegated original hook directory. Install is idempotent when the existing installation is intact. Natural-language /memory ai cannot install/remove hooks; use the explicit command.

The installer sets repository-local core.hooksPath to a managed directory inside Git metadata. Other standard hooks delegate through symlinks; post-commit runs the original executable first, then the plugin-owned indexing runner. It never edits shared release scripts or global Git settings. Nested release-hook amendments run existing hooks but skip duplicate indexing, so the outer run sees the final revision. Original hook failure skips indexing and preserves its exit code. Indexing failure is logged and preserves the Git commit and previous index.

Code-query text headers show AUTO-INDEX; JSON metadata contains automation. Status distinguishes off, enabled, missing, changed, and unavailable, and includes the last attempted revision/result. Automatic runs synchronously use the same clean-input/diagnostic/manifest guards as manual parse, without AI or network calls. Busy runs are skipped with a catch-up message; stale dead-process locks are reclaimed. Manual parsing or the next commit can catch up after a missed run. Dirty source or consumed dependency inputs may still block automatic indexing.

Remove restores the previous local hooksPath value (or removes the override) and only deletes validated managed files. Edited wrappers/delegation/config and active runs require reconciliation rather than overwriting user changes. Project roots must be repository roots, with Git metadata inside the workspace; worktree-scoped hooksPath overrides and multiple local hooksPath values are not supported in v1. The managed record/last-run state is local to Git metadata, not committed source.

Markdown and shared discovery

parse attempts code and Markdown independently for a selected project; a failed index retains its previous snapshot without rolling back a successful sibling. search combines their ranked results with separate revisions/status and typed inspection actions. It uses reciprocal rank scores, not incomparable raw FTS scores. Continue shared search with its returned nextCursor (per-index offsets).

bun src/cli.ts memory parse '{"project":"plugins/journal"}'
bun src/cli.ts memory search '{"project":"plugins/journal","query":"publication"}'
bun src/cli.ts memory markdown.parse '{"project":"plugins/journal"}'
bun src/cli.ts memory markdown.parse '{"project":"plugins/journal","exclude":["archive/**"]}'
bun src/cli.ts memory markdown.search '{"project":"plugins/journal","query":"relay","format":"json"}'
bun src/cli.ts memory markdown.inspect '{"project":"plugins/journal","id":"<section-id>"}'
bun src/cli.ts memory markdown.expand '{"project":"plugins/journal","id":"<section-id>","relations":["links-to"]}'

App commands use equivalent --project, --query, --id, --format flags. Repeat --exclude/--relations for arrays; shared --cursor accepts a quoted JSON object. Null/omitted exclusions preserve saved patterns; an empty JSON array clears them. Shared parsing and commit hooks preserve those settings.

Markdown requires Git, but not package.json/tsconfig.json. Folder arguments resolve to the nearest committed TypeScript project, independent Git root, or active workspace fallback. More-specific configured/indexed projects own their files; independent repositories are not traversed. Code is not applicable without its committed config pair, unless an existing code index needs explicit failure/status rather than removal.

Index committed .md/.markdown anywhere, including feature READMEs, with tracked Git semantics and saved project-relative exclusion globs. Dirty Markdown or ownership configuration rejects publication, including staged deletions, renames and eligible untracked additions. Unrelated dirty TypeScript does not block Markdown. Git revision is rechecked before publishing. Parsing never commits files or enables hooks.

CommonMark/GFM AST positions supply heading hierarchy, reference links, tables, lists and fenced examples; headings/links inside examples are not relationships. Every heading owns its direct body, with a separate introduction. Long sections use block-oriented chunks; oversized single blocks split into 6,000-character ranges. Inspection defaults to 12,000 characters with pagination (maxChars: 6,000–50,000). Files above 2,000,000 characters are rejected with exclusion/splitting advice.

FTS5 weights titles/headings/tags above body, returning the best chunk per section, exact locations and callable IDs. YAML title falls back to first heading/filename; tags must be a string array. Other fields/raw frontmatter are inspectable. Malformed or cyclic metadata warns without hiding the body; unterminated frontmatter remains ordinary Markdown with a warning.

Inline/reference/same-document links use GitHub slugs and duplicate-heading suffixes. URI paths/fragments are decoded; leading / paths are project-root relative. Cross-project links/backlinks expose source/target projects, revisions and locations, with separate source/target inspection actions. Missing files/headings, unindexed projects, external URLs, unsupported targets and workspace escapes remain explicit. Queries never fetch URLs or automatically inspect another project's content. Code-file links are preserved; their resolution is deferred. Link resolution uses latest indexed targets in one SQLite read snapshot, so target updates immediately refresh resolution and backlinks without reparsing referring documents.

memory_markdown_* tables retain one latest successful snapshot, parsed documents, FTS chunks and monotonic attempts. Unchanged blob hashes/parser versions reuse parsing; deletions/exclusions/rebuilds replace facts atomically with generation guards. Section IDs use project/path/slug, not lines; rename/reheading/duplicate reorder can change IDs. Chunk IDs are snapshot-local offsets. History search, vectors, wikilinks and AI-extracted knowledge are deferred.

The projects card has separate code/Markdown status and errors in one project row, shared Reindex and individual expanded actions. The existing opt-in runner now calls shared parsing; managed wrapper/consent remain unchanged. Restart the host for app use.

Architecture

See local architecture and source map.

Local modules