Turn markdown into a SQLite database that AI coding tools can query.
Claude Code stores context as markdown files. That works fine until your project grows -- more files means more tokens in the context window, and things start getting truncated or ignored. You can't ask "who handles finance?" and get a straight answer. Claude has to scan through everything and hope the right file is loaded.
memory-x takes those markdown files and puts them in SQLite. Now Claude can query for what it needs instead of loading everything and hoping for the best.
memory-x reads your markdown, finds tables, and creates matching SQLite tables. Section headings become table names. Column headers become column names. You don't configure any of this.
A file like this:
## Team
| Name | Role |
|------|------|
| Alice | Engineering Lead |
| Bob | Designer |
## Glossary
| Term | Definition |
|------|-----------|
| SLA | Service Level Agreement |Becomes two SQLite tables: team (with name, role columns) and glossary (with term, definition columns). Bullet lists and paragraphs under headings get stored as key-value context entries in a separate _mx_context table.
If two sections share the same column structure (say "Team" and "Investors" both have Name/Role), they get merged into one table with a _mx_section column so you can still filter by origin.
npm install -g memory-x# Create a database and import your markdown
memoryx init
memoryx import ./CLAUDE.md
# Import a whole directory
memoryx import ./docs/
# Import Claude's auto-generated memory files
memoryx import ~/.claude/projects/*/memory/
# See what got created
memoryx status
memoryx tables
# Query directly
memoryx query "SELECT * FROM team"memory-x creates the database. codemode-x exposes it to Claude as MCP tools. Add this to your codemode-x.config.js:
export default {
sdkName: 'myapp',
domains: [
{
name: 'memory',
adapter: 'database',
source: './memory.db',
options: { writable: true },
},
],
};Setting writable: true lets Claude store things it learns during a conversation. Those live writes get tagged with _mx_source = 'live', so re-importing your markdown files never clobbers what Claude picked up on its own.
memoryx init [--db path] Create an empty database (default: ./memory.db)
memoryx import <source> [--db path] Import a markdown file or directory
memoryx status [--db path] Show table counts and import history
memoryx tables [--db path] List tables with their columns
memoryx query <sql> [--db path] Run a read-only SQL query
memoryx reset [--db path] Drop imported data, keep live context
memoryx reset --all [--db path] Drop everything
Any markdown table under a heading becomes a SQLite table. Headings get cleaned up for SQL -- "Portfolio -- 8 Properties (Acquiring 9th)" becomes just portfolio.
Bullet lists go into _mx_context as key-value pairs. If a bullet has a colon, it splits there: "Ship v2: target March 30" becomes key=Ship v2, value=target March 30.
Files with --- frontmatter (Claude Code's auto-memory format) are handled too. The type field from frontmatter becomes the section name, and the body is stored as a context entry.
Re-running memoryx import on an unchanged file is a no-op (it checks the file hash). If the file changed, the old rows from that file get replaced. Live context is never touched.
import { MemoryDB } from 'memory-x';
const db = new MemoryDB('./memory.db');
await db.init();
db.importFile('./CLAUDE.md');
db.importDirectory('./docs/');
const tables = db.listTables();
const results = db.query('SELECT * FROM team');
db.reset(); // keeps live context
db.reset(false); // drops everything
db.close();memory-x tracks its own state in tables prefixed with _mx_:
_mx_tables-- registry of dynamically created tables_mx_columns-- column metadata (original header text, inferred type)_mx_context-- key-value entries from non-table content_mx_imports-- import history with file hashes
When using codemode-x, you can exclude these with options: { exclude: ['_mx_tables', '_mx_columns', '_mx_context', '_mx_imports'] } in your domain config so they don't show up as MCP tools.
MIT