Engraph
devwhodevs/engraph
Index and search document collections using hybrid semantic + graph + full-text search.
Interact with the Hypatia AI memory system using natural language.
$ npx skills add MarchLiu/hypatia --skill hypatia -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install MarchLiu/hypatia hypatia --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/MarchLiu/hypatia.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/hypatia .claude/skills/hypatia && 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 "hypatia" agent skill from https://github.com/MarchLiu/hypatia/tree/main/skills/hypatia into .claude/skills/hypatia/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "hypatia", 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/MarchLiu/hypatia/tree/main/skills/hypatiaType 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 MarchLiu/hypatia --skill hypatia -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install MarchLiu/hypatia hypatia --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/MarchLiu/hypatia.git skills-src && mkdir -p .agents/skills && cp -r skills-src/skills/hypatia .agents/skills/hypatia && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "hypatia" agent skill from https://github.com/MarchLiu/hypatia/tree/main/skills/hypatia into .agents/skills/hypatia/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "hypatia", 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 MarchLiu/hypatia --skill hypatia -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install MarchLiu/hypatia hypatia --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/MarchLiu/hypatia.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/skills/hypatia .cursor/skills/hypatia && 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 "hypatia" agent skill from https://github.com/MarchLiu/hypatia/tree/main/skills/hypatia into .cursor/skills/hypatia/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "hypatia", 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/MarchLiu/hypatia.git --path skills/hypatia--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 MarchLiu/hypatia --skill hypatia -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install MarchLiu/hypatia hypatia --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/MarchLiu/hypatia.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/skills/hypatia .gemini/skills/hypatia && 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 "hypatia" agent skill from https://github.com/MarchLiu/hypatia/tree/main/skills/hypatia into .gemini/skills/hypatia/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "hypatia", 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 MarchLiu/hypatia hypatiaInstalls 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 MarchLiu/hypatia --skill hypatia -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/MarchLiu/hypatia.git skills-src && mkdir -p .github/skills && cp -r skills-src/skills/hypatia .github/skills/hypatia && 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 "hypatia" agent skill from https://github.com/MarchLiu/hypatia/tree/main/skills/hypatia into .github/skills/hypatia/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "hypatia", 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 MarchLiu/hypatia --skill hypatia -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install MarchLiu/hypatia hypatia --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/MarchLiu/hypatia.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/skills/hypatia .opencode/skills/hypatia && 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 "hypatia" agent skill from https://github.com/MarchLiu/hypatia/tree/main/skills/hypatia into .opencode/skills/hypatia/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "hypatia", 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.
hypatiaInteract with the Hypatia AI memory system using natural language.
Hypatia is an agent skill from MarchLiu/hypatia. Interact with the Hypatia AI memory system using natural language. Translate user requests into hypatia CLI commands for knowledge CRUD, statement (RDF triple) management, JSE queries, full-text search, and shelf management. Trigger when: user mentions memories, knowledge bases, knowledge graphs, triples, statements, relationships, shelves, or asks to store, recall, remember, record, save, find, or search information in hypatia. Also trigger when user wants to create or explore relationships between concepts…
Its SKILL.md is about 7.9k 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 Knowledge Management, covering Search implementation, Knowledge bases and Knowledge graphs. It works with Rust. The repository describes itself as: "We can wander through the stacks of the Library of Alexandria, imagining the scrolls and the knowledge they contain. Its destruction is a warning: all we have is…. The licence is MIT.
3 steps, taken from the first numbered list in SKILL.md.
Read from SKILL.md and the folder at commit d32f94e. 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:
BashReadGrepGlobFrom allowed-tools in the SKILL.md frontmatter.
Shell commands in SKILL.md call:
sqlite3From 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.
Hypatia loads about 7.9k tokens when it runs. Until then it costs about 187 tokens; SKILL.md has 3,147 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 noted patterns worth knowing about, such as sudo or a known installer.
allowed-tools: Bash, Read, Grep, GlobAutomated 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 MarchLiu/hypatia at commit d32f94e, republished under its MIT licence (© MarchLiu). 3,147 words, ~7,931 tokens.
.claude/skills/hypatia/SKILL.md (or your agent's skills folder).You are operating the Hypatia CLI — an AI-oriented memory management system. Translate the user's natural language request into the appropriate hypatia CLI command and execute it via Bash.
First check which binary is available:
hypatia — if installed on PATH./target/debug/hypatia — debug build in current project./target/release/hypatia — release build in current projectUse the first one found. All examples below use hypatia for brevity.
| User says | Command |
|---|---|
| "list shelves" / "show connected shelves" | hypatia list |
| "connect shelf at PATH" / "open data at PATH" | hypatia connect <path> [-n <name>] |
| "disconnect shelf NAME" / "close shelf NAME" | hypatia disconnect <name> |
| "export shelf NAME to DEST" | hypatia export <name> <dest> |
Archive files (images, PDFs, data, etc.) are stored in the shelf's archives/ directory and referenced via archive:// paths.
| User says | Command |
|---|---|
| "store this image" / "add figure fig.png" | hypatia archive-store <file> -n <dest_path> |
| "get archive fig.png" / "show image path" | hypatia archive-get <name> |
| "copy archive to /tmp" | hypatia archive-get <name> -o /tmp/output.png |
| "list archives" / "show all files" | hypatia archive-list |
archive-store automatically creates a knowledge entry with file metadata (size, MIME type) and an is_a archive statement. Archive files can be queried via JSE:
hypatia query '["$knowledge", ["$contains", "tags", "archive"]]'
hypatia query '["$knowledge", ["$content", {"mime_type": "image/png"}]]'To reference an archive when creating knowledge:
hypatia knowledge-create "Euclid Prop 1" -d "equilateral triangle" --figures "archive://euclid/fig1.png"Use --scopes to assign project or global scope to knowledge and statements. The value is comma-separated. Global scope is stored as an empty-string entry, and only a trailing comma writes it: --scopes "," is global only, and --scopes "my-project," is both. --scopes "" stores no scope at all, so global lookups such as ["$has", "scopes", ""] will never find the entry.
# Project-scoped only
hypatia knowledge-create "API convention" -d "REST endpoints use kebab-case" --tags "rule" --scopes "my-project"
# Global scope only (trailing comma; `--scopes ""` would store no scope)
hypatia knowledge-create "prefer immutable" -d "always create new objects" --tags "rule" --scopes ","
# Both project and global (trailing comma)
hypatia knowledge-create "no mock DB" -d "never mock database in tests" --tags "taboo" --scopes "my-project,"A scope or tag you invent is not an error — the entry is stored, and every later lookup by the value you meant misses it. Check before you write:
# What this shelf already uses, with how many entries carry each
hypatia scope list --count
hypatia tag list --count
# Exact values, when you are going to write one back
hypatia scope list --json # [{"value":"","entries":12},{"value":"my-project",…}]
# Confirm one spelling; exit 0 if in use, 1 if not
hypatia tag exists rule
hypatia scope exists my-project
hypatia scope exists "" # the global scopeThe plain listing prints the global scope as (global). That is a label for the
terminal, not the value — the value is the empty string, and --json and
exists both give it back verbatim. Never copy (global) into --scopes.
Both cover knowledge and statements. An entry that declares no scopes at all is not listed as global.
| User says | Command |
|---|---|
| "what scopes/projects are in here?" | hypatia scope list --count |
| "what tags exist?" / "which labels are used?" | hypatia tag list --count |
"is there already a rule tag?" | hypatia tag exists rule |
Knowledge entries are independent information points with a name, content, and tags.
hypatia knowledge-create <name> -d "<data>" -t "<tag1,tag2>" --figures "archive://path/to/file" [--no-embed]--no-embed keeps the entry out of the vector index: it is still stored and still found by search and query, but it is never embedded, so it costs no model call on the way in and is not a similar result. Use it for raw session logs and other bulk that carries no distilled knowledge. A shelf can skip whole tags instead, with embedding.skip_tags in shelf.toml.
| User says | Command |
|---|---|
| "remember Rust as a systems programming language" | hypatia knowledge-create "Rust" -d "systems programming language" -t "language,compiled" |
| "save knowledge about Go with tags language and compiled" | hypatia knowledge-create "Go" -d "" -t "language,compiled" |
| "store that Python is a scripting language, tag it as dynamic" | hypatia knowledge-create "Python" -d "scripting language" -t "dynamic" |
| "log this turn but don't make it searchable by meaning" | hypatia knowledge-create "msg-42" -d "<turn>" -t "message" --no-embed |
hypatia knowledge-get <name>| User says | Command |
|---|---|
| "show me knowledge about Rust" / "get Rust entry" | hypatia knowledge-get "Rust" |
hypatia knowledge-update <name> [-d "<data>"] [-t "<tags>"] [--synonyms "<csv>"] [--figures "<refs>"] [--scopes "<scopes>"] [--no-embed | --embed]--no-embed takes the entry out of the vector index and discards the vector it had; --embed puts it back, and it is embedded on the next flush. The two are mutually exclusive. --embed does not override the shelf's embedding.skip_tags: an entry can ask for less indexing than its shelf, never more.
Only the fields you pass change. An omitted field keeps its stored value, and exactly "" clears a field, such as -t ""; for tags, "," or " " would store blank tags instead. --scopes replaces the stored scopes and is parsed as on create: end the list with a comma, such as "q,", to include the global scope, or the entry drops out of global lookups. The entry keeps its created_at. Its old vector is discarded, and a new one is generated on the next flush, as after knowledge-create. Updating an entry that does not exist is an error. An update that changes nothing prints Knowledge unchanged: <name> and writes nothing.
| User says | Command |
|---|---|
| "update Rust's description to mention memory safety" | hypatia knowledge-update "Rust" -d "systems programming language with memory safety" |
| "retag Go as language and google" | hypatia knowledge-update "Go" -t "language,google" |
| "remove all tags from Python" | hypatia knowledge-update "Python" -t "" |
hypatia knowledge-delete <name>| User says | Command |
|---|---|
| "delete knowledge Rust" / "remove the Rust entry" | hypatia knowledge-delete "Rust" |
Statements are RDF-style triples: (head, relation, tail). They form the edges of the knowledge graph.
When the user asks to store or remember information, always create statements alongside knowledge entries to build graph connectivity. The goal is a rich, traversable knowledge graph, not isolated data points.
Pattern: After creating a knowledge entry, identify entities mentioned in the content and create $triple relationships between them. At minimum, create one is_a statement for every new knowledge entry.
hypatia statement-create <head> <relation> <tail> -d "<data>" [--no-embed]--no-embed works as it does on knowledge-create: the triple is still stored and still traversable, but gets no vector. Two differences: statements carry no tags, so a shelf's embedding.skip_tags cannot reach them and bulk links must say --no-embed themselves; and there is no statement-update, so the choice is made once at creation.
| User says | head | relation | tail |
|---|---|---|---|
| "record that Alice knows Bob" | Alice | knows | Bob |
| "X is a Y" / "X is an Y" | X | is_a | Y |
| "X belongs to Y" / "X is part of Y" | X | belongs_to | Y |
| "X works for Y" | X | works_for | Y |
| "X is related to Y" | X | related_to | Y |
| "X depends on Y" | X | depends_on | Y |
| "X uses Y" | X | uses | Y |
| "X contains Y" | X | contains | Y |
| "X created Y" | X | created_by | Y (reversed) |
Normalize relations to snake_case. Common relations: is_a, knows, related_to, works_for, belongs_to, depends_on, uses, contains, created_by.
When the user says "remember that Rust is a systems programming language", execute BOTH:
hypatia knowledge-create "Rust" -d "systems programming language" -t "language,compiled"
hypatia statement-create "Rust" "is_a" "systems programming language"When the user says "remember that PostgreSQL is a relational database used by the API", execute:
hypatia knowledge-create "PostgreSQL" -d "relational database" -t "database,relational"
hypatia statement-create "PostgreSQL" "is_a" "relational database"
hypatia statement-create "API" "depends_on" "PostgreSQL" -d "primary data store"When the user says "note that Alice is a senior engineer on the Backend team", execute:
hypatia knowledge-create "Alice" -d "senior engineer on Backend team" -t "person,engineer"
hypatia statement-create "Alice" "is_a" "senior engineer"
hypatia statement-create "Alice" "works_for" "Backend team"When creating knowledge entries, automatically extract and create statements for:
"X" is_a "<category>" — every entity has a typeX depends_on YX belongs_to YEvery query execution MUST be preceded by a brief explanation. Before running any hypatia command, output a thinking block in this format:
**Step N: <goal>**
> `hypatia <command>`
为什么用这个查询:<1-2 sentence explanation of why this operator/strategy was chosen>
预期结果:<what kind of results to expect>Then execute the command. After results come back, briefly interpret them before deciding the next step.
User asks: "查找与 Alice 相关的所有知识,以及她的关系网络"
**Step 1: 直接获取 Alice 的知识条目**
> `hypatia knowledge-get "Alice"`
为什么用这个查询:用户提到了明确的实体名 "Alice",先尝试直接 lookup 获取完整条目。
预期结果:如果存在,返回 Alice 的知识条目(content, tags, figures 等)。(执行... 得到结果或 "not found")
**Step 2: 查找 Alice 参与的所有三元组关系**
> `hypatia query '["$statement", ["$triple", "Alice", "$*", "$*"]]'`
为什么用这个查询:用 $triple 对 head 位精确匹配 "Alice",wildcard relation 和 tail,
这样可以拿到 Alice 作为主语的所有关系(knows, is_a, works_for 等),$triple 走索引,比 $search 更快更精确。
预期结果:返回所有 Alice 作为 head 的 statement triples。(执行... 得到结果)
**Step 3: 查找指向 Alice 的关系(Alice 作为 tail)**
> `hypatia query '["$statement", ["$triple", "$*", "$*", "Alice"]]'`
为什么用这个查询:上一步只查了 Alice 作为 head 的关系,但其他人可能指向 Alice(如 "Bob knows Alice"),
需要查 tail 位 = Alice 的三元组才能得到完整的关系网络。
预期结果:返回所有以 Alice 为宾语的 statement triples。(执行... 得到结果)
**Step 4: 2-hop 图遍历,探索 Alice 的更远关系**
> `hypatia query '["$statement", ["$k-hop", "Alice", "$*", 2]]'`
为什么用这个查询:前两步只查了 Alice 的直接关系,用户问的是"关系网络",需要通过 2-hop 递归遍历
发现 Alice → Bob → Charlie 这样的间接关系。$k-hop 用递归 CTE 实现,适合图探索。
预期结果:返回 Alice 的 2-hop 邻域内所有 statement triples。When searching for information, prefer precise graph operators over broad FTS search. Use the following decision tree:
For each step, include the thinking aloud explanation before executing.
1. User mentions a specific entity name?
→ knowledge-get (direct lookup)
2. User asks about relationships involving a known entity?
→ $triple operator (fastest, indexed)
3. User asks about a type of relationship (e.g., "who works for X")?
→ $triple with wildcard on entity positions
4. User wants to explore graph neighborhood (e.g., "who can X reach in 2 hops")?
→ $k-hop operator (graph traversal)
5. User wants semantic/similarity search (e.g., "find similar concepts")?
→ hypatia similar (vector search)
6. User wants to match a pattern (e.g., "names starting with X")?
→ $like operator
7. User wants to filter by content attributes (e.g., "markdown entries", "entries with specific format")?
→ $content operator
8. User asks about a specific entity's relationships?
→ $triple + knowledge-get combined
9. Broad/ambiguous query?
→ $search (FTS fallback)When the query involves a known entity (person, tool, concept), use $triple for precise, indexed lookups instead of FTS:
| Instead of | Use |
|---|---|
["$statement", ["$search", "Alice"]] | ["$statement", ["$triple", "Alice", "$*", "$*"]] |
["$statement", ["$search", "manages"]] | ["$statement", ["$triple", "$*", "manages", "$*"]] |
["$statement", ["$contains", "triple", "Alice"]] | ["$statement", ["$triple", "Alice", "$*", "$*"]] |
For rich retrieval, combine graph traversal with content filtering:
# Find all relationships involving Alice, created after a date
hypatia query '["$statement", ["$and", ["$triple", "Alice", "$*", "$*"], ["$gt", "created_at", "2025-01-01"]]]'
# Find all knowledge entries in markdown format about a topic
hypatia query '["$knowledge", ["$and", ["$content", {"format": "markdown"}], ["$search", "database"]]]'
# Find all people (entities that are_a "engineer")
hypatia query '["$statement", ["$triple", "$*", "is_a", "engineer"]]'Search is the fallback for broad or ambiguous queries. It covers both knowledge and statements.
hypatia search <query> [-c <catalog>] [--limit N] [--offset N]-c knowledge — search only knowledge entries-c statement — search only statements-c — search everything| User says | Command |
|---|---|
| "search for programming" / "find everything about programming" | hypatia search "programming" |
| "search knowledge for rust" | hypatia search "rust" -c knowledge |
| "what do you know about databases?" | hypatia search "databases" |
Semantic search using embedding vectors. Finds entries with similar meaning, even when keywords don't match.
hypatia similar <query> [--limit N] [-t knowledge|statement|both] [--tags <a,b>] [--exclude-tags <a,b>] [--where '<JSE condition>']--tags keeps entries carrying at least one of the tags, --exclude-tags drops entries carrying any of them, and --where takes a JSE condition such as ["$contains", "scopes", "project-a"] ($eq, $like, $contains, $and/$or/$not and the other filters $knowledge takes, but not $search, $similar or $k-hop). They narrow the entries before ranking, so --limit N still returns N entries whenever that many qualify. --exclude-tags message,summary,session keeps the session-log layer from crowding out the knowledge distilled from it. With the default target both the filter applies to statements too, so a condition on name needs -t knowledge.
Requires an embedding model configured in shelf.toml (default: BAAI/bge-m3).
Entries are embedded in batches after they are written or updated. With a remote embedding API, similar can miss entries changed in the last minute; search finds them at once.
Entries written with --no-embed, and entries carrying a tag the shelf lists in embedding.skip_tags, are never embedded and so are never similar results. search and query still find them. Each entry keeps the answer it was written with, so after changing skip_tags run hypatia backfill once to settle what is already stored.
| User says | Command |
|---|---|
| "find similar to distributed systems" | hypatia similar "distributed systems" |
| "semantic search for memory management" | hypatia similar "memory management" --limit 5 |
| "what do we know about auth, not the chat logs" | hypatia similar "auth" --exclude-tags message,summary,session |
| "rules like this one for project-a" | hypatia similar "<rule text>" -t knowledge --tags rule --where '["$contains", "scopes", "project-a"]' |
JSE (JSON Search Expression) enables precise queries against the knowledge or statement tables.
hypatia query '<JSE-JSON>' [-s <shelf>]The top-level operator is always $knowledge or $statement:
["$knowledge", condition1, condition2, ...]
["$statement", condition1, condition2, ...]No conditions means "return all":
["$knowledge"]| Operator | Purpose | Syntax |
|---|---|---|
$eq | Equals | ["$eq", "field", "value"] |
$ne | Not equals | ["$ne", "field", "value"] |
$gt | Greater than | ["$gt", "field", "value"] |
$lt | Less than | ["$lt", "field", "value"] |
$gte | Greater than or equal | ["$gte", "field", "value"] |
$lte | Less than or equal | ["$lte", "field", "value"] |
$like | SQL LIKE pattern match | ["$like", "field", "pattern"] |
$contains | Substring match in content JSON | ["$contains", "field", "value"] |
$content | Match content JSON key-value pairs | ["$content", {"key": "value"}] |
$search | Full-text search (FTS) | ["$search", "query text"] |
$and | Logical AND | ["$and", cond1, cond2, ...] |
$or | Logical OR | ["$or", cond1, cond2, ...] |
$not | Logical NOT | ["$not", condition] |
$triple | Triple position match | ["$triple", "Alice", "$*", "Bob"] |
$k-hop | K-hop graph traversal (statement only) | ["$k-hop", "head", "relation", depth] |
$has | Exact membership in a JSON field (arrays: element; scalars: equality; array value = any-of) — indexed | ["$has", "tags", "rust"] |
$json-contains | Structural containment (PG @>) — indexed recall + exact recheck | ["$json-contains", {"tags": ["rust"]}] |
$and and $or take multiple operands directly, NOT a nested array:
["$and", ["$eq", "name", "rust"], ["$contains", "tags", "systems"]]["$and", [["$eq", "name", "rust"], ["$contains", "tags", "systems"]]]$search must be inside $knowledge or $statement, never top-level. When inside $knowledge, it searches FTS with catalog=knowledge. When inside $statement, it searches with catalog=statement.
Field names like "name", "triple" are used as plain strings. For content JSON sub-fields (e.g., tags), $contains uses json_extract_string automatically.
Available fields for knowledge: name, created_at, plus any content JSON field via $contains.
Available fields for statement: triple (CSV-formatted head,relation,tail), head, relation, tail, created_at, tr_start, tr_end, plus content JSON fields via $has/$contains. For position-based triple matching, prefer $triple over $contains.
New in 0.3: $has is the exact-membership operator (indexed; use it for tags/scopes lookups). $contains on array fields (tags/scopes/figures) routes to exact membership too; on other fields it stays substring. $json-contains matches whole-document containment (PG @>), e.g. ["$json-contains", {"tags": ["rust"]}].
$triple OperatorThe $triple operator provides position-based matching on statement triples. Each argument corresponds to head, relation, or tail. Use "$*" as a wildcard to match any value.
["$triple", <head_pattern>, <relation_pattern>, <tail_pattern>]| Pattern | Meaning |
|---|---|
"Alice" | Exact match |
"$*" | Wildcard — match any value |
Behavior:
triple = ? (primary key lookup, fastest)head = ? AND tail = ?, etc.)| User says | JSE | Command |
|---|---|---|
| "find all relationships where Alice is the head" | ["$statement", ["$triple", "Alice", "$*", "$*"]] | hypatia query '["$statement", ["$triple", "Alice", "$*", "$*"]]' |
| "find all knows relationships" | ["$statement", ["$triple", "$*", "knows", "$*"]] | hypatia query '["$statement", ["$triple", "$*", "knows", "$*"]]' |
| "find everything related to Bob as tail" | ["$statement", ["$triple", "$*", "$*", "Bob"]] | hypatia query '["$statement", ["$triple", "$*", "$*", "Bob"]]' |
| "find the exact Alice knows Bob triple" | ["$statement", ["$triple", "Alice", "knows", "Bob"]] | hypatia query '["$statement", ["$triple", "Alice", "knows", "Bob"]]' |
| "Alice's relationships with Bob, combined with date filter" | ["$statement", ["$and", ["$triple", "Alice", "$*", "Bob"], ["$gt", "created_at", "2025-01-01"]]] | hypatia query '["$statement", ["$and", ["$triple", "Alice", "$*", "Bob"], ["$gt", "created_at", "2025-01-01"]]]' |
$like OperatorSQL LIKE pattern matching with user-defined wildcards (% = any chars, _ = single char).
["$like", "field", "pattern"]| User says | JSE | Command |
|---|---|---|
| "find entries whose name starts with Rust" | ["$knowledge", ["$like", "name", "Rust%"]] | hypatia query '["$knowledge", ["$like", "name", "Rust%"]]' |
| "find entries created in January 2025" | ["$knowledge", ["$like", "created_at", "2025-01-%"]] | hypatia query '["$knowledge", ["$like", "created_at", "2025-01-%"]]' |
| "find statements with head matching pattern" | ["$statement", ["$like", "head", "Alice%"]] | hypatia query '["$statement", ["$like", "head", "Alice%"]]' |
$content OperatorMatch key-value pairs inside the content JSON column. Checks exact string equality for each specified key.
["$content", {"key1": "value1", "key2": "value2"}]| User says | JSE | Command |
|---|---|---|
| "find all markdown-format entries" | ["$knowledge", ["$content", {"format": "markdown"}]] | hypatia query '["$knowledge", ["$content", {"format": "markdown"}]]' |
| "find json-format statements" | ["$statement", ["$content", {"format": "json"}]] | hypatia query '["$statement", ["$content", {"format": "json"}]]' |
| "find entries with specific data and format" | ["$knowledge", ["$content", {"format": "markdown", "data": "hello"}]] | hypatia query '["$knowledge", ["$content", {"format": "markdown", "data": "hello"}]]' |
$k-hop OperatorK-hop graph traversal on statement triples using recursive CTE. Explores entity neighborhoods and relationship paths.
["$k-hop", "head", "relation", depth]"head" — starting entity (required)"relation" — filter by relation, or use "$*" for anydepth — number of hops (positive integer)| User says | JSE | Command |
|---|---|---|
| "who can Alice reach in 2 hops?" | ["$statement", ["$k-hop", "Alice", "$*", 2]] | hypatia query '["$statement", ["$k-hop", "Alice", "$*", 2]]' |
| "what's reachable from Alice via knows in 3 hops?" | ["$statement", ["$k-hop", "Alice", "knows", 3]] | hypatia query '["$statement", ["$k-hop", "Alice", "knows", 3]]' |
| "explore the graph around PostgreSQL" | ["$statement", ["$k-hop", "PostgreSQL", "$*", 2]] | hypatia query '["$statement", ["$k-hop", "PostgreSQL", "$*", 2]]' |
| User says | JSE | Command |
|---|---|---|
| "find knowledge named rust" | ["$knowledge", ["$eq", "name", "rust"]] | hypatia query '["$knowledge", ["$eq", "name", "rust"]]' |
| "find all relationships involving Alice" | ["$statement", ["$triple", "Alice", "$*", "$*"]] | hypatia query '["$statement", ["$triple", "Alice", "$*", "$*"]]' |
| "who does Alice know?" | ["$statement", ["$triple", "Alice", "knows", "$*"]] | hypatia query '["$statement", ["$triple", "Alice", "knows", "$*"]]' |
| "what type of things relate to Bob?" | ["$statement", ["$triple", "$*", "$*", "Bob"]] | hypatia query '["$statement", ["$triple", "$*", "$*", "Bob"]]' |
| "find knowledge named rust that contains 'systems' in tags" | ["$knowledge", ["$and", ["$eq", "name", "rust"], ["$contains", "tags", "systems"]]] | hypatia query '["$knowledge", ["$and", ["$eq", "name", "rust"], ["$contains", "tags", "systems"]]]' |
| "find knowledge NOT named rust" | ["$knowledge", ["$not", ["$eq", "name", "rust"]]] | hypatia query '["$knowledge", ["$not", ["$eq", "name", "rust"]]]' |
| "find all is_a relationships" | ["$statement", ["$triple", "$*", "is_a", "$*"]] | hypatia query '["$statement", ["$triple", "$*", "is_a", "$*"]]' |
| "find entries whose name starts with 'Al'" | ["$knowledge", ["$like", "name", "Al%"]] | hypatia query '["$knowledge", ["$like", "name", "Al%"]]' |
| "show all knowledge" | ["$knowledge"] | hypatia query '["$knowledge"]' |
| "find knowledge created after 2025-01-01" | ["$knowledge", ["$gt", "created_at", "2025-01-01"]] | hypatia query '["$knowledge", ["$gt", "created_at", "2025-01-01"]]' |
| "find knowledge containing 'language' in data" | ["$knowledge", ["$contains", "data", "language"]] | hypatia query '["$knowledge", ["$contains", "data", "language"]]' |
Use object form for the top-level operator to pass options:
{"$knowledge": [["$search", "rust"]], "limit": 10, "offset": 0}Command: hypatia query '{"$knowledge": [["$search", "rust"]], "limit": 10}'
When the user's request is ambiguous, follow this priority:
knowledge-get for direct lookup$statement query with $triple operator$k-hop operatorhypatia similar (vector search)$like operator$content operatorhypatia search (covers both knowledge and statements)Always wrap JSE JSON in single quotes to prevent shell interpretation of $, ", !, etc.:
hypatia query '["$knowledge", ["$eq", "name", "rust"]]'If the content contains single quotes, escape them:
hypatia query '["$knowledge", ["$eq", "name", "Alice'\''s project"]]'{"name": "...", "content": {"format": "...", "data": "...", "tags": [...]}, "created_at": "..."}{"triple": "head,relation,tail", "head": "...", "relation": "...", "tail": "...", "content": {...}, "created_at": "...", "tr_start": "...", "tr_end": "..."}{"id": N, "catalog": "...", "key": "...", "content": "...", "rank": N.N}When running inside a sandboxed harness (e.g. DSH workspace-write), the hypatia CLI and plain
sqlite3 ~/.hypatia/... may both fail with SQLite error 14 (unable to open database file):
even read-only SQLite needs to create WAL/journal temp files next to the database, and
~/.hypatia lies outside the writable workspace. Do not retry the same failing command —
go straight to the immutable read-only URI, which needs no journal and no directory writes:
sqlite3 "file:<shelf-dir>/hypatia.sqlite?mode=ro&immutable=1" "SELECT count(*) FROM knowledge;"immutable=1 tells SQLite the
file never changes, so writes would corrupt state or be lost.<shelf-dir> from hypatia list, which prints the directory each shelf is open at.
Do not assume ~/.hypatia/<shelf>/: any shelf, default included, can be registered elsewhere.
If the CLI itself cannot run, read the paths from ~/.hypatia/shelves.json.-wal/-shm siblings; if a WAL exists and is non-empty, immutable=1 may miss
recent un-checkpointed rows — in that case prefer requesting wider sandbox permissions for a
normal read instead.knowledge and statement; statement triples are stored in
head / relation / tail columns.This fallback was validated: the same query fails at error 14 without the URI params and returns correctly with them.
statement-get CLI command. Use JSE queries ($statement with conditions) to find statements. statement-delete is available for deletion.-s / --shelf flag defaults to "default" for all commands.hypatia repl) is interactive and should NOT be used from this skill. Always use one-shot CLI commands.-d) is stored as a string in the content JSON's data field.-t) are comma-separated strings.is_a statement.© MarchLiu, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
Just SKILL.md in skills/hypatia of MarchLiu/hypatia.
Open the folder on GitHubat commit d32f94e
Hypatia 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 |
|---|---|---|---|---|---|---|
| Hypatia this skillMarchLiu/hypatia | 239 | — | ~7.9k | Automated safety check: Notes | MIT | |
| Engraphdevwhodevs/engraph | 171 | — | ~792 | Automated safety check: Pass | MIT | |
| Wiki Viewerrohitg00/pro-workflow | 2.9k | — | ~1.1k | Automated safety check: Pass | None | |
| Graph Searchathola/claude-night-market | 341 | — | ~555 | Automated safety check: Pass | MIT | |
| LLM Wiki Knowledge GraphEgonex-AI/Understand-Anything | 86k | — | ~1.5k | Automated safety check: Pass | MIT | |
| Project Orchestratorthis-rs/project-orchestrator | 140 | — | ~2.6k | Automated safety check: Pass | Custom licence |
devwhodevs/engraph
Index and search document collections using hybrid semantic + graph + full-text search.
rohitg00/pro-workflow
Render a self-contained HTML viewer for a pro-workflow wiki.
athola/claude-night-market
Searches the code knowledge graph by function, class, or type using FTS5 full-text search.
Egonex-AI/Understand-Anything
Detects a Karpathy-pattern LLM wiki and builds an interactive knowledge graph with entities, implicit relationships and topic clusters.
this-rs/project-orchestrator
AI agent orchestrator with Neo4j knowledge graph, Meilisearch search, and Tree-sitter parsing.
NimaChu/my-wiki
Work with a local My Wiki knowledge base, Dashboard, and knowledge graph.
MarchLiu/hypatia
Run an incremental Hypatia graph-consolidation pass at a work-period boundary, like sleep-time knowledge organization.
MarchLiu/hypatia
Automatic memory extraction and management for hypatia knowledge graph
Works with
Categories
Interact with the Hypatia AI memory system using natural language. Hypatia is an agent skill from MarchLiu/hypatia. Interact with the Hypatia AI memory system using natural language.
Hypatia fits situations like: : user mentions memories; knowledge bases; knowledge graphs; search information in hypatia.
Run `npx skills add MarchLiu/hypatia --skill hypatia -a claude-code`. Or copy the skill folder (skills/hypatia in MarchLiu/hypatia) into .claude/skills/hypatia in your project. Claude Code loads it when a task matches its description.
Run `npx skills add MarchLiu/hypatia --skill hypatia -a codex`. Or copy the skill folder (skills/hypatia in MarchLiu/hypatia) into .agents/skills/hypatia 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 MarchLiu/hypatia --skill hypatia -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/hypatia, .gemini/skills/hypatia, .github/skills/hypatia and .opencode/skills/hypatia in your project.
Going by SKILL.md and its folder, Hypatia needs the command-line tools its instructions call (sqlite3). Our summary lists: Python 3. Its frontmatter pre-approves these tools: Bash, Read, Grep, Glob.
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 notes only (pre-approves every shell command (allowed-tools: bash)), nothing it rates as a warning. It is not a guarantee. Review the folder before installing.
Hypatia is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 7.9k tokens (SKILL.md is roughly 32k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Hypatia: Engraph (devwhodevs/engraph, 171 stars), Wiki Viewer (rohitg00/pro-workflow, 2.9k stars), Graph Search (athola/claude-night-market, 341 stars) and LLM Wiki Knowledge Graph (Egonex-AI/Understand-Anything, 86k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
MarchLiu (a GitHub user) maintains it in MarchLiu/hypatia, which has 239 GitHub stars. The repository holds 3 skills in this directory. The repository was last updated on September 29, 2026.
Source: MarchLiu/hypatia on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.