mindfork mindfork

mindfork 0.11.0 — from a bare Linux machine to a local model, in one line

mindfork 0.11.0 is out. It has one subject: the distance between "the app is unpacked" and "a local model answers", and what that distance costs on a machine you rent by the hour.

On a desktop you cross it once: download llama.cpp, install the Python sandbox, open the settings and type four paths and a number — the model, its vision projector, the embedding model, the context. On a rented GPU box you cross it every time. On RunPod the container's own disk is cleared whenever the pod stops, not only when it is terminated; what survives is one directory. So the set-up is done per rental, in a browser terminal, while the meter runs.

One command

mindfork setup --sandbox --llama cuda-12 \
  --model /models/gemma-4-31b-it-q4_0.gguf \
  --mmproj /models/mmproj-gemma-4-31b-it-f16.gguf \
  --embed-model /models/bge-m3-Q8_0.gguf \
  --ctx 32768 --verify

Every option is one step, and a step you do not name is not run — mindfork setup --ctx 65536 alone is a perfectly good use. What matters more than the list is how it behaves:

  • Paths and keys are checked before anything is downloaded. A model path that names no file, a part of a multi-file GGUF that is not the first, a setting that does not exist — each is an error now, in the words the app would have used at launch, not a status line ten minutes and a gigabyte later.
  • A step that fails does not stop the others. If the sandbox download fails, llama.cpp is still installed and the settings are still written; the command ends with what failed and a non-zero exit code. Run the same line again and it repeats only what is missing.
  • It writes the settings — once, at the end, and only if something changed. That is the difference from the MINDFORK_* environment variables, which override on every launch: what setup sets is what the settings screen shows, and what you change there afterwards sticks.
  • --set reaches everything else, by the field's path in settings.json: --set engine.managed.sessions=4 --set engine.managed.no_mmap=true. A key that does not exist is refused rather than silently dropped. API keys cannot be set this way — a key on a command line ends up in the shell's history; name the variable that holds it instead.

And then --verify starts exactly what the app will start — the chat server and the embedding server, both at once, since whether the two fit the card together is one of the questions — waits for each to load, and says what it found:

== Starting what was configured
  chat server: starting on port 8000…
  embedding server: starting on port 8001…
  chat server: ready in 41 s — context 32768, takes images, 4 slots
  embedding server: ready in 6 s

A context too large for the card, a projector that belongs to another model, a port something else already listens on — each shows up here as FAILED with the reason, while the command line can still be edited.

And the line before it

mindfork setup cannot put mindfork on a machine that does not have it. An install script does, and then hands over:

curl -fsSL https://github.com/vshylov/mindfork-rs/releases/latest/download/install.sh \
  | sh -s -- --dir /workspace/mindfork -- setup --sandbox --llama cuda-12 \
      --model /workspace/models/chat.gguf --ctx 32768 --verify

It unpacks the portable build into one directory, refuses the archive unless it matches the release's checksums, and then runs the binary to see whether it starts. On a bare image it does not — the app needs one system library that minimal images do not carry — so the script installs that package with the system's package manager, or stops and prints the exact command. Everything after -- goes to mindfork.

Run it again and it downloads nothing that is already there. On a pod that was stopped and started, the same line takes seconds: what sits on the volume is recognised, and only what the container lost is put back. Your data is never touched.

The script is an asset of the release, like the archive — listed in sha256sums.txt, covered by the same build attestation — so piping it adds no party to trust that the binary had not already added. If you would rather read before you run: download it, read it, sh install.sh. It is one short POSIX script. On a desktop the short form is all there is to it:

curl -fsSL https://github.com/vshylov/mindfork-rs/releases/latest/download/install.sh | sh

The install guide has the recipe for a rented box in full: which image to pick, why tmux is not decoration there, what to do about API keys in a container, and what to take with you before you terminate the pod.

CUDA on Linux

mindfork llama setup downloads llama.cpp for your machine. Until the middle of September llama.cpp published no CUDA build for Linux; now it does — and mindfork refused to install it. The build's CUDA runtime is a separate archive, and on Linux it is named differently than on Windows; the command looked for the Windows name, found nothing, listed the backend as "no CUDA runtime published" and stopped. It looks for what the release actually publishes now.

The same check turned up two more things. Recent llama.cpp builds print a log line ahead of their version, so the command showed that line as the version — and the check that the binary you got is the build you asked for, finding no number to compare, skipped itself without saying so. The version is found by what it says now, and a binary that names no build number is reported as such. And with no --build, the command takes the newest build that actually has the backend you named, complete — a nightly is now and then published empty or half-uploaded.

One small addition rides along: a backend family. llama.cpp renames its CUDA builds whenever it moves to the next toolkit — cuda-13.3 became cuda-13.4 inside two weeks — so a command you had saved stopped working. --backend cuda-12 installs the one cuda-12.* build on offer.

Nothing about the stored data changes in this release: no migration runs, and 0.10.2 and 0.11.0 open the same files.

The full list is in the changelog. Downloads — Windows installer and archive, Linux archive, .deb, .rpm and .pkg.tar.zst, and now install.sh — are on the releases page, and cargo install mindfork builds the same version from crates.io.