Metadata-Version: 2.4
Name: memcask
Version: 0.1.0
Summary: Durable, tamper-evident context for AI agents in one file. Zero dependencies.
Author: Drew Mattie
License: MIT
Project-URL: Homepage, https://github.com/drewmattie-code/memcask
Project-URL: Spec, https://github.com/drewmattie-code/Durable-Context-Spine
Keywords: ai,agents,memory,context,sqlite,llm,durable,state
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Software Development :: Libraries
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: license-file

# memcask: durable context for AI agents, in one file

**The SQLite of agent memory.** A tiny, zero-dependency, tamper-evident store for the context an agent needs to survive across sessions, restarts, and machines.

One file on disk. Python standard library only. MIT.

```python
from memcask import Context

ctx = Context("agent.cask")              # open or create one portable file
ctx.append("user", "Book me a flight to NYC")
ctx.append("assistant", "Searching flights...")
ctx.set("pref.seat", "aisle")           # durable key/value state

# ...new process, a week later...
ctx = Context("agent.cask")
ctx.messages(limit=20)                   # resume: recent log, ready for an LLM
ctx.get("pref.seat")                    # "aisle"
ctx.verify()                             # True: nothing was corrupted or tampered with
```

That's the whole idea. Your agent now remembers, across runs, in a file you can copy, commit, diff, and trust.

## Why

Every agent needs to remember what happened across sessions. Today you either:

- **reinvent it badly**: hand-rolled JSON blobs, a pickle file, a `messages` list you forget to persist; or
- **adopt a heavy dependency**: a hosted memory service or a framework's memory module that drags in a stack, an account, and a vendor.

There's no small, neutral, *boring* primitive for "durable agent context." `memcask` is that primitive: a single file, no dependencies, no server, no account, and because every entry is hash-chained, you can prove the record wasn't silently altered.

## Features

- **Zero dependencies.** Pure Python standard library (`sqlite3`, `json`, `hashlib`). Nothing to install but the file.
- **One portable file.** A `.cask` file *is* a SQLite database. Move it, commit it, ship it, inspect it with any SQLite tool.
- **Append-only log + key/value state.** The durable record of what happened, plus the facts your agent keeps.
- **Tamper-evident.** Every entry is SHA-256 hash-chained to the previous one. `verify()` catches any altered, reordered, or dropped entry.
- **Resume is just reopening the file.** No special "load" ceremony.
- **LLM-ready.** `messages()` hands you `[{"role", "content"}]` straight into a model call.
- **Tiny.** ~150 lines you can read in one sitting.

## Install

It's a single file with zero dependencies, so the simplest install is to **copy `memcask.py` into your project**.

Or, once it's on PyPI:

```bash
pip install memcask
```

> Note: the PyPI publish is pending; for now, copy the one file.

## API

```python
ctx = Context("agent.cask")           # open/create

# durable append-only log
ctx.append(role, content) -> seq     # content = any JSON-serializable value
ctx.history(limit=None, role=None)   # [{seq, ts, role, content}], oldest-first
ctx.messages(limit=None, roles=None) # [{"role","content"}] for an LLM call
ctx.head()                           # hash of the latest entry
len(ctx); for e in ctx: ...

# durable key/value state
ctx.set(key, value); ctx.get(key, default=None)
ctx.delete(key); ctx.state()         # full snapshot

# integrity
ctx.verify(raise_on_fail=False)      # walk the hash chain

ctx.close()                          # or use `with Context(...) as ctx:`
```

## It's just SQLite, no lock-in

A `.cask` file is a normal SQLite database. Inspect it with anything:

```bash
sqlite3 agent.cask "select seq, role, content from log order by seq;"
```

Your data is never trapped. That's the point.

## Why not Mem0 / Zep / Letta / LangChain memory?

Those are good, *bigger* tools: semantic memory, vector recall, hosted services, framework integration. Reach for them when you need that.

`memcask` is deliberately the layer underneath: the **boring, durable, portable record** of an agent's context, with **zero dependencies and tamper-evidence**, that you can drop into anything (including those tools) without taking on a stack or a vendor. It does one thing. Most agents need that one thing first.

## Integrity model

`memcask` is **tamper-evident**, not tamper-proof. Each entry's hash commits to the previous entry's hash, so any in-place edit, reordering, or deletion of a historical entry makes `verify()` return `False`. What it does *not* do on its own: stop someone with write access from rewriting the whole chain from scratch. Like any unanchored hash chain, catching that requires pinning a known-good head somewhere external (sign it, or store the latest `head()` elsewhere).

It is also **not** an encryption layer: a `.cask` file is plaintext SQLite, readable by anyone who has it. Treat it like any data file: don't put secrets in it unless the file itself is protected.

## Status

v0.1, small on purpose, and it will stay that way: the cleanest possible durable-context primitive. Reference implementation of the **Durable Context Spine** (DCS): https://github.com/drewmattie-code/Durable-Context-Spine

## License

MIT © Drew Mattie
