How Architecture Decision Records (ADRs) Are Managed in codebase-memory-mcp: A Complete Technical Guide

The codebase-memory-mcp project treats Architecture Decision Records as first-class artifacts stored as markdown blobs in SQLite, offering CRUD operations through a C API, CLI tool, and HTTP endpoints with support for section-level updates and automatic migration from legacy file storage.

The codebase-memory-mcp tool provides a robust system for managing Architecture Decision Records (ADRs) alongside code graph metadata. Unlike standalone documentation files, ADRs are persisted in the same storage layer as the rest of the project intelligence, making them searchable, versioned, and portable. This integration ensures that architectural decisions remain tightly coupled with the codebase they describe.

Storage Backend and Data Model

ADR content is stored in the SQLite project_summaries table, sharing the same database that backs other code-graph metadata. Each ADR is persisted as a plain-text markdown blob with a strict size limit of 8,000 bytes enforced by the CBM_ADR_MAX_LENGTH constant defined in src/store/store.h.

This design choice keeps ADRs portable while preventing storage bloat. The 8000-byte limit accommodates comprehensive decision records while maintaining query performance across the project_summaries table.

Core C API for ADR Management

The primary interface for ADR operations resides in src/store/store.c (lines 6217-6608), exposing four key functions declared in src/store/store.h (lines 601-630):

  • cbm_store_adr_store – Creates a new ADR or overwrites an existing one for a specified project.
  • cbm_store_adr_get – Retrieves the current ADR content into a cbm_adr_t structure.
  • cbm_store_adr_delete – Permanently removes the ADR record from the database.
  • cbm_store_adr_update_sections – Updates specific markdown sections (e.g., Status, Context) without modifying unrelated content.

Validation helpers cbm_adr_validate_content and cbm_adr_validate_section_keys ensure that stored ADRs conform to expected markdown formatting before persistence.

Parsing and Section-Level Updates

To enable surgical edits, the codebase implements parsing utilities that decompose markdown into key-value pairs. The cbm_adr_parse_sections function extracts headers and their content, while cbm_adr_render reconstructs the markdown blob after modifications.

This architecture allows developers to update individual sections—such as changing only the Status from "Proposed" to "Accepted"—without rewriting the entire document. The cbm_store_adr_update_sections function accepts arrays of keys and values, applies the changes to the parsed structure, and re-renders the final markdown for storage.

Legacy Migration Strategy

Earlier versions of codebase-memory-mcp stored ADRs in a standalone file at <repo_root>/.codebase-memory/adr.md. The migration logic in src/mcp/mcp.c (lines 6684-6782) handles backward compatibility seamlessly.

When accessing ADR data, the system first queries the SQLite database. If no record exists, it checks for the legacy file, imports the content into the database, and deletes the old file. This one-time migration ensures zero data loss when upgrading to newer versions of the tool.

HTTP API and Web Interface

The web UI exposes RESTful endpoints implemented in src/ui/http_server.c (lines 765-826):

  • GET /api/adr?project=X – Returns the raw markdown content for the specified project.
  • POST /api/adr – Accepts a JSON payload containing project and content fields to create or update an ADR.

These endpoints provide language-agnostic access to decision records, enabling integration with external documentation systems or CI/CD pipelines.

CLI Integration with manage_adr

The manage_adr command-line tool, registered in src/mcp/mcp.c, provides direct shell access to ADR operations:


# 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 the ADR

cbm manage_adr mode=delete project=myservice

The CLI surfaces detailed error messages—such as "no ADR found" or "merged ADR exceeds … chars"—providing immediate feedback when operations violate constraints like the 8000-byte limit.

Data Integrity and Consistency Guarantees

During full re-indexing operations, the pipeline safeguards against accidental ADR loss. Comments in src/pipeline/pipeline.c (lines 118-119) indicate that the system captures existing ADRs before wiping the database and restores them afterward.

This protection mechanism, implemented in response to issue #516, ensures that major migrations or schema updates do not destroy architectural decision history. All ADR functions set meaningful error messages that propagate to both the CLI and HTTP interfaces, maintaining clear communication about failure states.

Code Examples

Storing a New ADR in C

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_store_close(store);

Reading an ADR in C

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

Updating Only the Status Section

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);
}

Accessing ADRs via HTTP


# Retrieve ADR

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

# Update ADR

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

Summary

  • Architecture Decision Records in codebase-memory-mcp are stored as markdown blobs in the SQLite project_summaries table with an 8000-byte limit enforced by CBM_ADR_MAX_LENGTH.
  • Core operations leverage the C API in src/store/store.c, including cbm_store_adr_store, cbm_store_adr_get, and section-level updates via cbm_store_adr_update_sections.
  • Legacy compatibility is maintained through automatic migration from .codebase-memory/adr.md files to the database, handled in src/mcp/mcp.c.
  • Multi-interface access includes the manage_adr CLI tool and HTTP endpoints (/api/adr) defined in src/ui/http_server.c.
  • Data integrity is preserved across full re-indexes through safeguards in src/pipeline/pipeline.c that backup and restore ADRs during database migrations.

Frequently Asked Questions

What is the maximum size for an Architecture Decision Record in codebase-memory-mcp?

The system enforces a hard limit of 8,000 bytes (defined as CBM_ADR_MAX_LENGTH in src/store/store.h) for each ADR stored in the project_summaries table. This constraint ensures that markdown content remains concise and query performance stays optimal. Attempts to store larger records will fail with a "merged ADR exceeds … chars" error message.

How does the system handle ADRs created in older versions of the tool?

Legacy ADRs stored in <repo_root>/.codebase-memory/adr.md are automatically migrated on first access. The logic in src/mcp/mcp.c checks the database for existing content; if empty, it reads the legacy file, imports the markdown into SQLite, and deletes the old file. This seamless migration ensures backward compatibility without manual intervention.

Can I update specific sections of an ADR without rewriting the entire document?

Yes. The API provides cbm_store_adr_update_sections in src/store/store.c, which uses cbm_adr_parse_sections to decompose the markdown into key-value pairs, updates only the specified sections (such as Status or Context), and re-renders the content using cbm_adr_render. This allows surgical edits while preserving the rest of the document structure.

Are ADRs preserved during database re-indexing operations?

Yes. According to comments in src/pipeline/pipeline.c (lines 118-119), the pipeline explicitly captures existing ADRs before performing full database wipes and restores them afterward. This safeguard, implemented to address issue #516, prevents accidental loss of architectural decision history during major schema migrations or re-indexing tasks.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →