Trusted AI Recall System — local-first memory infrastructure for AI apps.
Give browser-based AI apps fast, private, local memory without a backend.
import { Tars } from "@tars/memory";
const tars = await Tars.create({ namespace: "my-agent" });
await tars.remember({
content: "The project uses SvelteKit",
type: "project",
importance: 0.9,
});
const memories = await tars.recall("What framework does the project use?");| Layer | Tech |
|---|---|
| Console | SvelteKit |
| SDK | TypeScript (@tars/memory) |
| Engine | Rust (tars-core) → WASM (@tars/wasm) |
| Storage | IndexedDB |
No backend in v1. Memories never leave the browser.
tars/
├── apps/web # developer console
├── crates/tars-core # Rust memory engine
├── packages/tars-wasm # wasm-bindgen bindings
└── packages/tars-memory# public TypeScript SDK
- Node 20+
- pnpm 9+
- Rust stable +
wasm32-unknown-unknown wasm-pack
# PATH must prefer rustup's toolchain for wasm builds
export PATH="$HOME/.cargo/bin:/opt/homebrew/opt/rustup/bin:$PATH"
rustup target add wasm32-unknown-unknown
cargo install wasm-packpnpm install
pnpm build:wasm
pnpm --filter @tars/memory build
pnpm devOpen http://localhost:5173.
| Command | What |
|---|---|
pnpm dev |
SvelteKit console |
pnpm build:wasm |
Build Rust → WASM package |
pnpm test:rust |
cargo test |
pnpm --filter @tars/memory test |
SDK unit tests |
- Phase 0 — Foundation Rust ↔ WASM ↔ SvelteKit
- Phase 1 — Memory CRUD, IndexedDB, import/export, types, importance
- Phase 2 — Search inverted index, BM25, stemming, synonyms, benchmarks UI
- Phase 3 — Intelligence dedup-on-write, consolidate, decay, richer context
- Phase 4 — Semantic built-in embeddings, vector index, hybrid search, pluggable embedder
- Phase 5 — SDK polish docs, recipes, publish
@tars/memory
- Query path: tokenize → stem → synonym expand → inverted-index candidates → BM25 → importance × recency
- Built-in synonym groups cover common AI/dev concepts plus pets/animals (
animal↔dog) - Full semantic similarity is still Phase 4
const tars = await Tars.create({ namespace?: string });
await tars.remember({ content, type?, importance?, metadata?, persistent? });
await tars.recall(query, limit?);
await tars.search({ query, limit? });
await tars.context({ query, maxTokens? });
await tars.get(id);
await tars.update(id, patch);
await tars.delete(id);
await tars.list();
await tars.stats();
await tars.export();
await tars.import(jsonOrBundle);
await tars.clear();Your memories stay on this device. The demo works without an account.
MIT