Ctrl K
ComunidadGuías…

CHANGELOG.md

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# Changelog

Notable changes to the scripts. Dates are the commit dates on `main`.

The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).

## [Unreleased]

## [1.2.0] — 2026-10-15

### Added

- **`kiln pi`** (`./kiln.sh pi`) lists the local models in
  [pi](https://pi.dev), the terminal coding agent. It adds a `kiln`
  provider to pi's `models.json` and takes the same `--print`,
  `--remove` and `--url` as `kiln opencode`. pi's built-in llama.cpp
  provider needs llama-server's router mode, so it lists nothing for a
  server `kiln start` runs. The key is read from `api_key.txt` by a
  command rather than copied. `p` in `kiln tui` runs it.
- **`kiln cursor`** (`./kiln.sh cursor`) sets Cursor up in one step. It
  points Cursor's OpenAI base URL at the tunnel `kiln start` opened,
  turns on the API-key override and lists the downloaded models. After
  that `kiln start` points Cursor at each new tunnel and `kiln stop`
  turns the override off. Changes wait for Cursor to close, which would
  otherwise write its own copy back. From WSL it sets up the Windows
  Cursor. `--off` gives back Cursor's own settings. The key is pasted
  once: Cursor encrypts it, so kiln puts it on the clipboard instead.
  `C` in `kiln tui` runs it. `scripts/unix/cursor_tunnel.sh` now goes
  through it too.
- **Gemma 4, opt-in.** `kiln get gemma-26b` and `kiln start gemma-26b`
  serve Google's Gemma 4. There are four variants: `gemma-31b`,
  `gemma-26b` (26B-A4B MoE), `gemma-12b` and `gemma-e4b`. Each one has
  its own MTP draft head and vision projector, and the same arithmetic
  as Qwen sizes the download and the context to your card. kiln never
  picks Gemma on its own. `kiln hardware`, a bare `kiln get` and a bare
  `kiln start` all stay on Qwen3.8, unless Gemma is the only thing
  downloaded. If a Gemma model is too big for the card, kiln points you
  at a smaller Gemma model. It never suggests E4B, which is weak at
  tool calls. Gemma needs llama.cpp b11059 or newer, and `kiln start`
  refuses an older build before it stops the running server.
  `hardware.py --table gemma` prints the Gemma context table. The sizing
  was checked by loading the 31B, 12B and E4B on a 5090. That showed
  Gemma's attention scratch and its MTP head both cost VRAM per token.
  Counting that keeps the 31B on a 32 GB card from running out of
  memory. The benchmark measures and picks within the model line you
  run, as it already did for abliterated builds, and it never picks
  E4B while anything else was measured.
- **`kiln quality` on Windows**, which only `./kiln.sh` had.
- **`kiln key set` on macOS and Linux.** It used to print the old key
  and change nothing. Only Windows had it.

### Changed

- **Each model family carries its own launch settings.** The registry in
  `scripts/hardware.py` now holds each family's MTP head and projector,
  sampling, draft length, reasoning flag and minimum llama.cpp build.
  The start scripts read these instead of assuming Qwen's. Qwen launches
  with exactly the flags it had before. The four Unix start scripts now
  share one copy of this logic in `lib_select.sh`.

- **Bare `kiln` opens the TUI.** `kiln` with no arguments (`./kiln.sh`
  on macOS and Linux) starts the full-screen app. `kiln status` still
  prints the status board. If the TUI cannot start — no Python, or the
  output is not a terminal — kiln says why and prints the board instead
  of hanging. Unix setup links `kiln` to `~/.local/bin/kiln` without
  sudo. That link resolves back to the checkout, so the command works
  from any directory.
- **`kiln` on PATH on Windows too.** `kiln setup` writes a `kiln.cmd`
  shim into `%USERPROFILE%\.local\bin` and adds that folder to the user
  PATH, so `kiln` runs from any folder in a new terminal. No admin
  rights are needed. The rest of the user PATH is kept as it was:
  `%USERPROFILE%`-style entries stay unexpanded. `kiln path` does only
  this step on every platform, and `kiln path --remove` undoes it. It
  never replaces or deletes a `kiln` that some other tool put there.
  On macOS and Linux, setup now says how to put `~/.local/bin` on PATH
  when it is missing, which it always is on macOS.

### Fixed

- **kiln stops only its own llama-server.** `kiln stop`, `kiln start`,
  the benchmark and the quality run stopped every llama-server on the
  machine (`pkill -x llama-server`, `taskkill /IM llama-server.exe`), and
  the status board counted any of them as kiln's. kiln's server is now
  the one on kiln's port, the same rule as the tunnel, through
  `scripts/unix/lib_server.sh` and `scripts/windows/kiln_server.ps1`.
  Stopping waits for it to exit, because the next launch needs its
  memory.
- **The macOS and Linux start scripts no longer quit on a slow tunnel.**
  They read the tunnel's address once, after 12 seconds, and exited
  when it was not there yet, before printing the API key, leaving the
  server and tunnel running. They now wait up to a minute and carry on
  either way. Ctrl+C while the model loads now stops the server too;
  until the load finished, it kept the GPU.
- **MTP is no longer reported missing on macOS.** The check for it read
  llama-server's help through `grep -q` under `pipefail`, which fails
  whenever grep stops reading first, and macOS's small pipe buffer made
  that likely.
- **Failing commands fail on Windows.** `kiln get VARIANT` and
  `kiln start VARIANT` returned success whatever happened, so `kiln tui`
  showed a failed download as done. Unknown commands return an error.
- **`kiln key set` on Windows keeps the key as typed.** It dropped or
  mangled `! ^ ' % & >`, and still said "key set". Quote the key:
  `kiln key set "YOUR-KEY"`.
- **The API key stays where it belongs.** The key is now sent to a
  server only after it answers as llama-server; before, `kiln tui`,
  `kiln opencode` and `kiln pi` sent it to whatever held port 8080, and
  to the WSL gateway. It no longer lands in `kiln-benchmark.json` when a
  setup fails, and the job logs `kiln tui` keeps are deleted when it
  quits. Keys made on macOS and Linux are 24 bytes, as on Windows and as
  documented, not 16. The file is created readable only by you, and
  locked down again on every start.
- **A small card gets a plan for the model you name.** `kiln get base`
  on a 16 GB card said nothing fits, and Windows then offered the
  31.5 GB download first. It now offers the largest quant that loads,
  says when that is a low-bit one, and defaults to the smallest when
  nothing fits comfortably. Intel Macs are sized for the CPU, not as
  Apple Silicon.
- **Windows paths and locales.** The free-space check reads the drive
  kiln is on, not always `C:`, and works where the decimal mark is a
  comma. A `'` in the folder path works. A `!`, `%`, `[` or `]` is
  refused with a message rather than breaking in odd places. The status
  board shows the tunnel URL again.
- **`kiln tui` copes.** A Python environment broken by an upgraded or
  removed Python is rebuilt instead of failing on every run. Closing
  the window cancels a download or setup still running, as quitting
  does; a model that is serving keeps serving. A benchmark whose results
  file cannot be written, say because OneDrive has it locked, keeps the
  results and says so instead of closing the app.
- **Setup keeps a working llama.cpp.** Linux setup in a Windows
  checkout used from WSL deleted the Windows build; it now stops and
  says how to go on. A new build replaces the old one only once it is
  in place, and a failing `nvidia-smi` is reported instead of ending
  setup without a word.
- **Linux and WSL setup give an NVIDIA card the CUDA build.** Newer
  `nvidia-smi` prints `CUDA UMD Version: 13.4` where it printed `CUDA
  Version: 13.4`, so setup read no CUDA version and fell back to Vulkan
  on every NVIDIA card. `./kiln.sh setup` on Ubuntu and WSL also asked
  for Vulkan outright. Under WSL that build sees no GPU and runs the
  model on the CPU, while CUDA passes straight through: on a 5090 the
  WSL CUDA build matched the Windows one. Setup now takes the CUDA
  build when there is an NVIDIA driver, and Vulkan, then CPU, otherwise.
  An existing `llama-bin/` is kept, so move it aside and re-run setup
  to switch.
- **Fedora setup no longer downloads a Vulkan build from `/releases/latest`.**
  That URL is the empty v0.x line, so `./kiln.sh setup` on Fedora found
  nothing. An NVIDIA card now gets the Ubuntu CUDA build whose toolkit
  the driver can load (12.8 unless the driver reports 13.4 or newer),
  plus the separate cudart tarball. Fedora does not ship those libraries,
  and the server looks for them beside the binary. No NVIDIA card still
  falls through to Vulkan, then CPU. The WSL/Linux installer keeps
  Vulkan and uses the same bNNNN tag lookup.
- **Linux and WSL serve on port 8080 again.** `start_linux.sh` had
  moved to 8081, while `kiln opencode`, the Cursor tunnel and the docs
  all use 8080, so on Linux and WSL they pointed at nothing. The Slurm
  job keeps 8081.
- **Config backups keep the file's permissions.** The `.kiln.bak` that
  `kiln opencode` and `kiln pi` make, and the temporary file each write
  goes through, start with the mode of the file they copy, so a config
  readable only by you never sits in a readable copy.
- **`kiln stop` stops only kiln's tunnel.** It, the macOS and Fedora
  start scripts and the Slurm job ran `pkill -x cloudflared`, and on
  Windows `kiln stop` and `kiln start` ran `taskkill /IM cloudflared.exe`.
  That stopped every cloudflared on the machine: a named tunnel, a
  tunnel run as a Windows service, or T3 Code's remote access. kiln now
  stops only the quick tunnel to its own port, matched by its command
  line, through `scripts/unix/lib_tunnel.sh` and
  `scripts/windows/kiln_tunnel.ps1`. `kiln tui` uses the same rule
  before it shows a tunnel URL, so another program's tunnel no longer
  makes an old URL look live.
- **`./kiln.sh get` on Fedora and Debian.** A plain `pip install` into
  the system Python is refused there. The download uses `huggingface_hub`
  when it is already installed, and otherwise installs it for the user.
- **`kiln update` and `kiln setup` on Windows.** llama.cpp moved its
  Windows CUDA builds from 13.3 to 13.4 at b11000. Both scripts were
  pinned to 13.3, so `kiln update` failed with a 404. `kiln setup` also
  read `/releases/latest`, which has no Windows CUDA build at all. Both
  now take the newest bNNNN release. From it they take the newest CUDA
  build that has a cudart zip of the same version, and they download
  that zip too. `kiln setup` also failed to parse, with
  `... was unexpected at this time`, in two places. One was its download
  progress line. The other was the cloudflared block, which breaks on
  the `(x86)` in the install path even when cloudflared is already
  installed.
- **The Windows status board shows the llama.cpp build again.** Newer
  builds print `version: 0.6.0-dev (build 11624, ...)`, and the board
  showed `build 0.6.0-dev`.
- **macOS setup downloads llama.cpp again.** `install_mac.sh` read
  `/releases/latest`, which is now the v0.x line with no binaries, and
  wanted a `.zip` where the Mac builds are now `.tar.gz`. It found
  nothing and exited without a message. It now uses the same bNNNN
  lookup as Linux and Fedora. Apple Silicon gets the Metal build, also
  from a shell running under Rosetta. Intel gets the x64 build, which
  llama.cpp compiles without Metal, so it runs on the CPU. Homebrew
  installs cloudflared from homebrew-core, where Cloudflare's tap moved
  it, and the direct download creates `/usr/local/bin` when it is
  missing. The README now asks for macOS 13.3, the oldest release those
  builds load on.
- **`kiln start` on macOS with the 9B or 4B.** macOS runs the start
  script with its stock bash 3.2, which treats an empty array as unset
  under `set -u`. A model with no MTP head and no projector left the
  extra flags empty, and the launch died with `EXTRA[@]: unbound
  variable`. The sampling flags now always fill that list, and
  `start_mac.sh` expands both of its arrays in a form bash 3.2 accepts
  when one is empty.

## [1.1.0] — 2026-10-01

### Added

- **`kiln tui`** (`./kiln.sh tui`) is the status board and the everyday
  commands as a full-screen terminal app. You can start, switch and stop
  models, download one, copy the URL and API key Cursor needs, set up
  OpenCode, and update kiln, with each command's output shown as it
  runs. It runs the same kiln commands rather than reimplementing them.
  The first run offers to install Textual into `.kiln/`, a folder inside
  the checkout. It needs Python 3.9+. A model started from it keeps
  serving after you quit. It is also item 9 on the Windows menu.
- **A benchmark in `kiln tui`** (press `b`, or `scripts/bench.py`)
  starts each downloaded model with and without the MTP head through
  `kiln start`, with the tunnel off. It times prefill, generation, MTP
  acceptance and, on a thorough run, generation 32K tokens deep. Then it
  recommends the fastest setup that keeps 96K of context, and starts
  the one you pick. Setups whose runs overlap are called a tie, and the
  abliterated build is only measured and picked if it is the one you
  run. `p` copies the results as a markdown table for a hardware report.
  Unlike `kiln bench`, it measures what MTP is worth.
- **`KILN_NO_TUNNEL=1`** makes every start script skip the Cloudflare
  tunnel. `l` in `kiln tui` sets it for the next start.
- **`./kiln.sh start --no-mtp`** trades the MTP draft head for a larger
  context window on macOS and Linux, as `kiln start --no-mtp` already
  did on Windows.
- **A warning when another program holds the server's port.** On
  Windows a WSL or Docker container publishing 8080 takes
  `127.0.0.1:8080` ahead of llama-server, so localhost and the tunnel
  reach that program instead. `kiln tui` says so and finds the server by
  the machine's name.
- **`.github/scripts/test_control.py`, `test_bench.py` and
  `test_tui.py`** run in CI. They check that only the fixed command list
  reaches a command line, that a benchmark never opens a tunnel and
  always frees the GPU, and that the app's keys do what they say.
- **`kiln self-update`** (`./kiln.sh self-update`) updates kiln itself
  from GitHub. By default it moves to the newest `vX.Y.Z` release.
  `--main` follows every change on `main` instead and is remembered.
  `--check` only reports. The update is a git fast-forward, so `models/`,
  `llama-bin/` and `api_key.txt` are never touched. It refuses, changing
  nothing, when there are local edits, local commits or another branch
  checked out. It is also item 8 on the Windows menu.
- **A `kiln` row on the status board** shows the version you are on, and
  the newest release when there is a newer one. It asks GitHub at most
  once a day with `git ls-remote`. `KILN_NO_UPDATE_CHECK=1` turns that
  off.
- **`.github/scripts/test_selfupdate.py`** runs in CI against throwaway
  repositories and checks that every refusal leaves HEAD where it was.
- **`kiln opencode`** (`./kiln.sh opencode`) — lists the downloaded
  Qwen builds in OpenCode as `kiln/<alias>`, each with the context window
  `kiln start` would open for it. Works on Windows, WSL and Linux, and
  works out the WSL-to-Windows address itself. Merges into an existing
  config rather than replacing it, and references `api_key.txt` instead
  of copying the key. `--remove` undoes it. Refuses, leaving the file
  untouched, when the config cannot be parsed or the key file is missing.
- **A Python job in CI** that byte-compiles every script and runs
  `.github/scripts/test_opencode.py`.
- **`kiln hardware`** — reads the GPU and prints the model, quant, MTP
  head, vision projector and context window that fit it, which is exactly
  what `kiln get` will download. Available as `kiln hardware` and
  `./kiln.sh hardware`.
- **`scripts/hardware.py`** — the model registry and the sizing
  arithmetic, shared by every script on both platforms. Holds the repos,
  the quant ladders with exact byte counts, and the per-family KV-cache
  model. Also generates the context tables in `README.md`, so the docs
  cannot drift from the code.
- **Two smaller model families**, for cards a 27B has no business on:
  `9b` and `4b`, Empero's Apache-2.0 distillations of Qwen3.8-2.4T-A95B.
  Both are third-party rather than Qwen releases, and are labelled as such
  everywhere they are offered. Both are text-only — no MTP head, no vision.
- **Six more 27B quants.** The ladder is now the eleven `UD-*` names
  present in both the unsloth and huihui-ai repos, rather than five.
- **The q4_0 MTP head and the q8_0 vision projector.** 1.4 GB and 0.3 GB
  smaller than the ones used before, and the reason a 24 GB card can now
  keep speculative decoding.

### Changed

- **The default model and context window are chosen from your GPU, not
  assumed.** `kiln get` used to default to `UD-Q5_K_XL` on every machine —
  right on the 32 GB card this repo was tuned on, a guaranteed OOM on a
  12 GB one. Downloads, launches and menus now default to what fits, and
  say what they picked. An explicit `QUANT=` or `VARIANT=` still wins.
- **24 GB cards no longer have to choose between MTP and quant quality.**
  `UD-IQ4_XS` with the q4_0 head reaches ~104K with speculative decoding
  on. The README previously recommended giving up MTP for `UD-Q4_K_XL` at
  72K; that advice predated the smaller head.
- **`kiln start` prefers the tier's quant among the files on disk** and
  prints a one-line note when a better one exists, but never re-picks
  weights behind your back.
- The three Unix start scripts and `slurm-llama.sh` now share
  `lib_select.sh` instead of each carrying its own hardcoded quant, MTP
  filename and context.
- **The root `kiln.bat` exits on the same line that calls the CLI.** An
  update that rewrites the file can no longer leave cmd reading half a
  line of the new version.

### Fixed

- The `kiln setup` and `kiln update` lines of the README quick start had
  run together onto one line.
- **The documented 131K context on a 32 GB card was never what the code
  produced.** The probe computes 114688 with `UD-Q5_K_XL` + the q8_0 head
  + f16 vision; 131072 is what loaded when tried by hand. The comment
  claiming the 0.85 safety factor reproduced 131072 was wrong, and every
  131K in the README has been corrected to the computed figure.
- **`start_mac.sh` and `start_fedora.sh` exited silently when the vision
  projector was absent.** `[ -f "$MMPROJ" ] && EXTRA+=(...)` returns
  non-zero under `set -euo pipefail`, killing the script before it printed
  anything. Same bug in `slurm-llama.sh`.
- **The Unix scripts could not find Python on Windows shells.** `command
  -v python3` resolves to the Microsoft Store alias stub, which exits 0
  and prints nothing, so every lookup silently fell back. `lib_python.sh`
  now verifies the interpreter answers, and strips the CR that Windows
  Python puts on each line — a trailing `
` made `V_MTP` compare unequal
  to `1` while still printing as `1`.
- **The status board's "shared files" row** reported "no MTP head" on
  machines given the q4_0 head, because it matched the q8_0 filename only.

## [1.0.0] — 2026-09-03

First tagged release. The repo has been usable for months; this marks the
point where the Qwen3.8 path, the API key, and the `kiln` CLI are all in
place across every platform.

### Added

- **`kiln`, a single entry point on every platform.** Prints a status
  board of what is installed, downloaded and running, names the one thing
  to do next, and offers a menu. Verbs for every step: `status`, `setup`,
  `update`, `get`, `start`, `stop`, `key`, `bench`, `clean`. `kiln.bat` on
  Windows, `./kiln.sh` on macOS and Linux — the latter detects your
  distribution and dispatches to the right platform script.
- **A `scripts/` layout.** The repo root was 36 loose files; it is now the
  entry point plus documentation, with `scripts/windows/` and
  `scripts/unix/` holding the rest.
- **Shared libraries** — `lib_variants`, `lib_api_key`, `lib_ui` — so the
  Windows and shell script families no longer duplicate variant
  definitions or key handling.
- **Abliterated build** alongside the stock one, selectable at launch with
  `kiln start ablit` or `VARIANT=ablit`. Both builds share one copy of the
  MTP head and vision projector, so the second download is weights-only.
- **`scripts/unix/slurm-llama.sh`**, to run the server as a Slurm batch job so the GPU
  shows as allocated in `squeue`.
- **`kiln quality`**, scoring each quant against `Q8_0` by
  KL-divergence rather than perplexity.
- **`kiln bench`** — quant speed, ubatch sweep, KV precision and
  throughput vs. context depth.
- **`kiln clean`**, to reclaim space from superseded GGUFs. Requires
  typing `DELETE`.

### Changed

- **Default model is now Qwen3.8-27B**, replacing Qwen3.6-35B-A3B. Better
  coding scores, native MTP, and a hybrid-attention stack that makes long
  context far cheaper.
- **MTP speculative decoding is wired up by default** via
  `--spec-type draft-mtp`, which needs llama.cpp **b9180+**
  ([PR #22673](https://github.com/ggml-org/llama.cpp/pull/22673)).
- **Context is sized from your actual hardware.** `probe_hardware.ps1`
  reads VRAM and the weight files on disk and computes the window that
  fits; the shell scripts use llama.cpp's `--fit on`. No card is
  hardcoded any more.
- **KV cache precision raised to `q8_0`** from the `q4_0` used in the
  Qwen3.6 setup. In a 75%-linear-attention stack, low-bit KV error
  accumulates along the sequence instead of being re-anchored each token.
- **`--parallel 1`** rather than llama.cpp's auto default, which splits
  the KV cache across slots and hands a single-user Cursor session only
  `ctx/N` of its own context window.

### Removed

- **Legacy Windows forwarders** `run.bat`, `start_windows.bat` and
  `download_model.bat`. Use `kiln` instead.
- The `qwen` command is now `kiln`. It collided with Alibaba's official
  Qwen Code CLI and tied the tool to a single model family.

### Security

- **All platforms now generate an API key** into `api_key.txt` and serve
  with `--api-key-file`. The file is locked to the invoking account on
  every launch (`chmod 600`; `icacls /inheritance:r` on Windows). See
  [SECURITY.md](SECURITY.md).

### Fixed

- A batch of cmd.exe bugs that were latent in shipped scripts: unescaped
  parentheses inside `( )` blocks aborting the launcher, `::` comments
  inside blocks, `for /f` splitting `nvidia-smi` options on commas,
  `timeout /t` spinning when stdin is redirected, and
  `if COND set A & set B` running the second `set` unconditionally. All
  are written up in [NOTES.md](NOTES.md).
- Line endings pinned in `.gitattributes` — a `.sh` checked out with CRLF
  fails on Linux with `\r: command not found`.

## Earlier

- **2026-07-21** — Slurm launch path and a `cloudflared` helper.
- **2026-04-25** — Fedora support (thanks @EmeryJJ).
- **2026-04-24** — Initial local model setup, Windows start scripts, and
  Cursor instructions.

[1.2.0]: https://github.com/Lampsdad/kiln-local-llm/releases/tag/v1.2.0
[1.1.0]: https://github.com/Lampsdad/kiln-local-llm/releases/tag/v1.1.0
[1.0.0]: https://github.com/Lampsdad/kiln-local-llm/releases/tag/v1.0.0