# How the .ai-memory.toml Marker File Enables Per-Project Isolation and Custom Routing

> Discover how the .ai-memory.toml marker file in akitaonrails/ai-memory creates per-project isolation and custom routing by establishing workspace boundaries and namespaces for your AI memory.

- Repository: [Fabio Akita/ai-memory](https://github.com/akitaonrails/ai-memory)
- Tags: how-to-guide
- Published: 2026-08-20

---

**The [`.ai-memory.toml`](https://github.com/akitaonrails/ai-memory/blob/main/.ai-memory.toml) marker file acts as a lightweight filesystem anchor that namespaces all wiki pages, handoffs, and memory queries by declaring workspace and project boundaries, which the ai-memory client discovers by walking up the directory tree from the current working directory.**

The ai-memory project implements a hierarchical configuration system to isolate data between different codebases, clients, and consulting engagements without requiring separate installations or global environment variables. By placing a **[`.ai-memory.toml`](https://github.com/akitaonrails/ai-memory/blob/main/.ai-memory.toml)** file anywhere in a directory tree, you create an authoritative routing boundary that automatically namespaces all subsequent operations according to the three-tuple **(workspace, project, path)**.

## Workspace Isolation and Project Scoping

The marker file defines routing metadata that prevents data collision across different contexts. The system uses three keys—`workspace`, `project`, and `project_strategy`—to construct the namespace for every memory operation.

**Workspace isolation** separates data between different clients or personal projects. By default, every session uses the workspace `"default"`, but a marker can override this:

```toml

# .ai-memory.toml

workspace = "acme-consulting"

```

According to the marker schema documented at lines 45-48 of [`docs/marker-file.md`](https://github.com/akitaonrails/ai-memory/blob/main/docs/marker-file.md), this value forces all child directories to share the same workspace boundary, effectively isolating data without requiring separate ai-memory installations.

**Project scoping** offers two strategies for deriving the project name. When `project = "<name>"` is explicitly set, that name applies to all current working directories under the marker. When omitted, the default strategy derives the project from the basename of the current working directory. Alternatively, setting `project_strategy = "repo-root"` (lines 54-58) forces the system to derive the project name from the main Git repository root, ensuring that subdirectories and linked worktrees share a single project namespace.

## Filesystem Discovery Mechanism

The ai-memory CLI discovers markers through an upward filesystem walk implemented in **[`crates/ai-memory-cli/src/marker.rs`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-cli/src/marker.rs)**. The **`find_marker`** function (lines 106-138) searches from the current working directory toward the filesystem root until it locates the nearest [`.ai-memory.toml`](https://github.com/akitaonrails/ai-memory/blob/main/.ai-memory.toml).

Once found, **`read_scope`** parses the configuration keys and returns a **`MarkerScope`** struct (lines 26-41). This scope object encapsulates the routing metadata required for all subsequent operations.

The discovery mechanism follows a strict **nearest-wins** precedence model. As documented at lines 26-31 in [`docs/marker-file.md`](https://github.com/akitaonrails/ai-memory/blob/main/docs/marker-file.md), the walk stops at the first marker encountered, making inner markers authoritative over outer ones. The system never merges multiple markers; it always uses a single source of truth to avoid configuration ambiguity.

## Routing Implementation and Query Parameters

The parsed marker fields drive server-side routing logic. In **[`crates/ai-memory-cli/src/commands/hook_capture.rs`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-cli/src/commands/hook_capture.rs)**, the hook-capture command converts the `MarkerScope` into query parameters (lines 247-254) that accompany every HTTP request to the server endpoint.

Because the marker's values are forwarded as query parameters, the server can route requests to the correct workspace and project without additional server-side configuration. This enables complex repository layouts including multi-client trees, mono-repos, and personal/workspace separation—all declared through a simple text file.

The following Rust example demonstrates how the CLI resolves the current scope using the marker discovery logic:

```rust
use ai_memory_cli::marker::{read_scope, find_marker};
use ai_memory_cli::env::RuntimeEnv;

fn main() {
    // Assume execution from "/home/dev/projects/acme/api"
    let cwd = std::env::current_dir().unwrap();
    let env = RuntimeEnv::load(); // Loads AI_MEMORY_* environment variables
    
    if let Some(scope) = read_scope(cwd.to_str().unwrap(), &env) {
        println!("Workspace: {}", scope.workspace.unwrap_or_else(|| "default".into()));
        println!("Project:   {}", scope.project.unwrap_or_else(|| "basename".into()));
    } else {
        println!("No marker found – falling back to defaults");
    }
}

```

## Practical Configuration Examples

Place the [`.ai-memory.toml`](https://github.com/akitaonrails/ai-memory/blob/main/.ai-memory.toml) at the repository root to establish consistent routing for the entire project:

```toml

# .ai-memory.toml at repository root

workspace = "client-acme"
project_strategy = "repo-root"

# Optional: explicitly pin project name instead of deriving from repo root

# project = "backend-api"

```

This configuration ensures that all subdirectories, feature branches, and linked worktrees share the same project namespace while isolating this data from other workspaces.

## Summary

- **The [`.ai-memory.toml`](https://github.com/akitaonrails/ai-memory/blob/main/.ai-memory.toml) marker** creates a filesystem-based isolation boundary that namespaces all memory operations through a `(workspace, project, path)` tuple.
- **Discovery walks upward** from the current working directory via `find_marker` in [`crates/ai-memory-cli/src/marker.rs`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-cli/src/marker.rs), stopping at the nearest marker to establish authority.
- **Project scoping strategies** include basename derivation (default) or repository-root derivation via `project_strategy = "repo-root"`.
- **Server routing** occurs by converting marker fields to query parameters in [`hook_capture.rs`](https://github.com/akitaonrails/ai-memory/blob/main/hook_capture.rs), enabling multi-client and mono-repo support without server reconfiguration.

## Frequently Asked Questions

### What happens if no [`.ai-memory.toml`](https://github.com/akitaonrails/ai-memory/blob/main/.ai-memory.toml) file exists in the directory tree?

If the filesystem walk reaches the root without finding a marker, the system falls back to default values: the workspace becomes `"default"`, and the project name derives from the basename of the current working directory. This ensures the CLI remains functional in unmarked directories while maintaining predictable, isolated defaults.

### Can I override a parent marker with a child directory configuration?

Yes. The discovery mechanism stops at the first [`.ai-memory.toml`](https://github.com/akitaonrails/ai-memory/blob/main/.ai-memory.toml) encountered when walking upward from the current working directory. An inner marker completely overrides any outer markers—the system does not merge configurations, ensuring the nearest configuration file serves as the single source of truth for that directory subtree.

### How does `project_strategy = "repo-root"` differ from the default behavior?

The default strategy derives the project name from the basename of the current working directory, meaning `src/` and `tests/` would appear as separate projects. Setting `project_strategy = "repo-root"` forces the system to identify the main Git repository root and use its name as the project identifier, ensuring all subdirectories and worktrees share a unified project namespace.

### Where should I place the [`.ai-memory.toml`](https://github.com/akitaonrails/ai-memory/blob/main/.ai-memory.toml) file in a mono-repo structure?

Place the marker at the repository root to share a single project namespace across all packages, or place individual markers within package subdirectories to create isolated projects for each component. According to the implementation in [`crates/ai-memory-cli/src/marker.rs`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-cli/src/marker.rs), the CLI will respect whichever marker is closest to your current working directory, enabling flexible per-package or per-team isolation within the same repository.