Obelisk

stars version license

Every past Claude Code and Codex session -- queryable by your agent, browsable by you.


Two sides of the same index

Obelisk has two sides that share one SQLite index:

Skill side — an agent skill that lets coding agents search and query their own session history. The agent writes JS queries, runs them locally, answers in plain language.

App side — an Electron desktop app for humans to browse sessions, manage memories, view usage stats, and see weekly recap cards.

Both read from the same ~/.obelisk/obelisk.sqlite database. The indexer reads Claude Code transcripts from ~/.claude/projects and Codex transcripts from ~/.codex/sessions.

Codex support

Obelisk indexes Claude Code and Codex into the same SQLite schema instead of keeping separate databases. Rows carry a source value (claude or codex), and Codex IDs are prefixed with codex: so they cannot collide with Claude session IDs.

Codex root threads become normal Obelisk sessions. Codex child threads are attached through the same subagents table when parent-thread metadata is available. Codex does not emit Claude-style workflow metadata, so workflow tables may be empty for Codex-only history.

For live app refresh, Obelisk watches ~/.claude/projects and ~/.codex/sessions. It does not watch the whole ~/.codex root. Codex's session_index.jsonl is used as lightweight title/update metadata during indexing, not as the message transcript source.

Skill: agent-first retrieval

Obelisk App

You can use obelisk like:

/obelisk 上次 auth bug 最后到底改了哪些文件,为什么这么改
/obelisk 这个文件最近在哪些 sessions 里被反复修改
/obelisk 找出最近失败的 tool calls,它们分别发生在哪些任务里
/obelisk 那个 review workflow 的 subagents 各自结论是什么
/obelisk recap this week

Install

npx skills add tommy0103/obelisk-skill

Or manually: copy obelisk-skill/ into your project's .claude/skills/

Then in any Claude Code session:

/obelisk <your question>

First run builds the index (~5 seconds for 100 sessions). After that it rebuilds incrementally.

How it works

You ask a question
  ↓
Agent writes a JS query against the SQLite index
  ↓
Runs it via node $SKILL_DIR/scripts/runtime.js --query <script>
  ↓
Reads the JSON result, answers in natural language

Core API: search(), context(), sql(), plus structured helpers (sessions, memories, summaries, workflows, failures, fileHistory, etc).

Memory layer

When a retrieval produces a conclusion worth keeping, the agent proposes a markdown memory file. After user approval, it registers the file with runtime.js --attune <script>. Memories are recalled via memories() in future sessions — a synthesis cache, not a replacement for raw evidence.

App: A surface for human

A companion desktop app for browsing what the skill indexes.

Obelisk App
  • Sessions — browse all sessions with search, project filtering, readable tool calls (diffs, terminal output, file viewers)
  • Memory — list and detail views for registered memory files
  • Activity — GitHub-style heatmap, weekly/cumulative token charts
  • Recap — shareable weekly/monthly recap cards with archetype theming
  • Settings — data source configuration, auto-refresh, rebuild index

macOS only. Download from Releases.

What gets indexed

Layer Source What's captured
Sessions Claude <project>/<sessionId>.jsonl; Codex sessions/YYYY/MM/DD/*.jsonl Title, project, timestamps, git branch, source
Messages user + assistant turns Full text, model, token usage, parent chain
Tool calls every tool invocation Tool name, input, file paths
Subagents Claude subagents/agent-<id>.jsonl; Codex child threads Agent type, description, full conversation
Workflows Claude workflows/wf_<runId>.json Script, result, agent count
Workflow agents Claude subagents/workflows/wf_<runId>/ Per-agent transcripts
Memories registered markdown files Conclusions linked to source sessions

Full-text search via FTS5 covers all layers.

Structure

packages/core/                # @obelisk/core npm workspace (TypeScript + ESM)
├── src/
│   ├── providers/
│   │   ├── types.ts          # Provider + IndexRecord contract
│   │   ├── claude.ts         # Claude Code adapter (line-incremental)
│   │   └── codex.ts          # Codex adapter (full-reparse)
│   ├── persist.ts            # Binding-agnostic record writer (upsert/merge)
│   ├── tx.ts                 # Write transaction + connection config
│   ├── write-coordinator.ts  # Bounded retry policy
│   ├── writer-lease.ts       # Cross-process single-writer lease (SQLite lock DB)
│   ├── core.ts               # buildIndex / searchText / executeQuery / executeAttune
│   ├── indexer.ts            # Skill orchestration (discover → persist → finalize)
│   ├── parsing.ts            # Pure helpers (node:sqlite-free, app-consumable)
│   ├── db.ts                 # node:sqlite lifecycle + migrations
│   ├── query.ts              # Query/attune sandbox API (helpers)
│   ├── runtime.ts            # Thin CLI shell (--build/--search/--query/--attune)
│   └── schema.sql            # SQLite schema (single source of truth)
├── package.json
└── dist/                     # Generated package JS, declarations, and schema

references/                   # Agent-readable docs (progressive disclosure)
├── schema.md
├── api-reference.md
├── query-patterns.md
├── retrieval-semantics.md
├── pitfalls.md
├── recap-patterns.md
├── recap-writing.md
└── recap/                    # Per-card pattern + writing references
    ├── overview.md
    ├── pattern1-cover.md … pattern5-closing.md
    └── writing1-cover.md … writing5-closing.md

app/                          # Electron desktop app (electron-vite + Vue)
├── src/main/                 # TypeScript main process (consumes shared core)
├── src/preload/              # CJS preload (sandbox)
├── src/renderer/             # Vue renderer
└── electron.vite.config.ts

packaging/                    # Skill publish infrastructure
├── skill-package.json
├── skill-README.md
├── skill-LICENSE             # MIT (relicensed for the skill artifact)
└── publish-skill.sh

SKILL.md                      # Skill definition (installed with the artifact)
CONTEXT.md                    # Project glossary
docs/adr/                     # Architecture decision records (00010006)

The optional /obelisk recap flow is loaded only for explicit /obelisk recap intent. It starts at references/recap/overview.md and proceeds card-by-card:

  • references/recap/pattern1-cover.md + references/recap/writing1-cover.md
  • references/recap/pattern2-thinking.md + references/recap/writing2-thinking.md
  • references/recap/pattern3-vibe.md + references/recap/writing3-vibe.md
  • references/recap/pattern4-workflow.md + references/recap/writing4-workflow.md
  • references/recap/pattern5-closing.md + references/recap/writing5-closing.md

Generated build outputs

  • packages/core/dist/ is produced by npm run build:core. It is the compiled @obelisk/core package: JavaScript, type declarations, and schema.sql.
  • dist/obelisk-skill/ is produced by npm run build:skill. It is the install-ready skill artifact: readable plain JavaScript under scripts/, SKILL.md, references, and the skill package metadata.
  • Skill publishing stages that artifact at skills/obelisk/ in the obelisk-skill repository; only README.md and LICENSE remain at the repository root for npx skills discovery.

Both directories are generated and should not be edited by hand. The Electron app imports packages/core/src/ directly so electron-vite can bundle Core.

Implementation Notes

The index rebuilds incrementally — only new or modified JSONL files are re-parsed. When the optional app is running, it is the active indexer: it watches Claude project files and builds in a worker thread. A fresh __app_heartbeat__ alone means the daemon owns writes, so the skill remains read-only; a separate SQLite writer lease prevents cross-process writes from overlapping. The __app_last_successful_build__ marker records index freshness, not ownership.

Zero npm dependencies. Uses Node 22's built-in node:sqlite with FTS5. The entire runtime is ~400 lines.

20K lines of scattered JSONL → something the agent can search() and sql() against in milliseconds.


License

AGPL-3.0 @tommy0103

S
Description
Fork of tommy0103/obelisk (AGPL-3.0): agent memory/search layer. Includes local fix so recent() accepts options objects.
Readme AGPL-3.0
8.4 MiB
Languages
JavaScript 51.3%
TypeScript 23%
Vue 15.4%
CSS 5.7%
HTML 4.4%
Other 0.2%