An Agent Skill and zero-dependency CLI for source-grounded, interactive evidence maps.
Try the zero-install playground → · Test Agent Skills portability → · Take the map-vs-memo study → · Bring a contested question →
AI research tools usually end with prose. Prose is good at sounding settled: support and contradiction blur together, missing evidence becomes a footnote, and a citation may merely mention the topic.
Doubt produces a different artifact:
- one falsifiable question and one provisional position;
- atomic claims, sourced observations, and explicit unknowns;
- typed
supports,contradicts,qualifies, andmissingedges; - a dated URL or local path, retrieval date, plus a section, page, timestamp, or line locator for every evidence node;
- one self-contained HTML file that stays inspectable without an account, server, or CDN.
Open the local-only Doubt playground →
Paste or drop a .doubt.json file to run the same evidence-contract module used
by the CLI, inspect exact findings, preview the interactive map, and download
portable JSON or HTML. Copy a share link to let another reader inspect the same
map without an upload: the payload lives in the URL fragment, which browsers do
not send in the HTTP request. Validation, SHA-256 receipts, rendering, and
downloads run in the tab; map content is never submitted over the network.
- Are Agent Skills actually portable? — one conservative core works across Claude Code, Codex, Copilot, Cursor, and Gemini CLI, but discovery paths, invocation, consent, permissions, metadata, and distribution still require per-host testing.
- Agent Skills vs MCP — when a capability should be reusable procedure, a live protocol boundary, or both. Built from the Agent Skills specification, GitHub's implementation, the discovery RFC, and the current MCP architecture and security guidance.
All maps are committed as editable .doubt.json, validated with the same
evidence contract, and rendered as self-contained HTML.
npx doubt-ai demo --out doubt-demo.htmlThe public package is doubt-ai; the
CLI has zero runtime dependencies and requires Node.js 18 or newer.
The command renders a current architecture decision from official Agent Skills, GitHub, and MCP sources:
Should an AI capability be an Agent Skill, an MCP server, or both?
Open doubt-demo.html to read the linear brief, switch to the reasoning graph,
and inspect exact source regions. The canonical editable input is
plain JSON; the generated
self-contained HTML has no runtime
dependencies.
Install directly from GitHub with GitHub CLI 2.90 or later:
gh skill install alsoleg89/doubt doubtOr use the open Agent Skills installer for Codex, Claude Code, Copilot, Cursor, Gemini CLI, and other compatible clients:
npx skills add alsoleg89/doubt --skill doubtOr install the portable skill into every supported local agent:
npx doubt-ai init --agent allThen ask:
Use $doubt to map whether we should replace our current auth provider.
Preserve contrary evidence and show the exact source region behind every edge.
The skill works with Claude Code, Codex, GitHub Copilot, Cursor, Gemini CLI, and clients that support the open Agent Skills layout. It uses the research and browsing capabilities the agent already has; Doubt does not proxy prompts or require a model key. The checked-in remote-install skill and GitHub project skill are byte-verified against the canonical install payload on every CI run.
The installed skill carries the same deterministic evidence contract as the
package in scripts/validate.mjs. An agent can validate and obtain the real
receipt with Node.js 18+ even when its sandbox cannot reach npm. The skill
explicitly forbids substituting a file hash, node count, or JSON parse check for
a successful Doubt receipt.
Compatible remote clients can also discover a digest-pinned archive through the Agent Skills well-known index.
npx doubt-ai validate decision.doubt.json
npx doubt-ai map decision.doubt.json --out decision.htmlVALID ccfb781d43c6
✓ 3 claims · 5 evidence · 5 sources
↯ 2 contradictions · 1 explicit unknowns
map /path/to/decision.html
Validation fails closed when:
- evidence has no source;
- a source has no valid publication/retrieval date, safe location, bounded locator, or substantive excerpt;
- evidence or sources are decorative and unused;
- an edge is duplicated, cyclic, points to a missing node, or lacks a reasoning note;
- any reasoning node lacks a directed path to the position;
- the position has no incoming support, contradiction, qualification, or gap;
- a map invents unsupported confidence percentages.
Each valid map receives a SHA-256 receipt over the canonicalized reasoning
record plus explicit hashes of every recorded excerpt and its retrievedAt
value. The receipt proves what the map recorded and when it says the source was
retrieved; it does not prove that a mutable URL still serves those same bytes.
Add one reusable Action to validate every *.doubt.json file in a repository:
name: Evidence contract
on: [push, pull_request]
jobs:
doubt:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: alsoleg89/doubt@v0.8.0The Action fails the check with file-level annotations and writes receipts, claim/evidence counts, and every violated invariant to the job summary. It uses the checked-in validator directly—no package install, model key, account, or network call.
Known negative fixtures can remain committed without weakening the gate:
- uses: alsoleg89/doubt@v0.8.0
with:
exclude: benchmarks/expected-failuresnpm run benchmarkThe published evidence-contract report mutates the dogfood map to introduce unsourced evidence, malformed dates, missing or unbounded locators, thin, oversized, and repeated-filler excerpts, dangling and duplicate edges, disconnected subgraphs, cycles, invented confidence, decorative sources, an unsupported position, and embedded markup. Every case names the invariant that must fire.
This benchmark measures structural traceability and safe rendering. It does not pretend to measure whether a source is true or whether an AI extracted it faithfully.
The public portability map identifies a missing edge: documentation shows a shared Agent Skills core, but not identical behavior across clients. The five-client benchmark kit fixes one synthetic fixture, one unchanged skill, and direct, implicit, and negative prompts for Claude Code, Codex, GitHub Copilot, Cursor, and Gemini CLI.
npm run benchmark:portabilityResults require exact client versions, relevant configuration, sanitized raw output, generated artifacts, and receipts. A contributor can submit one client; failures and blocked runs are valid evidence. The first submitted result is GitHub Copilot CLI 1.0.77: direct pass, implicit fail, and negative pass. The failure is preserved with its artifact and raw transcript; even though v0.6 now accepts its absolute local paths, the agent never ran or reported the required validation, so the historical run is not relabeled as a pass.
The Codex CLI result preserves a more useful before/after. With the old skill,
direct and implicit activation both failed because npx doubt-ai could not
reach npm from a network-disabled sandbox; both final answers then falsely
claimed validation. With the exact validator bundled in the skill, the same
client, model, fixture, prompts, and sandbox produced independently verified
receipts: direct pass, implicit pass, negative pass. See the
historical failure
and fixed-skill rerun.
One client may not claim cross-client behavioral equivalence.
Run a remaining client →: Claude Code, Codex result, GitHub Copilot result, Cursor, or Gemini CLI.
The structural benchmark does not answer the product question: does an interactive evidence map actually help a reader more than cited prose?
Take the five-topic map-vs-memo study →
The protocol was committed before data collection. Each reader sees five technical decisions, alternating between a Doubt map and a hand-edited cited memo built from the same frozen sources. The study measures position, contradiction, qualification, unknown, and exact source-region recall.
It runs entirely in the browser and downloads one anonymous result JSON. It does not request a name or email and never submits data over the network. The first analysis is locked until ten complete reader sessions; neutral and negative results will be published.
Build or validate the study locally:
npm run benchmark:reader
npm run benchmark:reader:check{
"nodes": [
{
"id": "observed-result",
"type": "evidence",
"label": "Observed result",
"text": "The focused acceptance suite passed.",
"sourceId": "test-run"
}
],
"edges": [
{
"from": "observed-result",
"to": "current-position",
"relation": "supports",
"note": "The suite exercises the promised narrow behavior."
}
],
"sources": [
{
"id": "test-run",
"title": "Acceptance test output",
"url": "./test-output.txt",
"publisher": "Local test runner",
"date": "2026-07-30",
"retrievedAt": "2026-07-30T12:00:00Z",
"locator": "Summary line 42",
"excerpt": "The focused suite completed with 18 passing checks and zero failures."
}
]
}Read the complete map schema and evidence ladder.
| Typical output | What gets lost | Doubt |
|---|---|---|
| Cited prose answer | Disagreement is flattened into a narrative | Keeps contrary and qualifying edges visible |
| Knowledge graph | Related concepts can look like evidence | Requires a plain-language entailment note |
| Argument-map platform | The reasoning lives in an account or database | Canonical JSON plus portable HTML |
| Diagram generator | A beautiful graph can still be unsourced | Refuses evidence without a bounded source region |
| Confidence score | Precision can be invented | Represents the specific unknown instead |
The renderer is deterministic. The AI may propose the map; it cannot make an invalid evidence record pass the validator.
| Command | Purpose |
|---|---|
doubt map <file.json> --out <file.html> |
Validate and render an interactive map |
doubt validate <file.json> |
Check the evidence contract without rendering |
doubt verify <file.json> --out <verified.json> |
Explicitly retrieve each source, match its excerpt, and write an attested map only if all sources pass |
doubt demo --out <file.html> |
Render the included dogfood map |
doubt init --agent all |
Install the map-building skill |
doubt doctor --agent all |
Detect missing or locally modified skill copies |
Existing skills are never overwritten unless --force is passed.
The renderer reads only the JSON file you pass and writes the requested HTML. The installer copies static skill files. No telemetry, background service, remote runtime, model call, or hidden network request is used.
doubt verify is the only network-capable command, and it runs only when you
invoke it explicitly. It sends an HTTP GET to each recorded http(s) source,
blocks localhost and private addresses by default, checks every redirect,
matches the normalized excerpt, and records the retrieved-byte SHA-256. It
never uploads the map or excerpt to Doubt. Local file sources stay local. If
one source is unreachable or mismatched, verification fails closed and no
output map or receipt is written. Page, section, and timestamp locators remain
marked not-machine-checked; line ranges are checked against the selected
lines.
The first live dogfood run rejected Doubt's own flagship example: all five recorded excerpts were paraphrases rather than text present in the cited pages. The example was rewritten with verbatim excerpts and now commits a successful attestation for every source. The portability map does the same for all eight of its sources.
A valid map proves structural traceability, not truth. A verified map adds evidence that its recorded excerpt appeared in the retrieved bytes at one time; it still does not prove that a source is true or correctly interpreted. That is why source regions, edge notes, contradictions, and unknowns remain visible for review.
See SECURITY.md for the threat model.
git clone https://github.com/alsoleg89/doubt.git
cd doubt
npm test
npm run demoDoubt uses Node.js built-ins only. Tests cover schema invariants, content-addressed receipts, self-contained rendering, the CLI, and skill installation.
Contributions are welcome—especially real contested questions, adversarial map fixtures, source-locator adapters, and accessibility improvements. Start with CONTRIBUTING.md.
If an answer matters, make its evidence navigable.