GitHub - tadelstein9/two-tier-memory: A queryable long-term memory for AI coding agents — the two-tier fix for the context-window wall · GitHub
/" data-turbo-transient="true" />
Skip to content
Search or jump to...
Search code, repositories, users, issues, pull requests...
-->
Search
Clear
Search syntax tips
Provide feedback
--><br>We read every piece of feedback, and take your input very seriously.
Include my email address so I can be contacted
Cancel
Submit feedback
Saved searches
Use saved searches to filter your results more quickly
-->
Name
Query
To see all available qualifiers, see our documentation.
Cancel
Create saved search
Sign in
/;ref_cta:Sign up;ref_loc:header logged out"}"<br>Sign up
Appearance settings
Resetting focus
You signed in with another tab or window. Reload to refresh your session.<br>You signed out in another tab or window. Reload to refresh your session.<br>You switched accounts on another tab or window. Reload to refresh your session.
Dismiss alert
{{ message }}
tadelstein9
two-tier-memory
Public
Notifications<br>You must be signed in to change notification settings
Fork
Star
master
BranchesTags
Go to file
CodeOpen more actions menu
Folders and files<br>NameNameLast commit message<br>Last commit date<br>Latest commit
History<br>2 Commits<br>2 Commits
.gitignore
.gitignore
LICENSE
LICENSE
README.md
README.md
memory.py
memory.py
schema.sql
schema.sql
View all files
Repository files navigation
two-tier-memory
A queryable long-term memory for AI coding agents — the two-tier fix for the context-window wall.
Companion essay: "Your AI's Memory Breaks on Real Work. The Fix Is Fifty Years Old."
The problem
An AI coding agent's default long-term memory is a stack of markdown files it loads into context at the start of every session. That works at ten files. It fails at a hundred and forty: everything competes for one finite context window, and past the edge the memory silently truncates — the agent quietly forgets, re-solves solved problems, contradicts last week's decisions. You blame the model. The filing system is the problem.
It's an old problem. Loading a whole file and scanning it is the pre-relational habit that databases were invented, in 1970, to kill: store it structured, index it, fetch only the row you need.
The fix: two tiers
Tier 1 — an index, always loaded. One line per solved problem: a title and a pointer. Cheap to carry every session. It tells the agent what exists, never the detail. (INDEX.md, generated from tier 2 so it never drifts.)
Tier 2 — a database, queried on demand. Every hard problem becomes a row in a plain SQLite file — problem, root cause, what worked, the gotcha, the artifacts. A thousand rows cost the agent nothing until it runs a query. When something smells familiar, it asks the table instead of rummaging through prose.
Stop loading the library. Keep an index you can hold, and a database you can question.
Use it
python3 memory.py init
python3 memory.py add \<br>--area db --title "SQLite can't persist a view over an ATTACH-ed database" \<br>--problem "CREATE VIEW over an attached db vanished on the next connection" \<br>--root-cause "the view binds to the attach alias, not the file" \<br>--solution "materialize into the main db, or re-ATTACH and re-create the view on open" \<br>--gotcha "no error is raised — the view simply isn't there next session" \<br>--tags "sqlite,attach,view"
python3 memory.py query "attach view disappears"<br>python3 memory.py get 1<br>python3 memory.py index # regenerate INDEX.md from the database
The part that isn't the database
The tool alone is a trap. It earns its keep only with a habit and a little hygiene:
Query before you rebuild. An agent's reflex is to solve, not to look up. Make "search the memory first" a standing rule, or the database becomes dead weight.
Keep rows honest. Write them the day you solve the thing; delete them the day they turn out wrong. A stale row misleads worse than an empty table.
Retrieval has a ceiling. Full-text search (built in here, via FTS5) finds the words you match, not the row you meant. When you outgrow it, bolt semantic search / embeddings onto this same relational base — don't start there.
Wiring it into an agent
Point your agent's project instructions at two rules:
On a new hard problem, query first ; act on a hit.
On solving something novel, add a row , then index .
The always-loaded INDEX.md primes the agent on what it already knows; the database holds the rest, for free.
Files
File<br>Role
schema.sql<br>the solutions table + an FTS5 full-text index kept in sync by triggers
memory.py<br>stdlib-only CLI: init / add / query / get / list / index
INDEX.md<br>tier-1 index, generated from the database (git-ignored)
memory.db<br>tier-2 store — your data (git-ignored)
No dependencies. Python 3 and its bundled sqlite3.
Credit
Built in the open by Tom Adelstein. The pattern came out of a working session with Claude Code, Anthropic's coding agent: I pitched the relational...