How Architecture Decision Records (ADRs) are Managed in codebase-memory-mcp
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.
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 (lines 601–630) and implemented in 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.
#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:
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 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 (lines 765–826).
- GET
/api/adr?project=X– Returns the stored markdown for project X. - POST
/api/adr– Accepts a JSON body withprojectandcontentfields to create or update an ADR.
# 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 (lines 6684–6782) provides command-line 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 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 (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_summariestable, 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.mdinto 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 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. If found, it imports the content into the SQLite database and removes the legacy file, completing the migration transparently.
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 →