Words To Data is a tool that let's you and your agents manage the The U.S. Code, the laws that change it, and the court opinions that cite it, as one dataset.
words_to_data is a Rust command and library.
It builds a SQLite dataset from public sources, and it answers questions about that dataset.
The dataset holds the U.S. Code at each release point that you add. It holds the public laws that amend the Code, and it links each amendment to the change that it made. It holds court opinions from CourtListener, by page and paragraph, and it links each U.S.C. citation to the provision that the court cited. It can also hold House roll calls.
Rules build each link from the publisher's markup. No language model writes a link. When the rules cannot place an amendment, the amendment goes on a work list with the reason.
SLEUTH is the official agent skillset for words-to-data. Install it into pi, or have your own agent install it themselves, then ask a question about the law.
You do not need to build a dataset: /sleuth-setup downloads the command and an example dataset.
You need 6 GB of free disk space. You do not need Rust, curl or zstd.
Install pi. The installer also installs Node.js when it is necessary.
curl -fsSL https://pi.dev/install.sh | sh
Install SLEUTH into pi.
pi install git:github.com/wordstodata/sleuth-pi
Start pi. Type /login to connect a model with a subscription or an API key. /sleuth-setup downloads the words_to_data command for your computer (Linux, macOS or Windows) and the example dataset (280 MB, 5.3 GB on disk), and opens the dataset. Then ask a question:
$ pi
/login
/sleuth-setup
# Then type your question:
› Where in the Internal Revenue Code is the new Trump account section, and in which printing of the Code does it first appear?
The session is read-only. SLEUTH finds the section from the words alone, and it shows the evidence.
Then ask more questions, for example:
Each release point of each title is one expression, such as uscode/title_26@2025-07-30. diff and path show what changed between two release points, field by field.
Public laws come from Congress.gov. A rule places each amendment from its address in the bill's markup, the first window after enactment, and the words it quotes. The OLRC's classification tables add a second source.
add-opinions adds cases from CourtListener. Each case keeps its writings (the opinion of the court, concurrences, dissents) with their type and author, and each writing keeps its pages, paragraphs and footnotes, so a pin cite such as 537 U.S. at 459 is a path. Each U.S.C. citation becomes a link from the paragraph that holds it to the subdivision that the court wrote. cases-citing tells you if a cited provision changed after the court filed the opinion.
settle --explain shows the source, the method and its version, the address, the window, and why the rule chose that change. An agent can quote it.
settle records a verdict as its own record. link-amendment records a link that an agent found, and refuses a path that did not change. Nothing is deleted. The newest review stands.
residue lists each amendment that no link names, and the stage and reason where the rule stopped. coverage shows the changes that no amendment explains.
votes shows how the House voted on a bill, counted by party on the date of the vote. The source has no Senate votes, so the dataset holds House roll calls only.
search gives scoped snippets. Lists stop at 20 rows and tell you how many rows they did not show. --work, --at, --path and --bill narrow the output, and --json gives rows for a program.
When the dataset holds no release point for a period, the commands say "out of scope". They do not say "unchanged". declare sets what a dataset is meant to cover, so that "not found" and "out of scope" are different answers.
add-release-points and add-bills add data to a dataset that you have. A grown dataset gives the same links as a new build. All downloads stay in a cache, and --offline reads only the cache.
The crate words-to-data opens a dataset and reads it from your own code. With default-features = false, it leaves out the command line and its dependencies.
Each output below is real. We ran each command with words-to-data 0.6.0 on a dataset that holds the U.S. Code at 5 release points (2025-07-18 to 2026-07-12), 7 bills of the 119th Congress, and 28 court cases. Long output is cut, and "…" shows each cut.
Search one title at one release point. Each result gives its path, its field and a snippet.
words_to_data search law.sqlite "domestic research or experimental" --work uscode/title_26 --at 2026-07-12
…
uscode/title_26@2026-07-12 uscode/title_26/subtitle_A/chapter_1/subchapter_B/part_VI/section_174A [heading] 1 occurrence
Domestic research or experimental expenditures
uscode/title_26@2026-07-12 uscode/title_26/subtitle_A/chapter_1/subchapter_B/part_VI/section_174A/subsection_a [content] 1 occurrence
Notwithstanding section 263, there shall be allowed as a deduction any domestic research or experimental expenditures which are paid or incurred by the taxpayer…
…
12 fields, 12 occurrences
Give a path and two expressions. The output shows each changed field, the old and new text, and the amendment linked to the change.
words_to_data path law.sqlite uscode/title_26/subtitle_A/chapter_1/subchapter_B/part_IX/section_280C/subsection_c/paragraph_1 \
--from uscode/title_26@2025-07-18 --to uscode/title_26@2025-07-30 --exact
PATH: uscode/title_26/subtitle_A/chapter_1/subchapter_B/part_IX/section_280C/subsection_c/paragraph_1
Present in: uscode/title_26@2025-07-18 (1 provision), uscode/title_26@2025-07-30 (1 provision), uscode/title_26@2025-08-14 (1 provision), uscode/title_26@2026-01-23 (1 provision), uscode/title_26@2026-07-12 (1 provision)
Provisions (uscode/title_26@2025-07-18 -> uscode/title_26@2025-07-30) (1):
in both — from position 0, to position 0
chapeau: "If—" -> ""
content: "" -> "The domestic research or experimental expenditures (as defined in section 174A(b)) otherwise taken into account as a deduction or charged to capital account under this chapter shall be reduced by the amount of the credit allowed under section 41(a).\n"
continuation: "the amount chargeable to capital account for the taxable year for such expenses shall be reduced by the amount of such excess." -> ""
Annotations on this path exactly (1):
[Pending] uscode/title_26 2025-07-18 -> 2025-07-30 amend 119-hr-1 amd 15684ad7c34c (conf -, by rule:evidence_matching, address, window and quoted words@6)
(B) Section 280C(c)(1) is amended to read as follows:139 STAT. 192"(1) Reduction.In general.-The dom…
link 7c1690c8ef8f uscode/title_26/subtitle_A/chapter_1/subchapter_B/part_IX/section_280C/subsection_c/paragraph_1 [quoted_words]
OLRC classifications of uscode/title_26/subtitle_A/chapter_1/subchapter_B/part_IX/section_280C (2):
classified by the OLRC from Pub. L. 119-21 §70302(b)(2)(B), amended
classified by the OLRC from Pub. L. 119-21 §70304(b), amended
First find the link on a path. Then settle --explain shows how the rule made it. With --explain alone, settle only reads.
words_to_data annotations law.sqlite --bill 119-hr-1 --path uscode/title_26/subtitle_A/chapter_1/subchapter_B/part_VI/section_174A
[Pending] uscode/title_26 2025-07-18 -> 2025-07-30 insert 119-hr-1 amd 2841e731435d (conf -, by rule:evidence_matching, address, window and quoted words@6)
(a) In General.-Part VI of subchapter B of chapter 1 is amended by inserting after section 174 the f…
link 7cdb05c5323a uscode/title_26/subtitle_A/chapter_1/subchapter_B/part_VI/section_174A [quoted_words]
1 annotation(s)
words_to_data settle law.sqlite --link 7cdb05c5323a --explain
Link 7cdb05c5323a
legislature.amended_by said by rule:evidence_matching
uscode/title_26/subtitle_A/chapter_1/subchapter_B/part_VI/section_174A
-> legislature.amendment:119-hr-1:2841e731435d7fb5b093e5bd6a39be845b1f565418a78949b0d8e0820ac2e62b
How it was made:
Source: rule:evidence_matching
Method: address, window and quoted words@6
Address: /us/usc/t26/s174A, from the bill's markup
Window: uscode/title_26@2025-07-18 to 2025-07-30
the first window after the law's enactment on 2025-07-04 in which something under the
address changed.
Changes under the address: 1
Chosen: by quoted words
the change shows the words the bill quotes: enacted text 1 of 1.
What the object says:
(a) In General.-Part VI of subchapter B of chapter 1 is amended by inserting
after section 174 the following new section:"SEC. 174A. 26 USC 174A.DOMESTIC RESEARCH OR EXPERIMENTAL
EXPENDITURES."(a) Treatment as Expenses.-Notwithstanding section 263, there shall be allowed as a deduction any
…
The provision is new in the window. It is at uscode/title_26@2025-07-30 uscode/title_26/subtitle_A/chapter_1/subchapter_B/part_VI/section_174A.
The words added (19 fields):
section_174A [heading] Domestic research or experimental expenditures
section_174A/subsection_a [heading] Treatment as expenses
…
residue is the work list for a law. It gives the stage where each amendment stopped, and the reason.
words_to_data residue law.sqlite --bill 119-hr-1
121 amendment(s) that no standing link names
55 work
9 address: no level above the clause says what it amends
2 address: no section under amendment was named
…
8 resolve: another amendment's words fit a change under its address as well as its own, and nothing breaks the tie
…
4 resolve: the words it quotes show in none of the 1 change(s) under its address
…
0 linked by the evidence method, and not written: run link-by-evidence
38 not held: the amendment changes something the dataset does not hold
28 quiet: nothing under the address changed after the law's enactment; not work
0 reviewed: no link: a reviewer concluded the amendment has no correct link; not work
Give a citation as a court writes it. For each opinion, cases-citing tells you if the provision changed after the court filed it. For a period with no release point in the dataset, it says "out of scope".
words_to_data cases-citing law.sqlite --cites "26 U.S.C. § 174"
26 U.S.C. § 174 names uscode/title_26
/us/usc/t26/s174 resolves to 1 provision(s)
=== uscode/title_26/subtitle_A/chapter_1/subchapter_B/part_VI/section_174
10 opinion(s) cite it:
…
United Stationers, Inc. v. United States (judicial/case_1527901/opinion_1527901, filed 1997-10-16)
opinion text: courtlistener:opinion/1527901:xml_harvard / ocr@1 / MachineSuggested
cites uscode/title_26/subtitle_A/chapter_1/subchapter_B/part_VI/section_174, from 1 passage(s):
judicial/case_1527901/opinion_1527901/page_1282/paragraph_2 — link ebed0c1162c7 is MachineSuggested, matched "26 U.S.C. § 174"
decided 1997-10-16. The link was resolved in the printing of 2025-07-18, the earliest held: this dataset holds no printing of the law as it stood on 1997-10-16, so that law is out of scope.
wrote the section alone
2025-07-18 → 2025-07-30: CHANGED at uscode/title_26/subtitle_A/chapter_1/subchapter_B/part_VI/section_174; 4 path(s) changed: uscode/title_26/subtitle_A/chapter_1/subchapter_B/part_VI/section_174/subsection_a, uscode/title_26/subtitle_A/chapter_1/subchapter_B/part_VI/section_174/subsection_a/paragraph_2/subparagraph_B, uscode/title_26/subtitle_A/chapter_1/subchapter_B/part_VI/section_174/subsection_b, and 1 more
2025-07-30 → 2025-08-14: unchanged at uscode/title_26/subtitle_A/chapter_1/subchapter_B/part_VI/section_174
2025-08-14 → 2026-01-23: unchanged at uscode/title_26/subtitle_A/chapter_1/subchapter_B/part_VI/section_174
2026-01-23 → 2026-07-12: unchanged at uscode/title_26/subtitle_A/chapter_1/subchapter_B/part_VI/section_174
1997-10-16 → 2025-07-18: OUT OF SCOPE. This dataset holds no printing of the cited work in that period, so it cannot say whether the provision changed in it. It is not a statement that nothing changed.
…
An opinion is stored by page and paragraph, so a pin cite becomes a path. Here, INDOPCO, Inc. v. Commissioner at 503 U.S. 84:
words_to_data search law.sqlite "strictly construed" --work judicial/case_112697
judicial/case_112697@1992-02-26 judicial/case_112697/opinion_112697/page_84/paragraph_1 [content] 1 occurrence
…ssioner
v.
Idaho Power Co.,
418 U. S., at 16. For these reasons, deductions are strictly construed and allowed only “as there is a clear provision therefor.”
Ne…
1 field, 1 occurrence
votes counts each position by party, as held on the date of the vote.
words_to_data votes law.sqlite 119-hr-1
Bill: 119-hr-1
Roll call 190 on 2025-07-03T14:31:00-04:00 — Passed
On Motion to Concur in the Senate Amendment
Democrat Nay 212
Republican Yea 218
Republican Nay 2
SLEUTH (Structured Legal Examination Using Tracked Histories) is a package for the pi coding agent. It answers legal questions from a words-to-data dataset, and it shows the evidence.
w2d_search, w2d_path, w2d_cases_citing and w2d_settle./dataset <path> --write. The agent cannot change which dataset is in use./sleuth-gaps shows the list.Try SLEUTH on a dataset that we built. It is 280 MB to download and 5.3 GB on disk. It holds:
We test SLEUTH with a benchmark of questions in five sets: bills, case law, the Code, seed questions and traps. A trap asks for something that the dataset cannot answer, or tells the agent to break a rule. The benchmark runs SLEUTH on a local model, and a script grades each answer.
Known weak spots: the dataset has no case-to-case links, so SLEUTH cannot answer questions about case history. Some court records hold the words of more than one author, so the agent must read the author from the text.
Any other agent can use the same playbook: give it the words_to_data binary, a dataset, and
docs/agents/working-a-dataset.md.
The example dataset is enough to try SLEUTH. To work on other bills, other printings of the Code, or other cases, build your own dataset. You need approximately 3.5 GB of disk space and a free Congress.gov API key. You need Rust only for the library, or to build the command from source.
The source code, the issues, and the changelog. The latest release is v0.6.1 (2026-10-26).
Get the crate from the Rust package registry. The API documentation is on docs.rs.
How an agent answers a question with evidence, resolves the residue, and reviews links, with the command alone.
CONTEXT.md is the glossary: work, expression, path, link, review. The ADRs record each design decision and its reason.
Send us your questions, feedback, or partnership requests.