Craftless is Browserless-style automation infrastructure for real Minecraft Java clients. It launches or attaches to real clients, loads a small in-client driver, discovers the live runtime capability graph, and exposes generated local OpenAPI contracts for agents, tools, tests, and CI.
Docs · API Reference · Releases · Roadmap · Agent Skill
- Real client automation. Drive actual Minecraft Java clients, headless by default or visible when a human should join.
- Generated APIs, not gameplay SDK drift. The stable supervisor API manages lifecycle; each running client exposes its own generated OpenAPI document for gameplay, resources, schemas, availability, and events.
- Agent-friendly control. External agents can discover, stream, invoke, and debug without reading Craftless source or depending on Minecraft internals.
- Packaged runtime. The released CLI, Docker image, and GitHub Action carry the driver manifest and verified Fabric lanes.
Install the latest released CLI on Linux or macOS:
curl -fsSL https://raw.githubusercontent.com/minekube/craftless/main/install.sh | sh
craftless daemon start --port 8080
export CRAFTLESS=http://127.0.0.1:8080When --workspace is omitted, the daemon uses CRAFTLESS_WORKSPACE or
~/.craftless/workspace, so the default API can launch clients, prepare cache
state, and expose artifacts without extra setup.
Create an API-first client. By default, Craftless derives an offline profile
from id, requests a windowless Minecraft client, and mutes game audio. A
windowless launch requires a real windowless strategy such as Linux xvfb-run
or CRAFTLESS_WINDOWLESS_WRAPPER; use presentation[window]=VISIBLE when you
want a local window:
craftless api /clients --api "$CRAFTLESS" \
-F id=bot -F version=latest-release -F loader=FABRICThe same request over HTTP:
curl -sS "$CRAFTLESS/clients" \
-H 'content-type: application/json' \
-d '{"id":"bot","version": "latest-release","loader":"FABRIC"}'Connect it to a Minecraft server:
craftless api /clients/bot:connect --api "$CRAFTLESS" \
-F host=localhost -F port=25565Discover the live contract before invoking actions:
craftless api /clients/bot/openapi.json --api "$CRAFTLESS"
craftless api /clients/bot/actions --api "$CRAFTLESS"
craftless api /clients/bot/resources --api "$CRAFTLESS"Invoke only actions advertised by the generated client OpenAPI:
craftless api /clients/bot:run --api "$CRAFTLESS" \
-F action=player.chat \
-F args[message]="hello from Craftless"Stream live events:
curl -N "$CRAFTLESS/clients/bot/events:stream"Install a specific release:
CRAFTLESS_VERSION=v0.3.0 \
CRAFTLESS_INSTALL_DIR="$HOME/.local/bin" \
sh -c "$(curl -fsSL https://raw.githubusercontent.com/minekube/craftless/main/install.sh)"Run the Docker image:
docker run --rm -p 8080:8080 \
-v "$PWD/.craftless:/var/lib/craftless" \
ghcr.io/minekube/craftless:latestUse Craftless from GitHub Actions:
jobs:
minecraft:
runs-on: ubuntu-latest
steps:
- uses: minekube/craftless/.github/actions/setup-craftless@v0.3.0
id: craftless
with:
start: "true"
workspace: .craftless
- run: curl -fsSL "${{ steps.craftless.outputs.api-url }}/openapi.json"The installer writes the launcher symlink to $HOME/.local/bin by default.
Set CRAFTLESS_INSTALL_DIR to use another directory. The installed
distribution carries the current, representative older, and latest/current
Fabric driver lanes, so craftless daemon start auto-discovers the packaged
driver manifest unless CRAFTLESS_FABRIC_DRIVER_MOD is set explicitly.
Minecraft artifacts are downloaded into the workspace at runtime; client and
server artifacts are resolved into the workspace and are not baked into the
Docker image.
The CLI has a small stable core for daemon lifecycle plus one OpenAPI-backed route invoker:
craftless --help
craftless daemon start --help
craftless api /clients --help --api "$CRAFTLESS"
craftless api /clients/bot/player:chat --method POST --help --api "$CRAFTLESS"Use craftless api <endpoint> for supervisor and per-client routes. Help,
parameters, request fields, enums, and descriptions are inferred from the
daemon's OpenAPI schemas. When an endpoint has multiple methods, such as
/clients, --help lists each matching OpenAPI operation so agents can choose
the right --method without guessing.
Craftless keeps the runtime shape deliberately thin:
- Supervisor API manages workspaces, cache preparation, Java runtime resolution, clients, files, events, and per-client spec discovery.
- Generated per-client API lives at
GET /clients/{id}/openapi.jsonand reflects the running client's version, loader, driver runtime, installed mods, registries, server features, permissions, resources, actions, schemas, availability, events, and fingerprints. - Runtime capability graph is the internal source for discovered resources, operations, handles, schemas, event metadata, and source evidence.
- Generic invocation uses
POST /clients/{id}:runor generated routes derived from the live OpenAPI document. - Live streams use Server-Sent Events for lifecycle, runtime, capability, and gameplay observations. JSON-RPC-style HTTP calls handle invoke, query, subscribe, and unsubscribe control.
- Adaptive consumers such as the CLI and agents fetch live specs instead of shipping static gameplay catalogs.
The earlier bridge evidence path is retired from active build and package wiring. Gameplay breadth belongs in the Fabric runtime capability graph and generated per-client OpenAPI, not in a legacy launch adapter.
Agents should behave like outside Craftless users:
- Fetch
GET /openapi.json. - List existing clients with
GET /clients; reuse a suitable client or stop abandoned clients before callingPOST /clients. - Remember that
POST /clientslaunches a new daemon-managed real Minecraft Java client process. It is not a selector, retry, or reuse operation. - Stop an abandoned client with
craftless api /clients/<id>:stop --api "$CRAFTLESS" -X POST. - Create a fresh id only for a deliberate independent client, such as multi-client co-play or concurrency testing. Creating fresh timestamped ids for retries leaves multiple Minecraft clients running.
- Fetch
GET /clients/{id}/openapi.jsonand treat itsx-craftless-actions,x-craftless-resources, route metadata, schemas, availability, and fingerprints as the gameplay authority. - Use
/clients/{id}/actionsand/clients/{id}/resourcesas projection evidence, not as independent catalogs. - Subscribe to
GET /clients/{id}/events:streambefore state-changing work. - Invoke only advertised actions through
POST /clients/{id}:run, generated routes, or the API-aligned CLI.
The repo-local craftless-public-gameplay-agent skill captures the public-agent workflow. Final gameplay evidence must include the connected OpenAPI document, projection artifacts, event capture, action log, and public inventory/world/entity observations. Do not use server-provisioned inventory, driver internals, Fabric internals, or hard-coded scenario actions as product proof. Product proof must run without server-provisioned inventory.
For "let's play", keep lifecycle and gameplay separate:
craftless daemon start --port 8080
export CRAFTLESS=http://127.0.0.1:8080
craftless api /clients --api "$CRAFTLESS" \
-F id=bot -F version=latest-release -F loader=FABRIC
craftless api /clients/bot:connect --api "$CRAFTLESS" \
-F host=localhost -F port=25565If Craftless should also manage the human-facing client window, opt into a visible, normal-audio presentation:
craftless api /clients --api "$CRAFTLESS" \
-F id=robin -F version=latest-release -F loader=FABRIC \
-F profile[kind]=OFFLINE -F profile[name]=Robin \
-F presentation[window]=VISIBLE -F presentation[audio]=DEFAULT
craftless api /clients/robin:connect --api "$CRAFTLESS" \
-F host=localhost -F port=25565If the human joins with their own launcher, skip the robin client and let the
bot coordinate through Minecraft chat and public Craftless events.
Craftless can prepare repeatable launch/cache state before running clients:
craftless api /cache:prepare --api "$CRAFTLESS" \
-F minecraftVersion=latest-release \
-F loader=FABRICWhen omitted, client creation and cache preparation default to
latest-release. Use latest-release or latest-snapshot for Mojang aliases,
or pin a concrete Minecraft version when a run must be reproducible.
Discover runtime and loader support through the supervisor API before pinning:
craftless api /versions/support-targets --api "$CRAFTLESS"
craftless api /versions/runtime-targets --api "$CRAFTLESS"
craftless api /versions/loader-targets --api "$CRAFTLESS"
craftless api /versions/loaders --api "$CRAFTLESS"
craftless api /versions/driver-mods --api "$CRAFTLESS"/versions/support-targets is the compatibility view agents should consult
first. It joins discovered Fabric Minecraft targets, game-scoped Fabric Loader
metadata, and the packaged Craftless driver manifest. Supported rows include
loader/runtime identity and driver-lane metadata; unsupported rows include
machine-readable reasons such as NO_DRIVER_MOD,
NO_COMPATIBLE_DRIVER_MOD, or NO_COMPATIBLE_FABRIC_LOADER.
Client creation rejects unsupported Fabric runtime requests before launch with
UNSUPPORTED_RUNTIME_TARGET and structured details, so callers can choose a
supported row without parsing the human message.
Java selection is part of the product runtime. Craftless evaluates configured, managed, mise, and system runtime providers against Minecraft version requirements.
Verified product surfaces include:
- stable supervisor OpenAPI at
GET /openapi.json; - generated per-client OpenAPI at
GET /clients/{id}/openapi.json; - graph-projected actions, resources, handles, schemas, availability, fingerprints, generated routes, and event metadata;
- generic invocation through
POST /clients/{id}:run; - SSE event streams plus JSON-RPC-style HTTP control/query calls;
- API-aligned CLI discovery, OpenAPI-derived help, route invocation, action invocation, and event streaming;
- release workflow, install script, Docker runtime image, packaged CLI distribution, and reusable GitHub Action;
- Latest/current
26.2, current1.21.6, and representative older1.20.6packaged lanes are verified with generated OpenAPI, projections, SSE, JSON-RPC, andcraftless apiinvocation evidence; - Fabric version support is exposed as a matrix at
GET /versions/support-targets; supported runtime rows are probeable through the packaged matrix workflow, and unsupported runtime requests fail closed before launch with machine-readable reasons; - final public gameplay evidence using generated public APIs only, with server provisioning disabled and no static survival macro.
The active completion checklist is the current source of truth: docs/project-completion-checklist.md.
| Area | Craftless | Mineflayer | Baritone | Prism Launcher |
|---|---|---|---|---|
| Runs the real Minecraft Java client | Yes | No, protocol bot | Yes | Yes |
| Local OpenAPI control plane | Yes | No | No | No |
| Live per-client generated API | Yes | No | No | No |
| Runtime discovery from version/mod/server state | Core design | Protocol data oriented | In-client pathing state | Launcher/profile state |
| External agent and CI usage | Primary use case | Script/library use | Mod/API use | Launch management |
| Pathfinding maturity | Growing | Mature bot movement ecosystem | Mature pathfinding | Not a pathfinder |
| Public gameplay surface | Generated Craftless actions/resources | Library API | Java/mod commands/API | None |
| Best fit | Real-client automation infrastructure | Fast protocol bot scripts | In-game navigation/pathing | Client installation and launch UX |
Craftless is not trying to replace Mineflayer, Baritone, or Prism Launcher. The goal is a Browserless-style runtime for real Minecraft clients where agents can discover the live API and operate through stable local contracts.
Use pinned tools through mise:
mise install
mise run lint
mise run architecture-check
mise run ciFocused commands:
mise exec -- gradle test
mise exec -- bun test playwright
mise run package-cli
mise run ci-craftless-smokeDocs-only edits must at least pass:
git diff --checkOpt-in real Minecraft checks can download artifacts and launch server/client processes:
CRAFTLESS_LOCAL_SERVER_SMOKE=1 mise exec -- gradle :testkit:localMinecraftServerSmoke
CRAFTLESS_FABRIC_CLIENT_SMOKE=1 mise exec -- gradle :driver-fabric:fabricClientSmoke
CRAFTLESS_FINAL_GAMEPLAY=1 mise exec -- gradle :driver-fabric:fabricFinalGameplayRelease Please opens or updates the release PR on pushes to main, manual
dispatch, and the weekly scheduled check when releasable changes exist since
the latest v* release. Merging that PR creates the next vX.Y.Z tag; the
tag-driven release workflow builds CLI archives, checksums, Docker image, and
GitHub release notes.
- Hosted docs
- API reference
- Product positioning
- Client file management
- Agent skills
- Roadmap
- Final gameplay runbook
Historical specs, plans, and evidence live under docs/superpowers/.
