How Codebase Memory Implements Architecture Decision Records (ADR) Management

The ADR management system in Codebase Memory provides a full-featured subsystem for creating, storing, retrieving, and updating Architecture Decision Records in a SQLite-backed repository, complete with CLI, HTTP API, and web UI interfaces.

Codebase Memory, an open-source project under DeusData/codebase-memory-mcp, embeds a complete Architecture Decision Records (ADR) management system directly into its analysis engine. Unlike external documentation tools, this system stores ADRs alongside code intelligence in a unified SQLite database, enabling programmatic access through C libraries, command-line tools, and REST endpoints.

ADR Storage Architecture

The foundation of the ADR management system rests on a three-layer design that separates persistent storage from content processing and user interfaces.

SQLite Storage Layer

ADRs persist in the project_summaries table, sharing the same transactional storage as other project-level metadata. The public C API, declared in src/store/store.h, exposes four core operations:

  • cbm_store_adr_store – Inserts a new ADR or overwrites an existing record for a project
  • cbm_store_adr_get – Retrieves the complete ADR content for a given project identifier
  • cbm_store_adr_delete – Permanently removes an ADR from the database
  • cbm_store_adr_update_sections – Performs partial updates to specific sections without rewriting the entire document

These functions operate on a cbm_store_t handle, ensuring ACID compliance across all ADR operations.

ADR Content Processing

The system treats ADR content as structured markdown with strict schema validation, ensuring consistency across all architectural records.

Parsing and Rendering Engine

In src/store/store.c, the cbm_adr_parse_sections function implements a line-by-line markdown parser that detects ## headers and maps them to a cbm_adr_sections_t structure. This parser recognizes six canonical sections: PURPOSE, STACK, ARCHITECTURE, PATTERNS, TRADEOFFS, and PHILOSOPHY.

For output generation, cbm_adr_render reassembles the section map into canonical markdown, emitting required sections in standard order followed by any custom sections sorted alphabetically. This round-trip parsing ensures that partial updates maintain document integrity.

Validation Rules

Before persistence, cbm_adr_validate_content verifies that all six required sections are present, while cbm_adr_validate_section_keys restricts section names to the allowed set. This schema enforcement prevents malformed ADRs from entering the codebase memory.

User Interfaces for ADR Management

Codebase Memory exposes ADR functionality through three complementary interfaces, accommodating different workflows from automation to manual editing.

CLI Command Interface

The manage_adr command, registered in src/mcp/mcp.c, supports mode='create' and mode='update' actions that wrap the underlying store functions. This command also includes migration logic to import legacy file-based ADRs from .codebase-memory/adr.md into the database store.

HTTP API Endpoints

The HTTP server in src/ui/http_server.c provides RESTful access to ADR data:

  • GET /api/adr?project={name} – Returns the stored ADR as JSON
  • POST /api/adr – Creates or updates an ADR using a JSON body with project and content fields

These endpoints enable external tools and CI/CD pipelines to read and write architectural decisions programmatically.

Web UI Component

The React frontend includes ADR management through graph-ui/src/components/StatsTab.tsx, where an "ADR" button opens a modal interface for creating or editing records. This provides non-technical stakeholders with direct access to architectural documentation without requiring API calls or command-line usage.

Working with ADRs in Code

The following examples demonstrate the C API for common ADR operations.

Storing a New ADR

const char *my_adr = 
    "## PURPOSE\n"

    "Explain why we choose SQLite.\n"
    "## STACK\n"

    "SQLite, libpq, …\n"
    "## ARCHITECTURE\n"

    "Single‑process DB.\n"
    "## PATTERNS\n"

    "Repository, DAO.\n"
    "## TRADEOFFS\n"

    "No clustering.\n"
    "## PHILOSOPHY\n"

    "Keep it simple.\n";

cbm_store_t *store = cbm_store_open("mydb.sqlite3");
int rc = cbm_store_adr_store(store, "my‑project", my_adr);
if (rc != CBM_STORE_OK) {
    fprintf(stderr, "Failed to store ADR: %s\n", cbm_store_errmsg(store));
}

Retrieving an ADR

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

Updating Specific Sections

const char *keys[]   = {"TRADEOFFS"};
const char *values[] = {"We give up clustering for simplicity."};
cbm_adr_t updated = {0};
int rc = cbm_store_adr_update_sections(store,
                                       "my‑project",
                                       keys, values, 1,
                                       &updated);
if (rc == CBM_STORE_OK) {
    printf("Updated ADR: %s\n", updated.content);
    cbm_store_adr_free(&updated);
}

Using the HTTP API


# Get the ADR

curl -s "http://localhost:8080/api/adr?project=my-project" | jq .

# Update the ADR

curl -X POST http://localhost:8080/api/adr \
     -H "Content-Type: application/json" \
     -d '{"project":"my-project","content":"## PURPOSE\n…"}'

Summary

  • Unified Storage: ADRs live in the project_summaries table alongside other codebase metadata, accessible via cbm_store_adr_* functions in src/store/store.h.
  • Structured Content: The system enforces six canonical sections (PURPOSE, STACK, ARCHITECTURE, PATTERNS, TRADEOFFS, PHILOSOPHY) through parsing and validation logic in src/store/store.c.
  • Multi-Modal Access: Users interact with ADRs through the manage_adr CLI command, REST endpoints in src/ui/http_server.c, or the React-based web interface.
  • Partial Updates: The cbm_store_adr_update_sections function enables surgical modifications to specific sections without rewriting entire documents.

Frequently Asked Questions

What is the required format for ADR content in Codebase Memory?

ADR content must be valid markdown containing six specific sections marked with ## headers: PURPOSE, STACK, ARCHITECTURE, PATTERNS, TRADEOFFS, and PHILOSOPHY. The cbm_adr_parse_sections function in src/store/store.c validates this structure during storage operations, and cbm_adr_render ensures canonical ordering when retrieving records.

How does the ADR management system handle legacy file-based records?

The manage_adr command in src/mcp/mcp.c includes migration logic that automatically imports existing ADRs from .codebase-memory/adr.md files into the SQLite database when running with mode='create'. This ensures historical architectural decisions are preserved when upgrading to newer versions of the tool.

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

Yes. The cbm_store_adr_update_sections function accepts arrays of section keys and values, allowing targeted updates to specific sections like TRADEOFFS or STACK while preserving all other content. This is particularly useful for automated tooling that needs to append decisions without parsing the full markdown document.

Which database table stores ADR data in Codebase Memory?

ADRs are stored in the project_summaries table within the SQLite database, using the same storage layer as other project metadata. The cbm_store_adr_store and cbm_store_adr_get functions in src/store/store.h provide the abstraction layer for reading and writing to this table.

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 →