---
title: "CLI"
description: "The puzzles command. Seventeen subcommands and what each prints. Which ones exit 1 and what --json gives a script."
canonical_url: "https://puzzles.agntn.dev/guide/cli"
---
# CLI

> The puzzles command. Seventeen subcommands and what each prints. Which ones exit 1 and what --json gives a script.

## Run it

```bash
pnpm add -g @agntn/puzzles
puzzles stats
```

<dataset-stats>



</dataset-stats>

<table>
<thead>
  <tr>
    <th>
      Command
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        puzzles stats
      </code>
    </td>
    
    <td>
      Totals, status counts, prize sums and the data version, the same text <code>
        puzzles_stats
      </code>
      
       hands a model
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        puzzles collections
      </code>
    </td>
    
    <td>
      One line per collection: key, count, the count per status, author. <code>
        --json
      </code>
      
       puts them under <code>
        collections
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        puzzles authors [key]
      </code>
    </td>
    
    <td>
      One line per author, or one author's record by author key or collection key: aliases, profiles, addresses, sourced facts
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        puzzles author <key>
      </code>
    </td>
    
    <td>
      The <code>
        puzzles_author
      </code>
      
       tool as a command, one author's record by author key or collection key
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        puzzles solvers [key]
      </code>
    </td>
    
    <td>
      One line per named solver, or one solver's record by solver key or puzzle identifier: every solve with date and prize, profiles, sourced facts
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        puzzles solver <key>
      </code>
    </td>
    
    <td>
      The <code>
        puzzles_solver
      </code>
      
       tool as a command, one solver's record by solver key or puzzle identifier
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        puzzles show <id>
      </code>
    </td>
    
    <td>
      One puzzle's record: address, key material, transactions, stages and hints, folded past three per block, links. <code>
        --all-transactions
      </code>
      
       unfolds the dust, <code>
        --json
      </code>
      
       for the data
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        puzzles hints <id>
      </code>
    </td>
    
    <td>
      The collection's hints first, then the puzzle's own, then its hint files. <code>
        --json
      </code>
      
       for both
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        puzzles stages <id>
      </code>
    </td>
    
    <td>
      The stages of a puzzle that runs in several: what each shows, its pages and files, and the published answer when there is one. <code>
        --json
      </code>
      
       for the list
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        puzzles assets <id>
      </code>
    </td>
    
    <td>
      The files a puzzle ships with SHA-256 and size, then the archived pages it cites. <code>
        --read <path>
      </code>
      
       writes one to stdout, <code>
        --check <dir>
      </code>
      
       hashes your copies, <code>
        --live
      </code>
      
       the author's URLs
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        puzzles list [collection]
      </code>
    </td>
    
    <td>
      Puzzles, one per line, <code>
        --address
      </code>
      
      , <code>
        --chain
      </code>
      
      , <code>
        --status <status>
      </code>
      
      , <code>
        --technique <name>
      </code>
      
       and <code>
        --with-pubkey
      </code>
      
       to narrow, <code>
        --limit <n>
      </code>
      
       and <code>
        --offset <n>
      </code>
      
       to page, <code>
        --json
      </code>
      
       for the records
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        puzzles verify [id]
      </code>
    </td>
    
    <td>
      A published key and its recipe against the address, or a set by <code>
        --collection
      </code>
      
       and the <code>
        list
      </code>
      
       filters, <code>
        --all
      </code>
      
       for every puzzle, <code>
        --quiet
      </code>
      
       for the exit code alone
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        puzzles balance [id]
      </code>
    </td>
    
    <td>
      The live balance through the chain's explorer, or <code>
        --collection
      </code>
      
       and the <code>
        list
      </code>
      
       filters for one row per puzzle, <code>
        --api-key
      </code>
      
       for Ethereum
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        puzzles watch [id]
      </code>
    </td>
    
    <td>
      What the chain knows and the record doesn't, by id or by the <code>
        list
      </code>
      
       filters. <code>
        --since <date>
      </code>
      
       compares the source pages too
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        puzzles eligibility <query>
      </code>
    </td>
    
    <td>
      The checklist before working on a prize: record, live totals, status with evidence, carriers, verifier, a <code>
        missing
      </code>
      
       row per gap
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        puzzles export
      </code>
    </td>
    
    <td>
      The complete dataset envelope, <code>
        --compact
      </code>
      
       without indentation
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        puzzles mcp
      </code>
    </td>
    
    <td>
      Run the MCP server over stdio
    </td>
  </tr>
</tbody>
</table>

## Examples

```bash
puzzles list bits --status unsolved              # one line per unsolved puzzle: id, status, prize, address
puzzles list --with-pubkey --json | jq -r '.[].id' # every puzzle with a known public key
puzzles list --no-with-pubkey --status solved      # solved, and still no public key on record
puzzles list --technique atbash                    # every puzzle with an Atbash step
puzzles list --chain ethereum                      # every Ethereum record, wherever it lives
puzzles list --address 1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH # which puzzle is this? bits/1
puzzles list bits --limit 5 --offset 70           # five rows from bits/71, not the whole collection
puzzles show hash-collision/sha256 --json          # the record, redeem script included
puzzles hints bits/71                             # the author's one statement about the keys
puzzles verify bits/135                           # OK  bits/135
puzzles verify --collection rushwallet             # every SHA-256 brainwallet rerun, one SKIP without a key
puzzles assets gsmg --check ./gsmg               # MATCH, MISMATCH or MISSING per file, exit 1 unless every copy matches
puzzles assets gsmg --read assets/gsmg/phase3.txt # the page itself, only if its bytes match the pin
puzzles solvers bits/135                          # the solver behind it: RetiredCoder, four solves
puzzles balance --status unsolved                  # OK bits/71 7.10195986 BTC, one row per open prize
puzzles watch --status unsolved --since 2026-09-01 # DEPOSIT, SPEND, BALANCE, PUBKEY, SOURCE, PARTIAL or OK per puzzle
puzzles eligibility bits/71                       # live totals, a conflict row, the key range, exit 0
puzzles export --compact > puzzles.json            # a snapshot with its data_version
puzzles stats --json | jq -c .unsolved_prize       # {"AR":…,"ETH":…,"BTC":…}, what is still on the table
```

A `collections` row prints the key, the puzzle count, the statuses and the author, `bits: N puzzles, N solved, N unsolved, N swept, by saatoshi_rising`: solved and unsolved always, then claimed, swept and expired when the collection has any, so the counts add up to the total. A `list` row, and the first line of `show`, is tab separated: `bits/71	unsolved	7.10195986 BTC	1PWo3JeB9jrGwfHDNpdGK54CRas7fsVzXU`. A puzzle without a recorded prize prints `-` in the third column. The rest of `show` is one `name: value` field per line, the same text `puzzles_show` hands a model. Statuses for `--status` are `unsolved`, `solved`, `claimed`, `swept` and `expired`. Anything else is an error, not an empty list. `--limit` and `--offset` page the rows the way `puzzles_list` pages them for a model: the offset skips matching puzzles after the filters, in dataset order. There is no default limit, a bare `list` still prints every match. Both want an integer, `--limit 0` or `--offset -1` is an error. `--address` goes the other way: you have an address and want the record behind it. Case matters only where the chain says it does, so an EIP-55 Ethereum address and a shouted bech32 one both find their puzzle, while a recased base58 string does not, because that is a different address.

## Exit codes

`show`, `hints`, `stages`, `assets`, `verify`, `balance` and a `list` with an unknown collection print a message and exit 1. `verify --all`, and a filtered `verify`, exit 1 when any key or recipe derives the wrong address. Filters that match nothing exit 1 too, because checking nothing isn't a pass. Puzzles without a key don't count, which is what a CI gate wants. A filtered `balance` exits 1 when any lookup failed, after it tried every puzzle. `watch` exits 1 on any finding and 2 when the only news is a failed lookup. A cron job can tell the two apart. `eligibility` exits 1 when any field is missing, so the exit code says whether the record is complete. `assets --check` exits 1 when a copy is missing or has other bytes. `assets --read` exits 1 when no copy answers with the pinned bytes, and stdout stays empty, so a redirect never saves a wrong file. `assets --live` exits 1 only on other bytes: an author URL that answers 404 or times out prints `UNREACHABLE` with the reason, because a dead host says nothing about the file, and a file the record has no author URL for prints `NO_ORIGIN`. `list` with a status that matches nothing prints nothing and exits 0. Don't use an empty list as a check. A flag a command doesn't take is an error too. `verify bits/1 --key abc` has no `--key`, so it exits 1 and names it instead of checking the stored key and printing `OK`. The same goes for a second ID after `show`. And a misspelled flag never sneaks into the ID. `list --withPubkey` names the option instead of hunting for a collection called `--withPubkey`. `mcp` still shrugs off whatever flags a client config throws at it. Only `--help` gets the usage.

```bash
puzzles verify --all --quiet && echo "every published key derives its address"
```

A closed pipe ends the process quietly: `puzzles export | head` doesn't crash with an EPIPE trace. So what does `--help` load? The command definitions, and that's it. Each command imports its modules once it runs. Listing them loads no collection, no curve and no MCP SDK.

## Machine output

`--json` prints the details a command answers with, through the same serializer every command shares. `bigint` comes out as a string and absent fields stay out. Nothing on the CLI prints data through a logger.

`balance` and `watch` print each row the moment its lookup lands. Who wants to stare at a silent terminal through a hundred lookups? Under `--json` they wait and print one array instead, valid to the last bracket. `assets --read --json` gets refused before a single byte goes out. A PNG with JSON glued to its tail is just a broken PNG.


## Sitemap

See the full [sitemap](https://puzzles.agntn.dev/sitemap.md) for all pages.
