# How Architecture Decision Records (ADRs) are Managed in codebase-memory-mcp

> Discover how Architecture Decision Records ADR are managed in codebase-memory-mcp. Learn about storage, API manipulation, and access via HTTP and CLI.

- Repository: [Martin Vogel/codebase-memory-mcp](https://github.com/DeusData/codebase-memory-mcp)
- Tags: how-to-guide
- Published: 2026-07-16

---

**Architecture Decision Records in codebase-memory-mcp are stored as markdown blobs in a SQLite database, manipulated through a dedicated C API with section-level granularity, and exposed via both HTTP endpoints and a CLI tool.**

The codebase-memory-mcp project treats Architecture Decision Records (ADRs) as first-class metadata artifacts that persist alongside your code graph. Unlike standalone documentation files, ADRs live within the same storage layer as the rest of your project intelligence, enabling programmatic access, selective updates, and automatic migration from legacy file-based formats.

## Storage Backend and Data Model

ADRs are persisted in the **`project_summaries`** table within the same SQLite database that backs the rest of the code-graph metadata. The implementation stores each ADR as a plain-text markdown blob with a strict size limit of **8,000 bytes** defined by the constant `CBM_ADR_MAX_LENGTH` in [`src/store/store.h`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/store/store.h).

This design keeps architectural decisions searchable and versioned alongside code entities, while the size constraint ensures the database remains performant during graph traversal operations.

## Core C API for ADR Management

The storage layer exposes a dedicated C API for CRUD operations declared in [`src/store/store.h`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/store/store.h) (lines 601–630) and implemented in [`src/store/store.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/store/store.c) (lines 6217–6608).

### Storing and Retrieving ADRs

The primary functions for full-document operations are:

- **`cbm_store_adr_store(cbm_store_t *s, const char *project, const char *content)`** – Creates a new ADR or overwrites an existing one for the specified project.
- **`cbm_store_adr_get(cbm_store_t *s, const char *project, cbm_adr_t *out)`** – Retrieves the current ADR content into the provided structure.
- **`cbm_store_adr_delete(cbm_store_t *s, const char *project)`** – Permanently removes the ADR from the database.

```c
#include "store.h"

cbm_store_t *store = cbm_store_open("mydb.sqlite");
const char *project = "myservice";
const char *adr_md = "# Decision 001\n\n**Status:** Accepted\n\n...";

int rc = cbm_store_adr_store(store, project, adr_md);
if (rc != 0) {
    fprintf(stderr, "Failed to store ADR: %s\n", cbm_store_last_error(store));
}

cbm_adr_t adr = {0};
if (cbm_store_adr_get(store, "myservice", &adr) == 0) {
    printf("ADR content:\n%s\n", adr.content);
    cbm_store_adr_free(&adr);
}
cbm_store_close(store);

```

### Section-Level Updates

The **`cbm_store_adr_update_sections`** function allows surgical updates to specific markdown sections (such as *Status* or *Context*) without rewriting the entire document:

```c
const char *keys[]   = {"Status"};
const char *values[] = {"Deprecated"};
cbm_adr_t updated;

if (cbm_store_adr_update_sections(store, "myservice",
                                  keys, values, 1, &updated) == 0) {
    printf("Updated ADR:\n%s\n", updated.content);
    cbm_store_adr_free(&updated);
}

```

This is supported by helper functions **`cbm_adr_parse_sections`** and **`cbm_adr_render`** which convert between markdown blobs and key/value maps, along with validation helpers **`cbm_adr_validate_content`** and **`cbm_adr_validate_section_keys`** that enforce format constraints.

## Legacy Migration from File-Based Storage

Earlier versions of codebase-memory-mcp stored ADRs in a flat file at `<repo_root>/.codebase-memory/adr.md`. The system now automatically migrates this legacy data:

When `cbm_store_adr_get` is called and the database returns empty, the code in [`src/mcp/mcp.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/mcp/mcp.c) checks for the legacy file. If found, it imports the content into the SQLite database and deletes the original file. This ensures seamless upgrades without manual data migration.

## HTTP API Interface

The web UI exposes RESTful endpoints for external integrations. The implementation resides in [`src/ui/http_server.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/ui/http_server.c) (lines 765–826).

- **GET `/api/adr?project=X`** – Returns the stored markdown for project *X*.
- **POST `/api/adr`** – Accepts a JSON body with `project` and `content` fields to create or update an ADR.

```bash

# Retrieve ADR

curl https://cbm.local/api/adr?project=myservice

# Create or update ADR

curl -X POST https://cbm.local/api/adr \
    -H "Content-Type: application/json" \
    -d '{"project":"myservice","content":"# New ADR\n\n**Status:** Proposed\n\n..."}'

```

## CLI Integration with manage_adr

The `manage_adr` tool registered in [`src/mcp/mcp.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/mcp/mcp.c) (lines 6684–6782) provides command-line access to ADR operations:

```bash

# Create or update an ADR

cbm manage_adr mode=update project=myservice \
    content="$(cat path/to/adr.md)"

# Display current ADR

cbm manage_adr mode=read project=myservice

# Remove ADR

cbm manage_adr mode=delete project=myservice

```

All CLI operations surface meaningful error messages such as `"no ADR found"` or `"merged ADR exceeds … chars"` directly to the user.

## Data Consistency During Re-indexing

To prevent accidental loss during large-scale migrations, the pipeline in [`src/pipeline/pipeline.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/pipeline/pipeline.c) (lines 118–119) implements a safeguard: when a full re-index is triggered, the system captures any existing ADR before wiping the database and restores it afterward. This addresses the specific edge case documented in issue #516, ensuring that architectural decisions persist across database rebuilds.

## Summary

- ADRs are stored as **8000-byte markdown blobs** in the SQLite `project_summaries` table, enforcing portability and searchability.
- The **C API** (`cbm_store_adr_store`, `cbm_store_adr_get`, `cbm_store_adr_update_sections`, `cbm_store_adr_delete`) provides full CRUD capabilities with section-level granularity.
- **Legacy file-based ADRs** are automatically migrated from [`.codebase-memory/adr.md`](https://github.com/DeusData/codebase-memory-mcp/blob/main/.codebase-memory/adr.md) into the database on first access.
- Both **HTTP endpoints** (`/api/adr`) and the **CLI tool** (`manage_adr`) expose the same underlying storage layer.
- **Re-indexing operations** preserve ADR data by capturing and restoring the content before and after database wipes.

## Frequently Asked Questions

### What is the maximum size for an ADR in codebase-memory-mcp?

The system enforces a hard limit of **8,000 bytes** (the `CBM_ADR_MAX_LENGTH` constant). If you attempt to store content exceeding this limit, the API returns an error message indicating the merged ADR exceeds the character threshold.

### Can I update only the status section of an ADR without rewriting the entire document?

Yes. Use the **`cbm_store_adr_update_sections`** function (or the equivalent HTTP/CLI interfaces) to modify specific markdown sections such as *Status* or *Context*. The underlying parser preserves all other sections unchanged, maintaining the document's history and formatting.

### How does the system handle existing ADRs when I rebuild the code graph?

The pipeline in [`src/pipeline/pipeline.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/pipeline/pipeline.c) explicitly safeguards ADRs during full re-index operations. It captures the existing ADR content before clearing the database and restores it afterward, preventing data loss that was previously reported in issue #516.

### Where is the legacy ADR file migrated from?

Older versions used `<repo_root>/.codebase-memory/adr.md`. Upon first access to the ADR API, the system checks for this file in [`src/mcp/mcp.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/mcp/mcp.c). If found, it imports the content into the SQLite database and removes the legacy file, completing the migration transparently.