# Changelog

All notable changes to Keelcode will be documented in this file.

The format is based on Keep a Changelog, and this project follows Semantic
Versioning.

## [Unreleased]

## [0.2.0] - 2026-08-16

### Changed

- The CLI now completes a short client handshake with the Keelcode gateway on
  login and on first use, which links this machine to your account and keeps
  it eligible for API access. Older releases will be asked to update.

### Added

- `keelcode login` reports immediately when a machine has reached its account
  limit, instead of failing later at the first prompt.

## [0.1.19] - 2026-08-16

### Fixed

- `/bypass` (and `--yolo`) is now actually prompt-free. The workspace-escape
  check ran before the bypass check, so any file access outside the project
  directory still prompted in bypass mode. With an approver present
  (interactive TUI, or headless with `--approval-protocol`), bypass now
  crosses the workspace boundary silently. Deny rules stay absolute, and
  approver-less contexts (subagents, plain headless) still fail closed
  outside the workspace.
- Answering "always allow" on an outside-the-workspace prompt now sticks. The
  persisted rule was never consulted on that path, so the same access re-asked
  forever; a matching allow rule now counts as the explicit approval the
  boundary demands, in every permission mode.
- On Windows, rules persisted by "always allow" for file tools are stored with
  `/` separators. The previous escaped-backslash form could never match the
  slash-normalized candidate path, so the rule was dead on arrival.

## [0.1.18] - 2026-08-16

### Fixed

- A model the gateway currently serves is no longer remapped away by the
  retirement table. The Claude aliases withdrawn on 2026-08-01 came back as
  staff-only models, and the old unconditional remap silently sent a staff
  user's `claude-fable-5` or `claude-sonnet-5` run to `gpt-5.6-luna`. The
  remap now consults the live `/v1/models` catalog and only migrates
  selections the gateway no longer answers for; offline, the conservative
  migration still applies.

## [0.1.17] - 2026-08-13

### Changed

- A failed request now shows what the server actually said. Asking for a model
  that does not exist reads `Model not found — Choose a model returned by
  /v1/models.` instead of a paragraph about the endpoint having no Messages API,
  followed by the raw JSON body and a request id.
- `--help` is grouped into ACCOUNT, WORK, EXTEND and MAINTAIN, so the common
  path is visible without reading a flat list of twenty-seven commands.
- A first run is greeted instead of reported as a failure: with no session,
  `keelcode` prints a short welcome and the one command to run. The exit code
  stays non-zero, so scripts and CI still see a failed invocation.
- Signed-out runs report the error code `not_logged_in` rather than the
  catch-all `config`, so `--output-format json` and desktop `stream-json`
  clients can tell "sign in" from "your settings are wrong". This is a
  behavioural change for anything matching on the old code.

### Fixed

- A 404 that is not a wrong base URL is no longer diagnosed as one. The CLI no
  longer tells you to check your connection and sign in again when the real
  problem was the model name.
- Error text on stderr is no longer dimmed. Dimming put the one line you have
  to read at the same weight as tool chatter, and below comfortable contrast on
  some terminal themes.
- An oversized or non-JSON error body is bounded to 300 characters instead of
  filling the terminal, and internal error codes no longer appear in the
  sentence shown to the user.

### Performance

- Subcommands no longer load the interactive TUI. React, Ink, the tool
  registry, MCP, the extensions runtime and the per-command CLIs are now
  imported where they are used, so `keelcode status` starts in about 30 ms
  rather than 80 ms and peaks near 62 MB rather than 100 MB.

## [0.1.16] - 2026-08-07

### Added

- Hosted requests now carry a browser fingerprint and identify the CLI build,
  so the gateway can tell client versions apart when a rollout needs to give
  newer builds different guidance.

### Fixed

- A request rejected because the account needs browser verification now shows
  what to do — the verification URL and the steps — instead of the raw error
  body from the gateway.

## [0.1.15] - 2026-08-06

### Added

- The `/models` picker is now searchable: type to fuzzy-filter the catalog,
  see highlighted matches, and keep using the arrow keys to choose a model.
- `/update` checks for a new version from inside a session and starts the
  install (or names the exact package-manager command, on managed installs).
- `/changelog [version]` shows release notes embedded in every install, and
  the one-time notice after an automatic update now points to it.
- `keelcode doctor` gained an Updates row with the install channel, current
  version, last registry check, pending version, and last update failure.

### Fixed

- A fully spent git-context probe timeout now stops immediately instead of
  being interpreted by Node as no timeout, which could block the TUI.

## [0.1.14] - 2026-08-04

### Added

- Keelcode keeps itself up to date. An interactive session checks the registry
  in the background at most once every six hours; curl-script installs
  download the new version, verify its sha512 against the registry manifest,
  and switch the `~/.keelcode/bin` links to it atomically — the next launch
  runs the new version and says so once. Package-manager installs are never
  written to behind the manager's back: they get a one-line notice on the
  startup screen instead.
- `keelcode update [--check]` — the same update in the foreground, on demand.
  On npm-managed installs it runs the detected package manager (npm, pnpm,
  yarn, or bun) rather than touching `node_modules` itself.
- `autoUpdate` setting (default `true`); `KEELCODE_AUTO_UPDATE=0` and CI
  environments disable the background updater without touching settings.

### Changed

- Startup got measurably lighter: syntax highlighting and the MCP SDK moved
  off the launch path (main chunk 3.0MB → 1.45MB, first paint ~1.0s → ~0.6s,
  idle RSS ~155MB → ~110MB). Sessions that never use an MCP server never load
  the SDK at all.
- Long sessions hold memory instead of growing it: the read-before-write
  cache and the /rewind checkpoint store are now LRU-bounded, losing only
  history depth, never correctness.
- Thinking-phase streaming stopped committing a full UI frame per SSE event,
  and live-tail rendering skips re-highlighting pathological open code blocks
  past 20k characters.
- Dropped unused dependencies (`marked-terminal`, `lodash-es`) and bumped
  four transitive security pins (`fast-uri`, `brace-expansion`, `hono`,
  `ip-address`) past fresh advisories; `bun audit` is clean.

### Fixed

- Tool calls from open models with structurally malformed arguments (a JSON
  array sent as a string, a lone value where a list was wanted, `null` for an
  omitted optional) are repaired at the exact paths schema validation names,
  instead of surfacing as confusing runtime errors inside the tool. Valid
  input is never touched: validation runs first, repair only on failure.
- `/usage` reported "Keelcode usage is temporarily unavailable" against a
  healthy endpoint. The hosted response schemas rejected unknown keys, so when
  the gateway added a `model_quotas` field every installed CLI refused to read
  an otherwise valid `200`. Response schemas now ignore fields they do not
  recognise while still validating every field the CLI reads, so a future server
  addition cannot break an older client.
- A `200` the CLI cannot parse and a genuine HTTP failure no longer share one
  message. An unreadable response names itself a client problem and points at an
  upgrade; an outage reports its status code.
- Hosted command failures are labelled with the command that failed rather than
  `Authentication failed`, which sent signed-in users to re-authenticate over
  errors that had nothing to do with authentication.

## [0.1.13] - 2026-08-02

### Added

- Fuzzy command palette spanning commands, files, sessions, models and themes,
  ranked by match quality blended with recency and frequency.
- Changes pane listing the files a session has touched with per-file `+/-`
  counts, expandable to a scrollable inline diff.
- Session HUD: context pressure, burn rate, live tokens/sec, time-to-first-token
  and a turn clock, each appearing only once it has something to report.
- Live git context on the startup screen and the header — branch, dirty count,
  ahead/behind and the tip commit.
- Startup suggestions adapt to repository state and are keyboard-navigable:
  arrows move the caret, Enter runs the row, Tab loads it into the composer.
- `scripts/render-frames.ts`, a frame-capture rig that writes the real ANSI the
  UI paints, one file per state, for visual review.

### Changed

- The default `space` palette carries a single warm accent; body text stays
  greyscale so a dense transcript remains readable over long sessions.
- The composer is a cmdline rather than a bordered panel, and the chrome beneath
  it is one hairline rule plus one status row.
- Slash-command output renders in full. Long notes still collapse, but output
  the user explicitly asked for is exempt — `/resume` was hiding the very list
  it told you to choose from.
- The shortcut bar is permanent again, folded into the status row. Progressive
  hints ride beside it rather than replacing it.
- The context meter no longer renders at zero usage.

### Removed

- The live World Cup score surface: `/football`, its `football` config block,
  the header segment and the supporting modules. Existing settings files keep
  loading — the key is ignored, not rejected.
- The character mascot and its animated faces, replaced by a typographic mark.
- The live row's dot-matrix loader, label shimmer and rotating status word. The
  elapsed clock reports the same fact more precisely.

### Fixed

- Enter no longer runs a fuzzy-matched command when the typed text merely
  resembles one; a match now requires an explicit prefix, alias or selection.
- Branch names and commit subjects are stripped of control characters and
  bidirectional overrides before reaching the terminal.

## [0.1.12] - 2026-08-01

### Added

- Refresh the model catalog from the authenticated endpoint when the
  interactive picker opens, so newly available models appear without
  restarting the CLI. A failed or empty refresh keeps the last usable list.

### Changed

- Render streaming replies from a committed-prefix cache that re-parses only
  the unstable tail instead of the whole accumulated message.
- Memoize transcript turns so a rebuild costs the new turns rather than the
  entire session history.
- Emit one text node per viewport row so scrolling stops retaining a
  multi-kilobyte interned string for every scroll position.
- Share one clock between the spinner tick and the stream flush, and play the
  splash blink as a bounded greeting instead of an endless idle timer.

### Fixed

- Open the model picker even when only one model is known, instead of
  refusing with a note.
- Restore the blank line between a heading and the block after it while a
  reply streams. marked 18 emits a block separator after headings, which the
  incremental renderer had been suppressing.

### Dependencies

- Update chalk to 6, marked to 18, nanoid to 6, `@modelcontextprotocol/sdk` to
  1.30, OpenTelemetry to 0.221/2.10, and the TypeScript type packages.

## [0.1.11] - 2026-07-27

### Fixed

- Keep bypass mode live for the rest of an in-progress turn after it is enabled
  from a permission prompt, so later tools do not ask again.
- Migrate retired Kimi and GLM Nitro selections to their current model aliases.
- Cancel silent or interrupted provider streams promptly instead of leaving the
  CLI waiting for the full request timeout.
- Bound whole-turn recovery to three attempts and avoid multiplying transport
  retries after a request fails before streaming begins.
- Make Escape and the first Ctrl+C immediately interrupt an active turn while
  keeping a second Ctrl+C available as the forced-exit path.

## [0.1.10] - 2026-07-27

### Added

- Add isolated mission workspaces with verification, independent review,
  recoverable refs, and conflict-safe integration.
- Add role-specific worker, reviewer, synthesizer, and scout model selection
  with `/crew` controls and session-model fallback.
- Add the compact Rover companion and live mission fleet panel without keeping
  animation timers active while the interface is idle.

### Fixed

- Keep command callbacks on the latest mission, model, and companion state.
- Probe independent Git metadata concurrently and avoid duplicate mission
  updates during integration.

## [0.1.9] - 2026-07-26

### Fixed

- Run the privileged npm OIDC publish job on a GitHub-hosted runner, as
  required by npm trusted publishing.

## [0.1.8] - 2026-07-26

### Security

- Prevent recursive fatal-error logging from exhausting the host disk when
  stderr is broken. Interactive fatal errors now write one redacted, bounded,
  owner-only diagnostic and terminate non-zero; existing oversized crash logs
  are truncated on startup, and symlinked crash-log targets are rejected.
- Pin `brace-expansion` to 5.0.8 to remove the high-severity unbounded-expansion
  denial-of-service advisory from the release toolchain.

## [0.1.7] - 2026-07-23

### Fixed

- Fix package-manager installs on Windows. 0.1.6's launcher used a `#!/bin/sh`
  shebang, which Windows shims (and Bun) resolve to `/bin/sh` — absent on Windows
  — so `npm`/`pnpm`/`yarn`/`bun` global installs produced a `command not found`
  / `interpreter "/bin/sh" not found` error. The launcher now uses a Node shebang,
  which every package manager provides a working shim for on all platforms.

### Changed

- The globally installed command now runs under **Node 18+** (which npm, pnpm,
  yarn, and Bun all provide). A machine with Bun but no Node uses the native
  `install.sh` / `install.ps1` script, which needs no runtime.

## [0.1.6] - 2026-07-23

### Added

- Add one-line native installers, `install.sh` (macOS/Linux) and `install.ps1`
  (Windows), that download the platform binary straight from npm, verify its
  checksum, install under `~/.keelcode`, and — unless `--no-modify-path` /
  `-NoModifyPath` is passed — add Keelcode to `PATH`. No package manager, Node,
  or Bun required.

### Changed

- The globally installed launcher now runs under **Node 18+ or Bun**, whichever
  is present, so `npm`, `pnpm`, `yarn`, and `bun` global installs all work on
  machines that do not have Bun.
- Remove the `engines` constraint from the published package so no package
  manager refuses to install on an older or non-Bun runtime.
- A standalone (curl-installed) executable now finds its ripgrep sidecar next to
  itself, so it needs no `KEELCODE_RG_PATH` or bundled npm dependency.

### Fixed

- `command not found` after installing with `npm`/`pnpm`/`yarn` on a machine
  without Bun, and pnpm's engine-strict refusal to install the previous package.

## [0.1.5] - 2026-07-20

### Fixed

- Make the trusted project settings path test portable across Windows and POSIX CI runners.

## [0.1.4] - 2026-07-20

### Added

- Add `kc`, `kcode`, and `keel` as packaged aliases for the `keelcode` command.
- Add safe custom command aliases with `keelcode alias setup|add|list|remove`.
- Show client-observed TTFT and provider-token TPS in interactive and headless
  output without mixing tool time into model throughput; keep interactive
  context and performance telemetry immediately above the input box.
- Make the CLI hosted-only: `keelcode login` now owns the API origin and bearer
  session, while customer provider keys, custom endpoints, and `ANTHROPIC_*`
  transport configuration are ignored.
- Add `/ship`, an objective-bound deliverable workflow whose runtime withholds
  completion until a persisted passing `Verify` receipt, a read-only final
  review, the cited receipt ID, and a stabilized Git fingerprint all agree.
- Discover layered `AGENTS.md` and `KEELCODE.md` instructions from the Git root
  to the active directory with source provenance and bounded, symlink-safe reads.
- Add stable `json` and streaming `jsonl` headless output formats with explicit
  terminal outcomes and automation-friendly exit codes.
- Add lease-checked detached Git worktree primitives for repository-state
  isolation without claiming operating-system sandboxing.
- Add standalone `proof list/show` and `worktree create/status/cleanup` commands
  so automation can inspect receipts and manage isolated runs without an API key.
- Add an opt-in-aware World Cup match surface with a startup Match Centre,
  compact in-session scores, scorer-specific goal takeovers, and `/football`
  controls. Live provider traffic stays in the Keelcode backend.

### Security

- Treat checked-in `.keelcode/settings.json` and `.keelcode/settings.local.json`
  as untrusted input: repositories can add restrictions and presentation
  preferences, but cannot enable prompt-free modes, auto-allow tools, inject
  environment variables, or launch MCP processes.
- Store explicitly approved per-project MCP and allow settings in an owner-only
  directory outside the checkout, and pass MCP processes a minimal environment
  instead of every credential held by the CLI.
- Require an explicit permission decision for filesystem access outside the
  active workspace, including symbolic-link escapes, and make delegated agents
  inherit the parent permission gate and deny rules.
- Pin each WebFetch HTTPS connection to the public address that was validated,
  revalidating every redirect to prevent DNS-rebinding SSRF.
- Require approval for Git commands that write through `--output` or `-o`.
- Redact and cap persisted verification output, store receipts and worktree
  leases with owner-only POSIX permissions, and bound gate count and execution time.
- Make Verify approvals fully scrollable and auditable, hard-limit observed
  output, show exact executable command text, reject destructive checks and
  common background syntax, detect residual children, and anchor local receipt
  bytes per ship run.
- Hash actual tracked/untracked worktree bytes and submodules independently of
  Git stat-cache, filter, assume-unchanged, and skip-worktree behavior; isolate
  Git subprocesses from ambient `GIT_*` injection.
- Reject symlinked private receipt roots and revalidate directory/file identity
  across receipt publication and reads.
- Block WebFetch access to unsafe URL schemes, credentials, local/private
  networks, and unsafe redirect targets.
- Store user transcripts, mission artifacts, caches, and crash logs with
  owner-only POSIX permissions.
- Clarify that `bypassPermissions` is an explicit no-prompt mode while deny
  rules and tool hard denials remain enforced.

### Fixed

- Keep installation and normal startup independent of Nerd Fonts; failed,
  skipped, unsupported, and manual-only setup paths now remain on safe Unicode.
- Extract the optional pinned Nerd Font archive inside Keelcode instead of
  depending on `tar` or PowerShell, and verify its SHA-256 before installation.
- Reject Windows UNC paths before POSIX normalization can hide their form.
- Run the npm launcher with Bun so globally installed commands work on Bun-only
  machines without a `node` executable.
- Avoid misclassifying an already-exiting Windows verification child as a
  residual background process when no process tree was actually terminated.

### Build

- Standardize development, security auditing, packing, and CI on Bun.
- Replace the unpublished JavaScript npm artifact with a small launcher and
  exact platform-suffixed versions of the single `keelcode` package name for
  macOS, Linux, and Windows on x64/arm64.
- Fail release packing when source files, source maps, private metadata,
  upstream endpoints, or secret-shaped credentials appear in an npm artifact.
