Blog · 4 October 2026 · Volodymyr Pavlyshyn

tg and lat.md: what is the same, what differs

tg reads the same lat.md/ folders as lat.md and agrees with its check. It adds a graph, typed links from code and a few developer conveniences. lat.md is stronger in places too, and this page says where.

lat.md is a separate open-source project (MIT) by Yury Selivanov, and Typed Graph is not affiliated with it. Statements about lat.md below describe version 0.12.2, the one tg is tested against. Check its documentation for anything newer.

The short version

Side by side

lat.md 0.12tg 0.5
Folder format and idslat.md/, file#Heading#Sub, short idsThe same
check verdictsReference behaviorSame findings on the 3 projects it is tested on
Commandslocate, section, refs, check, expand, search, reindex, gen, init, hook, mcp, configlocate, section, refs, check, expand, search, reindex, gen, init, hook, mcp, plus cypher, edges, export, import
Code annotations@lat: plain links@lat: plus @tg: typed, signed edges with properties
QueryingLocate by name, refs, searchAll of those, plus openCypher over sections and code
Code symbolsTree-sitter grammars: TS, TSX, JS, JSX, Python, Rust, Go, CRegex finders: TS/JS (also .mts .cts .mjs .cjs), Python, Go, Rust, C
SearchSemantic: a local offline model or a hosted API keyLexical by default, no model; optional Ollama or OpenAI-compatible embeddings
AgentsClaude Code, Cursor, plus Pi and OpenCode templatesClaude Code, Cursor, AGENTS.md
MCP tools6 (locate, section, search, expand, check, refs)8 (the same plus cypher and edges)
ObsidianFolder opens as plain MarkdownPlugin resolves lat ids on click, shows diagnostics, draws code nodes in the graph
Move content between formatsNo equivalentexport (lossy, with a report) and import
Installnpm package with tree-sitter grammars and a database client as dependenciesOne bundled file, no runtime dependencies
check on this repositoryabout 0.38 sabout 0.17 s

The timing is one machine, warm caches, this repository's own lat.md/. Treat it as an order of magnitude, not a benchmark.

What tg adds

Typed edges from code

A lat.md reference says that this function relates to that section. A @tg: edge says how:

// @tg: implements:: [[auth#Token expiry]] {since: 2}
// @tg: -contradicts:: [[design#Stateless sessions]]

Types, a negative sign and properties give you something to filter and count. Plain @lat: comments keep working, and a bare @tg: [[x]] is the same thing.

A query language over docs and code

Because sections and code symbols are graph nodes, questions that need several greps become one query:

tg cypher "MATCH (c:CodeSymbol)-[:implements]->(s:Section)
           RETURN s.title, count(c) AS functions
           ORDER BY functions DESC"

Which design sections have no implementation, which are implemented by many functions, which docs nothing links to. The engine is the one inside the Obsidian plugin, so the same queries run in both places.

Search with no setup

lat.md can search semantically, with a local model or an API key. tg search starts one step earlier: a lexical index with no model to download and no key to set, which is enough for a docs folder of a few hundred sections and safe to run inside a prompt hook. Embeddings are an option, not a requirement, and a provider outage degrades to lexical results rather than an error. The LAT_LLM_KEY variables are accepted as aliases.

Obsidian and interchange

If your notes live in Obsidian, the plugin makes a lat.md/ folder in your vault navigable and checkable in place. tg export turns a vault into a lat.md folder that both tools accept. Typed edges and properties have no lat.md equivalent, so export flattens them and tells you what it dropped; it does not claim a lossless round trip.

Safer setup

tg init prints a diff and writes nothing until you pass --write. Moving from lat.md is explicit: --migrate replaces the lat block, hooks and MCP entry, and leaves everything else in your files byte-for-byte as it was.

Where lat.md is better

The deliberate differences

tg accepts .mts, .cts, .mjs and .cjs as source links, which lat.md reports as unresolved. That is the only intentional difference in check verdicts, and the parity test normalizes it. Everything else the test compares has to match: on the upstream lat.md project snapshot, which has 231 findings, both tools report the same set.

Which should you use

Switching in four commands

npm install -g @typedgraph/cli
tg check                       # should match lat check
tg init                        # dry run: see the diff
tg init --write --migrate      # swap the lat block, hooks and MCP entry

Your lat.md/ folder and @lat: comments stay as they are. If something differs from lat.md that is not on the list above, that is a bug, and the issue tracker is the place for it.