Expand description
§toolpath-claude
Derive Toolpath provenance documents from Claude conversation logs.
When Claude Code writes your code, the conversation — the reasoning, the tool calls, the abandoned approaches — is the provenance. This crate reads those conversations directly and maps them to Toolpath documents so every AI-assisted change has a traceable origin.
§Overview
Reads Claude Code conversation data from ~/.claude/projects/ and provides:
- Conversation reading: Parse JSONL conversation files into typed structures
- Query: Filter and search conversation entries by role, tool use, text content
- Derivation: Map conversations to Toolpath Path documents
- Watching: Monitor conversation files for live updates (feature-gated)
§Derivation
Convert Claude conversations into Toolpath documents:
use toolpath_claude::{ClaudeConvo, derive::{DeriveConfig, derive_path}};
let manager = ClaudeConvo::new();
let convo = manager.read_conversation("/Users/alex/project", "session-uuid")?;
let config = DeriveConfig::default();
let path = derive_path(&convo, &config);§Mapping
| Claude concept | Toolpath concept |
|---|---|
| Session (JSONL file) | Path |
| Project path | path.base.uri as file:///... |
| User message | Step with actor: "human:user" |
| Assistant message | Step with actor: "agent:{model}" |
| Tool use (Write/Edit) | change entry keyed by file path |
| Assistant text | meta.intent |
| Sidechain entries | Steps parented to branch point |
§Reading conversations
use toolpath_claude::ClaudeConvo;
let manager = ClaudeConvo::new();
// List projects
let projects = manager.list_projects()?;
// Read a conversation
let convo = manager.read_conversation("/Users/alex/project", "session-uuid")?;
println!("{} entries", convo.entries.len());
// Most recent conversation
let latest = manager.most_recent_conversation("/Users/alex/project")?;
// Search
let matches = manager.find_conversations_with_text("/Users/alex/project", "authentication")?;§Querying
ⓘ
use toolpath_claude::{ConversationQuery, MessageRole};
let query = ConversationQuery::new(&convo);
let user_msgs = query.by_role(MessageRole::User);
let tool_uses = query.tool_uses_by_name("Write");
let errors = query.errors();
let matches = query.contains_text("authentication");§Watching
With the watcher feature (enabled by default):
ⓘ
use toolpath_claude::{AsyncConversationWatcher, WatcherConfig};
let config = WatcherConfig::new("/Users/alex/project", "session-uuid");
let mut watcher = AsyncConversationWatcher::new(config)?;
let handle = watcher.start().await?;
// New entries arrive via the handle
while let Some(entries) = handle.recv().await {
for entry in entries {
println!("{}: {:?}", entry.uuid, entry.message);
}
}§Feature flags
| Feature | Default | Description |
|---|---|---|
watcher | yes | Filesystem watching via notify + tokio |
§Part of Toolpath
This crate is part of the Toolpath workspace. See also:
toolpath– core types and query APItoolpath-git– derive from git historytoolpath-dot– Graphviz DOT renderingtoolpath-cli– unified CLI (cargo install toolpath-cli)- RFC – full format specification
Re-exports§
pub use async_watcher::AsyncConversationWatcher;pub use async_watcher::WatcherConfig;pub use async_watcher::WatcherHandle;pub use error::ConvoError;pub use error::Result;pub use io::ConvoIO;pub use paths::PathResolver;pub use query::ConversationQuery;pub use query::HistoryQuery;pub use reader::ConversationReader;pub use types::CacheCreation;pub use types::ContentPart;pub use types::Conversation;pub use types::ConversationEntry;pub use types::ConversationMetadata;pub use types::HistoryEntry;pub use types::Message;pub use types::MessageContent;pub use types::MessageRole;pub use types::ToolResultContent;pub use types::Usage;pub use watcher::ConversationWatcher;
Modules§
- async_
watcher - Async Conversation Watcher
- derive
- Derive Toolpath documents from Claude conversation logs.
- error
- io
- paths
- query
- reader
- types
- watcher
- Conversation watching/tailing functionality.
Structs§
- Claude
Convo - High-level interface for reading Claude conversations.