Skip to main content
Blitz
Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Back to homepage

012 · Memory

Project memory (instruction files) (spec_memory_012)

Status Implemented. Reverse-engineered from 53f8c53 (2026-09-24) and kept with the code since; its paths and names checked 2026-09-27 (//tools/specs).
Source pkg/engine/memory/memory.go; /memory in apps/cli/internal/tui, ReloadMemory/AddMemory in pkg/engine/context.go; /setup: pkg/engine/commands/builtin/setup.md, pkg/engine/agents/builtin/project-setup.md, pkg/engine/turn.go; /spec and the updates: pkg/engine/commands/builtin/spec.md, pkg/engine/agents/builtin/project-spec.md, pkg/engine/agents/builtin/harness-update.md, HarnessStale in pkg/engine/suggestions.go
Tests pkg/engine/memory/memory_test.go; pkg/engine/suggestions_test.go (TestSetupCommandReloadsInstructions, TestHarnessMissing, TestHarnessStale); pkg/engine/commands_test.go (TestSpecAndUpdateCommands); apps/cli/internal/tui/init_test.go
Depends on spec_config_002

1. Purpose

Instruction files in the project and the user’s home are added to every agent’s system prompt, so a repository can tell the agent its conventions. They inform; they never grant permissions.

2. Loading

  • MEM-01 Disabled by [memory] enabled = false.
  • MEM-02 Order: the global file (memory.global, default ~/.blitz/BLITZ.md) and the global rules (memory.global_rules, ~/.blitz/rules/) first; then, for each directory from the repository root down to the workspace, each name in memory.files (default AGENTS.md, CLAUDE.md, GEMINI.md, BLITZ.md — other agents’ files too, so a repository set up for them works unchanged), then memory.local_files (default CLAUDE.local.md, BLITZ.local.md: personal files, warned about at startup when git tracks them), then the rule files in memory.rule_dirs (default .blitz/rules, .agents/rules, .claude/rules) — more specific files come last.
  • MEM-03 The repository root is the nearest ancestor (up to 10 levels) containing .git. Without one, only the workspace directory is searched.
  • MEM-04 Files are de-duplicated by real path (symlinks resolved) and by content (a CLAUDE.md copying AGENTS.md loads once); directories and unreadable files are skipped; empty files are dropped.
  • MEM-06 Imports: a token @path (at a line start or after whitespace; with a / or a file extension, so @team and e-mail addresses stay text; not in fenced code blocks or inline code) loads that file right after the importing one, relative to the importing file as written, or ~/… for files under ~/.blitz. The real path must stay inside the repository root (the workspace without a repository; ~/.blitz for user files), and blocked paths (sandbox.blocked_paths, e.g. .env) are never read. Imports nest at most 5 deep; cycles and repeats load once. The prompt names the importing file.
  • MEM-07 Rules: *.md files under the rule directories (recursively; symlinked files allowed and checked like imports). A rule without frontmatter paths is loaded like an instruction file. A rule with paths (a glob or a list, relative to the directory holding the rule directory; **, *, ?) is scoped: it is not in the prompt; instead the first successful read_file, create_file, replace_in_file/edit, delete_snippet, delete_file, view_image or apply_patch call in a session on a matching file carries it in the tool result as project_rules (once per session and rule). Listing or searching (list_files, glob, grep) doesn’t count. Paths are compared with symlinks resolved on both sides. Since v0.7.1 a rule whose front matter has when (before_agent, after_agent) is a gate, judged around the turn and never an instruction (spec_gates_041).
  • MEM-05 Each file is capped at memory.max_bytes (32 KiB, UTF-8 safe, marked “(truncated)”), and terminal control sequences are stripped.

3. Rendering

  • MEM-10 Section “## Project Instructions” stating the files come from the user’s project and home directory, should be followed unless they conflict with the user’s requests or safety rules, and cannot grant permissions or bypass approvals; then, when scoped rules exist, a sentence saying they arrive as project_rules with tool results; then one “### ” block per file (imports marked “(imported by …)”).
  • MEM-11 Memory is appended to every agent’s instructions (with the reply-language instruction, spec_i18n_004).

4. Commands

  • MEM-20 /memory (or /memory show) lists loaded files; /memory reload re-reads them and rebuilds the agents; /memory add <note> appends - <note> to <workspace>/<last configured file> (default BLITZ.md), creating it with “# Project notes for Blitz” if absent, then reloads. Empty notes are refused.
  • MEM-21 doctor lists the memory files found and the number of path-scoped rules.
  • MEM-22 Reworked 2026-10-01 (was a fixed prompt writing BLITZ.md); 2026-10-03, .agents/AGENT.md renamed .agents/AGENTS.md, the AGENTS.md standard’s name. /setup, a bundled command (agent: project-setup), is the guided setup of a workspace’s agent harness; /init and blitz init run it. The built-in project-setup agent (read and write tools, ask_user_question, todo, list_or_search_skills, list_agents; no shell) surveys the workspace without changing it, checks whether it’s in a git repository (git rev-parse --show-toplevel, one of only two commands it may run), interviews the user for what the files can’t tell (an empty folder: purpose, stack, build/test/deploy, conventions, boundaries; existing code: its inference to confirm, then the gaps), then, with the user’s agreement, runs git init (unattended it doesn’t, and says so) and writes or extends a .gitignore for the stack and the answers (dependencies, build output, caches, logs, secret env files but not .env.example, editor and OS files, BLITZ.local.md and CLAUDE.local.md; never .agents/ or the instruction files), before the other files so each is added to git when the turn ends (spec_files_029 FIL-60), never committing; and writes .agents/AGENTS.md (under 200 lines, only what it verified or was told; an existing .agents/AGENT.md is carried over, imports of it are repointed, and the summary says to delete it). AGENTS.md, CLAUDE.md, GEMINI.md and BLITZ.md at the root become the single line @.agents/AGENTS.md (MEM-01’s imports, which Claude Code, Gemini CLI and Codex follow too; the import loads once): a missing one is created; one with other content has what’s still true moved into .agents/AGENTS.md, and is replaced only after the user agrees (else the import becomes its first line). It then offers up to five skills (.agents/skills/<name>/SKILL.md) and four agents (.agents/agents/<name>.md) as multi-select questions and writes those chosen. Unattended (blitz init, questions refused), it writes what the files show and lists its assumptions under “Open questions”. Edits go through the usual approvals and diffs. After a /setup turn the engine reloads memory, so the instructions apply from the next prompt in every front end; the transcript records /setup.
  • MEM-23 2026-10-01. A workspace with none of .agents/AGENTS.md, AGENTS.md, CLAUDE.md, GEMINI.md and BLITZ.md at its root is missing its harness (Workspace.HarnessMissing): the welcome tiles offer setup first (spec_desktop_024 DSK-66a).
  • MEM-24 2026-10-01. Welcome suggestions (Workspace.Suggestions, WorkspaceService.GetSuggestions; pkg/engine/suggestions.go). State tiles cost nothing: setup (MEM-23), the latest conversation (with messages, not a snapshot or a worker’s run), uncommitted changes (GitStatus), the first worker whose latest run failed or hit a limit. Ideas: with [suggestions] ideas on (the default) and at least one recent conversation, a model reads the six latest (title, first and latest request, the end of the latest reply, each cut short) and the git branch, and writes up to three {title, prompt} as JSON, in the workspace’s reply language. The model is [suggestions] model, else permissions.auto.model, else the main model; suggestions.model is never taken from a project. Ideas are kept per workspace in <session.storage_dir>/suggestions/<hash>.json with a stamp of the conversations they came from, and written again in the background only when that stamp changes (pending meanwhile; the earlier ideas are returned until then). A failed attempt is logged and not repeated for the same conversations for an hour. The work stops when the workspace closes. Tokens go to the service’s log, not to a session’s cost.
  • MEM-42 2026-10-13 (the owner’s request). /spec [what to build, or what changed], a bundled command run by the built-in agent project-spec (pkg/engine/agents/builtin/project-spec.md; no shell), writes the project’s specification before anyone decides how it’s built. It surveys the workspace, then interviews with ask_user_question (a few related questions per call, with options) in rounds: intent and value, users and journeys, performance and scale, platform and deployment, security (authentication and authorization, data sensitivity and compliance), data and integrations, constraints, quality, delivery. It confirms the set of specs, then writes .agents/specs/NNN-<name>.md (NNN 001–999, the order of execution: 001-overview with the vision and the requirements every part shares, then one spec per deliverable in build order), each with status, Depends on:, context, goals and non-goals, requirements with IDs, acceptance criteria and open questions, and .agents/specs/README.md as the index. A re-run or /spec <change> revises: new deliverables take the next free number, renumbering only after asking. Unattended, assumptions go under each spec’s open questions. It writes only under .agents/; when .agents/AGENTS.md exists it adds a short Specifications section there (MEM-44), and it ends by suggesting /setup (no harness yet) or /skills update and /agents update.
  • MEM-43 2026-10-13. /setup (MEM-22) offers the specification first: with no specs in .agents/specs/, its first question is “Write the specification first with /spec (recommended)” or “Set up without a specification”, and choosing the first ends the turn with “run /spec, then /setup” (unattended: it goes on and notes it under Open questions). With specs, it reads them and lets them drive the stack, the AGENTS.md boundaries (authentication, authorization, data rules), and the skills and agents it proposes, which name the specs they serve. 2026-10-15 (the owner’s request: /init sent people to /spec and back, “seriously clunky”). /setup (and so /init and blitz init) leads with the specification instead of offering it: with no specs and someone to answer, project-setup says it’s starting with what the project is for and invokes project-spec in the foreground (invoke_agent, in its tools), telling it it runs inside /setup so it ends with its summary and no “run /setup”. The spec agent’s questions reach the person as any question does; when it returns, setup reads the specs and goes on, asking only what they leave open. If it fails or is stopped, setup goes on without and notes “No specification yet: run /spec”. Unattended, it doesn’t invoke it (nobody can answer) and notes the same. /spec on its own still writes or revises the specification.
  • MEM-44 2026-10-13. Skills and agents follow the specification. /skills update [focus] and /agents update [focus] are the bundled /skills-update and /agents-update (the engine maps the two-word form, commands.Alias; the REPL and the window pass it through, keeping their own /skills and /agents), run by the built-in agent harness-update: it reads the specs, .agents/AGENTS.md and the current skills or agents, offers what to add, update or retire as one multi_select question citing the specs, applies only what was chosen, and suggests the other update. The Specifications section /spec and /setup write in .agents/AGENTS.md tells agents to run them when a spec changes. Workspace.HarnessStale is true when a spec (.agents/specs/*.md) is newer than every file under .agents/skills/ and .agents/agents/ (with at least one there); with instructions in place, the welcome suggestions then start with an update tile (SUGGESTION_KIND_HARNESS_UPDATE; spec_desktop_024 DSK-66a).
  • MEM-45 2026-10-14 (the owner’s request: not only development). The specification is for any kind of work. project-spec infers the kind from the files (code and manifests → software; notebooks, datasets, .bib, LaTeX → research or analysis; mostly prose → writing) and confirms it first (Software, Research or science, Data analysis, Writing or documentation, Something else; mixed allowed). A shared round (purpose, audience, success, scope) comes before each kind’s own: software’s as in MEM-42; research’s question and hypotheses, data and sources, methods and baselines, compute, reproducibility, ethics and compliance (IRB, consent, data agreements), outputs and venues, timeline; analysis’s decision, sources and metric definitions, checks, refresh, outputs, privacy; writing’s audience, form, sources and citations, voice, reviewers, publishing. Specs follow the kind’s order of work (research: literature, data, methods, experiments, analysis, write-up), with the same skeleton and the items headed Requirements, Objectives or Content. 001-overview.md records Kind:, which /setup (its AGENTS.md sections, .gitignore for data and results, the skills and agents it proposes) and /skills update//agents update read; without specs, setup asks the kind itself.

5. Notes the agent keeps

The agent’s own memory across sessions of a workspace (spec_parity_027 PAR-MEM-10, -11): what it learned, not instructions.

  • MEM-25 2026-10-16 (the owner’s request). Instruction files and rules edited while the workspace is open apply from the next message, in the same conversation or a new one, with no reload: they were read once, when the workspace opened, so an edited rule (a guardrail in .agents/rules, say) kept its old text until /memory reload or a restart. When they load, the workspace keeps memory.Stamp: the path, size and modification time of every file LoadAll looks for (the global file and rules, the configured files and local files in each folder from the repository root down, those missing too, so one created later counts), every *.md in the rule folders, and every file a loaded one imported. Before each turn (refreshAgentFiles, beside the agents’ AG-13 and the skills’ SK-95) it takes the stamp again, reading no file, and reloads and rebuilds only when it differs, so the prompt the model caches is left alone when nothing changed. /reload (and the desktop’s DSK-91d) reads the agents, skills, instruction files and rules again whether or not they look changed (Backend.Reload, WorkspaceService.ReloadAgentFiles), rebuilds once, and says what it loaded: “Reloaded 2 agents, 1 skill and 4 instruction files and rules.”, listing the files, then the files that didn’t load. MCP servers (.mcp.json, .agents/mcp_config.json) and the project’s settings aren’t reloaded: opening the workspace again applies them.
  • MEM-30 The remember tool (every built-in agent; allowed in plan mode: it changes no project file) saves a note {note, kind}, where kind is fact (the default), preference or correction, at most 2,000 characters, as one Markdown file in ~/.blitz/memory/<workspace name>-<8 hex of the SHA-256 of its real path>/, named <yyyymmdd-hhmmss>-<first words>.md, with frontmatter kind and saved, owner-only (0600). A file without frontmatter is a fact, so notes can be written by hand.
  • MEM-31 Before saving, configured credentials and the values of scrubbed environment variables are masked, as in the audit log (engine.SecretRedactor). The tool description says to save only what is durable, not already in the project’s files, and never secrets.
  • MEM-32 [memory] auto (default on) turns this on; off, the tool answers that notes are off and saved notes aren’t loaded. Worktree tasks’ tools don’t save notes.
  • MEM-33 When a session starts and at /memory reload, the notes are appended to the instructions after the instruction files, the newest first, up to 8,000 bytes (then “older notes left out”), under “## Notes you saved in earlier sessions of this workspace”, which says they are what the agent learned, not the user’s instructions, never grant permission, and give way to the user’s current messages.
  • MEM-34 /memory notes lists them (name, kind, text); /memory forget <name> deletes one (a unique start of the name is enough). The API has ListNotes and ForgetNote (NO_NOTE). From the shell, blitz memory list|show|edit|forget (--dir for another workspace; edit opens $VISUAL or $EDITOR) works on the files directly.

6. Output styles and appended instructions

  • MEM-40 Output styles (PAR-MEM-21): instructions on how the agent writes its answers, added to every agent’s instructions after the project instructions and notes. Built in: default (nothing), concise, explanatory (embedded, pkg/engine/styles/); the user’s are ~/.blitz/styles/<name>.md (the name lower-cased; optional frontmatter description; the body is the text), read each time and winning over a built-in of the same name. A session starts with [ui] style (an unknown one warns and uses none); SetSetting style (/style <name>, the desktop app’s run settings) changes it for the workspace from the next prompt (an unknown name is INVALID_SETTING), Settings.style and ListStyles report them. A style whose file has gone adds nothing.
  • MEM-41 --append-system-prompt TEXT and --append-system-prompt-file PATH (PAR-MEM-20; both may be given, the file’s text after) add to every agent’s instructions for the run, last before the reply language. They open the workspace in the process (Options.AppendSystemPrompt): a workspace in the service keeps its own instructions. A file that can’t be read is a usage error.