Skip to content

Latest commit

 

History

236 Commits

Folders and files

Repository files navigation

Desire Path: stepping stones turn friction into a useful route, in the shared Thread Workshop illustration style

Desire Path

Desire Path

👣 Find the tool calls your agents get wrong, and turn repeats into fixes.

License: Apache-2.0 CI Quipu stack

Desire Path (dp) is a CLI and a set of agent hooks for developers who want fewer repeated tool-call failures. It stores calls locally, ranks recurring failures, and records mappings from mistaken tool names to real ones. The name comes from the trails people wear through grass: evidence of where a path is needed.

Why you would want it

  • Find recurring friction: rank failed tool calls rather than guessing what to fix.
  • Record the intended tool: keep explicit mappings from mistaken names to real tools.
  • Inspect calls locally: collect and query failures without a Quipu server.

The Desire Path book explains ingestion, analysis and agent integration.

Install

curl -fsSL https://raw.githubusercontent.com/scbrown/desire-path/main/install.sh | sh

Python 3.9+, curl, and a Linux or macOS shell. Downloads the latest published archive, verifies SHA-256 and the executable version before publishing command links in ~/.local/bin. Add it to PATH. The complete versioned bundle stays in ~/.local/lib/desire-path/TAG for rollback. Published targets: Linux and macOS, x86_64 and arm64.

Set STACK_INSTALL_ROOT on the receiving shell for another prefix. Pinned releases, alternatives, configuration and removal are in the installation and usage reference.

First success in three commands

Animated terminal: collect a failed call and add operator-authored guidance

A synthetic failure is collected in a local database; the operator writes the correction. Read the transcript or reproduce the recording.

Use a temporary database and one synthetic failed call; Python 3 formats the result:

DP_DEMO=$(mktemp -d)
printf '%s\n' '{"tool_name":"read_file","error":"unknown tool","session_id":"demo"}' | dp --db "$DP_DEMO/desires.db" ingest --source claude-code --json > "$DP_DEMO/record.json"
dp --db "$DP_DEMO/desires.db" paths --json | python3 -c 'import json,sys; p=json.load(sys.stdin)[0]; print(p["pattern"], p["count"])'

Expected stdout:

read_file 1

The failure became a queryable pattern without configuring an agent or touching your usual database. An optional-metrics diagnostic may also appear on stderr; see troubleshooting.

On your own data

After your agent has recorded calls:

question command
Which failures repeat? dp paths --top 5
What happened for this tool? dp inspect read_file
What tool might have been intended? dp similar read_file
How do I record the intended mapping? dp alias read_file Read
How do I export the failures? dp export --format json

An alias records a mapping. Active interception is a separate pave setup. See the CLI reference for flags and all commands.

Bounded failure-family measurements

Repeated failures can be measured with dp failure-families --since <RFC3339> --until <RFC3339> --window 1h --max-records 10000 --json. It groups by tool, parsed shell command-program shape and a bounded error class; compound commands are grouped as programs, without claiming which subcommand failed. Argument values, paths and error messages are absent from output. Unsupported wrappers and dynamic command identities are counted separately as UNKNOWN. Synthetic turn-pattern observations are excluded. peak_window measures the historical rolling maximum; current_window measures the window ending at --until. These are observations, not an alerting policy or a claim of complete capture.

--max-records defaults to 10000 and accepts 1 through 100000. The store query loads at most the cap plus one sentinel; overflow returns an error without partial counts. Future records after --until conservatively consume this candidate cap because the existing store selector bounds only --since. JSON also identifies the exact since/until, max_records, input_records and complete: true. Complete means the candidate inventory fit the cap, not that normalization or failure capture was complete: consumers must still inspect unknown and excluded. Nonzero counts also include fixed-key unknown_by_reason (invalid_tool_name, unsupported_command_shape) and excluded_by_reason (turn_pattern) maps. These are coarse parser branches, not individual commands or a reason to treat unsupported records as normalized. Older reports omit them; their unsupported kinds cannot be recovered from aggregate totals alone. A record cap bounds materialized rows, not total input bytes or query latency. Prefer one current window for scheduled threshold evaluation; a historical report requires its own bounded read-cost admission.

Local failure-families reads require an existing database at the current schema version. The command opens it read-only: missing databases and schema mismatches return an error without creating a store or migrating it. Configured remote stores continue to use their existing read API.

Wire it into your agent

For Claude Code, with dp on the agent's PATH:

dp init --source claude-code
dp sources

The installer merges hooks into ~/.claude/settings.json. It installs ingestion for successes and failures, plus signposting and correction hooks. Review that file after installation. Using agents explains the installed hooks and the Codex, Cursor, and Kiro source plugins.

Start agent orientation with dp prime (--brief, --json, or --static). It reads existing state without initializing a database or installing hooks. See the agent primer and Desire Path skill.

Before you start

The shell installer needs Python 3.9+, curl and Linux or macOS. The example needs a Bash-compatible shell and Python 3; source builds need Go 1.24+. Calls are stored locally by default. Review hook settings and captured data before enabling an agent integration. A recorded alias and active interception are separate capabilities.

What's next

Related tools and repository knowledge

Load this repository’s graph: public repository-pendant assets have not yet been verified. When a release supplies the archive, checksum and provenance, follow the verified import workflow: extract the share directory and use quipu import SHARE_DIR --db repository.db. Import stages knowledge; ROOT stays unchanged.

🧺 The stack

The Quipu stack is built around a governed, bitemporal knowledge store: shared facts, decisions and work history your agents can query. Quipu can check writes against your rules, records where each fact came from, and answers what was true when.

tool what it gives your agents
tambo 🧰 Agent Platform Toolkit - installs and configures the quipu stack
quipu stores shared facts with provenance and history; can check writes against your rules
camayoc prepares knowledge and vocabulary for Quipu, with checks before it is admitted
quechua shared vocabulary and shapes for interoperable knowledge
chaski reacts to graph changes and delivers governed notifications
bobbin indexes your codebase and injects context from that index and Quipu knowledge
yupana shows code impact and can read policies from Quipu to govern agent actions
desire-path turns agent mistakes into feature requests; works on its own without Quipu
seeds a work item tracker backed by the Quipu knowledge base
shantytown runs crews of AI agents on work items, triggered by hand, on a schedule or by events; can share work and memory through Quipu
rikuy live brief: status, graphs, watches and signed decisions over Quipu
shuttle runs signed agent workflows and keeps their records in Quipu

Contributing

From a checkout, with just, Go, Python 3, pre-commit, and mdBook installed:

just build
just test
just check

See the development guide.

📜 License

Apache-2.0.

Releases

Packages

Contributors

Languages