# Project rules and memory

> AGENTS.md discovery and precedence; cross-session memory (/flush, /dream, hybrid search); when rules inject into the system prompt versus when memory retrieval runs.

- Repository: xai-org/grok-build
- GitHub: https://github.com/xai-org/grok-build
- Human docs: https://grok-wiki.com/public/docs/xai-org-grok-build-90205de50458
- Complete Markdown: https://grok-wiki.com/public/docs/xai-org-grok-build-90205de50458/llms-full.txt

## Source Files

- `crates/codegen/xai-grok-pager/docs/user-guide/12-project-rules.md`
- `crates/codegen/xai-grok-pager/docs/user-guide/13-memory.md`
- `crates/codegen/xai-grok-memory/src/lib.rs`
- `crates/codegen/xai-grok-memory/src/search.rs`
- `crates/codegen/xai-grok-memory/src/dream.rs`
- `crates/codegen/xai-grok-pager/src/memory_cmd.rs`
- `crates/codegen/xai-grok-shell/src/util/config/resolve/system_prompt.rs`

---

---
title: "Project rules and memory"
description: "AGENTS.md discovery and precedence; cross-session memory (/flush, /dream, hybrid search); when rules inject into the system prompt versus when memory retrieval runs."
---

Grok Build loads **project rules** from `AGENTS.md` (and compat aliases / rules directories) on every session, and optionally maintains **cross-session memory** under `~/.grok/memory/` with hybrid search. Rules and memory enter the model through different conversation slots: session CLI rules fold into the **system prompt**; discovered project instruction files inject as a tagged **user** item; memory search hits inject into the **system** message as `<memory-context>` on the first turn (and again after compaction when needed).

## Rules vs memory at a glance

| Concern | Project rules (`AGENTS.md`, rules dirs) | Cross-session memory |
|---------|----------------------------------------|----------------------|
| Default | Always discovered when present | **Off** (experimental) |
| On-disk location | Repo tree + `~/.grok/` (+ optional `~/.claude/`, `~/.cursor/`) | `~/.grok/memory/` only |
| When loaded | Session spawn (full file contents); later path access may **remind** of new files | Storage init when enabled; index + search on demand |
| Primary injection slot | **User** message: `SyntheticReason::ProjectInstructions` (`<system-reminder>` block) | **System** message: `<memory-context>…</memory-context>` on first turn |
| System prompt role | Template may note tools; **not** the full AGENTS body | `memory_enabled` placeholder enables tool guidance; retrieved chunks are separate |
| Session-only override | `--rules` / `--append-system-prompt` → `<human_rules>` on system prompt | `/memory on\|off` (session-scoped, does not rewrite `config.toml`) |
| Full replace | `--system-prompt-override` / `--system-prompt` replaces the agent system prompt | N/A |
| Model tools | None for rules (agent reads files if needed) | `memory_search`, `memory_get` when enabled |

```mermaid
flowchart TB
  subgraph sources [On-disk sources]
    AG["AGENTS.md / Claude.md / rules/*.md"]
    MEM["~/.grok/memory/**/*.md"]
    CLI["--rules / --system-prompt-override"]
  end

  subgraph spawn [Session spawn]
    DISC["read_agents_config_with_options"]
    SYS["Rendered system prompt"]
    PI["ConversationItem::project_instructions"]
  end

  subgraph turn [First turn / tools]
    INJ["hybrid_search → inject_memory_reminder"]
    TOOLS["memory_search / memory_get"]
  end

  AG --> DISC
  DISC --> PI
  CLI --> SYS
  MEM --> INJ
  MEM --> TOOLS
  INJ --> SYS
```

## Project rules

### Recognized filenames

In each scanned directory, Grok checks these names **in order** (all matches load; case-insensitive filesystems dedupe by canonical path):

| Order | Name | Notes |
|-------|------|--------|
| 1 | `Agents.md` | |
| 2 | `Claude.md` | Claude Code compat |
| 3 | `CLAUDE.md` | Claude Code compat |
| 4 | `CLAUDE.local.md` | Often gitignored for personal overrides |
| 5 | `AGENT.md` | |
| 6 | `AGENTS.md` | Common project default |
| 7–8 | `.claude/CLAUDE.md`, `.claude/CLAUDE.local.md` | Only when Claude **agents** compat is on |

Only these top-level names are discovered as project instruction files. Custom names (for example `AGENTS.local.md`) are **not** loaded unless they live inside a rules directory as `*.md`.

### Rules directories

At each directory level `<dir>` from the discovery chain:

| Path | When scanned |
|------|----------------|
| `<dir>/.grok/rules/*.md` | Always |
| `<dir>/.claude/rules/*.md` | Claude **rules** compat on (default) |
| `<dir>/.cursor/rules/*.md` | Cursor **rules** compat on (default) |

Files are sorted alphabetically within each rules directory. YAML frontmatter is stripped for `.grok/rules/` and `.claude/rules/` content before injection so globs/metadata do not leak into the prompt.

Disable vendor surfaces via `[compat]` in config or the corresponding env vars (see [Configure Grok](/configure-grok)).

### Discovery order and precedence

Implementation: `xai_grok_agent::prompt::agents_md::read_agents_config_with_options`.

1. **Global** — `~/.grok/` (always first).
2. **Home vendor dirs** — `~/.claude/`, `~/.cursor/` when the matching compat **agents** cell is enabled and the directory exists.
3. **Git chain** — if `cwd` is inside a git workdir, every directory from **repo root → cwd** (inclusive), root first so **deeper files appear later and win on conflicts**.
4. **Non-git** — only `cwd` (plus globals).
5. Optional **workspace user dir** may insert after the repo root (higher priority than root AGENTS, lower than intermediate/cwd).

```text
~/.grok/AGENTS.md
repo/AGENTS.md
repo/src/AGENTS.md
repo/src/components/AGENTS.md   ← later in the reminder = higher precedence
```

**Gitignore:** paths ignored by `.gitignore` are skipped during discovery.

**Size:** each matched file is loaded in full (no character cap / truncation). Keep rules concise; they consume context.

**`.grok/` project layout (related, not all rules):** project-scoped `config.toml`, `skills/`, `plugins/`, `agents/`, `hooks/`, `lsp.json` live under `.grok/` but are separate surfaces from AGENTS discovery.

### How project rules enter the conversation

Project instruction files are **not** merged into the default system prompt template body.

| Stage | Behavior |
|-------|----------|
| Spawn | Full contents render into a `<system-reminder>` block (“deeper files take precedence…”). Inserted as `ConversationItem::project_instructions` near the head of the conversation (user-role synthetic item). |
| Subagents | Same full AGENTS reminder as the primary agent (`agents_md_user_reminder`). |
| Permission classifier | AGENTS text can be forwarded as project instructions for auto-mode classification. |
| Mid-session access | `AgentsMdTracker` walks parents (max depth 10, within git root) when tools touch paths outside the initial chain. New files produce **path-only** reminders once per session/compaction cycle; the model decides whether to read them. Initial discovery paths are never re-reminded. |

Inspect loaded files and approximate token cost:

```bash
grok inspect
```

### Session CLI rules (system prompt)

| Flag | Effect |
|------|--------|
| `--rules` / `--append-system-prompt` | Appends text to the **system** prompt wrapped in `<human_rules>…</human_rules>` (fresh session only; not re-applied on resume unless the full override path is used). |
| `--system-prompt-override` / `--system-prompt` | Uses the text **verbatim** as the system prompt; skips default template and `--rules`. |

ACP clients can pass the same fields via session/init `_meta` (`rules`, `systemPromptOverride`). Override wins over rules; blank override is ignored.

```bash
grok --rules "Always use TypeScript. Prefer functional components."
grok --system-prompt-override "You are a release bot. Only answer about versioning."
```

### Authoring guidance (concise)

- Put monorepo-wide conventions in root `AGENTS.md`; package-specific rules in package dirs.
- Prefer actionable commands (`cargo test -p foo`) over essay-style docs.
- Commit shared rules; keep personal overrides in `~/.grok/` or gitignored `CLAUDE.local.md`.
- Do not duplicate the README; link out when needed.

## Cross-session memory

Memory is **experimental and disabled by default**. When enabled, Markdown files under `~/.grok/memory/` are chunked, indexed (SQLite FTS5 + optional vec0 embeddings), and searchable via hybrid search and model tools.

### Enable / disable

| Priority | Source | Effect |
|----------|--------|--------|
| 1 (highest) | `--no-memory` or `GROK_MEMORY=0`/`false` | Force off |
| 2 | `--experimental-memory` or `GROK_MEMORY=1`/`true` | Force on |
| 3 | `[memory] enabled` in config (plus remote settings when local section absent) | Persistent preference |
| 4 | Default | `enabled = false` |

```bash
grok --experimental-memory
export GROK_MEMORY=1
```

```toml
# ~/.grok/config.toml
[memory]
enabled = true
```

Mid-session (TUI): `/memory on`, `/memory off`, or `t` inside the `/memory` modal. Toggle is **session-scoped**; it does not write `config.toml`. Off unregisters memory tools but leaves files on disk.

### Storage layout

```text
~/.grok/memory/
├── MEMORY.md                          # Global curated knowledge
└── {project-slug}-{hash8}/            # Workspace scope
    ├── MEMORY.md                      # Project curated knowledge
    ├── sessions/
    │   └── YYYY-MM-DD-{slug}-{sid8}.md
    └── index.sqlite                   # FTS + optional embeddings
```

**Workspace directory naming:** `{slug}-{hash8}` where `slug` is the repo name (or directory name) and `hash8` is the first 8 hex chars of a blake3 hash. Identity prefers git remote `origin` as `org/repo` so clones and worktrees of the same remote share one memory directory; otherwise the canonical filesystem path is used.

Writes from ephemeral temp CWDs are skipped. Optional GC under `[memory.gc]` can remove orphan workspace dirs after age thresholds.

### What gets written

| Mechanism | Content | When |
|-----------|---------|------|
| Session-end auto-save | Metadata summary: message counts, up to five topic prompts, UTC time — **no** tool I/O, paths, or shell commands | Session end if `session.save_on_end = true` (default). Skips trivial sessions (&lt;3 substantive prompts or &lt;50 bytes user text). |
| `/flush` | LLM-written rich summary of decisions/patterns into a dated session log | Manual, or pre-compaction flush when configured under `[compaction.memory_flush]` |
| `/remember` or natural-language “remember …” | Append to global or workspace `MEMORY.md` (review panel; confirm before write) | User-initiated |
| “forget …” | Best-effort model edit of matching entries | User-initiated; edit files directly for guaranteed removal |
| `/dream` / auto-dream | Consolidate session logs into durable workspace topics; may delete consolidated session files | Manual or gated auto at session end (and optional interval) |

Background flush/dream/session-end saves do **not** post scrollback confirmations. `/remember` does: `Memory saved to …`.

### Dream consolidation

`/dream` and auto-dream synthesize recent session logs into organized markdown (merge, resolve contradictions, drop ephemeral noise). Gates (`[memory.dream]`):

| Key | Default | Role |
|-----|---------|------|
| `enabled` | `true` | Master switch for auto-dream |
| `min_hours` | `4` | Minimum hours since last consolidation |
| `min_sessions` | `3` | Minimum sessions since last consolidation |
| `stale_lock_secs` | `3600` | Reclaim stale dream lock |
| `check_interval_secs` | unset | If set, also check on an interval; default is session-end only |

Input to the dream model is capped (~32k chars). Empty/scaffold results yield no write.

### Hybrid search

Pipeline (`xai_grok_memory::search::hybrid_search`):

1. FTS5 BM25 (always)
2. Vector KNN when embeddings exist (else FTS-only with `text_weight = 1.0`)
3. Merge / normalize scores; drop empty/scaffold chunks
4. Temporal decay on **session** sources only (global/workspace evergreen)
5. Source weights + min score filter
6. Optional MMR diversity re-rank
7. Cap at `max_results`

Defaults (`[memory.search]`):

| Key | Default |
|-----|---------|
| `max_results` | `6` |
| `min_score` | `0.35` |
| `vector_weight` | `0.7` |
| `text_weight` | `0.3` |
| `temporal_decay.enabled` | `true` |
| `temporal_decay.half_life_days` | `7.0` |
| `mmr.enabled` | `false` |
| `mmr.lambda` | `0.7` |
| `source_weights.*` | `1.0` for `workspace`, `session`, `global` |

Session hits can include **staleness notes** in formatted output; global/workspace never do.

### When memory retrieval runs

| Trigger | Behavior |
|---------|----------|
| **First turn** (if `initial_injection.enabled`, default true) | Hybrid search on the last real user query (or a project-conventions fallback for greetings / short openers). Results upserted into the **system** message as `<memory-context>`. Skipped if a prior block already exists (prompt-cache preservation) or injection already ran this process. Default injection min score is **unset → 0.0** (no threshold) unless configured. |
| **After compaction** | Search again to recover context lost from history. |
| **Model tools** | `memory_search` (hybrid), `memory_get` (read by path) whenever memory is enabled for the session. |
| **File watcher** | Optional watch on `~/.grok/memory/`; dirty files reindex on the next search. |

Memory-enabled sessions also pass `memory_enabled` (and global/workspace paths) into system-prompt template placeholders so the base prompt can describe memory tools — that is **capability guidance**, not the retrieved snippets.

### TUI and CLI surfaces

| Surface | Role |
|---------|------|
| `/memory` | Browse global / workspace / session files (preview pane; filter `/`; copy path `y`; delete session files with `x`; toggle `t`) |
| `/remember [text]` | Confirm-and-save note |
| `/flush` | Rich session capture (requires memory on) |
| `/dream` | Manual consolidation (requires memory on) |
| `grok memory clear` | Shell clear: workspace (default), `--global`, `--all`, `--yes` |

```bash
grok memory clear              # workspace MEMORY.md, sessions/, index.sqlite
grok memory clear --global
grok memory clear --all --yes
```

### Configuration map

**Core (`[memory]`)**

| Key | Default | Description |
|-----|---------|-------------|
| `enabled` | `false` | Master enable |
| `session.save_on_end` | `true` | Metadata summary on end |
| `watcher.enabled` | `true` | External edit reindex |

**Index (`[memory.index]`)** — `max_chunk_chars` 1600, `chunk_overlap_chars` 320.

**Embedding (`[memory.embedding]`)** — `provider` `"api"`, `model` optional (unset disables vectors), `dimensions` 1024.

**Initial injection (`[memory.initial_injection]`)** — `enabled` true; `min_score` optional.

**Flush / pruning** live under **`[compaction]`**, not `[memory]`:

| Section | Purpose |
|---------|---------|
| `[compaction.memory_flush]` | Pre-compaction / idle flush limits, model, semantic dedup |
| `[compaction.pruning]` | Soft-trim / hard-clear old tool results in the live transcript (not memory files) |

Remote settings can override search/injection/dream/flush when the matching local TOML subsection is absent.

## Injection comparison (operational)

```text
System prompt (identity + tools template)
  ├─ optional <human_rules> from --rules          [spawn only]
  ├─ optional full override from --system-prompt-override
  └─ optional <memory-context> from first-turn / post-compact search

User conversation prefix
  └─ project_instructions: full AGENTS/rules <system-reminder>   [spawn]
       + later path-only reminders from AgentsMdTracker

Tool loop (memory on)
  └─ memory_search / memory_get against ~/.grok/memory index
```

**Practical rules of thumb**

- Put **stable project law** in `AGENTS.md` (always on, no feature flag).
- Put **learned decisions across sessions** in memory (opt-in; searchable; decays for session logs).
- Use `--rules` for one-shot session constraints without editing the repo.
- Use `/flush` before compaction or at the end of a high-value session; use `/dream` when session logs get noisy.
- After enabling memory mid-life of a session, start `/new` if you need first-turn injection for that enablement path.

## Troubleshooting

| Symptom | Check |
|---------|--------|
| Rules not applied | `grok inspect`; confirm filename is recognized; ensure file is not gitignored; run from intended cwd inside the git tree. |
| Conflicting instructions | Deeper directory wins; move conflicting guidance or delete the lower-priority file. |
| Memory “not working” | Confirm not overridden by `--no-memory` / `GROK_MEMORY=0`; enable with flag, env, or config; verify `grok inspect`. |
| No memory on first turn | Injection only on first turn of a session with memory already enabled; use `/new` after enabling. |
| Stale or empty search | Empty MEMORY.md scaffolds are filtered; run `/flush` or edit MEMORY.md; wait for watcher reindex on next search. |
| Shared memory across clones missing | Ensure shared `origin` remote identity; otherwise path-based hashes diverge. |

```bash
RUST_LOG=debug GROK_LOG_FILE=/tmp/grok.log grok --experimental-memory
grep -i memory /tmp/grok.log
```

## Related pages

<CardGroup>
  <Card title="Sessions" href="/sessions">
    Session lifecycle, resume/fork, and compaction — where flush and re-injection interact with history.
  </Card>
  <Card title="Configure Grok" href="/configure-grok">
    Config precedence, `[compat]` vendor toggles, and `grok inspect` for resolved settings.
  </Card>
  <Card title="Configuration reference" href="/configuration-reference">
    Full schema for `[memory.*]`, `[compaction.memory_flush]`, and related keys.
  </Card>
  <Card title="Slash commands" href="/slash-commands">
    `/memory`, `/flush`, `/dream`, `/remember`, and availability gates.
  </Card>
  <Card title="CLI reference" href="/cli-reference">
    `--experimental-memory`, `--no-memory`, `--rules`, `--system-prompt-override`, `grok memory clear`.
  </Card>
  <Card title="Skills" href="/skills">
    Skill packages under `.grok` / vendor trees — complementary to AGENTS rules directories.
  </Card>
  <Card title="Permissions and safety" href="/permissions-and-safety">
    Project instructions can feed the permission classifier alongside tool allow/deny rules.
  </Card>
</CardGroup>
