Local-first · Multi-agent · SQLite

Untangle your
agent history

Coding agents already write everything to disk. Spaghetti indexes ~/.claude and ~/.codex into one local SQLite workspace — searchable conversations, browsable artifacts, and an SDK you can build on.

MIT License Node ≥ 18 v0.5.17 Claude · Codex
~120ms
Warm start, unchanged files
Faster cold start with Rust
FTS5
Full-text search, always on
Local
No cloud. Your machine only.
Why Spaghetti

Your agent history, finally usable

Not another chat archive. A structured multi-agent index of what coding agents leave on disk — built for search, inspection, and tooling.

Search that scales

Content-synced FTS5 over every message. Query across projects, agents, and years of work — hundreds of thousands of rows stay responsive.

Multi-agent by design

Claude Code and OpenAI Codex side by side in one index. Agent tabs in the TUI, an Agent column in lists, and source-scoped session reads so slugs never collide.

Local-first by design

SQLite under ~/.spaghetti. No accounts, no cloud sync, no phone-home. Your history never leaves the machine.

Native Rust ingest

Claude bulk path is a napi-rs addon with rayon parallelism. Pure TypeScript for Codex and as automatic fallback — zero configuration.

SDK + React exports

The same pipeline powers the CLI. Scripts, Electron apps, and React UIs share @vibecook/spaghetti-sdk.

Three ingest planes

Static disk index, live filesystem deltas, and runtime hooks/channels — keep history warm while agents write without polluting the durable store.

Architecture

One pipeline. Multiple agents. One index.

Stream from disk, write once to SQLite, resume with fingerprints. Claude Code and Codex share a single source_id-tagged store — no per-agent databases.

SOURCE INGEST INDEX CONSUMERS AgentSources multi-agent roots ~/.claude ~/.codex sessions · rollouts subagents · tools todos · plans memory · history source_id column ENGINE · RS Native Rust napi-rs · rayon · rusqlite Default · ~2× cold start ENGINE · TS TypeScript workers · streaming · FTS Ground truth · fallback SQLITE Local Index ~/.spaghetti/cache/ source_id · FTS5 one index · schema v7 CLI · TUI spag · Ink SDK API createSpaghettiService React · Live /react · api.live fingerprints · byte-offset resume · warm start ~120ms
Rust ingest (default)
TypeScript ingest (parity + fallback)
Shared SQLite schema + FTS5
Optional live updates
01

Discover

Per-source adapters walk ~/.claude and ~/.codex; each owns classify + extract.

02

Stream parse

Buffered JSONL reads — Claude sessions and Codex rollouts never need to fit in RAM.

03

Single-write

One SQLite connection, rows stamped with source_id, FTS rebuilt at finalize.

04

Fingerprint

Store path, mtime, size, and byte offset for incremental warm starts per source.

05

Query

Source-scoped lists, FTS5 search, and token totals (official or estimated) across agents.

Three planes

History, deltas, and live agent state

Planes 1–2 share the durable index. Plane 3 is a separate event stream — runtime events never write SQLite.

1

Static disk

Cold/warm full parse of agent homes into SQLite + FTS5. Schema v7 with composite project keys (source_id, slug).

2

Live disk Δ

Opt-in watchers for Claude and Codex files. Typed Change events after commit — { live: true }api.live.

3

Runtime

Hooks and channel sessions via plugins. Read-only relative to the index; if it matters historically, the agent wrote a file first.

Dual engines

Speed by default. Correctness always.

Rust and TypeScript write the same schema. A fixture-based ingest-diff harness keeps them honest in CI.

◈ engine: 'ts'

TypeScript

Full streaming pipeline with worker threads. Ground truth for Claude, exclusive path for Codex today, automatic fallback when native is unavailable.

  • Claude config, analytics, plugins · full Codex reader
  • Codex token_count + tiktoken estimate fallback
  • Worker pool with sequential fallback
  • Pin with SPAG_ENGINE=ts
Engine resolution: per-service engine option → SPAG_ENGINE env → legacy SPAG_NATIVE_INGEST~/.spaghetti/config.json → default rs. Each engine uses its own DB file so switching never forces a re-ingest.
Coverage

What Spaghetti indexes

From session transcripts to orchestration workflows — structured tables, not opaque blobs.

Both agents

Projects & sessions

source_id, composite project PK, branches, token totals (official or ~ estimated)

Both agents

Messages

Full JSONL / rollouts with FTS text; Claude usage columns · Codex token_count

Claude

Subagents

Transcripts, agent types, nested workflow agents

Claude

Workflows

Agent-orchestration runs with nested subagent graphs

Claude

Todos & plans

Session todos, plan markdown, task metadata

Claude

Memory & tools

MEMORY.md, persisted tool results, file history

Codex

Rollouts & tokens

sessions/**/rollout-*.jsonl, token_count events, tiktoken estimate

TS only

Config · plugins · analytics

Claude settings, marketplaces, telemetry, session-env

CLI & TUI

Terminal-native from day one

Full-screen Ink TUI with bare spag, or one-shot commands when you just need a fast answer. Same index either way.

spag Interactive TUI
spag projects List indexed projects
spag sessions . Sessions for the current repo
spag messages . latest Latest session transcript
spag search "…" Full-text search
spag doctor Health-check paths & plugins

Full command reference →

SDK

Build on the same index

One factory. One API. Scripts, dashboards, and Electron apps all read the SQLite index the CLI builds. React components live under @vibecook/spaghetti-sdk/react.

API reference →
example.ts
import {
  createSpaghettiService,
  createCodexSource,
} from '@vibecook/spaghetti-sdk';

const api = createSpaghettiService({
  additionalSources: [createCodexSource()],
  live: true,
});
await api.initialize();

const sources = api.getSourceIds(); // ['claude-code','codex']
const projects = api.getProjectList();
const sessions = api.getSessionList(
  projects[0].slug,
  { sourceId: projects[0].sourceId },
);

await api.dispose();
Get started

Install in one line

Ship the CLI for daily use, or embed the SDK in any Node project.

shell
npm install -g @vibecook/spaghetti
spag