Everything you need to know — from zero to power user.
- What is git-mind?
- Installation
- Your first knowledge graph
- Core concepts
- CLI reference
- Views
- Importing graphs from YAML
- Commit directives
- Time-travel with
git mind at - Comparing graph snapshots
- Using git-mind as a library
- Appendix A: How it works under the hood
- Appendix B: Edge types reference
git-mind adds a semantic knowledge graph to any Git repository. You create nodes (files, concepts, tasks, modules — anything) and connect them with typed edges (implements, depends-on, documents, etc.). The graph lives inside Git — no external databases, no servers.
Why?
Code tells a computer what to do. Comments tell a human what the code does. But neither captures why things are connected — which spec does this file implement? What does this module depend on? What task does this commit address?
git-mind captures those relationships explicitly, so you can query them, visualize them, and watch them evolve with your code.
What makes it different?
- Git-native — Your graph is versioned alongside your code. Use
git mind atto see the graph at any historical point. - Conflict-free — Built on CRDTs, so multiple people can add edges simultaneously without conflicts.
- Branch and merge — Try experimental connections in a branch, merge what works.
- No setup — No database to run. No config files. Just
git mind init.
git clone https://github.com/neuroglyph/git-mind.git
cd git-mind
npm installgit-mind depends on @git-stunts/git-warp, which is currently installed from a local path. See CONTRIBUTING.md for development setup details.
node bin/git-mind.js --helpYou should see the help text with available commands.
Let's walk through building a knowledge graph from scratch.
Navigate to any Git repository and initialize git-mind:
cd /path/to/your/repo
npx git-mind init
# ✔ Initialized git-mind graphThis creates a WARP graph stored inside Git's ref system. It's invisible to normal Git operations — your working tree stays clean.
Let's say your repo has a spec document and an implementation:
# This file implements that spec
npx git-mind link file:src/auth.js spec:auth --type implements
# These two modules are related
npx git-mind link module:cache module:db --type depends-on
# This test documents the expected behavior
npx git-mind link file:test/auth.test.js file:src/auth.js --type documentsEach link command creates an edge between two nodes. If the nodes don't exist yet, they're created automatically. Node IDs must use the prefix:identifier format.
npx git-mind list
# ℹ 3 edge(s):
# file:src/auth.js --[implements]--> spec:auth (100%)
# module:cache --[depends-on]--> module:db (100%)
# file:test/auth.test.js --[documents]--> file:src/auth.js (100%)npx git-mind view architecture
# Shows only module/crate/pkg nodes and depends-on edges
npx git-mind view roadmap
# Shows only phase/task nodes and their relationshipsYour knowledge graph is stored in Git. It persists across clones (once pushed), branches, and merges. No cleanup needed.
A node ID follows the prefix:identifier format. The prefix is always lowercase, and the identifier can contain letters, digits, dots, slashes, @, and hyphens. See GRAPH_SCHEMA.md for the full grammar.
| Prefix | Meaning | Example |
|---|---|---|
file: |
File path | file:src/auth.js |
module: |
Software module | module:authentication |
task: |
Work item | task:implement-oauth |
phase: |
Project phase | phase:beta |
commit: |
Git commit (system-generated) | commit:abc123 |
concept: |
Abstract idea | concept:zero-trust |
milestone: |
Major project phase | milestone:BEDROCK |
feature: |
Feature grouping | feature:BDK-SCHEMA |
spec: |
Specification document | spec:graph-schema |
Unknown prefixes produce a warning but are allowed — this lets the taxonomy grow organically. See the full prefix list in GRAPH_SCHEMA.md.
Nodes are created implicitly when you create an edge referencing them. You don't need to declare nodes separately.
An edge is a directed, typed, scored connection between two nodes.
source --[type]--> target
Every edge has:
- type — One of the 8 defined edge types (see Appendix B)
- confidence — A score from 0.0 to 1.0. Human-created edges default to 1.0. AI suggestions start low.
- createdAt — ISO timestamp of when the edge was created
- rationale — Optional text explaining why the edge exists
Confidence answers the question: how sure are we about this connection?
| Score | Meaning | Typical source |
|---|---|---|
| 1.0 | Verified by a human | Manual git mind link |
| 0.8 | High confidence, not reviewed | Commit directive (auto-created) |
| 0.3–0.5 | Suggestion | AI-generated (future feature) |
| 0.0 | Unknown/untrusted | Should be reviewed or removed |
Views are filtered projections of the graph. Instead of looking at every node and edge, a view shows you only what's relevant to a particular question.
git-mind ships with built-in views:
- roadmap — Phase and task nodes
- architecture — Module nodes and dependency edges
- backlog — Task nodes and their relationships
- suggestions — Low-confidence edges that need review
- progress — Task/feature completion grouped by
statusproperty
You can also define custom views programmatically (see Using git-mind as a library).
Initialize a git-mind knowledge graph in the current repository.
git mind initSafe to run multiple times — initialization is idempotent.
Create a semantic edge between two nodes.
git mind link file:src/auth.js spec:auth --type implements
git mind link module:a module:b --type depends-on --confidence 0.9Flags:
| Flag | Default | Description |
|---|---|---|
--type <type> |
relates-to |
Edge type |
--confidence <n> |
1.0 |
Confidence score (0.0–1.0) |
Show all edges in the graph, optionally filtered.
git mind list
git mind list --type implements
git mind list --source file:src/auth.js
git mind list --target spec:authFlags:
| Flag | Description |
|---|---|
--type <type> |
Filter by edge type |
--source <node> |
Filter by source node |
--target <node> |
Filter by target node |
List and inspect nodes in the graph.
git mind nodes # list all nodes
git mind nodes --prefix task # list only task:* nodes
git mind nodes --id task:auth # show details for one node
git mind nodes --json # JSON outputFlags:
| Flag | Description |
|---|---|
--prefix <prefix> |
Filter by prefix (e.g. task, spec, module) |
--id <nodeId> |
Show details for a single node (prefix classification, properties) |
--json |
Output as JSON |
Set a property on a node.
git mind set task:BDK-001 status done
git mind set task:BDK-001 status done --jsonReturns changed: true on first set, changed: false if the value is already set to the same thing (idempotent). The --json output includes the previous value for audit trails. git mind set treats <value> as a string in CLI usage.
Flags:
| Flag | Description |
|---|---|
--json |
Output as JSON (includes previous, changed) |
Remove a property from a node.
git mind unset task:BDK-001 status
git mind unset task:BDK-001 status --jsonReturns removed: true if the property was set, removed: false if it wasn't.
Flags:
| Flag | Description |
|---|---|
--json |
Output as JSON (includes previous, removed) |
Show a health dashboard for the graph.
git mind status
git mind status --jsonDisplays:
- Node counts by prefix (with percentages)
- Edge counts by type
- Health indicators — blocked items, low-confidence edges (< 0.5), orphan nodes (0 edges)
The --json flag outputs a structured object suitable for CI pipelines.
Import a YAML graph file.
git mind import graph.yaml # import
git mind import graph.yaml --dry-run # validate without writing
git mind import graph.yaml --json # structured outputFlags:
| Flag | Description |
|---|---|
--dry-run |
Validate the file and report what would be imported, without writing |
--validate |
Alias for --dry-run |
--json |
Output as JSON |
See Importing graphs from YAML for the file format.
Render a named view, or list available views.
git mind view # list available views
git mind view roadmap # render the roadmap view
git mind view architecture # render the architecture view
git mind view progress --json # structured JSON output
git mind view progress --scope task # only task: nodes
git mind view progress --scope task,feature # explicit defaultFlags:
| Flag | Description |
|---|---|
--scope <prefixes> |
Comma-separated prefix filter (progress view only, default: task,feature) |
--json |
Output as JSON (validated by view-progress.schema.json for the progress view) |
Show the graph at a historical point in time.
git mind at HEAD~50
git mind at v1.0.0
git mind at abc123 --jsonResolves the ref to a commit SHA, finds the epoch marker (or nearest ancestor), and materializes the graph at that Lamport tick. See Time-travel with git mind at for details.
Flags:
| Flag | Description |
|---|---|
--json |
Output as JSON (includes epoch metadata) |
Compare the knowledge graph between two commits.
git mind diff HEAD~10..HEAD # range syntax
git mind diff abc1234 def5678 # two-arg syntax
git mind diff HEAD~10 # shorthand for HEAD~10..HEAD
git mind diff HEAD~5..HEAD --prefix task # scope to task: nodes
git mind diff HEAD~5..HEAD --json # structured outputFlags:
| Flag | Description |
|---|---|
--json |
Output as JSON (includes schemaVersion for compatibility) |
--prefix <prefix> |
Only include nodes with this prefix (edges must have both endpoints matching) |
See Comparing graph snapshots for details.
Generate AI-powered edge suggestions based on recent code changes.
git mind suggest
git mind suggest --agent "my-agent-cmd" --context HEAD~5..HEAD --jsonReview pending AI suggestions interactively or in batch.
git mind review # interactive mode
git mind review --batch accept # accept all pending
git mind review --batch reject # reject all pending
git mind review --json # list pending as JSONShow usage information.
git mind --helpShows nodes with phase: or task: prefixes and their connecting edges.
git mind link phase:alpha task:build-cli --type blocks
git mind link task:build-cli task:write-tests --type blocks
git mind view roadmapShows nodes with module:, crate:, or pkg: prefixes and depends-on edges between them.
git mind link module:auth module:db --type depends-on
git mind link module:api module:auth --type depends-on
git mind view architectureShows all task: nodes and their relationships.
Shows edges with confidence below 0.5 — connections that need human review.
Groups task: and feature: nodes by their status property. Shows completion percentage.
git mind set task:auth status done
git mind set task:deploy status in-progress
git mind view progress
# Progress: 50% (1/2 done)
#
# done 1
# in-progress 1
# todo 0
# blocked 0
# unknown 0Use --scope to narrow which prefixes count as work items:
git mind view progress --scope task # only task: nodes
git mind view progress --scope task,feature # default behaviorUse --json for structured output (includes ratio and remaining in summary):
git mind view progress --json
# { "meta": { "summary": { "ratio": "1/2", "remaining": 1, ... } } }Canonical status values: todo, in-progress, blocked, done
Status values are normalized on read — Done, DONE, complete, finished all map to done. WIP, in_progress, inprogress all map to in-progress. Unrecognized values appear as unknown.
import { defineView, renderView, loadGraph } from '@neuroglyph/git-mind';
defineView('my-view', (nodes, edges) => ({
nodes: nodes.filter(n => n.startsWith('feature:')),
edges: edges.filter(e => e.label === 'implements'),
}));
const graph = await loadGraph('.');
const result = await renderView(graph, 'my-view');
console.log(result);For bulk ingestion, git-mind supports a YAML import format. This is useful for bootstrapping a graph from existing documentation, seeding a project template, or sharing graph snapshots.
version: 1
nodes:
- id: "spec:auth"
- id: "file:src/auth.js"
properties:
status: active
owner: alice
edges:
- source: "file:src/auth.js"
target: "spec:auth"
type: implements
confidence: 1.0
rationale: "Main auth implementation"Rules:
version: 1is required. Unknown versions produce a hard error.nodesis optional. Each node must have anidfield. Nodes can optionally includeproperties(key/value map).edgesis optional. Each edge requiressource,target, andtype.confidencedefaults to 1.0.rationaleis optional.- Reference validation — every edge endpoint must be declared in the
nodesarray or already exist in the graph. Dangling references are rejected. - Atomic writes — if any validation fails, nothing is written. It's all-or-nothing.
- Idempotent — importing the same file twice is safe. Nodes merge, edges update.
Validate without writing:
git mind import graph.yaml --dry-run
# ✔ Validation passed
# Would import: 2 node(s), 1 edge(s)import { importFile, loadGraph } from '@neuroglyph/git-mind';
const graph = await loadGraph('.');
const result = await importFile(graph, 'graph.yaml', { dryRun: false });
console.log(result.valid); // true
console.log(result.stats.nodes); // 2
console.log(result.stats.edges); // 1git-mind can automatically create edges from commit messages. Include directives in your commit body:
feat: add OAuth2 login flow
Implements the social login spec with Google and GitHub providers.
IMPLEMENTS: spec:social-login
AUGMENTS: module:auth-basic
RELATES-TO: concept:zero-trust
| Directive | Edge type created |
|---|---|
IMPLEMENTS: |
implements |
AUGMENTS: |
augments |
RELATES-TO: |
relates-to |
BLOCKS: |
blocks |
DEPENDS-ON: |
depends-on |
DOCUMENTS: |
documents |
Edges created from directives get a confidence of 0.8 — high, but flagged as not human-reviewed. The commit SHA is recorded as provenance.
import { processCommit, loadGraph } from '@neuroglyph/git-mind';
const graph = await loadGraph('.');
await processCommit(graph, {
sha: 'abc123def456',
message: 'feat: add login\n\nIMPLEMENTS: spec:auth',
});git-mind records epoch markers as you commit. Each epoch correlates a git commit SHA to a Lamport tick in the CRDT graph, allowing you to materialize the graph at any historical point in time.
Epoch markers are recorded automatically when you use git mind process-commit (either manually or via the post-commit hook). Install the hook to start recording:
git mind install-hooks# See the graph as it was at a specific commit
git mind at HEAD~50
# Use any git ref — branch names, tags, SHAs
git mind at v1.0.0
git mind at abc123
# JSON output (includes epoch metadata)
git mind at HEAD~10 --jsonWhen a commit is processed, git-mind:
- Records the current Lamport tick (the CRDT's logical clock)
- Stores an
epoch:<sha8>node in the graph with the tick, full SHA, and timestamp - These epoch nodes travel with the graph on push/pull/merge — they're part of the CRDT
When you run git mind at <ref>:
- The ref is resolved to a commit SHA
- The epoch node for that SHA is looked up (or the nearest ancestor's epoch)
- The graph is materialized with a ceiling at that tick — only patches with
lamport <= tickare visible - You see the graph exactly as it was at that moment in time
import { loadGraph, getEpochForRef, computeStatus, getCurrentTick, recordEpoch } from '@neuroglyph/git-mind';
const graph = await loadGraph('.');
// Record an epoch for the current commit
const tick = await getCurrentTick(graph);
await recordEpoch(graph, commitSha, tick);
// Time-travel to a ref
const result = await getEpochForRef(graph, '.', 'HEAD~10');
if (result) {
graph._seekCeiling = result.epoch.tick;
await graph.materialize({ ceiling: result.epoch.tick });
const status = await computeStatus(graph);
console.log(status);
}git mind diff shows what changed in your knowledge graph between two commits. It resolves each ref to an epoch marker, materializes the graph at both points in time, and reports the delta.
# Range syntax
git mind diff HEAD~10..HEAD
# Two-arg syntax
git mind diff abc1234 def5678
# Shorthand: ref..HEAD
git mind diff HEAD~10
# Scope to a single prefix
git mind diff HEAD~10..HEAD --prefix task
# JSON output (includes schemaVersion for compatibility)
git mind diff HEAD~10..HEAD --json- Both refs are resolved to commit SHAs
- Each SHA is looked up in the epoch markers (or the nearest ancestor's epoch)
- Two separate graph instances are materialized at those Lamport ticks
- The diff engine compares nodes and edges, reporting additions and removals
System-generated nodes (epoch:, decision:, commit:) are excluded from the diff, matching export behavior.
When --prefix is specified, only nodes with that prefix are included. Edges are included only if both endpoints pass the prefix filter — no partial cross-prefix edges appear in the output.
git mind diff HEAD~5..HEAD --prefix module
# Only shows module:* node changes and edges between module:* nodesAll --json outputs include a standard envelope with schemaVersion (currently 1) and command fields. Breaking changes to any JSON structure will increment schemaVersion, so downstream tools can detect incompatible output.
git mind status --json | jq '.schemaVersion, .command'
# 1
# "status"JSON Schema files for every command are published in docs/contracts/cli/. See the CLI Contracts guide for validation examples and migration notes.
If a ref doesn't have an exact epoch marker, the diff engine walks up the commit ancestry to find the nearest one. When this happens, the TTY output shows a warning icon next to the endpoint.
git-mind exports its core modules for use in scripts and integrations.
import {
// Graph lifecycle
initGraph, loadGraph, saveGraph,
// Edge CRUD
createEdge, queryEdges, removeEdge, EDGE_TYPES,
// Node queries + properties
getNodes, hasNode, getNode, getNodesByPrefix,
setNodeProperty, unsetNodeProperty,
// Status
computeStatus,
// Import
importFile, parseImportFile, validateImportData,
// Validation
validateNodeId, validateEdgeType, validateConfidence, validateEdge,
extractPrefix, classifyPrefix,
NODE_ID_REGEX, NODE_ID_MAX_LENGTH, CANONICAL_PREFIXES, SYSTEM_PREFIXES,
// Views
defineView, renderView, listViews, classifyStatus,
// Hooks
parseDirectives, processCommit,
} from '@neuroglyph/git-mind';// Initialize in a repo (idempotent)
const graph = await initGraph('/path/to/repo');
// Load an existing graph
const graph = await loadGraph('/path/to/repo');
// Checkpoint the graph state
const sha = await saveGraph(graph);// Create — node IDs must use prefix:identifier format
await createEdge(graph, {
source: 'file:src/auth.js',
target: 'spec:auth',
type: 'implements',
confidence: 1.0,
rationale: 'Direct implementation of the spec',
});
// Query
const allEdges = await queryEdges(graph);
const authEdges = await queryEdges(graph, { source: 'file:src/auth.js' });
const implEdges = await queryEdges(graph, { type: 'implements' });
// Remove
await removeEdge(graph, 'file:src/auth.js', 'spec:auth', 'implements');// Get all node IDs
const allNodes = await getNodes(graph);
// Check existence
const exists = await hasNode(graph, 'task:auth');
// Get full node info (prefix classification, properties)
const node = await getNode(graph, 'file:src/auth.js');
// { id: 'file:src/auth.js', prefix: 'file', prefixClass: 'canonical', properties: {} }
// Filter by prefix
const tasks = await getNodesByPrefix(graph, 'task');
// ['task:auth', 'task:login', ...]const status = await computeStatus(graph);
// {
// nodes: { total: 12, byPrefix: { task: 5, spec: 3, ... } },
// edges: { total: 8, byType: { implements: 4, ... } },
// health: { blockedItems: 1, lowConfidence: 2, orphanNodes: 0 }
// }Validators return result objects — they don't throw. Callers decide how to handle errors.
// Validate a node ID
const r = validateNodeId('task:BDK-001'); // { valid: true }
const bad = validateNodeId('bad id'); // { valid: false, error: '...' }
// Validate a full edge (composite — checks everything)
const result = validateEdge('task:X', 'feature:Y', 'implements', 0.8);
// { valid: true, errors: [], warnings: [] }
// Classify a prefix
classifyPrefix('milestone'); // 'canonical'
classifyPrefix('commit'); // 'system'
classifyPrefix('banana'); // 'unknown'// List available views
const views = listViews(); // ['roadmap', 'architecture', 'backlog', 'suggestions']
// Render a view
const result = await renderView(graph, 'architecture');
// { nodes: ['module:auth', 'module:db'], edges: [...] }
// Define a custom view
defineView('unreviewed', (nodes, edges) => ({
nodes: [],
edges: edges.filter(e => e.props?.confidence < 1.0),
}));// Parse directives from a message
const directives = parseDirectives('IMPLEMENTS: spec:auth\nBLOCKS: task:deploy');
// [{ type: 'implements', target: 'spec:auth' }, { type: 'blocks', target: 'task:deploy' }]
// Process a full commit (parse + create edges)
const processed = await processCommit(graph, {
sha: 'abc123',
message: 'feat: login\n\nIMPLEMENTS: spec:auth',
});git-mind stores its graph using git-warp, a CRDT graph database that lives entirely inside Git's object store. Here's how:
Git commits as an append-only log. Every graph mutation (add node, add edge, set property) is a "patch" — a small operation recorded as a Git commit. These commits point to Git's empty tree object (4b825dc...) so they don't create any files in your working directory. They're invisible to git status, git diff, and normal Git operations.
Refs as namespaces. The graph is stored under refs/warp/gitmind/writers/<writerId>. Each writer gets its own ref — there's no contention. Multiple people (or bots) can write to the graph simultaneously without conflicts.
Materialization. To read the graph, git-warp "materializes" it by replaying all patches in causal order. The result is an in-memory graph of nodes, edges, and properties. git-mind sets autoMaterialize: true, so this happens transparently on every query.
The graph uses two CRDT types:
-
OR-Set (Observed-Remove Set) for nodes and edges. If writer A adds a node and writer B removes it concurrently, the add wins (add-wins semantics). Only explicit removals after the latest add take effect.
-
LWW (Last-Writer-Wins) registers for properties. If two writers set the same property simultaneously, the one with the later timestamp wins. This is deterministic — both sides converge to the same value.
This means you can git push and git pull your knowledge graph freely. Merges always converge. No manual conflict resolution needed.
Internally, a patch is a JSON blob committed to Git:
{
"ops": [
{ "op": "addNode", "id": "file:src/auth.js" },
{ "op": "addEdge", "from": "file:src/auth.js", "to": "spec:auth", "label": "implements" },
{ "op": "setProp", "id": "file:src/auth.js", "key": "type", "value": "file" }
],
"writerId": "local",
"tick": 42,
"vv": { "local": 42 }
}Each patch carries a version vector (vv) for causal ordering and a tick (logical clock) for property conflict resolution.
| Operation | Complexity | Notes |
|---|---|---|
| Add node/edge | O(1) | Append-only |
| Materialize | O(P) | P = total patches across all writers |
| Query (after materialize) | O(N) | N = nodes matching the query |
| Checkpoint | O(S) | S = state size; creates a snapshot for faster future loads |
For large graphs, use saveGraph() to create checkpoints. Future materializations replay only patches since the last checkpoint.
refs/
warp/
gitmind/
writers/
local ← your patches (a chain of Git commits)
alice ← another writer's patches
bot ← a CI bot's patches
checkpoints/
latest ← most recent snapshot
All of this is under refs/, not in your working tree. Your .gitmind/ directory (in .gitignore) is for future local caching — it's not used yet.
| Type | Direction | Meaning | Example |
|---|---|---|---|
implements |
source implements target | Code fulfills a spec | file:src/auth.js implements spec:auth |
augments |
source extends target | Enhancement or extension | module:auth-oauth augments module:auth |
relates-to |
source relates to target | General association | doc:README relates-to concept:philosophy |
blocks |
source blocks target | Dependency/ordering (no self-edges) | task:migrate-db blocks task:deploy |
belongs-to |
source is part of target | Membership/containment | file:src/auth.js belongs-to module:security |
consumed-by |
source is consumed by target | Usage relationship | pkg:chalk consumed-by module:format |
depends-on |
source depends on target | Dependency (no self-edges) | module:api depends-on module:auth |
documents |
source documents target | Documentation | doc:api documents module:api |