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-convo     (conversation abstraction)
 +-- toolpath-git     -> toolpath
 +-- toolpath-github  -> toolpath
 +-- toolpath-claude  -> toolpath, toolpath-convo
 +-- toolpath-dot     -> toolpath
 +-- toolpath-md      -> toolpath

No cross-dependencies between satellite crates except toolpath-claude -> toolpath-convo.

toolpath

v0.1.5

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-convo

v0.5.0

Provider-agnostic conversation types and traits

Defines Turn, Role, ConversationView, and the ConversationProvider/ConversationWatcher traits. Provider crates (like toolpath-claude) implement the traits; consumer apps code against them.

toolpath-git

v0.1.3

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-github

v0.2.0

Derive from GitHub pull requests

Reads GitHub PRs via the REST API and maps commits, reviews, comments, and CI checks to Steps. Everything is a Step in the DAG — code changes, review threads, approvals, and CI results.

toolpath-claude

v0.6.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-md

v0.2.0

Markdown rendering for LLM consumption

Renders any Toolpath Document as readable Markdown — a narrative an LLM can reason about. Dead ends are called out explicitly, diffs are included at configurable detail levels, and the output preserves enough anchoring info for an LLM to reference back into the original document.

toolpath-cli

v0.2.1

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

Markdown rendering

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

let md_string = render(&doc, &RenderOptions::default());
// Feed to an LLM for contextual assistance