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 projectcbm_store_adr_get– Retrieves the complete ADR content for a given project identifiercbm_store_adr_delete– Permanently removes an ADR from the databasecbm_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 JSONPOST /api/adr– Creates or updates an ADR using a JSON body withprojectandcontentfields
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_summariestable alongside other codebase metadata, accessible viacbm_store_adr_*functions insrc/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_adrCLI command, REST endpoints insrc/ui/http_server.c, or the React-based web interface. - Partial Updates: The
cbm_store_adr_update_sectionsfunction 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →