Agent skill

AI Persistence

by TanStack in TanStack/ai

Durability and state persistence for TanStack AI chats with @tanstack/ai-persistence.

MITAuto-check passedAgent Workflows

Install AI Persistence

skills CLI
$ npx skills add TanStack/ai --skill ai-persistence -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install TanStack/ai ai-persistence --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/TanStack/ai.git skills-src && mkdir -p .claude/skills && cp -r skills-src/packages/ai-persistence/skills/ai-persistence .claude/skills/ai-persistence && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
ai-persistence
GitHub stars
3.2k
Token cost
~3.3k tokens
SKILL.md length
1,096 words
Files
1
Skills in repo
24
Repo updated
First seen
Licence
MIT

At a glance

Durability and state persistence for TanStack AI chats with @tanstack/ai-persistence.

  • Works in 4 steps: Client: persistence: true —… → Server: withPersistence(backend) —… → Route: delivery durability if mid-stream… → …
  • Conversations must survive reloads
  • SKILL.md covers Persistence is a contract, not…, Sub-skills, State persistence has two halves and Identity: threadId and Scope, plus 5 more sections
  • Instructions only: no scripts, shell commands, URLs or credentials in SKILL.md

What it does

AI Persistence is an agent skill from TanStack/ai. Durability and state persistence for TanStack AI chats with @tanstack/ai-persistence. Routes to server chat persistence (withPersistence), client persistence (localStorage/IndexedDB), the store contracts, and adapter recipes. Distinguishes delivery durability (resumable streams) from conversation state. Use when conversations must survive reloads, multi-device, approvals, or server restarts — NOT for stream reconnect alone.

Its SKILL.md is about 3.3k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.

It sits in Agent Workflows, covering Agent memory. It works with TanStack. The repository describes itself as: 🤖 Type-safe, provider-agnostic TypeScript AI SDK for streaming chat, tool calling, agents, and multimodal apps across OpenAI, Anthropic, Gemini, React, Vue, Svelte, and Solid. The licence is MIT.

When your agent uses it

  • Conversations must survive reloads
  • Server restarts — NOT for stream reconnect alone

Example prompts

  • “/ai-persistence”

Workflow steps

4 steps, taken from the first numbered list in SKILL.md.

  1. Client: persistence: true — server-authoritative, no client cache.
  2. Server: withPersistence(backend) — messages + runs + interrupts.
  3. Route: delivery durability if mid-stream reconnect matters.
  4. Optional: withLocks(distributedLockStore) from @tanstack/ai/locks when other middleware needs multi-instance coordination (not part of the…

What it can do on your machine

Read from SKILL.md and the folder at commit 5a41239. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    No scripts in the folder and no shell commands in SKILL.md (its code samples are typescript).

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

AI Persistence loads about 3.3k tokens when it runs. Until then it costs about 111 tokens; SKILL.md has 1,096 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~111
When it runs · the whole SKILL.md, loaded when a task matches
~3.3k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from TanStack/ai at commit 5a41239, republished under its MIT licence (© TanStack). 1,096 words, ~3,250 tokens.

Download SKILL.mdSave it as .claude/skills/ai-persistence/SKILL.md (or your agent's skills folder).
name
ai-persistence
description
Durability and state persistence for TanStack AI chats with @tanstack/ai-persistence. Routes to server chat persistence (withPersistence), client persistence (localStorage/IndexedDB), the store contracts, and adapter recipes. Distinguishes delivery durability (resumable streams) from conversation state. Use when conversations must survive reloads, multi-device, approvals, or server restarts — NOT for stream reconnect alone.
type
core
library
tanstack-ai
library_version
0.0.0
sources
TanStack/ai:docs/persistence/overview.md, TanStack/ai:docs/persistence/chat-persistence.md, TanStack/ai:docs/persistence/client-persistence.md…

TanStack AI Persistence

Builds on the ai-core skill in @tanstack/ai, and usually ai-core/chat-experience.

TanStack AI splits delivery durability from state persistence. They share no code and solve different problems.

LayerAnswersPackage / API
Delivery durabilityReconnect to a stream still runningmemoryStream / @tanstack/ai-durable-stream on the response; see resumable streams docs
State persistenceWhat is the conversation, later?Client persistence on useChat + server withPersistence from @tanstack/ai-persistence

A replayable stream is not a saved conversation. A saved conversation is not a live stream. Production apps often use both.

Persistence is a contract, not a database

@tanstack/ai-persistence ships the store interfaces, the middleware that drives them, an in-memory reference backend, and a conformance testkit. It does not ship a backend for your database, and you do not need one: implement the stores against whatever you already run — Postgres, SQLite, D1, Mongo — and hand the result to withPersistence. The core never inspects your tables.

Ships in the packageWhat it is
MessageStore / RunStore / InterruptStore / MetadataStoreThe four chat state contracts
GenerationRunStore / ArtifactStore / BlobStoreThe generation contracts (job lifecycle + bytes)
withPersistence / withGenerationPersistenceChat + generation middleware
memoryPersistence()In-process reference backend, all seven stores (dev, tests)
reconstructChat / reconstructGenerationServer hydrate route helpers (chat / generation)
retrieveArtifact / retrieveBlob / resolveArtifactBlobKeyServe persisted generation-media bytes back
LockStore / withLocks / InMemoryLockStore (from @tanstack/ai/locks)Coordination, not this package — see ai-core/locks
@tanstack/ai-persistence/testkitrunPersistenceConformance gate (chat state stores)

Chat vs generation stores. Chat persistence keys on threadId and uses messages + optional runs / interrupts / metadata. Generation persistence keys on its own runId and uses generationRuns (required by withGenerationPersistence) plus an optional artifacts + blobs pair — provide both or neither — to store the generated media bytes at blob key artifacts/<runId>/<artifactId>. A generation run's identity is its own runId, but threadId is required on the record: it is the stable slot successive runs fill, and findLatestForThread — the only query that hydrates a run — keys on it. To build the R2/D1-backed byte stores for a Worker, see ai-persistence/build-cloudflare-artifact-store.

Where bytes land. Default blob key is artifacts/<runId>/<artifactId>. Pass storageKey to withGenerationPersistence for your own folder structure — it receives { artifactId, runId, threadId, role, activity, path, mimeType, name } and returns the key. Server-side only (a browser-supplied key is path traversal + cross-tenant writes). The resolved key is recorded on ArtifactRecord.blobKey because it is no longer derivable; read through resolveArtifactBlobKey(record), never by recomputing. Records predating blobKey fall back to the default convention — which is why that convention can never be changed retroactively. A non-unique key overwrites, so include artifactId unless that is intended.

Byte storage stores generated output, not prompt URLs. Provider result URLs expire, so they are downloaded and kept. Prompt media sent as base64 (source: { type: 'data' }) is stored too. Prompt media sent as a URL is NOT fetched — that URL is caller-supplied, so downloading it server-side is an SSRF vector, and the bytes are redundant. Apps that genuinely need a durable copy opt in with allowInputUrl, a predicate so the check can't be skipped: allowInputUrl: ({ url }) => url.hostname.endsWith('.cdn.example.com'). Never suggest () => true. All artifact fetches are http/https-only, timed out (artifactFetchTimeoutMs) and size-capped (maxArtifactBytes); input fetches also block loopback/private/link-local hosts and refuse redirects. artifactFetch injects the fetch, for routing through an egress-restricted proxy.

Two related route-level rules: a GET that serves artifact bytes by id MUST authorize the caller against ArtifactRecord.threadId before serving (404, not 403, so valid ids aren't confirmed), and reconstructGeneration MUST be given authorize on any multi-user route. Both take ids straight from the caller.

Portable sandbox snapshots use the same messages, artifacts, and blobs stores. Their artifact reader checks the checkpoint thread, but it does not authenticate a caller. Authorize the thread before any route reads a snapshot artifact. The snapshot checkpoint store also needs atomic append and fork operations. A SQLite adapter must write a checkpoint, its head, and blob reference counts in one transaction.

Show full SKILL.md (472 more words)Show less

Sub-skills

Need to...Read
Wire server-side chat history, runs, interruptsai-persistence/server/SKILL.md
Survive reloads in the browserai-core/client-persistence/SKILL.md in @tanstack/ai
Implement the store interfaces for your DBai-persistence/stores/SKILL.md
Multi-instance locks (separate from state)ai-core/locks/SKILL.md in @tanstack/ai

Adding persistence to an app? Pick the recipe that matches what it already runs — each one writes a single chat-persistence.ts against the app's existing database client and schema:

The app runs...Read
Drizzle ORM (SQLite / Postgres / MySQL)ai-persistence/build-drizzle-adapter/SKILL.md
Prismaai-persistence/build-prisma-adapter/SKILL.md
Cloudflare Workers + D1 (± Durable Object locks)ai-persistence/build-cloudflare-adapter/SKILL.md
Cloudflare Workers + R2/D1 for generated media bytesai-persistence/build-cloudflare-artifact-store/SKILL.md
Anything else — raw pg, Kysely, SQLite, Mongoai-persistence/build-custom-adapter/SKILL.md

State persistence has two halves

HalfStoresSurvivesTypical use
Clienttranscript ± resume pointer in browser storagereload / tab close (per browser)SPA restore, offline-first
Servermessages, runs, interrupts, metadata in your DBrestart + multi-deviceauthoritative history, durable approvals

They are independent. Use either alone or both.

Identity: threadId and Scope

Server stores key on threadId (same as chat({ threadId }) / ChatMiddlewareContext.threadId / Scope.threadId from @tanstack/ai).

  • Store methods take bare threadId strings for adapter simplicity.
  • Multi-user isolation is your job: derive userId / tenantId from session server-side; authorize before load/save / reconstructChat.
  • Never treat a client-supplied thread id alone as ownership — ids are guessable.

Authoritative-history contract

When both halves run, ownership per turn is decided by request messages:

Client sendsMeaningOn finish
Non-empty messagesFull transcript (source of truth)Server overwrites stored thread
Empty messagesContinue from server copyServer loads stored thread

Never post a delta as messages — that wipes history down to the delta.

Client-authoritative: always send full transcript; browser is truth, server mirrors.
Server-authoritative: send empty messages (or hydrate via server load); server is truth, multi-device works.

  1. Client: persistence: true — server-authoritative, no client cache.
  2. Server: withPersistence(backend) — messages + runs + interrupts.
  3. Route: delivery durability if mid-stream reconnect matters.
  4. Optional: withLocks(distributedLockStore) from @tanstack/ai/locks when other middleware needs multi-instance coordination (not part of the state bag).

Minimal end-to-end sketch

Server

ts
import {
  chat,
  chatParamsFromRequest,
  toServerSentEventsResponse,
} from '@tanstack/ai'
import { openaiText } from '@tanstack/ai-openai'
import { withPersistence } from '@tanstack/ai-persistence'
// Your adapter — see ai-persistence/stores.
import { persistence } from './persistence'

export async function POST(request: Request) {
  const params = await chatParamsFromRequest(request)
  const stream = chat({
    adapter: openaiText('gpt-5.5'),
    messages: params.messages,
    threadId: params.threadId,
    runId: params.runId,
    ...(params.resume ? { resume: params.resume } : {}),
    middleware: [withPersistence(persistence)],
  })
  return toServerSentEventsResponse(stream)
}

Client (server-authoritative)

tsx
import { useChat, fetchServerSentEvents } from '@tanstack/ai-react'

function Chat({ threadId }: { threadId: string }) {
  const { messages, sendMessage } = useChat({
    threadId,
    connection: fetchServerSentEvents('/api/chat'),
    persistence: true,
  })
  // ...
}

With persistence: true, the client caches nothing and hydrates the transcript from the server on mount (thread id is the key). Pair with a server load path such as reconstructChat for the GET.

Critical rules

  1. Not Vercel AI SDK. Persistence is @tanstack/ai-persistence + middleware, not Vercel useChat storage hacks.
  2. saveThread is full overwrite, never append.
  3. createOrResume is insert-if-absent for the same runId.
  4. Interrupt create is insert-if-absent — never clobber resolved → pending.
  5. Locks ≠ state. Import withLocks from @tanstack/ai/locks. Sandbox resume is a sandbox-package concern — not a stores key. stores accepts only messages, runs, interrupts, metadata.
  6. You own the schema. No package invents migrations for you.
  7. Run the conformance testkit against any adapter you write.
  8. Authorize thread access at the route boundary.

Cross-references

  • ai-core/chat-experience (@tanstack/ai) — useChat, SSE, client persistence option overview
  • ai-core/middleware (@tanstack/ai) — middleware hooks; withPersistence is a ChatMiddleware
  • Resumable streams docs — delivery durability only

© TanStack, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in packages/ai-persistence/skills/ai-persistence of TanStack/ai.

Open the folder on GitHubat commit 5a41239

Compare with similar skills

AI Persistence next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

AI Persistence compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
AI Persistence this skillTanStack/ai3.2k—~3.3kAutomated safety check: PassMIT
Project Timeline Reportthedotmack/claude-mem97k1 repos~3.1kAutomated safety check: PassApache-2.0
Neat-Freak Knowledge CloseoutKKKKhazix/khazix-skills21k—~1.9kAutomated safety check: PassMIT
Beads Task Memorygastownhall/beads28k—~1.2kAutomated safety check: PassMIT
MemPalace Memory SearchMemPalace/mempalace59k—~1.4kAutomated safety check: PassMIT
Reflect on Session Learningscursor/plugins10k5 repos~1.2kAutomated safety check: PassNone

Similar skills

  • Project Timeline Report

    thedotmack/claude-mem

    Writes a narrative Journey Into report on a project's whole development history, built from the timeline that claude-mem has recorded.

    97k GitHub starsUsed in 1 repo~3.1k tokens
    Agent WorkflowsAuto-check passed
  • Neat-Freak Knowledge Closeout

    KKKKhazix/khazix-skills

    Brings project docs, agent rule files, authorized memory and leftover workspace files back in line with what the code and runtime actually do at the end of a work session.

    21k GitHub stars~1.9k tokensUpdated 6 days ago
    Agent WorkflowsAuto-check passed
  • Beads Task Memory

    gastownhall/beads

    Tracks multi-session work with dependencies in the bd issue tracker so the agent can find ready tasks and recover its context after conversation compaction.

    28k GitHub stars~1.2k tokensUpdated today
    Agent WorkflowsAuto-check passed
  • MemPalace Memory Search

    MemPalace/mempalace

    Mines project files and conversation exports into a local, searchable memory palace and recalls past work by semantic search through the mempalace CLI.

    59k GitHub stars~1.4k tokensUpdated today
    Agent WorkflowsAuto-check passed
  • Official

    Starts three parallel reviewer subagents over the current conversation transcript, then turns their findings into concrete edits to existing skills.

    10k GitHub starsUsed in 5 repos~1.2k tokens
    Agent WorkflowsAuto-check passed
  • Compound Learning Writer

    EveryInc/compound-engineering-plugin

    Records one solved and verified problem as a durable learning in the repository, but only when the reasoning is not already clear from the final code, tests or docs.

    25k GitHub stars~2k tokensUpdated today
    Agent WorkflowsAuto-check passed

More from TanStack/ai

All 24 skills in this repo
  • I Have Adhd

    TanStack/ai

    A skill your agent uses when the user invokes /i-have-adhd, says they have ADHD, or asks for ADHD-friendly output.

    3.2k GitHub starsUsed in 5 repos~1.8k tokens
    Auto-check passed
  • PR Sweep

    TanStack/ai

    Sweep open (or listed) PRs with up to 100 parallel agents: security-scan outside contributors, rebase onto main when behind (push --force-with-lease), approve pending first-time-contributor CI when…

    3.2k GitHub stars~4.6k tokensUpdated today
    Auto-check passed
  • A skill your agent uses when wiring honcho() from @tanstack/ai-memory/honcho — a hosted memory adapter where recall is a dialectic answer over the user's representation (no discrete fragments).

    3.2k GitHub starsUsed in 1 repo~457 tokens
    Auto-check passed
  • A skill your agent uses when wiring inMemory() from @tanstack/ai-memory/in-memory — explains setup, options (embedder, extract, topK/minScore), when to pick it (dev/tests/single-process demos), and…

    3.2k GitHub starsUsed in 1 repo~448 tokens
    Auto-check passed
  • A skill your agent uses when wiring redis() from @tanstack/ai-memory/redis in production — covers client setup (ioredis or node-redis via fromNodeRedis), the storage model, client-side ranking…

    3.2k GitHub starsUsed in 1 repo~840 tokens
    Auto-check passed
  • A skill your agent uses when adding a public teaching example or a docs tutorial.

    3.2k GitHub stars~1.4k tokensUpdated today
    Auto-check passed

Works with

Categories

Questions about AI Persistence

What does AI Persistence do?

Durability and state persistence for TanStack AI chats with @tanstack/ai-persistence. AI Persistence is an agent skill from TanStack/ai. Durability and state persistence for TanStack AI chats with @tanstack/ai-persistence.

When should I use AI Persistence?

AI Persistence fits situations like: conversations must survive reloads; server restarts — NOT for stream reconnect alone.

How do I install AI Persistence in Claude Code?

Run `npx skills add TanStack/ai --skill ai-persistence -a claude-code`. Or copy the skill folder (packages/ai-persistence/skills/ai-persistence in TanStack/ai) into .claude/skills/ai-persistence in your project. Claude Code loads it when a task matches its description.

How do I install AI Persistence in Codex?

Run `npx skills add TanStack/ai --skill ai-persistence -a codex`. Or copy the skill folder (packages/ai-persistence/skills/ai-persistence in TanStack/ai) into .agents/skills/ai-persistence in your project. Codex loads it when a task matches its description.

Can I use AI Persistence in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add TanStack/ai --skill ai-persistence -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/ai-persistence, .gemini/skills/ai-persistence, .github/skills/ai-persistence and .opencode/skills/ai-persistence in your project.

What does AI Persistence need to run?

SKILL.md names no scripts, command-line tools or credentials: AI Persistence is instructions for the agent only.

Does AI Persistence access the network?

SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.

Is AI Persistence safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does AI Persistence use?

AI Persistence is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does AI Persistence use?

About 3.3k tokens (SKILL.md is roughly 13k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to AI Persistence?

Skills that share tags, products or a category with AI Persistence: Project Timeline Report (thedotmack/claude-mem, 97k stars), Neat-Freak Knowledge Closeout (KKKKhazix/khazix-skills, 21k stars), Beads Task Memory (gastownhall/beads, 28k stars) and MemPalace Memory Search (MemPalace/mempalace, 59k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains AI Persistence?

TanStack (a GitHub organization) maintains it in TanStack/ai, which has 3,169 GitHub stars. The repository holds 24 skills in this directory. The repository was last updated on October 7, 2026.

Source: TanStack/ai on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.