3SAT CLI
Official command line client for the 3SAT protocol.
The package installs a 3sat command for users who want to search the answer database, create bounties, buy answer access, and download answer bundles without using the web UI.
Links
- Website: https://3sat.network/
- Web app: https://3sat.network/app
- Protocol docs: https://3sat.network/docs/api
- SAT Academy: https://3sat.network/docs/academy
Install
Python 3.10 or newer is required. Install the published CLI in your Python environment:
python -m pip install --upgrade 3sat
Verify the installation:
3sat --version
3sat --help
3sat doctor
The wheel embeds its own Python implementation of the
3sat-dimacs-strict-v1 parser plus the shared conformance corpus. It does not
need the TypeScript core or Node.js at runtime. File-based CNF commands validate
bounded raw bytes locally before configuration, wallet, or network operations;
SAT artifacts must additionally be non-conflicting unit-clause assignments.
Security
Use a dedicated protocol wallet. Do not use your main wallet.
The CLI does not store private keys by default. Pass a private key with --private-key, or set:
export THREESAT_PRIVATE_KEY=0x...
On PowerShell:
$env:THREESAT_PRIVATE_KEY="0x..."
Quickstart
Show current configuration:
3sat config show
Initialize the default public deployment configuration:
3sat config init
The bundled defaults target the production deployment on Arbitrum One (chain ID 42161). Existing ~/.3sat/config.json files are not overwritten by source-default changes; preserve intentional custom values, then replace every public deployment field with 3sat config set before connecting to production.
Search for an existing answer:
3sat search problem.cnf
Check the configured API, RPC, contracts, tokens, and optional wallet balances:
3sat doctor --address 0xYourWallet
3sat tokens --onchain
Create a bounty. The command accepts a DIMACS CNF instance up to 256 MiB, validates/hashes it incrementally, uploads an immutable snapshot directly to R2 in 8 MiB parts, and waits for background validation before preparing the bounty. File bytes do not pass through Vercel. Upload authorization requires the issuer's wallet key even without --send; this is an off-chain signature and does not spend gas. Broadcasting still requires --send:
3sat issue problem.cnf --reward 100 --token USDC --send
Before broadcasting, the CLI locally ABI-encodes the expected approval and bounty call, verifies the complete prepared transaction batch (to, data, and value), and signs only the locally reconstructed transactions. Commit and reveal broadcasts use the same fail-closed check.
The CLI currently processes one CNF per issue invocation and one artifact per upload-solution invocation. It does not provide a built-in batch manifest, directory/glob input, or atomic batch upload/issue command.
The default open, reveal, and verification windows are 1 hour each. Every window must be at least 1 hour. During the official-verifier launch phase, verifier quorum is fixed at 1; --quorum is retained for compatibility but rejects every value other than 1.
Run a true local dry run without uploading files:
3sat issue problem.cnf --reward 100 --token USDC --dry-run
Buy answer access:
3sat buy-answer SAT-XXXX-XXXX-XXXX --send
Download an original finalized bounty bundle:
3sat download-answer SAT-XXXX-XXXX-XXXX -o answer.zip
Download a matched answer for a CNF you searched. SAT assignments may be rebuilt for an equivalent CNF. For a format-normalized or variable-renamed UNSAT match, the service converts the finalized proof in an isolated worker and returns the bundle only after the matching checker accepts the proof against the exact CNF you supplied:
3sat download-answer SAT-XXXX-XXXX-XXXX --cnf my-query.cnf -o matched-answer.zip
Original/raw-exact downloads request a small, access-checked manifest containing signed R2 URLs, sizes and digests. The CLI streams each file to disk, checks its size and Keccak digest, then creates the ZIP locally. Neither a 256 MiB CNF nor a 1 GiB proof is buffered into a Vercel response. Temporary downloads are removed on failure and an existing output ZIP is replaced only after successful verification.
Non-exact UNSAT conversion jobs are asynchronous. The CLI waits up to 60 minutes by default (override with --transform-timeout-minutes) and verifies the checker-bound ZIP size and digest while downloading. Interactive non-exact/variable-renaming matching remains a separately bounded operation: CNFs above 3.5 MiB require a raw-exact match; the CLI rejects unsupported large non-exact queries before buying access. Raising the artifact limit does not silently enable unlimited graph-isomorphism processing.
Large artifacts and resource budgets
This release supports CNFs and SAT assignments up to 256 MiB, UNSAT proofs up to 1 GiB, and answer ZIPs up to 1.5 GiB. The strict DIMACS grammar is unchanged. The shared resource ceilings are 5,000,000 variables, 20,000,000 clauses, 100,000,000 literal occurrences, 25,000,000 physical lines, 1 MiB per physical line, and 5,000,000 literals in one clause. Exceeding a resource budget is not proof that an answer is mathematically invalid.
For CNFs above 3.5 MiB, search sends only the locally computed raw digest and explicitly uses exact-byte matching. Above the same threshold, standardize runs locally and reports streaming-format-only: it normalizes DIMACS formatting while preserving clause and literal order. It does not compute or claim the website's sorted canonical/variable-renaming digest. Smaller requests use the separately resource-limited API; being under the byte limit does not guarantee that structural matching is available. Use -o normalized.cnf for the resulting file; large JSON output contains a summary rather than the entire CNF text.
Upload snapshots require temporary free disk space of at least the artifact size plus 64 MiB. Manifest downloads require approximately twice the combined file size plus 64 MiB while assembling the ZIP. In-process failures clean up temporary files; an operating-system crash or forced kill can leave OS-temporary 3sat-upload-* or .3sat-answer-* directories. Only remove those after confirming the originating CLI process is stopped. Never remove reveal bundles as part of download cleanup.
Failed R2 parts are retried with the same upload identity. Immediately before completion, the CLI atomically saves a private receipt under the configuration directory's upload-receipts/ folder (normally ~/.3sat/upload-receipts/). It contains the scoped upload token, file/wallet/API binding and completed part ETags, never the private key. POSIX permissions are restricted to the user; Windows uses the containing user directory's ACLs. If a completion response is lost or the 30-minute validation wait expires, rerun the same command with the same file, wallet and API configuration: the receipt resumes the existing completed/queued upload instead of uploading another copy. A forced stop before all parts finish is not resumable across CLI processes; that attempt's unfinished server upload expires instead. Pending server reservations expire after 24 hours; failed/expired local receipts are removed individually, while ready receipts and published artifacts are preserved. Receipts are private operational data and must not be included in release packages.
Upload recovery is not transaction recovery: do not rerun issue --send blindly if the bounty transaction may already have been broadcast. Check the wallet transaction and bounty first to avoid creating a second bounty. For commit/reveal recovery, preserve and use the existing reveal bundle.
The website, background artifact-validation worker, solver and official verifier must be upgraded together before using these ceilings. A larger byte limit does not guarantee that every instance can be solved or that every proof finishes before the bounty's deadline.
Commands
3sat config show3sat config init3sat config set KEY VALUE3sat doctor3sat tokens3sat standardize problem.cnf3sat search problem.cnf3sat marketplace(shows 20 bounties by default)3sat marketplace --offset 20(load the next page)3sat bounty SAT-...3sat issue problem.cnf --reward 100 --token USDC --dry-run3sat issue problem.cnf --reward 100 --token USDC --send3sat buy-answer SAT-... --send3sat download-answer SAT-... --cnf query.cnf3sat balance --address 0x...3sat upload-solution answer.cnf --kind sat --private-key 0x...3sat upload-solution proof.frat --kind unsat --proof-format frat --private-key 0x...3sat prepare-commit SAT-... --solver 0x... --artifact-id artifact-... --solution-digest 0x... -o reveal.json3sat commit SAT-... --artifact-id artifact-... --solution-digest 0x... --private-key 0x... --send -o reveal.json3sat reveal --bundle reveal.json --submission-id 1 --private-key 0x... --send
Solver flow for advanced users
The fully automated solver clients are still the easiest way to solve bounties. Advanced users can also use the CLI.
Issuer task descriptions are limited to 200 characters. This keeps public metadata concise and prevents oversized bounty descriptions from being used as an abuse vector.
Upload a SAT answer:
3sat upload-solution answer.cnf --kind sat --private-key 0x...
Upload an UNSAT proof:
3sat upload-solution unsat-proof.frat --kind unsat --proof-format frat --private-key 0x...
UNSAT proof uploads are limited to 1 GiB; SAT assignments are limited to 256 MiB. Every artifact uses a wallet-authenticated multipart upload and background validation. A lost reservation response is retried with the same signed upload identity, and failed R2 parts are retried independently. upload-solution returns only after the artifact is ready; do not commit an unvalidated upload. The private key may be supplied by --private-key or THREESAT_PRIVATE_KEY.
Upload ready means the storage, size and digest checks (and applicable CNF/assignment format checks) completed. It does not mean an UNSAT proof has already been accepted as mathematically correct: the official verifier checks the proof after commit and reveal. Choose --kind unsat --proof-format drat|frat|lrat to match the actual proof format, and pass the same kind and format to prepare-commit or commit.
Successful solution uploads return an opaque artifactId, not an R2 object location. Keep the artifact id and digest for commit and reveal. The artifact id is used only by the API to bind the private upload to the solver; it is not placed on chain and is not included in the commitment hash.
The solver passed to prepare-commit must be the same wallet that signed upload-solution. A different wallet cannot claim or reveal that private artifact.
Prepare a commit without broadcasting:
3sat prepare-commit SAT-XXXX-XXXX-XXXX \
--solver 0xSolverWallet \
--artifact-id artifact-... \
--solution-digest 0x... \
-o reveal.json
Broadcast a commit:
3sat commit SAT-XXXX-XXXX-XXXX \
--artifact-id artifact-... \
--solution-digest 0x... \
--private-key 0x... \
--send \
-o reveal.json
Before preparing or sending a commit, the CLI verifies the bounty's snapshotted solver bond directly on chain and rebuilds the approval with that value. A snapshot value of zero is rejected.
The commitment binds the chain id, BountyManager address, bounty id, solver, solution kind, proof format, solution digest, and salt. The opaque artifact id stays in the local reveal bundle so the API can recover and verify the private upload binding, but neither commit nor reveal stores it on chain.
For commit --send, the CLI writes the reveal bundle atomically before broadcasting any approval or commit. Without -o, it uses data/reveal-bundles/bounty-<id>-commit-<hash>.json; if that write fails, nothing is broadcast. The bundle contains the secret salt required to reveal, so keep it durable and private and do not delete, share, sync, upload, or include it in a ZIP until the submission has been revealed.
Reveal after commit. Use the submission id assigned by the commit transaction:
3sat reveal --bundle reveal.json --submission-id 1 --private-key 0x... --send
Configuration
The config file is stored at:
~/.3sat/config.json
Supported environment variable overrides:
THREESAT_CONFIGTHREESAT_CONFIG_DIRTHREESAT_API_URLTHREESAT_RPC_URLTHREESAT_CHAIN_IDTHREESAT_CHAIN_NAMETHREESAT_BOUNTY_MANAGER_ADDRESSTHREESAT_ARTIFACT_ACCESS_CONTROLLER_ADDRESSTHREESAT_USDC_ADDRESSTHREESAT_TOKEN_ADDRESSTHREESAT_PRIVATE_KEY
Notes
The CLI uses the public 3SAT API for artifact storage, search, metadata generation, and transaction preparation. Wallet signing and transaction broadcasting happen locally on the user's machine.
The solver and verifier automation clients remain separate because they bundle SAT solvers, proof checkers, and long-running polling loops.
Development
Install from source when contributing to the CLI:
git clone https://github.com/spencerg-sys/3sat-cli.git
cd 3sat-cli
python -m pip install -e .
Maintainer release checklist: 0.1.1
Version 0.1.1 requires the matching website multipart-upload API, R2 multipart CORS configuration, artifact-validation worker, solver and official verifier rollout. Publishing a Python package does not deploy those services. Do not announce large-upload availability until that coordinated deployment is ready.
From this repository root, use a development virtual environment to test and build:
python -m pip install --upgrade build twine
python -m pip install -e .
python -m unittest discover -s tests
python -m build
python -m twine check --strict dist/3sat-0.1.1-py3-none-any.whl dist/3sat-0.1.1.tar.gz
Check that pyproject.toml, threesat_cli.__version__, 3sat --version and both distribution metadata files all say 0.1.1. Inspect both archives: include the Python modules, parser corpus, license and package metadata; exclude credentials, upload receipts, reveal bundles, caches and local runtime files. MANIFEST.in is a packaging instruction file used by the source distribution; keep it in the repository.
Only after the release has been approved, upload these exact two files to production PyPI:
python -m twine upload --repository pypi dist/3sat-0.1.1-py3-none-any.whl dist/3sat-0.1.1.tar.gz
Do not use dist/*: older 0.1.0 artifacts may coexist in that folder and must not be uploaded again. PyPI cannot replace already-published release files; if 0.1.1 is already published, use a new version for further changes. Keep publishing credentials outside the repository and distribution archives.
After publication, check installation in a fresh virtual environment:
python -m pip install --index-url https://pypi.org/simple "3sat==0.1.1"
3sat --version
3sat issue --help
3sat upload-solution --help
Installation and help checks do not upload artifacts or send transactions. See the Python Packaging User Guide for the build and publishing workflow.
Metadata
Release files for 3sat 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| 3sat-0.1.1.tar.gz | 52.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| 3sat-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 107.0 kB
Release files / 3sat-0.1.1.tar.gz
| Download URL | 3sat-0.1.1.tar.gz |
|---|---|
| Size | 52.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
eaa5886da03a8fae4bc6d05cb03da8a954a6a44659e91fa5d8aa76184e4e8fc1
|
|
BLAKE2b-256 checksum How to use checksums |
ae4b5a3ba664deda13929c511aa25f51a7d973ad0d1b13d70350b13595a81909
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.4
|
Release files / 3sat-0.1.1-py3-none-any.whl
| Download URL | 3sat-0.1.1-py3-none-any.whl |
|---|---|
| Size | 54.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
d5166d2ff62d90ccef806a379c465cd45ec59f6f5f0b9f6958ad8934bcaf3cbf
|
|
BLAKE2b-256 checksum How to use checksums |
33907e885bebaa78eff430f8bfbc7971430d4832fcedd9741f7f10c12a3c5e27
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.4
|