Crates

Toolpath is a Rust workspace of focused, composable crates. The core crate has zero dependencies beyond serde; satellite crates add derivation sources and rendering.

toolpath-cli (binary: path)
 +-- toolpath           (core types)
 +-- toolpath-git     -> toolpath
 +-- toolpath-claude  -> toolpath
 +-- toolpath-dot     -> toolpath

No cross-dependencies between satellite crates. toolpath is the sole shared foundation.

toolpath

v0.1.3

Core types, builders, and query API

The gravity well. All other crates depend on this; it depends on nothing except serde. Defines Step, Path, Graph, and the query functions to traverse them.

toolpath-git

v0.1.2

Derive from git repository history

Reads git history via libgit2 and maps commits to Steps, branches to Paths. Single branch produces a Path; multiple branches produce a Graph.

toolpath-claude

v0.1.2

Derive from Claude conversation logs

Reads Claude Code conversation data from ~/.claude/projects/ and maps messages, tool calls, and abandoned approaches to Toolpath documents.

toolpath-dot

v0.1.2

Graphviz DOT visualization

Renders any Toolpath Document as a Graphviz diagram. Steps are color-coded by actor type, dead ends get red dashed borders, and the DAG structure is preserved visually.

toolpath-cli

v0.1.2

Unified CLI (binary: path)

One binary called `path` that ties everything together: derive, query, render, merge, track, validate.

Using the libraries

Core types

use toolpath::v1::{Step, Path, Base, Document};

let step = Step::new("step-001", "human:alex", "2026-01-29T10:00:00Z")
    .with_parent("step-000")
    .with_raw_change("src/main.rs", "@@ -1,1 +1,1 @@\n-hello\n+world")
    .with_intent("Fix greeting");

let path = Path::new(
    "path-pr-42",
    Some(Base::vcs("github:org/repo", "abc123")),
    "step-001",
);

Query operations

use toolpath::v1::query;

let ancestors = query::ancestors(&path.steps, &path.path.head);
let dead_ends = query::dead_ends(&path.steps, &path.path.head);
let by_actor = query::filter_by_actor(&path.steps, "agent:");
let artifacts = query::all_artifacts(&path.steps);

Git derivation

use toolpath_git::{derive, DeriveConfig};

let repo = git2::Repository::open(".")?;
let config = DeriveConfig {
    remote: "origin".into(),
    title: None,
    base: None,
};
let doc = derive(&repo, &["main".into()], &config)?;

DOT rendering

use toolpath::v1::Document;
use toolpath_dot::{render, RenderOptions};

let dot_string = render(&doc, &RenderOptions::default());
// Pipe through `dot -Tpng` for an image