p.enthalabs

Words to Data - Your Agent's Favorite Legal Database

Words to Data

- Try it

- Features

- Examples

- SLEUTH

- Build a dataset

- Roadmap

- Docs

- Contact

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.

What It Is

A dataset of the law, with evidence

`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.

Who it is for

- **AI agents** that must answer legal questions from a record, not from memory. Each answer comes with words to quote and an address to check.

- **The people who check those agents.** Each link shows how it was made. A person can confirm or refute it, and the review stays as its own record.

- **Researchers and developers** who need the Code, its changes and their causes as data. They can use the command, the SQLite file, or the Rust library.

Try SLEUTH

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.

[Prompts] /dataset, /report [Extensions] wordstodata/sleuth-pi:w2d-guard.ts, wordstodata/sleuth-pi:w2d-setup.ts, wordstodata/sleuth-pi:w2d-sql.ts, wordstodata/sleuth-pi:w2d.ts Warning: SLEUTH found no words_to_data binary. Run /sleuth-setup to download it and the example dataset. Dataset registered: /home/you/.pi/agent/sleuth/example.sqlite Write access: read-only Where in the Internal Revenue Code is the new Trump account section, and in which printing of the Code does it first appear? The user asks about the "Trump account" section in the Internal Revenue Code — this is likely the "Trump Accounts" for children created by the One Big Beautiful Bill Act (Pub. L. 119-21), 26 U.S.C. § 530D maybe? Let me check the dataset. Let me start by loading the skill and orienting. read ~ ── ⠼ Working ───────────────────────────────────────────────────────────────────────────────────────────────── ──────────────────────────────────────────────────────────────────────────────────────────────────────────────~ 10.2%/98k (auto) local • mediumw2d: example.sqlite

00:00-00:32

Three steps

You need 6 GB of free disk space. You do not need Rust, `curl` or `zstd`.

1. **Install pi.** The installer also installs Node.js when it is necessary.

`curl -fsSL https://pi.dev/install.sh | sh` 2. **Install SLEUTH** into pi.

`pi install git:github.com/wordstodata/sleuth-pi`

3. **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:

- What does 26 U.S.C. § 280C(c)(1) say now, and what did it say before the One Big Beautiful Bill Act changed it?

- In Boeing Co. v. United States, what did Justice Thomas say at 537 U.S. 459, and which Code sections does his dissent cite?

- BMW (US) Holding Corp. v. United States (Court of Federal Claims, August 2026) cites the bonus depreciation rule, 26 U.S.C. § 168(k). Has § 168(k) changed since the decision?

Features

📚

The U.S. Code by Release Point

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.

🔗

Amendments Linked to Changes

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.

⚖️

Case Law Linked to the Code

`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.

🧾

Evidence for Every Link

`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.

✅

Review and Correction

`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.

🧩

A Work List, Not a Guess

`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.

🗳️

House Votes

`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.

🔍

Answers That Fit in Context

`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.

🚧

It Says What It Does Not Know

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.

🌱

Datasets That Grow

`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.

🦀

A Rust Library

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.

What Comes Next

The roadmap shows the work in progress and the work that we plan.

View Full Roadmap

Examples

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.

1. Find a provision from its words

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` #### Output

``` … 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 ```

2. See what changed, and which amendment did it

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

#### Output

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

3. Ask why a link is true

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` #### Output

``` [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` #### Output

``` 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 … ```

4. Find what the rules could not link

`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` #### Output

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

5. Find the cases that cite a section

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"` #### Output

``` 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. … ```

6. Read an opinion by page and paragraph

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` #### Output

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

7. See how the House voted

`votes` counts each position by party, as held on the date of the vote.

`words_to_data votes law.sqlite 119-hr-1` #### Output

``` 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, the Official Agent

SLEUTH (**S**tructured **L**egal **E**xamination **U**sing **T**racked **H**istories) is a package for the pi coding agent. It answers legal questions from a words-to-data dataset, and it shows the evidence.

What it adds to pi

- **A tool for each command**, such as `w2d_search`, `w2d_path`, `w2d_cases_citing` and `w2d_settle`.

- **Four skills** from the words-to-data playbook: answer a question, resolve the residue, review links, and build a dataset.

- **A write gate.** A session is read-only. Only a person can give write access, with `/dataset <path> --write`. The agent cannot change which dataset is in use.

- **A gap list.** When no command answers a question, SLEUTH can use read-only SQL. It records each such case as a gap, and `/sleuth-gaps` shows the list.

The example dataset

Try SLEUTH on a dataset that we built. It is 280 MB to download and 5.3 GB on disk. It holds:

- **The U.S. Code**, every title, at 5 printings: 2025-07-18, 2025-07-30, 2025-08-14, 2026-01-23 and 2026-07-12.

- **7 bills of the 119th Congress**, with their amendments linked to the changes in the Code, and the House roll calls. Two of them are H.R. 1 (Pub. L. 119-21, the One Big Beautiful Bill Act) and S. 1071 (the NDAA for FY2026, Pub. L. 119-60).

- **49 court writings in 28 cases**, with pages, paragraphs, footnotes and their citations of the Code.

How well it works

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.

304 / 314 runs passed (97%), 2 runs per question, 2026-10-26, words_to_data with the code of 0.6.1, graded again with corrected answer keys. 2 of the 10 failed runs stopped on a model-server error

6 agents with only the playbook, the binary and a dataset, answered 4 questions about Pub. L. 119-21 correctly (words-to-data PR #267)

55 → 3 items in the residue of Pub. L. 119-21 after those agents worked it

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.

Build Your Own Dataset

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 command

Download the command, then build a dataset. These steps get two release points of the whole Code and Public Law 119-21, and link the law to the changes that it made.

``` curl -fsSL https://github.com/wordstodata/words-to-data/releases/latest/download/words_to_data-x86_64-unknown-linux-musl.tar.gz | tar xz sudo mv words_to_data /usr/local/bin/ export CONGRESS_API_KEY=<your key>

words_to_data build-dataset law.sqlite --uslm-dates 2025-07-18,2025-07-30 --bills 119-hr-1 words_to_data add-classifications law.sqlite words_to_data link-by-evidence law.sqlite ```

This line is for Linux on x86_64. The releases page has the command for Linux (x86_64 and aarch64), macOS (Apple silicon and Intel) and Windows (x86_64). If you have Rust, `cargo install words-to-data` also installs the command.

To add court opinions, set `COURTLISTENER_API_KEY` and use `add-opinions`. `words_to_data --help` lists each command.

The Rust library

Add the crate to `Cargo.toml`. Then open a dataset and read the annotations on a path.

``` [dependencies] words-to-data = { version = "0.6", default-features = false } ```

``` use words_to_data::dataset::Dataset;

let dataset = Dataset::open_sqlite("law.sqlite")?; let path = "uscode/title_26/subtitle_A/chapter_1/subchapter_B/part_VI/section_174A"; for annotation in dataset.annotations_for_path(path)? { println!("{:?} by {}", annotation.operation, annotation.source_bill.bill_id); } // Insert by 119-hr-1 ```

Upgrade from 0.6.0: the stored format does not change, so a 0.6.0 dataset opens with 0.6.1. To get the new links, run `redesignations` for each bill and window, then `link-by-evidence` again, and add the opinions again with `add-opinions`. An input that the dataset does not hold now stops a command with exit 1 and the notice on stderr. The changelog lists the changes that break code and agents.

Documentation & Resources

🔧

GitHub Repository

The source code, the issues, and the changelog. The latest release is v0.6.1 (2026-10-26).

📦

Crates.io and docs.rs

Get the crate from the Rust package registry. The API documentation is on docs.rs.

🤖

The Agent Playbook

How an agent answers a question with evidence, resolves the residue, and reviews links, with the command alone.

📖

Concepts and Decisions

CONTEXT.md is the glossary: work, expression, path, link, review. The ADRs record each design decision and its reason.

Get in Touch

Send us your questions, feedback, or partnership requests.