infinite-craft-cli
Interactive CLI for Infinite Craft — combine elements from the terminal. Also available as a browser extension and web trainer.
Originally built on infinite-craft by @sqdnoises. As of v1.0, uses curl_cffi directly.
Installation
pip install infinite-craft-cli
Browser extension
Install the Infinite Craft Trainer from the Chrome Web Store — it loads automatically on neal.fun/infinite-craft and fetches the current trainer (trainer.min.js) from GitHub Pages with cache: 'no-store', so feature updates ship without waiting for a Chrome Web Store release. The extension manifest version (extension/manifest.json) is independent of the Python CLI package version (git tags). See PRIVACY.md for the remote-script trust model. Works in Edge, Brave, and other Chromium browsers.
Manual QA (extension): After changes to extension/loader.js, load the unpacked extension on live neal.fun/infinite-craft and confirm the trainer UI appears and IndexedDB-backed commands work (e.g. /list).
For other install methods (console snippet, userscript), see the web trainer page.
Usage
Interactive mode
infinite-craft
This opens a REPL where you can combine elements, search discoveries, and more:
=== Infinite Craft CLI ===
craft> Water + Fire
💨 Water + 🔥 Fire = 💨 Steam
craft> /search steam
💨 Steam
craft> /target Steam
Target set: Steam — you'll be asked whether to continue the batch when this is crafted.
craft> /help
Sticky chrome under the log always shows the pair-API rate bar (next-slot wait + remaining budget). While a job runs it also shows running command + progress, or ◆ confirm with the reason (pair count, target hit). y / n is only on confirm [y/n]>.
Non-interactive mode
Most REPL commands are available as subcommands (shorthand operators like +, ++, and * are REPL-only; script runs a script non-interactively):
infinite-craft combine "Water" "Fire"
infinite-craft search "steam"
infinite-craft list
infinite-craft recipe "Steam"
infinite-craft import "Steam"
infinite-craft export
infinite-craft fill
infinite-craft unfilled
infinite-craft prune
infinite-craft exhaust "Water"
infinite-craft crawl "Water" "Fire"
infinite-craft permute "w*"
infinite-craft with "Water" "fire*"
infinite-craft cross "fire*" "water*"
infinite-craft lucky 25
infinite-craft --version
Commands
Combine & crawl
| Shorthand | Slash command | Description |
|---|---|---|
<element> + <element> |
/combine <element> <element> |
Combine two elements |
<element> ++ <element> |
/crawl <element> <element> |
Crawl: generations over a growing pool until one adds nothing to it |
Bulk combine
| Shorthand | Slash command | Description |
|---|---|---|
<query> * <query> |
/cross <query> <query> |
Cross-combine matches from both queries |
/permute <query> |
Combine all matching elements with each other | |
/permutate <query> |
Permute repeatedly until no new discoveries | |
/exhaust <query> |
Each match combined with all discoveries | |
/lucky [count] |
Try random untried pairs — entropy mining (default 10). Pairs that produced Nothing aren't persisted, so later sessions may re-draw them |
Query syntax
Used by /search, /with, /permute, /permutate, /cross, /exhaust, and script patterns:
| Syntax | Meaning |
|---|---|
substring |
Case-insensitive substring (default) |
* ? [] |
fnmatch wildcards (e.g. fire*, mu?) |
/pattern/ |
Regex, case-insensitive; real alternation (/steam|mist/), grouping, anchors |
!<query> |
Exclude matches (e.g. !fire* = everything except fire*) |
! |
All elements (exclude nothing) |
^<query> |
First discoveries only (e.g. ^fire* = new fire* matches) |
^ |
All first discoveries |
Other commands
| Command | Description |
|---|---|
/search <query> |
Search discoveries |
/recipe <element> |
Show shortest recipe from base elements |
/list |
List all discovered elements |
/import <element|file.ic> |
Import from Infinibrowser or .ic save file |
/fill |
Fetch missing recipes from Infinibrowser |
/unfilled |
List elements without recipes |
/prune |
Remove orphan elements Infinibrowser can't fill |
/export [path] |
Export discoveries as .ic save file |
/history |
Show combinations tried this session |
/target <element> |
Watch for a result; ask y/n to continue the batch on hit |
/target |
Show current target |
/target clear |
Clear target |
| `/auto [on | off]` |
/queue |
Show running and pending commands (status also appears in chrome) |
/help |
Show help |
/quit |
Exit |
Scripting
Every non-slash line in the REPL is a script (the old shorthands are one-statement scripts). Statements are separated by ;; whitespace-delimited operators are structure and everything attached is pattern material, so mountain range + ship still combines exactly what it says. Bare words are element references (error if unknown); patterns with metacharacters (* ? [] /regex/ ! ^) are queries; quoted strings are exact element references.
targets := ^(fire* / water*) ; # bind first-discoveries having a fire*+water* recipe
(targets)* -> |[]| < 2 ; # permute passes until a pass yields < 2 new
[] * (earth* / fire*) # cross what that made against filtered earth*
Pure, loop-free scripts (bare queries, unions, filters, walrus bindings) run immediately and interleave with a running bulk command, like /search; mutating scripts and loops queue on the pair lane.
Highlights: , union, - difference, & intersect, //% known-recipe filters, (expr)*/(expr)**/(expr)! permute/permutate/exhaust, (expr)100 first-100 ((expr)(|x*|) dynamic counts), (expr)100? random-100, (expr)? shuffle, A * B cross, A ++ B crawl, [ expr ]/[] new-element sets, set @x body for-each, body -> cond do-until, body ~ cond while, cond ? a : b ternary. Conditions are statically pure — mutations inside a condition are parse errors. Every mutating operation's value is the set it produced, so pipelines chain. Save scripts as .ice files and run them with /script <path> (file picker in the trainer) or infinite-craft script -f path. Non-interactive runs have no y/n prompt: bulk operations over the warn threshold announce their pair count and proceed; script failures exit non-zero. Full spec: docs/superpowers/specs/2026-08-20-script-language-v0.6.md.
Breaking changes in 2.0: +| is removed (use *; /with remains), bare words in old *//+| positions were substring queries and are now element references (write *fire* for substring), bare pattern lines print matches instead of erroring, A + B + C chains combines, and /permutate no longer stops at 50 rounds.
Queues and confirm (Python REPL + trainer)
Pair-API work (combine, crawl, permute, exhaust, …) and Infinibrowser work (/fill, /prune, /import) use independent queues so one lane can run while the other is busy. Local commands (/help, /search, /list, /recipe, /history, /clear, /unfilled, /queue, /target) run immediately — their output may interleave with a running job.
Large batches and /target hits pause on confirm [y/n]>: y continues, n / Esc / Stop cancels remaining work. The job row states the reason (331 pairs, target hit); keybindings are not repeated in the log.
| Key | Action |
|---|---|
| Esc | Skip current command, continue to next in that lane (TTY / Stop in the trainer) |
| Ctrl+C | While running: stop and discard remaining queue; at confirm: decline only |
Deferred commands print Queued: when that lane is already running.
Data storage
Discoveries and recipes are stored in ~/.infinite-craft-cli/:
discoveries.json-- all discovered elementsrecipes.json-- known element combinationsexport.ic-- default export location
Browser extension / bookmarklet
The browser trainers share the same command syntax, query matching, and script language as the Python CLI (wildcards, /regex/, ! exclude, ^ first discoveries, /combine, /with, /cross, /target, and scripts). Browser-only additions: /clear to clear the output panel, and IndexedDB storage instead of ~/.infinite-craft-cli/. Rate, job, and queue status live in the sticky panel above the input (visual-only; no /queue command). Local commands such as /search may interleave output with a running queued command.
Long runs in a background tab: the trainer holds a Web Lock while a run is active, which keeps Chrome's Memory Saver / Energy Saver from freezing the tab under current heuristics. If a backgrounded run still pauses (the exemption is a heuristic, not a guarantee), add neal.fun to chrome://settings/performance → "Always keep these sites active", or keep the tab in a partially visible window. Truly long unattended jobs are what the Python CLI is for.
Development
After editing bookmarklet/trainer.src.mjs, rebuild the bundles:
bazel build //bookmarklet:site
Build the Python wheel:
bazel build //release:wheel.dist
Run all tests:
bazel test //...
This includes //sudo:craft_lockstep_test, which runs the kernel's own test
suite against both the generated Python and JavaScript and diffs the two.
//tests/... alone skips it.
Run integration tests (hits the real API):
bazel test //tests:test_integration --test_env=INTEGRATION_TESTS=1
License
MIT
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file infinite_craft_cli-2.1.1-py3-none-any.whl.
File metadata
- Download URL: infinite_craft_cli-2.1.1-py3-none-any.whl
- Upload date:
- Size: 92.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f6029d32136a3a9e9e9f7c89a6c8c7c0475509ff2516c5fa6351c485a0ebfa99
|
|
| MD5 |
5eac922f76410d116bac1565b73de78f
|
|
| BLAKE2b-256 |
f37ed37a5f66d02ee98f7cf8fe32a5844fc46773b8c421a9eac225de49efb700
|
Provenance
The following attestation bundles were made for infinite_craft_cli-2.1.1-py3-none-any.whl:
Publisher:
publish.yml on hacker6284/infinite-craft-cli
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
infinite_craft_cli-2.1.1-py3-none-any.whl -
Subject digest:
f6029d32136a3a9e9e9f7c89a6c8c7c0475509ff2516c5fa6351c485a0ebfa99 - Sigstore transparency entry: 2543777249
- Sigstore integration time:
-
Permalink:
hacker6284/infinite-craft-cli@76dd1c686eb852f40b32a6344d8f32d21ef102e5 -
Branch / Tag:
refs/tags/v2.1.1 - Owner: https://github.com/hacker6284
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@76dd1c686eb852f40b32a6344d8f32d21ef102e5 -
Trigger Event:
push
-
Statement type: