Files
obelisk/README.md
T
tommy0103andClaude Opus 4.8 410b0a8df3 docs(readme): rewrite for dual-surface product (skill + app) and workspace structure
Rewrite README to reflect the current state of the project:
- Describe both surfaces: skill (agent-first retrieval) and app (human browser).
- Add Codex support section (unified schema, source tagging, child-thread mapping).
- Update Structure tree to match the packages/core workspace layout with all
  TypeScript modules (providers, persist, tx, write-coordinator, writer-lease).
- Document generated build outputs (packages/core/dist, dist/obelisk-skill).
- License badge corrected to AGPL-3.0 (skill artifact is MIT; source is AGPL).
- Skill invocation examples updated to /obelisk-skill.
- Add recap flow documentation.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-12 00:59:33 +08:00

207 lines
9.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<div align="center">
<picture>
<source media="(prefers-color-scheme: dark)" srcset=".github/assets/obelisk-wordmark-d.svg">
<img src=".github/assets/obelisk-wordmark-l2.svg" alt="Obelisk" width="540">
</picture>
[![stars](https://img.shields.io/github/stars/tommy0103/obelisk?style=flat-square)](https://github.com/tommy0103/obelisk/stargazers)
[![version](https://img.shields.io/github/v/tag/tommy0103/obelisk?label=version&style=flat-square)](https://github.com/tommy0103/obelisk/releases)
[![license](https://img.shields.io/badge/license-AGPL--3.0-blue.svg?style=flat-square)](LICENSE)
Every past Claude Code and Codex session -- queryable by your agent, browsable by you.
</div>
<br />
## 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
<div align="center">
<img src=".github/assets/demo.png" alt="Obelisk App" width="720">
</div>
You can use obelisk like:
```
/obelisk-skill 上次 auth bug 最后到底改了哪些文件,为什么这么改
/obelisk-skill 这个文件最近在哪些 sessions 里被反复修改
/obelisk-skill 找出最近失败的 tool calls,它们分别发生在哪些任务里
/obelisk-skill 那个 review workflow 的 subagents 各自结论是什么
/obelisk-skill recap this week
```
### Install
```bash
npx skills add tommy0103/obelisk-skill
```
Or manually: copy `obelisk-skill/` into your project's `.claude/skills/`
Then in any Claude Code session:
```
/obelisk-skill <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.
<div align="center">
<img src=".github/assets/app-screenshot.png" alt="Obelisk App" width="720">
</div>
- **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](https://github.com/tommy0103/obelisk/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.
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