# ai-Memory Data Directory Structure: Complete Guide to File Layout and Storage Subsystems

> Explore the ai-memory data directory structure. Understand the file layout and storage subsystems including wiki raw db models logs hook-spool and config files.

- Repository: [Fabio Akita/ai-memory](https://github.com/akitaonrails/ai-memory)
- Tags: deep-dive
- Published: 2026-08-28

---

**The ai-memory runtime stores all persistent state in a single data directory containing seven top-level subdirectories (wiki/, raw/, db/, models/, logs/, hook-spool/) and two configuration files (config.toml, state.json), with the default location being `~/.local/share/ai-memory` on Linux systems.**

The **ai-memory data directory structure** serves as the central persistence layer for this Rust-based memory management system. This directory encapsulates every storage subsystem—from the markdown-based wiki to the SQLite FTS5 index—providing a deterministic, version-controlled layout that multiple core crates coordinate against at runtime.

## Default Data Directory Location

The system resolves the data directory through a cascading priority:

1. **`AI_MEMORY_DATA_DIR`** environment variable (highest priority)
2. **[`config.toml`](https://github.com/akitaonrails/ai-memory/blob/main/config.toml)** file's recorded absolute path
3. Platform-specific default (e.g., `~/.local/share/ai-memory` on Linux via `dirs::data_local_dir()`)

This resolution logic is implemented in [`crates/ai-memory-cli/src/config.rs`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-cli/src/config.rs), where the `Config` struct exposes `data_dir: PathBuf` as the canonical reference point.

```rust
// Load configuration and resolve the data directory
let config = Config::load(None, None)?;
let data_dir = &config.data_dir;  // PathBuf used throughout the codebase

```

## Core Subdirectories of the ai-Memory Data Directory

### wiki/

The **`wiki/`** directory contains the markdown wiki—the **source-of-truth** for all notes, pages, and generated content. The `ai-memory-wiki` crate exclusively manages this subtree, treating it as a plain-text document store that other systems index but never modify directly.

```rust
let wiki_dir = data_dir.join("wiki");
// List all wiki pages
for entry in std::fs::read_dir(&wiki_dir)? {
    println!("Wiki page: {}", entry?.path().display());
}

```

### raw/

The **`raw/`** directory stores **unprocessed observation JSONL files** spooled from lifecycle hooks before ingestion. These files represent the raw event stream captured by hook integrations, awaiting transformation and indexing by the processing pipeline.

### db/

The **`db/`** directory contains the **SQLite database** (`memory.sqlite`) powering:
- **FTS5 full-text search index**
- Entity store
- Session management
- Hand-off records
- Structured metadata tables

The `ai-memory-store` crate opens this file at `db/memory.sqlite` relative to the resolved `data_dir`.

### models/

The **`models/`** directory is an **optional cache location** for LLM models or embedding files when a provider is configured for local inference. This directory remains empty unless explicit model downloading is enabled.

### logs/

The **`logs/`** directory contains runtime logs written by both the server and CLI components. The primary log file is `ai-memory.log`, created and rotated by the logging subsystem in [`crates/ai-memory-cli/src/logging.rs`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-cli/src/logging.rs).

```rust
let logs_dir = data_dir.join("logs");
// Directory created on first log write

```

### hook-spool/

The **`hook-spool/`** directory acts as a **temporary staging area** for hook payloads awaiting processing by the writer actor. This decouples hook emission from ingestion, preventing backpressure on observing services.

## Configuration and State Files

### config.toml

The **[`config.toml`](https://github.com/akitaonrails/ai-memory/blob/main/config.toml)** file is generated on first run and persistently records:
- The absolute `data_dir` path (enabling relocation detection)
- Provider settings
- Other user-configurable parameters

### state.json

The **[`state.json`](https://github.com/akitaonrails/ai-memory/blob/main/state.json)** file (marked internal) tracks transient server state including active sessions. This file is not user-editable and may be rewritten frequently during operation.

## Bash Inspection of the ai-Memory Directory Structure

```bash

# Resolve and display the complete directory tree

AI_MEMORY_DATA_DIR=${AI_MEMORY_DATA_DIR:-$(dirs::data_local_dir)/ai-memory}
tree "$AI_MEMORY_DATA_DIR"

# Expected output:

# .

# ├── wiki/

# ├── raw/

# ├── db/

# │   └── memory.sqlite

# ├── models/

# ├── logs/

# │   └── ai-memory.log

# ├── hook-spool/

# ├── config.toml

# └── state.json

```

## Source Code Locations Defining the Directory Structure

| Crate | File | Responsibility |
|-------|------|--------------|
| `ai-memory-cli` | [`crates/ai-memory-cli/src/config.rs`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-cli/src/config.rs) | `Config` struct and `data_dir` resolution |
| `ai-memory-wiki` | [`crates/ai-memory-wiki/src/wiki.rs`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-wiki/src/wiki.rs) | `wiki/` subtree management |
| `ai-memory-store` | [`crates/ai-memory-store/src/lib.rs`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-store/src/lib.rs) | SQLite file at `db/memory.sqlite` |
| `ai-memory-cli` | [`crates/ai-memory-cli/src/logging.rs`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-cli/src/logging.rs) | `logs/` directory creation |
| `ai-memory-hooks` | [`crates/ai-memory-hooks/src/workstream.rs`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-hooks/src/workstream.rs) | `raw/` and `hook-spool/` write paths |

All paths derive from the same `data_dir: PathBuf` loaded once at startup, ensuring consistency across the **ai-memory data directory structure**.

## Summary

- The **ai-memory data directory** defaults to `~/.local/share/ai-memory` but respects `AI_MEMORY_DATA_DIR` and [`config.toml`](https://github.com/akitaonrails/ai-memory/blob/main/config.toml) overrides
- **Seven subdirectories** partition storage by concern: `wiki/`, `raw/`, `db/`, `models/`, `logs/`, `hook-spool/`
- **Two files** track configuration and runtime state: [`config.toml`](https://github.com/akitaonrails/ai-memory/blob/main/config.toml), [`state.json`](https://github.com/akitaonrails/ai-memory/blob/main/state.json)
- The **SQLite database** at `db/memory.sqlite` powers all structured queries and search
- All crates coordinate through the **single `data_dir` value** in `Config::load()`

## Frequently Asked Questions

### How do I change the ai-memory data directory location?

Set the **`AI_MEMORY_DATA_DIR`** environment variable before running any ai-memory command. This overrides both the default platform directory and any path recorded in [`config.toml`](https://github.com/akitaonrails/ai-memory/blob/main/config.toml). The CLI will persist this path to [`config.toml`](https://github.com/akitaonrails/ai-memory/blob/main/config.toml) on first run for subsequent invocations.

### What happens if I delete the db/ directory or memory.sqlite file?

The **FTS5 index, entity store, and session data will be lost**, requiring a full re-ingestion from `raw/` and `wiki/` sources. The `wiki/` directory remains intact as the source-of-truth, but search functionality will be unavailable until reindexing completes.

### Can multiple ai-memory instances share the same data directory?

**No.** The SQLite database uses file-level locking, and [`state.json`](https://github.com/akitaonrails/ai-memory/blob/main/state.json) tracks singleton server state. Concurrent access from multiple processes will cause database lock contention and potential corruption. Use separate `data_dir` values for isolated instances.

### Where are hook observations stored before processing?

Raw hook JSONL events land in **`raw/`**, while payloads awaiting the writer actor stage temporarily in **`hook-spool/`**. The latter is periodically drained; files persisting there may indicate a stalled ingestion pipeline.