Keep an agent connected to its context across sessions. Durable memory, in-flight project state, and an append-only session ledger — as plain files on disk, owned by you, readable by any runtime.
An agent starts every session cold. Tether is the cord that snaps it back: boot to load what matters, work, handoff to persist what changed. No database, no service, no vendor lock-in. Just Markdown and JSON you can read, grep, version, and carry between tools.
┌─────────────────────────────────────────────────────┐
│ T E T H E R │
├───────────┬───────────┬───────────┬─────────────────┤
│ Memory │ Pickups │ Ledger │ Skills │
│ durable │ in-flight │ append- │ runtime-neutral │
│ facts, │ project │ only │ behavior │
│ one per │ state for │ session │ contracts, │
│ file │ cold │ events │ rendered per │
│ │ pickup │ │ runtime │
└───────────┴───────────┴───────────┴─────────────────┘
boot ──▶ work ──▶ handoff
(load) (persist)
audits keep it honest
~1,500 LOC · stdlib-only Python · zero dependencies · 27 tests · CI
Agent runtimes remember within a session and forget between them. The usual fix is to pour everything into a vendor's cloud memory and hope the retrieval is good. Tether takes the opposite bet: your context is just files, and you own them. One fact per file with frontmatter, ranked recall you can inspect, an audit trail you can tail. Any runtime that can read a file can use it; nothing is trapped in a format you can't leave.
Four surfaces, each with one job:
| Surface | Job | Where |
|---|---|---|
| Memory | durable facts, one per file | unified store (symlinked into ~/.tether/state/) |
| Pickups | in-flight project state for cold pickup | ~/.tether/notes/workspaces/default/pickups/ |
| Ledger | append-only session events (start/end/handoff) | ~/.tether/ledger/events.jsonl |
| Skills | runtime-neutral behavior contracts | skills/, rendered per runtime by adapters/ |
The session loop: boot at start (index tiers, active pickups, ledger warnings), work, handoff at close (update the pickup, log the event). Audits keep the surfaces honest over time.
$ tether boot
tether 0.1.0 — session boot
Memory: 4 facts (index generated 2026-07-01T21:55:46Z)
• project-recipe-box-import — 2 linked memories, freshest 2026-06-05
• 2 standalone memories
Active pickups: none
Ledger: no other active sessions
$ tether recall sql
9.5 user_prefers_plain_sql.md — Prefers hand-written SQL over query builders in personal projects, verified 2026-06-01Recall ranks by term relevance × freshness × reinforcement, then follows one hop of related links — so re-confirmed, well-connected facts surface first, and the score is right there to inspect.
One fact per file, Markdown with frontmatter:
---
name: short-kebab-slug
description: one-line summary used for recall relevance ranking
metadata:
type: user | feedback | project | reference
related: [other_file.md] # optional, 2–4 cross-cluster bridges
last_verified: YYYY-MM-DD # optional freshness stamp
reinforced: 0 # bumped when a fact is re-confirmed
---
The fact, citing its source. Inline-link related memories with [[name]].Two index files sit beside the memories: MEMORY.md (human-curated one-liners, under 200 chars/line and 24KB total — it loads into every session) and MEMORY-INDEX.json (generated cluster/freshness tiers for compact boot context).
The agent runtime keeps its own per-workspace auto-memory directory. Tether does not duplicate it: the installer symlinks ~/.tether/state/workspaces/default/memory to that native directory, so the CLI, hooks, and the runtime's auto-memory all read and write one store. There are never two copies.
tether boot [topic] deterministic session context (+ optional recall)
tether recall <topic> ranked retrieval: term relevance × freshness ×
reinforcement, plus one hop of related links
tether handoff append a handoff ledger event + close checklist
tether audit stale memories, broken/one-way links, index drift,
handoff coverage, stale pickups
tether index regenerate MEMORY-INDEX.json, report index drift
tether doctor end-to-end health check incl. repo-vs-installed drift
tether update pull the repo and reinstall
Seven skills mirror this for in-session use: /tether, /handoff, /recall, /memory-audit, /memory-index, /context-health, /skills-audit. Each is a neutral contract (triggers, inputs, stop conditions, judgment rules) plus a capability.json; adapters render them into runtime-specific form.
Requirements: Python 3.11+, POSIX shell. No third-party dependencies.
git clone https://github.com/alerubbio/tether.git && cd tether
sh install.sh
tether doctorSee INSTALL.md for what the installer does, environment overrides, and hook wiring (which is deliberately a separate, diff-reviewed step).
tether update # pulls the repo, re-runs the installerThe drift gotcha, prominently: the repo is the source of truth, and the installed copy under ~/.tether is what actually runs. Editing the repo does nothing until you reinstall. tether doctor diffs the two and tells you when they've diverged.
- Files you own. Plain Markdown + JSON on disk. No database, no service, no proprietary format to be locked into.
- Runtime-neutral. Skills are behavior contracts;
adapters/render them per runtime. The engine has no opinion about which agent drives it. - Zero dependencies. Stdlib-only Python 3.11+. Nothing to
pip install, nothing to keep patched. - Honest about drift. The installed copy, not the repo, is what runs — and
tether doctorsays so out loud when they diverge. - One store, never two. The unified-store symlink means the CLI and the runtime's own memory are the same files.
core/ stdlib-only python package (memory, graph, index, trim,
pickups, ledger, skills)
bin/tether CLI
skills/ seven neutral skill contracts
adapters/ per-runtime skill renderers (anthropic, generic)
hooks/ session-start/end runtime hooks
scripts/ settings wiring (diff-first), CI checks
jobs/ optional maintenance jobs
memory/examples/ synthetic format examples (the live store starts empty)
tests/ unit tests (run: python3 -m unittest discover -s tests)
MIT — see LICENSE.
Alejandro Rubio