MCP Server Builder
shareAI-lab/learn-claude-code
Walks through building MCP servers in Python or TypeScript that expose tools, resources and prompts to Claude, with templates, registration and testing.
Search and query past Claude Code, Codex, Kimi Code, Kiro, and Pi session history.
$ npx skills add tommy0103/obelisk --skill obelisk -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install tommy0103/obelisk obelisk --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/tommy0103/obelisk.git skills-src && mkdir -p .claude/skills && cp -r skills-src/packages/dsh-plugin/skill .claude/skills/obelisk && rm -rf skills-srcUse ~/.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/
Install the "obelisk" agent skill from https://github.com/tommy0103/obelisk/tree/main/packages/dsh-plugin/skill into .claude/skills/obelisk/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "obelisk", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/tommy0103/obelisk/tree/main/packages/dsh-plugin/skillType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add tommy0103/obelisk --skill obelisk -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install tommy0103/obelisk obelisk --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/tommy0103/obelisk.git skills-src && mkdir -p .agents/skills && cp -r skills-src/packages/dsh-plugin/skill .agents/skills/obelisk && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "obelisk" agent skill from https://github.com/tommy0103/obelisk/tree/main/packages/dsh-plugin/skill into .agents/skills/obelisk/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "obelisk", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add tommy0103/obelisk --skill obelisk -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install tommy0103/obelisk obelisk --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/tommy0103/obelisk.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/packages/dsh-plugin/skill .cursor/skills/obelisk && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "obelisk" agent skill from https://github.com/tommy0103/obelisk/tree/main/packages/dsh-plugin/skill into .cursor/skills/obelisk/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "obelisk", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/tommy0103/obelisk.git --path packages/dsh-plugin/skill--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add tommy0103/obelisk --skill obelisk -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install tommy0103/obelisk obelisk --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/tommy0103/obelisk.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/packages/dsh-plugin/skill .gemini/skills/obelisk && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "obelisk" agent skill from https://github.com/tommy0103/obelisk/tree/main/packages/dsh-plugin/skill into .gemini/skills/obelisk/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "obelisk", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install tommy0103/obelisk obeliskInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add tommy0103/obelisk --skill obelisk -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/tommy0103/obelisk.git skills-src && mkdir -p .github/skills && cp -r skills-src/packages/dsh-plugin/skill .github/skills/obelisk && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "obelisk" agent skill from https://github.com/tommy0103/obelisk/tree/main/packages/dsh-plugin/skill into .github/skills/obelisk/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "obelisk", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add tommy0103/obelisk --skill obelisk -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install tommy0103/obelisk obelisk --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/tommy0103/obelisk.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/packages/dsh-plugin/skill .opencode/skills/obelisk && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "obelisk" agent skill from https://github.com/tommy0103/obelisk/tree/main/packages/dsh-plugin/skill into .opencode/skills/obelisk/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "obelisk", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
obeliskSearch and query past Claude Code, Codex, Kimi Code, Kiro, and Pi session history.
Obelisk is an agent skill from tommy0103/obelisk. Search and query past Claude Code, Codex, Kimi Code, Kiro, and Pi session history. Reactive: when the user asks "how did I fix X", "what did we do last time", "find the session where", "上次怎么修的", "之前的session", "历史记录". Proactive: when the user references past work you lack context for, when you're about to modify a file with complex edit history, when the user says "继续之前的" or "continue where we left off", or when understanding prior decisions would improve your current response. Memory: when the user says "记住这个"…
Its SKILL.md is about 6.5k tokens, which your agent loads only when the skill is triggered. The skill folder holds 20 other files, including reference files (for example `references/api-reference.md`, `references/pitfalls.md` and `references/query-patterns.md`).
It sits in Agent Workflows. It works with Kimi and SQLite. The repository describes itself as: Every past session, subagent, and workflow -- queryable by your agent, browsable by you. The licence is AGPL-3.0.
3 steps, taken from the first numbered list in SKILL.md.
Read from SKILL.md and the folder at commit a4b7329. It shows what the files ask for, not the result of running them.
Pre-approves these tools, so the agent can use them without asking each time:
ReadBash(obelisk:*)WriteFrom allowed-tools in the SKILL.md frontmatter.
No scripts in the folder and no shell commands in SKILL.md (its code samples are javascript and bash).
From the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Obelisk loads about 6.5k tokens when it runs, and up to ~28k if it reads all its reference files. Until then it costs about 164 tokens; SKILL.md has 3,137 words of instructions outside code blocks.
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.
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.
The full file from tommy0103/obelisk at commit a4b7329, republished under its AGPL-3.0 licence (© tommy0103). 3,137 words, ~6,488 tokens.
.claude/skills/obelisk/SKILL.md (or your agent's skills folder). This skill also uses 18 other files; get the full folder from GitHub.Search and query local Claude Code, Codex, Kimi Code, Kiro, and Pi session history. Obelisk indexes sessions, messages, tool calls, tool results, summaries, subagents, workflows, workflow agents, parent chains, and raw JSONL lines into SQLite + FTS5.
Obelisk has several transcript sources. Treat all of them as ordinary sessions by
default: Claude rows use source='claude', Codex rows use source='codex',
Kimi Code rows use source='kimi', Kiro rows use source='kiro', and Pi rows use source='pi'. Use source
only when provenance matters or the user asks to scope to one provider.
Provider-specific records are projected into the same canonical tables; some
providers may not emit every kind of subagent or workflow metadata.
Obelisk is a CodeAct memory layer: write a small JS query, run it locally, read the JSON, then answer. Do not turn history into a flat document or browse entire sessions by default.
Treat a successful Obelisk invocation as a precondition for using its results.
Obelisk refreshes ~/.obelisk/obelisk.sqlite before retrieval so the answer
includes the latest sessions and can identify the invoking session. Never
degrade to a stale, read-only index when that refresh cannot write.
In Codex workspace-write or managed sandboxes, ~/.obelisk may be outside the
writable roots. If an Obelisk command fails with SQLITE_READONLY, EACCES,
EPERM, attempt to write a readonly database, or another permission error for
~/.obelisk, rerun the same command with
sandbox_permissions: "require_escalated". On another agent host, use its
equivalent mechanism to grant write access to ~/.obelisk. Do not replace the
failed command with direct SQLite, JSONL, or stale-index reads.
If write access is unavailable or the user denies escalation, stop and report the permission blocker. Retrieval is complete only when the Obelisk command exits successfully and returns its query result.
Fast keyword search (pass a unique nonce so Obelisk can recognize your own session in results):
obelisk --search "keyword" --nonce "$(uuidgen 2>/dev/null || echo "$$.$RANDOM.$RANDOM")"Custom query:
Write a bounded JS query to a unique temp file — the as-typed file path is your invocation nonce:
qdir=$(mktemp -d /tmp/obq.XXXXXX 2>/dev/null || { d="/tmp/obq.$$.$RANDOM"; mkdir "$d"; echo "$d"; })
qfile="$qdir/query.mjs"The .mjs name lives inside the unique directory, so the mktemp
template always ends on the X run (BSD mktemp requires that).
Run:
obelisk --query "$qfile"Parse JSON stdout and answer with concise evidence.
The query file runs inside (async () => { ... })(). Use return to emit JSON.
Query scripts are read-only: remember() and forget() are not available, and
sql() only accepts read-only SELECT/WITH queries.
Obelisk refreshes the index before each query, so your own live session shows
up in results. The invocation nonce (--search --nonce, or the unique
--query file path) lets Obelisk mark it: session projections in search()
hits and sessions() rows carry is_invoking: true, and
overview().current.session_id holds the invoking session id when known. Treat
a session flagged is_invoking as your own current context, NOT as independent
historical evidence. Resolution is newest-wins over recent matches; only a
near-simultaneous same-nonce collision (or no match at all) leaves nothing
marked and current.session_id null — identity is honestly unknown.
When the current context begins with an Obelisk rollover handoff, read that
handoff before searching. Treat its session_id as the default scope for
recovering this task: pass it as sessionId to search() or other helpers.
When you need evidence around the end of the previous context, call
context() with the supplied message_uuid. Expand to global or cross-session
search only when the task actually needs evidence outside that session.
Start with helpers, not raw SQL. For the first Obelisk query in a task, normally
call overview({ limit: 6 }) unless the user already gave an exact
session_id, message uuid, or absolute file path.
For semantic or synthesis tasks, combine orientation, memory recall, and raw session evidence before deciding whether a detail pass is needed:
const map = overview({ limit: 6 });
const project = map.current.project?.project;
const topic = 'English topic terms translated from the user request';
return {
orientation: map.current_project,
prior_memories: memories({ project, query: topic, limit: 5 }),
session_evidence: search(topic.replace(/[-_]/g, ' '), { project, limit: 8 }),
};Use sql() only as an escalation path for exact joins, aggregations, or schema
questions that helpers cannot express cleanly. Do not use raw SQL as a generic
fallback for broad retrieval.
Obelisk supports a small intent prefix layer after /obelisk. This is for
output intent, not retrieval architecture.
| Intent | Description | Reference |
|---|---|---|
recap [target] | Generate weekly/monthly recap card content for app handoff or share-style output. | references/recap/overview.md |
Routing rules:
recap, read references/recap/overview.md before the
first query. Everything after recap is the recap target.
Common app-generated prompts include /obelisk recap this week,
/obelisk recap last week, /obelisk recap this month, and
/obelisk recap last month; interpret these as natural period targets
relative to the current date and timezone.recap does not create a separate retrieval layer. It still uses
overview(), memories(), helpers, and sql() only when needed.recap, do not load
references/recap/overview.md. Continue with Query Routing below. Do not
infer recap from broad requests for weekly/monthly summaries, charts,
rankings, shareable cards, or playlist-style metaphors.Use references by job, not by habit:
| Reference | Use when |
|---|---|
references/query-patterns.md | Broad synthesis, progress summaries, design history, weekly/monthly reviews, approved memory write/archive/update scripts, or questions about what the user did/learned/decided/tried/abandoned. |
references/retrieval-semantics.md | Multi-step retrieval, scoped project/file/session searches, or when scope/artifact/semantic boundaries affect query design. |
references/schema.md | Raw SQL field and join quick reference before writing non-trivial sql(). |
references/api-reference.md | Helper signatures, option names, return fields, or exact remember() / forget() parameter details are unclear. |
references/pitfalls.md | Error recovery, FTS syntax, aliases, ordering, row-shape surprises, or compact/raw tradeoffs. |
references/recap/overview.md | Explicit /obelisk recap ... requests only. |
Before writing a query, classify the task. Progressive disclosure is useful, but skipping the relevant reference usually costs extra query rounds.
references/query-patterns.md before the first query for broad synthesis, progress summaries, design history, ordinary weekly/monthly reviews, or questions that ask what the user did, learned, decided, tried, or abandoned. Start from the first-pass or one-shot synthesis pattern, then run a faceted detail pass if needed.references/retrieval-semantics.md before multi-step retrieval, scoped project/file/session searches, or synthesis/conclusion/history questions. It defines the query design frame.references/schema.md before raw sql() unless the needed table/column relationship is already explicit here. It is intentionally short and SQL-focused. Do this before running the SQL, not after a missing-column error. Do not start with raw SQL for broad synthesis unless helpers cannot express the needed aggregation or join.references/api-reference.md when helper option names, return fields, scalar shorthand behavior, or remember()/forget() details are unclear.references/pitfalls.md after an error or when FTS syntax, aliases, ordering, row shapes, or compact/raw tradeoffs are unclear.If a helper row shape is unclear, first run a tiny scoped query and return
Object.keys(row) or a compact sample. Do not invent field names.
For approved memory mutations, follow the Memory Layer section below first.
Use references/query-patterns.md for copyable --attune scripts
(Attune Approved Memory, Forget Approved Memory, Update Approved Memory),
and references/api-reference.md only for exact parameter semantics.
search(text, opts?)Full-text search across main messages, subagent messages, and workflow-agent messages.
Returns:
[{ message: { uuid, text, content_type, is_meta, role, timestamp, model, cwd, visibility, source },
session: { id, title, project, started_at, source, is_invoking? },
rank,
context }]session.is_invoking is true only when the hit belongs to the session that
ran this query (see "Your Own Session In Results"); it is omitted otherwise.
context here means temporal neighbors: nearby messages in the same session by
timestamp. It is not the parent chain. Use context(uuid) or trace(uuid) for
causal/parent-chain context.
Use message.content_type to keep evidence boundaries intact:
text is user/assistant visible language, thinking is trace/debug material,
tool_use marks a tool-call message whose details live in tool_calls, and
tool_result marks a tool-result message whose details live in tool_results.
unknown is a conservative fallback. Do not treat thinking as a user-visible
assistant conclusion. Real user input is type='user' plus content_type='text';
do not invent a separate user_message content type.
Use message.is_meta to separate transcript control-plane material from
conversation evidence. is_meta=1 marks injected caveats, command envelopes, or
other messages that entered the transcript as user-role content but should not
be treated as the user's request by default. search() and thread() omit meta
messages unless includeMeta: true is passed; context() and trace() preserve
the current causal chain and expose is_meta on returned rows.
Pi can preserve a branch that was tried and later superseded as
visibility='inactive'. Only Pi populates it: other sources either do not
record supersession in their transcripts or discard it while indexing, so an
empty inactive result never means nothing was abandoned -- only that this
source cannot say. Default helpers return only visible evidence. Pass
includeInactive: true to search(), context(), trace(), thread(),
summaries(), raw(), fileHistory(), or failures() only when the abandoned
path matters. Every returned message or evidence row is labeled with
visibility; describe inactive evidence as something tried and then
superseded, never as the final decision. hidden is reserved for
display-suppressed or transport-only records and is never returned by these
helpers, even with the option enabled.
Opts:
{ limit, sessionId, project, after, before, cwd, source, includeMeta, includeInactive }.
project is a SQL LIKE filter over sessions.project, not an exact project
identity. Results are already ordered by FTS5 rank; lower rank sorts earlier.
Prefer returned order over manually interpreting numeric rank unless you are
deliberately using FTS5 semantics.
source can be 'claude', 'codex', 'deepseek', 'kimi', 'pi', or omitted. Omitted
means search all indexed sources.
context(uuid, opts?)Returns the full story around one indexed message:
{ message, parentChain, session, subagent, workflow }Use this after search() finds a promising message. It is the usual way to
expand vertically from one evidence point without dumping the whole session.
The target and returned ancestors must be visible by default. Pass
{ includeInactive: true } to follow an explicitly superseded Pi path.
sql(query, ...params)Read-only SQL SELECT/WITH with ? placeholders. Returns array rows. SQL is an
escape hatch for exact structured joins and aggregations after the helper-first
surface is insufficient; it is not the default retrieval entry point.
Before writing non-trivial SQL, read references/schema.md. It is the raw SQL
field/join quick reference. The executable DDL is CLI-owned and is deliberately
not duplicated in this docs-only skill. Common safe joins:
tool_calls does not have timestamps. Join messages m ON m.uuid = tc.message_uuid.tool_results does not have timestamps. Join messages m ON m.uuid = tr.message_uuid.sessions s ON s.id = <table>.session_id.GROUP BY, COUNT, MAX, ORDER BY, and LIMIT over hand-counting in the final answer.Tables: sessions, messages, tool_calls, tool_results, summaries,
memories, subagents, workflows, workflow_agents, messages_fts.
These helpers are convenience accessors over the same SQLite structure. They do
not replace sql(), but they are the default first-pass surface. Use sql()
when you need an exact aggregation or a join the helper does not expose.
All list helpers accept a bounded limit. Many also accept:
{ project, after, before, sessionId, sessions, branch, source }. Check
references/api-reference.md or a tiny sample before relying on less common
filters or return fields.
overview(opts?) -- compact orientation map. Returns current cwd/project if knowable, the invoking session id (current.session_id) when the invocation nonce resolved, global project/source counts, and current-project recent sessions plus memory records. It is a map, not evidence.sessions(opts?) -- session rows, newest first. project is a SQL LIKE pattern. message_count counts the visible canonical transcript; inactive and hidden records are excluded. The invoking session row carries is_invoking: true.recent(n?) -- shorthand for recent sessions.summaries(opts?) -- summary rows, newest first: { id, session_id, timestamp, source, content, visibility, session_title, project }; inactive rows require includeInactive: true, hidden rows are never returned, and source is the summary kind rather than the transcript provider.subagents(opts?) -- subagent metadata plus messageCount.workflows(opts?) -- workflow runs, newest first.workflowTree(runId) -- workflow row plus parsed result and agents; may include bulky script and result_json, so project compact fields.fileHistory(filePath, opts?) -- Read/Edit/Write tool calls for a file, oldest first; includes many Read rows and labels each result with visibility.failures(opts?) -- failed tool results with tool/session context and visibility, newest first.trace(uuid, opts?) -- parent chain from root to message.thread(sessionId, opts?) -- session messages ordered by timestamp, omitting meta messages by default. Pass { includeMeta: true } for injected context or { includeInactive: true } for superseded Pi history.raw(uuid, opts?) -- windowed source access for one visible message. Pi returns the selected source-message container whether it was stored directly or inside a retained tail. Inactive targets require includeInactive: true; hidden targets return null.memories(opts?) -- recall memory layer. opts: { query, project, sessionId, sessions, after, before, branch, limit }. Without query, returns active memory records newest first. With query, searches summary/path through safe FTS5 tokenization and returns rank; lower rank sorts earlier. Records may include nullable JSON anchors for explicit recall surfaces such as files. Read the file at path for full content.Keep queries scoped, bounded, and structural.
overview({ limit: 6 }) before deeper retrieval unless the user gave an exact session/message/file locator. It is a navigation map; confirm facts with memories(), search(), helpers, or, only when needed, sql().overview(), memories(), search(), sessions(), summaries(), fileHistory(), and other helpers for first-pass retrieval. Escalate to raw sql() only when helpers cannot express the needed join, grouping, or exact schema-level check.session_id, uuid, tool_call_id, run_id, agent_id) and short snippets, then synthesize in the final answer.is_meta=1 rows are injected/control-plane transcript material. Helpers hide them by default; raw SQL for ordinary conversation evidence should include COALESCE(m.is_meta,0)=0 unless meta rows are the investigation target.memories() does not already cover it, explicitly offer to write a memory. Keep the offer brief. Do not write the markdown file or run --attune until the user approves.If field, context, ordering, FTS, or helper semantics affect the query, read
references/retrieval-semantics.md before coding. If a query errors, read
references/pitfalls.md before retrying.
Obelisk has a persistent memory layer alongside raw session data. Every
retrieval queries both layers: memories() for prior conclusions, search()
and helpers for raw session evidence. Use memory as prior notes, not final
authority. If a memory record influences your answer, say naturally that it was
previously recorded, and compare it with raw session evidence when correctness
depends on it. Raw session data is the evidence layer, but one hit is not a
complete truth; query and cite it compactly.
The memory layer is English-indexed. Use English terms in memories({ query })
even when the user asks in another language. Write every remember().summary
in English, regardless of the current conversation language. The runtime rejects
obvious CJK text in memory queries and summaries as a guardrail.
Recall: query memories({ query: 'English topic terms', project: '...' })
to find prior conclusions relevant to the current task. Translate non-English
user requests into concise English query terms before calling memories().
Memory recall uses safe FTS5 tokenization over summary and path, so
hyphens/punctuation are tokenized instead of causing raw MATCH syntax errors.
Like other list helpers, passing a string is treated as sessionId, and passing
a number is treated as limit. Read the file at path for full content.
memories() returns active memories only. An archived memory is
management/audit data, not recall data.
Good memory candidates include design decisions, project conventions, abandoned alternatives, repeated failure causes, workflow patterns, and conclusions synthesized across multiple raw evidence points. Do not propose memory for one-off lookups, uncertain findings, or conclusions already covered by existing memories.
Mutation approvals: judging whether to use a memory in the current answer is an agent decision and does not require approval. Persistent memory changes do. If the user explicitly says a memory is wrong, outdated, should be forgotten, or should now say something else, that request is the approval to archive or update the exact matching memory. Do not ask for a second confirmation unless multiple memories could match. If you notice a possible conflict yourself, explain it briefly and ask before changing memory state.
Writing memories: after a retrieval produces a conclusion worth persisting, propose writing a memory file. The user must approve. Flow:
Write tool (user approves).remember() in a narrow memory-registration script:return remember({
path: '.obelisk/memories/design-decision-x.md',
session_id: 'current-session-id',
message_start: 'uuid-of-first-relevant-msg',
message_end: 'uuid-of-last-relevant-msg',
anchors: [{ kind: 'file', path: 'src/path/to/file.ts' }],
summary: 'Detailed summary: what was decided, why, what alternatives were considered, and what constraints drove the choice.'
})Run the registration script with:
obelisk --attune /tmp/register-memory.mjs--attune exposes only memory mutation helpers: remember() and forget().
It does not expose search(), sql(), memories(), or other retrieval
helpers. If you need source IDs or memory IDs, find them first with a normal
--query script.
remember() validates that path already exists and points to a file. Relative
paths are resolved against the source session's project_path when
session_id is provided, then stored as normalized absolute paths. Prefer
project-relative paths such as .obelisk/memories/... plus session_id.
Optional anchors must be an array of objects and is stored as nullable JSON
text. Use it only for explicit recall surfaces, such as files associated with
the memory.
summary must be English and detailed enough that memories() results alone
can judge relevance without reading the file. Include the decision, the
reasoning, and the key constraints — not just a title.
The message_start/message_end range marks where in the conversation this
conclusion was drawn. Use it later to trace back to the original evidence.
Forgetting memories: if the user says a memory is outdated, wrong, or should
be forgotten, use normal recall first to identify the exact memory ID. If there
is exactly one clear candidate, the user's request is approval to archive it. If
multiple memories could match, ask which one to forget. Then run an --attune
script:
return forget({
id: 'mem-id-to-delete',
reason: 'Outdated by newer project guidance.',
});forget() archives the memory record by setting deleted_at and
deleted_reason. It removes the record from active recall but does not delete
the markdown file. Memory records survive index rebuilds and are never changed
automatically.
Updating memories: updating memory is one user-approved operation:
archive the old memory with forget(), then write and register a replacement
markdown memory with remember(). If the user explicitly corrected the memory,
that correction is approval for the combined archive-plus-write flow. If you
discovered the mismatch yourself, ask first.
Search, then expand one promising hit:
const hits = search('auth fix', { limit: 5 });
if (!hits.length) return [];
return hits.slice(0, 3).map(h => ({
session_id: h.session.id,
session_title: h.session.title,
uuid: h.message.uuid,
snippet: h.message.text?.slice(0, 240),
}));Check helper fields before assuming names:
const rows = summaries({ project: '%quiet-zero%', limit: 1 });
return rows.length ? Object.keys(rows[0]) : [];Fetch message neighbors without a full thread:
const hit = search('runtime query', { limit: 1 })[0];
return sql(
`SELECT uuid, role, timestamp, substr(text,1,240) AS snippet
FROM messages
WHERE session_id=? AND timestamp>=?
AND COALESCE(visibility, 'visible') = 'visible'
ORDER BY timestamp LIMIT 6`,
hit.session.id,
hit.message.timestamp
);See references/query-patterns.md for longer recipes.
~/.obelisk/obelisk.sqlite; old ~/.claude/obelisk.sqlite is copied forward if needed.raw(uuid, { offset, limit }) for specific JSONL windows.© tommy0103, AGPL-3.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 18 other files (references) in packages/dsh-plugin/skill of tommy0103/obelisk.
Open the folder on GitHubat commit a4b7329
Obelisk 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.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Obelisk this skilltommy0103/obelisk | 571 | — | ~6.5k | Automated safety check: Pass | AGPL-3.0 | |
| MCP Server BuildershareAI-lab/learn-claude-code | 78k | 4 repos | ~1.2k | Automated safety check: Pass | MIT | |
| Copilot Session Failure Analysisdotnet/maui | 23k | — | ~3.4k | Automated safety check: Pass | MIT | |
| CCS Task Delegationkaitranntt/ccs | 2.9k | — | ~1.8k | Automated safety check: Pass | MIT | |
| Bd To Br MigrationDicklesworthstone/beads_rust | 1.1k | — | ~2.2k | Automated safety check: Pass | Custom licence | |
| Helmor Bump Vendorsdohooo/helmor | 1.3k | — | ~2.1k | Automated safety check: Pass | Apache-2.0 |
shareAI-lab/learn-claude-code
Walks through building MCP servers in Python or TypeScript that expose tools, resources and prompts to Claude, with templates, registration and testing.
dotnet/maui
Mines local Copilot CLI session logs for dotnet/maui to rank costly or failing runs, tag recurring failure modes, propose repo edits and emit guard evals.
kaitranntt/ccs
Hands simple, deterministic tasks such as typo fixes, tests and small refactors to cheaper models through the ccs CLI, choosing a profile from your config.
Dicklesworthstone/beads_rust
Migrate docs from bd (beads) to br (beadsrust). An agent skill from Dicklesworthstone/beads_rust.
dohooo/helmor
Bump or upgrade the pinned versions of Helmor's bundled agent CLIs, SDKs, and supporting binaries — Claude Code + claude-agent-sdk (lockstep), Codex, Cursor SDK, OpenCode, Kimi, Pi, and gh / glab /…
tigerless-labs/agent-memory
Read and write the shared long-term memory store. An agent skill from tigerless-labs/agent-memory.
tommy0103/obelisk
Search and query past Claude Code, Codex, Kimi Code, Kiro, OMP, and Pi session history.
tommy0103/obelisk
Review a provider/agent adapter implementation or PR — transcript discovery, parsing, and indexing for agent hosts (Claude, Codex, Kimi, Pi, DeepSeek Harness, OMP, Copilot, etc.).
Categories
Search and query past Claude Code, Codex, Kimi Code, Kiro, and Pi session history. Obelisk is an agent skill from tommy0103/obelisk. Search and query past Claude Code, Codex, Kimi Code, Kiro, and Pi session history.
Obelisk fits situations like: asks how did I fix X; what did we do last time; find the session where; references past work you lack context for.
Run `npx skills add tommy0103/obelisk --skill obelisk -a claude-code`. Or copy the skill folder (packages/dsh-plugin/skill in tommy0103/obelisk) into .claude/skills/obelisk in your project. Claude Code loads it when a task matches its description.
Run `npx skills add tommy0103/obelisk --skill obelisk -a codex`. Or copy the skill folder (packages/dsh-plugin/skill in tommy0103/obelisk) into .agents/skills/obelisk in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add tommy0103/obelisk --skill obelisk -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/obelisk, .gemini/skills/obelisk, .github/skills/obelisk and .opencode/skills/obelisk in your project.
SKILL.md names no scripts, command-line tools or credentials: Obelisk is instructions for the agent only. Its frontmatter pre-approves these tools: Read, Bash(obelisk:*), Write.
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.
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.
Obelisk is published under the AGPL-3.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 6.5k tokens (SKILL.md is roughly 26k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full. Its references folder adds about 22k tokens, read only when the agent opens those files.
Skills that share tags, products or a category with Obelisk: MCP Server Builder (shareAI-lab/learn-claude-code, 78k stars), Copilot Session Failure Analysis (dotnet/maui, 23k stars), CCS Task Delegation (kaitranntt/ccs, 2.9k stars) and Bd To Br Migration (Dicklesworthstone/beads_rust, 1.1k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
tommy0103 (a GitHub user) maintains it in tommy0103/obelisk, which has 571 GitHub stars. The repository holds 3 skills in this directory. The repository was last updated on October 9, 2026.
Source: tommy0103/obelisk on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.