glovrex-cli
v0.2.0
Published
Import/export connector for Obsidian vaults. Turns a markdown vault into a portable knowledge graph (JSON/GraphML/Markdown) with zero lock-in.
Maintainers
Readme
glovrex-cli
Import/export connector for Obsidian vaults. Point it at a vault, get a portable knowledge graph back. No lock-in: export to JSON, GraphML, or plain markdown at any time.
Usage
glovrex import obsidian ./my-vault -o graph.json
glovrex export graphml graph.json -o graph.graphml
glovrex export markdown graph.json -o restored-vaultimport walks the vault, splits frontmatter, and extracts links the same
way Obsidian resolves them:
[[wikilinks]], including#headinganchors, block references ([[note#^id]]), and|aliastext![[embeds]](transclusion), tagged with edge typeembedinstead ofwikilink- standard markdown links to notes (
[text](note.md), with or without a#headinganchor) aliasesin frontmatter — a link to an alias resolves to the note that declares it, same as Obsidian- nested tags (
#a/b), both inline and in frontmattertags
Resolution is by note title/alias, not folder — a link to a note in a
different folder still resolves. Links that don't match any note are kept
as unresolved edges rather than dropped. .canvas files are not parsed
(out of scope for now).
export never mutates note content: markdown export writes files back out
byte-for-byte plus reconstructed frontmatter, so round-tripping through
glovrex is lossless on the content you actually wrote.
Graph shape
interface KnowledgeGraph {
version: "1";
source: string;
generatedAt: string;
nodes: { id: string; title: string; path: string; tags: string[]; frontmatter: Record<string, string>; content: string; kind?: "decision" | "commit" | "outcome" }[];
edges: { from: string; to: string; type: "wikilink" | "unresolved" | "embed" | "markdown-link" | "decision-of" | "outcome-of"; label?: string }[];
}Decision hook (MVP)
Most "why did we do this" lives in someone's head, or in an ADR file nobody
reopens. glovrex decision links it to the commit that shipped it instead,
so it shows up in the same graph as everything else.
glovrex decision "picked JSON store over sqlite: zero deps, one file"
glovrex outcome d1 shipped --note "held up fine after a week in prod"
glovrex hook install
glovrex decisions graph -o decisions.json
glovrex export graphml decisions.json -o decisions.graphmldecision <why>records the why against the current HEAD commit, in.glovrex/decisions.json.outcome <decisionId> <shipped|reverted|used|dropped> [--note]records what actually happened, whenever that turns out to be true.hook installadds apost-commithook to.git/hooks: put aDecision: <why>line in a commit message and it's captured automatically. Requiresglovrexon PATH. Appends to an existing hook instead of overwriting it.decisions graphturns the ledger into a KnowledgeGraph — same shape asimport— so the existingexportcommand renders it as graphml or markdown with no changes toexportitself. A decision with no outcome recorded yet has no outgoing outcome edge: visible as a gap, the same way an unresolved wikilink stays visible instead of silently dropped.
Compared to adr-tools / log4brains: those write decisions to files
nobody reopens. This ties a decision to the commit and to what happened
after, so the graph shows rot instead of just intent.
v1.1 (not built yet): reading the "why" out of the diff with an LLM instead
of a manual Decision: line, and a PR-bot / editor integration. Left out of
this MVP on purpose — no network call, no extra dependency.
