Blog · 4 October 2026 · Volodymyr Pavlyshyn

tg: your docs and your code as one typed graph

Design notes drift from code because nothing connects them. tg is a command line that keeps a folder of Markdown design docs honest against the source, lets code point back at the docs with typed edges, and hands the result to coding agents.

Why a CLI, when this site is about Obsidian

Typed Graph started as an Obsidian plugin. The same model, notes as nodes and typed signed links as edges, turned out to fit a developer's lat.md/ folder just as well: a set of cross-linked Markdown files that describe what a project does and why. lat.md is an existing tool for that format. tg reads the same folder, gives the same verdicts, and adds the graph.

You can use it without Obsidian, in a terminal or in CI. In Obsidian the plugin reads the same folder in place.

1. A lat.md folder, checked

A lat.md/ folder holds ordinary Markdown. Sections link to each other and to code with wiki links, and every section starts with a one-sentence overview:

## Token expiry

Tokens past their expiry timestamp are rejected with 401, even if
otherwise valid. Implemented by [[src/auth.ts#verifyToken]];
see also [[security#Session lifetime]].

tg check validates all of it:

It exits 1 when anything is wrong, so it works as a CI gate and as a hook that stops an agent from finishing with stale docs.

2. Code that points back

A comment links code to the docs that describe it:

// @lat: [[auth#Token expiry]]
export function verifyToken(token: string) { /* ... */ }

That is a plain reference. With @tg: the link carries a type, a sign and properties, using the same edge syntax as notes:

// @tg: implements:: [[auth#Token expiry]] {since: 2}
export function verifyToken(token: string) { /* ... */ }

// @tg: -contradicts:: [[design#Stateless sessions]]
function legacySessionCheck() { /* ... */ }

The edge starts at the declaration that follows the comment, so it names the function, not the file. If nothing follows within three lines, the edge falls back to the file and tg check warns. A bare @tg: [[x]] means exactly what @lat: means, and projects that use @lat: need no changes.

3. Ask the graph

Sections and, when you ask for them, code symbols are nodes in one property graph. tg cypher runs read-only openCypher over it, with the same engine the plugin uses:

tg cypher --code annotated "
  MATCH (c:CodeSymbol)-[r:implements]->(s:Section)
  RETURN c.path, c.symbol, s.title"

tg cypher "MATCH (s:Section)
           OPTIONAL MATCH (a)-[r:references]->(s)
           WITH s, count(r) AS n WHERE n = 0
           RETURN s.section LIMIT 20"

The first lists which functions implement which design sections. The second finds sections that nothing links to. Code nodes are derived in memory from your annotations and never written to disk: by default only annotated symbols and what they point at appear, and --code all adds every symbol.

4. Search that works on a fresh clone

tg search ranks sections with a lexical index over title, overview and body. It needs no model, no key and no network, so it works in a new checkout and inside a hook. If you want semantic matches, point it at Ollama or any OpenAI-compatible endpoint with TG_EMBED_PROVIDER or a key, and it fuses both rankings. If the provider is down, you still get lexical results and a note.

5. Agents get the picture first

tg init sets a project up for Claude Code, Cursor or any agent that reads AGENTS.md. It never writes without --write: the default run prints a diff of every file it would touch.

$ tg init
+++ b/CLAUDE.md          (instruction block: search first, check last)
+++ b/.claude/settings.json   (UserPromptSubmit and Stop hooks)
+++ b/.mcp.json          (the tg MCP server)
+++ b/.claude/skills/tg-docs/SKILL.md
+++ b/.claude/skills/tg-graph/SKILL.md
Dry run: 5 files would change. Re-run with --write to apply.

Once applied, the prompt hook reminds the agent to search before it works and expands any [[refs]] in your prompt. The stop hook blocks the agent from finishing when tg check fails or when it changed a lot of code without touching lat.md/. Hooks never fail the agent: on any internal error they exit 0.

tg mcp serves eight tools to MCP clients: tg_locate, tg_section, tg_search, tg_expand, tg_check, tg_refs, tg_cypher and tg_edges. The two bundled skills teach an agent how to maintain the docs and how to query the graph.

6. Obsidian, both ways

What it is not

Try it

npm install -g @typedgraph/cli
cd your-project
tg init          # dry run
tg check
tg search "how are tokens validated"

The full command reference is in the docs. If you already use lat.md, read how tg compares first.