Command line tool for the 404 subnet to submit miner solutions.
Install the package in editable mode to use the 404-cli command directly:
pip install -e .After installation, you can use 404-cli directly without python:
404-cli --help
404-cli commit-hash --hash <hash> --wallet.name <name> --wallet.hotkey <hotkey>If you prefer to use python commit.py instead:
pip install -r requirements.txt404-cli commit-hash \
--hash <full_40_char_commit_sha> \
--wallet.name <wallet> \
--wallet.hotkey <hotkey>Or using python commit.py:
python commit.py commit-hash \
--hash <full_40_char_commit_sha> \
--wallet.name <wallet> \
--wallet.hotkey <hotkey>404-cli commit-repo-cdn \
--repo <owner/repo-name> \
--cdn-url <s3-compatible-storage-url> \
--wallet.name <wallet> \
--wallet.hotkey <hotkey>Or using python commit.py:
python commit.py commit-repo-cdn \
--repo <owner/repo-name> \
--cdn-url <s3-compatible-storage-url> \
--wallet.name <wallet> \
--wallet.hotkey <hotkey>The commit-repo-cdn command commits both the repository reference and CDN URL in a single transaction. Before committing, it validates that the CDN URL is accessible by performing a HEAD request.
Example:
404-cli commit-repo-cdn \
--repo your-username/your-solution \
--cdn-url https://my-bucket.s3.amazonaws.com/models/ \
--wallet.name miner \
--wallet.hotkey defaultOutput: On success, outputs JSON:
{"success": true, "repo": "your-username/your-solution", "cdn_url": "https://my-bucket.s3.amazonaws.com/models/"}On failure (if CDN URL is not accessible), outputs error JSON:
{"success": false, "error": "CDN URL https://my-bucket.s3.amazonaws.com/models/ is not accessible: 404"}Notes:
- Both
--repoand--cdn-urlare required - The command validates CDN URL accessibility before committing
- Uses the same wallet and network options as other commit commands
404-cli list-allOr using python commit.py:
python commit.py list-all| Option | Default | Description |
|---|---|---|
--wallet.name |
required | Wallet name |
--wallet.hotkey |
required | Wallet hotkey |
--wallet.path |
~/.bittensor | Path to wallet |
--subtensor.endpoint |
finney | Subtensor network |
--netuid |
17 | Subnet UID |
-v |
Verbosity: -v INFO, -vv DEBUG |
The 404 subnet uses a "king of the hill" competition where submission timing matters — earlier submissions gain priority. We use a commit-reveal scheme with Git's content-addressable hashing:
- Commit phase: Submit only your git commit SHA (a cryptographic hash of your code)
- Reveal phase: Submit your repository reference so validators can fetch and evaluate your code
The block when you call commit-hash determines your submission timestamp.
Git commit hashes are deterministic — derived from your code, commit message, author info, and timestamps. You cannot find different code that produces the same hash. This means:
- Your hash commits you to specific code before anyone sees it
- When you reveal the repo, validators verify the hash matches
# 1. Create your solution in a PRIVATE repository
git add . && git commit -m "My solution"
git log --format="%H" -1
# → a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0 ← full 40-char SHA
# 2. Submit the hash to claim your timestamp
404-cli commit-hash \
--hash a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0 \
--wallet.name miner \
--wallet.hotkey default
# 3. Make your repo accessible to validators
# 4. Submit the repo reference and CDN URL
404-cli commit-repo-cdn \
--repo your-username/your-solution \
--cdn-url https://my-bucket.s3.amazonaws.com/models/ \
--wallet.name miner \
--wallet.hotkey defaultAvoid these after submitting — they create new commits with different SHAs:
git commit --amendgit rebase- Cherry-picking into a different repo
- Re-committing the same files (different timestamp = different hash)
The start-generator command deploys and starts a generator container on Targon. It deploys the container and outputs the container URL which can then be used with the generate command.
Options:
--image-url(required): URL of the Docker image to deploy--targon-api-key(required): Targon API key for authentication
Example:
404-cli start-generator \
--image-url docker.io/username/model-generator:v1.0.0 \
--targon-api-key your-targon-api-key-hereOutput: On success, outputs JSON with the container URL:
{"success": true, "container_url": "https://generator-abc123.targon.io"}The container URL is also displayed on stderr and should be used as the --endpoint parameter for the generate command.
The generate command submits a prompt batch to the generator service and downloads generated .js files. It:
- Reads prompts from a JSON file (
--prompts-json) with prompt objects containingimage_urland optionalstem - Submits the full prompt batch to
/generate - Polls
/statusuntil generation reachescomplete - Downloads
/resultsZIP and saves generated.jsfiles locally
Options:
--prompts-json(required): Path to JSON file with format:{ "prompts": [ {"stem": "a1b2c3d4", "image_url": "https://storage.example.com/prompts/a1b2c3d4.jpg"}, {"stem": "e5f6g7h8", "image_url": "https://storage.example.com/prompts/e5f6g7h8.png"} ], "seed": 42 }--endpoint(required): Generator endpoint URL (obtained fromstart-generatorcommand)--seed(optional): Seed value override. If omitted, usesseedfrom the prompts JSON--output-folder(optional, default: "results"): Local folder path where generated .js files will be saved
Example:
First, start the generator container:
404-cli start-generator \
--image-url docker.io/username/model-generator:v1.0.0 \
--targon-api-key your-targon-api-key-hereNote the container URL from the output (e.g., https://generator-abc123.targon.io).
Then, create a prompts JSON file (for example example_prompts.json).
Run the generate command:
404-cli generate \
--prompts-json example_prompts.json \
--endpoint https://generator-abc123.targon.io \
--output-folder resultsWhen stem is provided in JSON, output files are named <stem>.js.
The generated files will be saved locally at paths like:
results/22de4efc4723f624b92889e8c79c9b4fb903e8a6b5907c9f0727ede8f2ccab47.jsresults/8c6c463fe4d3d9ed969a71ca8171b2571bb14f5fae057cf12d3743014d46c747.js- etc.
Output: On success, outputs JSON:
{"success": true}On failure, outputs error JSON:
{"success": false, "error": "Error message here"}Notes:
- Prompts are processed with concurrency control to limit resource usage
- Each generation attempt includes automatic retries (up to 3 attempts) with exponential backoff
- Generation progress and status messages are output to stderr, while JSON results go to stdout
- The output folder is created automatically if it doesn't exist
The start-renderer command deploys and starts a renderer container on Targon. It deploys the container using the predefined renderer image and outputs the container URL which can then be used with the render command.
Options:
--targon-api-key(required): Targon API key for authentication
Example:
404-cli start-renderer \
--targon-api-key your-targon-api-key-hereOutput: On success, outputs JSON with the container URL:
{"success": true, "container_url": "https://render-abc123.targon.io"}The container URL is also displayed on stderr and should be used as the --endpoint parameter for the render command.
Notes:
- Uses the predefined image:
europe-west3-docker.pkg.dev/gen-456515/active-competition/render-service-js:0.4.3 - Deploys on
cpu-smallresource type - Uses port 8000 and health check path
/health
The render command processes JavaScript submission files (.js) and renders them to PNG images using a renderer endpoint. It:
- Scans the specified directory for all
.jsfiles - Sends each file as JSON
{ "source": "<js code>" }to the renderer endpoint (/render/grid) - Saves the rendered PNG images to the output directory
Options:
--data-dir(required): Path to the directory containing the.jssubmission files to render--endpoint(required): Renderer endpoint URL (obtained fromstart-renderercommand)--output-dir(optional, default: "results"): Path to the directory where rendered PNG images will be saved
Example:
First, start the renderer container:
404-cli start-renderer \
--targon-api-key your-targon-api-key-hereNote the container URL from the output (e.g., https://render-abc123.targon.io).
Then, render the .js files:
404-cli render \
--data-dir results \
--endpoint https://render-abc123.targon.io \
--output-dir imagesThe rendered files will be saved locally at paths like:
images/22de4efc4723f624b92889e8c79c9b4fb903e8a6b5907c9f0727ede8f2ccab47.pngimages/8c6c463fe4d3d9ed969a71ca8171b2571bb14f5fae057cf12d3743014d46c747.png- etc.
Output: On success, outputs JSON:
{"success": true, "output_dir": "images"}On failure, outputs error JSON:
{"success": false, "error": "Error message here"}Notes:
- Files are processed with concurrency control (up to 2 concurrent renders)
- Each .js file is rendered to a PNG with the same base filename
- The output directory is created automatically if it doesn't exist
- Render progress and status messages are output to stderr, while JSON results go to stdout
The start-judge command deploys and starts the VLLM judge container on Targon. It outputs the container URL which can then be used with the judge command.
Options:
--targon-api-key(required): Targon API key for authentication
Example:
404-cli start-judge \
--targon-api-key your-targon-api-key-hereOutput: On success, outputs JSON with the container URL:
{"success": true, "container_url": "https://judge-abc123.targon.io"}The container URL is also displayed on stderr and should be used as the --endpoint parameter for the judge command.
Notes:
- Uses the predefined image:
vllm/vllm-openai:v0.20.0 - Serves
zai-org/GLM-4.6V-Flashasglm-4.6v-flash - Deploys on
rtx6000b-small - Uses port 8000 and health check path
/health
The judge command compares two rendered image sets with the multi-stage duel judge. It prints every stage result to stderr and saves all duel records to an output folder.
It expects both image directories to be grouped by prompt stem, matching the renderer output structure:
images-a/<stem>/grid.png
images-a/<stem>/white/front.png
images-a/<stem>/white/front_left.png
images-a/<stem>/white/front_right.png
images-a/<stem>/white/front_above.png
images-a/<stem>/white/right.png
images-a/<stem>/white/back.png
images-a/<stem>/white/left.png
images-a/<stem>/white/top_down.png
images-a/<stem>/gray/front.png
Options:
--prompts-json(required): Path to JSON file withprompts[].stemandprompts[].image_url--image-dir-1(required): Directory containing the first rendered image set, grouped by stem--image-dir-2(required): Directory containing the second rendered image set, grouped by stem--endpoint(required): Judge endpoint URL (obtained fromstart-judge;/v1is appended when omitted)--seed(required): Seed for deterministic VLM calls--output-dir(optional, default: "judge-results"): Folder for per-duel JSON files andduels.json--concurrency(optional, default: 1): Maximum number of duels judged concurrently
Example:
First, start the judge container:
404-cli start-judge \
--targon-api-key your-targon-api-key-hereNote the container URL from the output (e.g., https://judge-abc123.targon.io).
Then, judge two rendered image sets:
404-cli judge \
--prompts-json prompts.json \
--image-dir-1 images-a \
--image-dir-2 images-b \
--endpoint https://judge-abc123.targon.io \
--seed 42 \
--output-dir judge-resultsOutput: On success, outputs JSON:
{"success": true, "output_dir": "judge-results"}Judge records are saved as:
judge-results/<stem>.jsonjudge-results/duels.json
Notes:
- Stage logs include
S1,S2, gatedS3when reached,S4, and the final winner - If a stage short-circuits the duel, later gated stages are not run or logged
- Missing rendered previews produce win-by-default or draw records
The stop-pods command stops all running generator, render, and judge containers on Targon. This is useful for cleaning up resources after completing generation tasks.
Options:
--targon-api-key(required): Targon API key for authentication
Example:
404-cli stop-pods \
--targon-api-key your-targon-api-key-hereOutput: The command outputs status messages to stderr as it stops each container. No JSON output is produced on success.
Notes:
- Only containers with names matching "generator", "render", or "judge" are stopped
- If a container is already stopped, it will be skipped