# CLI changelog

Read versioned Composal CLI release notes, including new commands, fixes, and compatibility changes. Check what changed before updating your installation.

Release notes for the Composal CLI follow
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/). The version tracks the
`[workspace.package]` version in the repo-root `Cargo.toml` (which `com-cli`
inherits). For the release process, see the `com-cli-release` skill.

## [Unreleased]

## [1.17.95] - 2026-10-24

### Changed

- New installs and saved hosted API defaults use `composal.com`, with official downloads from `dl.composal.com`. Existing tokens, organization/project context and datacenter settings are preserved; explicit API overrides, local profiles and private endpoints keep their configured origin.
- Installer, npm, Verify and Docker builder action defaults and bundled public guides use the new domain. Existing API/download aliases, registry, MCP, Verify identity and scenario schema identifiers remain compatible.

## [1.17.94] - 2026-10-24

### Added

- `com verify schedules` discovers setup choices, previews scenario selection, and creates, lists, edits, pauses and resumes daily environment runs. Select all scenarios or any matching label, saved persona credentials, and email reports by default or a configured Slack channel.
- Local MCP `verify_schedules` exposes the same daily schedule setup and management actions.

## [1.17.93] - 2026-10-23

### Added

- `com repo list` shows the repositories a Project tests, with their `repo_…` IDs and slugs. It uses `--project` or the default project from `com switch`; `--all` lists every repository in the organization. `--format json` prints `{project, repositories}`.
- `com registry delete <repo>` deletes an image repository. It asks for confirmation in a terminal and refuses without `--yes` when it cannot prompt.
- `com deploy image --build` accepts `--platform` and repeatable `--build-arg KEY=VALUE`.

### Changed

- `com deploy logs` and `com deploy allocation` take `--env`, like the other hosting commands. `--environment` still works.
- `com deploy image --build` builds for `linux/amd64`, the platform hosting nodes run. It and `com registry push` refuse to push a local image built for another platform, such as arm64 from Apple Silicon, unless you pass `--allow-platform-mismatch`.
- `com verify environments revoke` and `destroy` help explains that only a revoked or failed revision can be destroyed.

### Fixed

- `com app create` sends the `--org` organization and the app's repository. The repository comes from `--project` (or the default project) when the project has exactly one; with several, pass `--repo <slug>`. Without a project, `--repo` resolves the slug in the organization. Values set in the request body still win.
- `com secrets upload` waits up to 5 minutes for large imports. When the response is lost, it says the server may still be applying the import, and to check `com secrets list` before running it again (unchanged values are skipped).
- `com service create` creates services that run on Nomad. It previously left the simulated `database` adapter in place, so the service never started a container.
- `com deploy image` help and errors name the `registry.composal.ai` registry.

## [1.17.92] - 2026-10-21

### Added

- `com verify pr-testing show`, `detect`, and `setup` read and configure a project's PR testing from the terminal, including preview links from bot comments, CI-supplied URLs, and Composal builds.

### Fixed

- Keep the selected repository when confirming PR testing setup. Projects with several repositories share scenarios and test access while each repository keeps its own preview source; pass `--repository` for setup and detection, or `--repo` when requesting a PR run.

## [1.17.91] - 2026-10-18

### Added

- Scenario YAML files support optional `cleanup` instructions. Download, upload, and run preserve them; version 2 files can assign each cleanup action to a named actor. Use `cleanup: []` to declare that no cleanup is needed.

### Changed

- `com verify scenarios lint` validates version 1 and version 2 files offline, including cleanup shape and actor references, without signing in. Invalid files report their field errors and exit nonzero.

## [1.17.90] - 2026-10-16

### Added

- Vex: register and prepare organization-owned GitHub Actions toolchain images, select them per repository/label, and choose explicit VM or sandbox runner families.
- Vex: `agent-help` includes Dockerfile, registry, private-secret, preparation, workflow, verification and rollback instructions for custom runners.

## [1.17.89] - 2026-10-16

### Changed

- Keep Composal focused on product operations, without Git cloning or Modal runner execution.
- Use the separate Vex CLI for authenticated Git repositories and runner execution, preserving original Git commits and stable Change IDs.
- Retire JJ transport, virtual repositories and public source browsing.

## [1.17.88] - 2026-10-16

### Changed

- Use `COMPOSAL_API_TOKEN` for CLI and CI authentication. It takes precedence over the compatible `VEX_API_TOKEN` alias; command flags still override environment variables and saved configuration.

## [1.17.87] - 2026-10-15

### Fixed

- `com verify scenarios run --local --headless` no longer loses checkpoint screenshots to "Page.captureScreenshot timed out". Headless Chrome could wait for a frame an idle page never draws; the tab is now brought to the front before each screenshot.

## [1.17.86] - 2026-10-15

### Fixed

- `com verify scenarios run --local` opens its Chrome window from shells that do not name the desktop's display, such as an agent's or an SSH session on a Linux desktop. With no display at all, Chrome runs headless and says so. A Chrome that still fails to start reports its own error instead of only an exit status.

## [1.17.85] - 2026-10-15

### Fixed

- Retry brief server failures when checking remote builder status before opening a native Docker connection.

## [1.17.84] - 2026-10-15

### Fixed

- Warm Docker builder connections create sessions concurrently, so a delayed session no longer blocks native version requests, builds or registry pushes behind the builder wake lock.

### Added

- `com verify scenarios run --local` works without a model key of your own when `com` is signed in: it uses Composal's model access, with usage recorded against your organization. Pass `--provider openai`, `codex` or `anthropic` to use your own.
- Signed-in local runs check clicks, typing and selections with Decisions before they reach the page, when the organization has Decisions enabled.
- Signed-in local runs can search and read the public web through Composal, with each search recorded against your organization.

## [1.17.83] - 2026-10-14

### Changed

- `com verify runs get` and `com verify scenarios run --wait` report why each
  Scenario stopped and who can fix it. The report includes each step and outcome,
  what failed checks observed, console errors, failed requests, and commands to
  download a screenshot and read the full log. Passed Scenarios take one line.
- `--json` run output leaves out the full console and network log unless
  `--diagnostics` is given; `browser_errors` lists what went wrong.

## [1.17.82] - 2026-10-13

### Added

- Upload real file fixtures from Scenario YAML files and use them in Verify runs.

## [1.17.81] - 2026-10-12

### Fixed

- `com exec` streams command output again instead of stopping with a TLS crypto provider panic after creating the run.

## [1.17.80] - 2026-10-10

### Added

- Manage project-owned Linux application packages with `com verify binaries`: register a URL, wait for preparation, inspect immutable versions, and archive or delete unused packages.
- Attach an exact ready application version to a Computer use environment with `--binary <binary>@<version-id>`.


## [1.17.79] - 2026-10-10

### Fixed

- Remote Docker builders and hosted command WebSockets connect reliably when TLS dependencies enable multiple crypto providers.

## [1.17.78] - 2026-10-10

### Changed

- Sign-in hints from inside the built-in agent now say `com agent login` instead of naming the `roder` CLI.

## [1.17.77] - 2026-10-10

### Added

- `com agent login` signs the built-in agent in to your ChatGPT plan for local Scenario runs, `com agent status` shows which model credentials are set and the model local runs use, and `com agent logout` signs out. Local runs no longer point at the `roder` CLI.

## [1.17.76] - 2026-10-10

### Added

- `com verify runs get <run> --diagnostics` shows saved console logs, network events, redacted request and response bodies, failure codes and evidence availability after the browser closes. JSON includes the available diagnostic payload.

### Changed

- Discovery defaults to a two-hour limit. Explicit shorter durations remain supported, and exploration can run for up to six hours.

## [1.17.75] - 2026-10-10

### Fixed

- `com verify browser-session --login` can create your first project credential without `--account`. Sign in through the private browser, then confirm and save the session. Use `--name` to name the new credential, or `--account` to refresh an existing one.

## [1.17.74] - 2026-10-10

### Added

- `com verify scenarios run --local` runs Scenario files on your machine with the built-in agent in a visible Chrome browser. It writes a Markdown report for each Scenario and a suite summary. It runs GPT-6 Luna in Fast mode using your own OpenAI key or Codex sign-in, or you can use Anthropic. Sign-ins stay in a dedicated Chrome profile, and failed Scenarios leave their tabs open for inspection. Configure runs with `--cdp`, `--chrome-profile`, `--headless`, `--provider`, `--model` and `--out`.
- `--concurrency` sets how many Scenarios run at once: tabs of one Chrome locally, with no limit, or up to 50 in the cloud.

### Changed

- `com verify scenarios run` accepts directories and skips project.yaml, and uses an `environment:` key in project.yaml as the default `--environment`.

## [1.17.73] - 2026-10-09

### Changed

- Internal Vex: fresh repository clones default to Git transport and a local JJ Git store. Existing workspaces keep their recorded backend; explicit `--backend com` remains available for legacy recovery.
- Internal Vex: unsupported live, virtual filesystem, and workspace-registration options fail before a Git clone contacts the server.

## [1.17.72] - 2026-10-09

### Changed

- Use saved YAML Scenarios and grouped Runs for repeatable Verify testing and PR verification.
- Remove retired scenario-pack, test-plan, test-group, sweep, and impact-plan commands from the public CLI and MCP surface.

## [1.17.71] - 2026-10-09

### Changed

- Scenario lint help describes offline version 1 and version 2 validation, including named actor references.

### Fixed

- `com verify scenarios lint` works without a saved API token. The standalone CLI no longer requires sign-in before local validation; mixed version 1/version 2 packs and invalid actor bindings have command-level regression coverage.

## [1.17.70] - 2026-10-09

### Added

- Version 2 Verify Scenario files declare named actors, actor-owned steps and shared outcomes. `com verify scenarios download`, `lint` and `upload` preserve the actor bindings and identity probe alongside existing version 1 scenarios.

### Changed

- `com skills setup` installs a testing-focused `composal` skill. Its new QA planning reference (`com skills get --topic qa`) has agents learn how the product works from the codebase, `com knowledge`, and plans before setting up Verify Scenarios.
- Deployment guidance is now the optional `com-deploy` skill. Install it with `com skills setup --with deploy`; later setup runs refresh an installed copy. `com skills get --topic deploy` reads it.

## [1.17.69] - 2026-10-07

### Added

- Scenario files take `labels: [checkout, smoke]` to group Scenarios. `com verify scenarios download` writes them, `lint` checks them, and `upload` saves them; a file without `labels` keeps a Scenario's labels and `labels: []` removes them.
- Run one label with `com verify scenarios run scenarios/*.yaml --label smoke`, which skips files without that label.

## [1.17.68] - 2026-10-06

### Added

- Run Scenario files as written, uploaded or not, with `com verify scenarios run`. `--wait` follows the run and exits nonzero unless every Scenario passes.
- Check Scenario files against the public schema with `com verify scenarios lint [paths]`. It works offline without signing in, lists each error by file and field, and exits nonzero when any file is invalid.

### Changed

- Scenario files name their format with `$schema: https://composal.ai/schema/verify/v1/scenario.json`, and download points editors at that public schema instead of writing `scenario.schema.json`. Files written with `schema: vex.scenario/v1` still upload.

## [1.17.67] - 2026-10-06

### Changed

- Install one Composal skill with focused workflow references through `com skills setup`. Bare `com skills` shows a compact guide; the old root `com setup` command is removed.
- Align the agent guide with Project Scenario creation, YAML upload, and prepared test runs.
- Build release binaries with ThinLTO and one code generation unit, with debug information disabled and symbols stripped.

## [1.17.66] - 2026-10-06

### Added

- Discover commands with `com schema` and the embedded `com agent-guide`, check authentication with `com auth check`, and use `--agent` for structured results, actionable errors, and bounded output.
- List, read, and install bundled project skills with `com skills`, including the compact Composal bootstrap guide.
- Download and upload Project Scenarios as editable YAML files with `com verify scenarios download` and `upload`, including a JSON schema, per-file results, and safe version checks that preserve comments and local drafts.

### Changed

- Use consistent `list` and `get` actions across resources, with field selection and result limits that preserve pagination.
- Manage Scenario Packs through `com verify scenario-packs`.

## [1.17.65] - 2026-10-05

### Fixed

- Resolve canonical hosted environment, service, and preview IDs directly, and look up environment/service names through the lightweight selector catalog instead of loading deployment history.

### Added

- Configure Verify projects and their scoped environments, credentials, history, and PR preview settings through the CLI.

## [1.17.64] - 2026-10-06

- Fetch Git-backed CI workspaces directly from Git storage at the exact leased commit, without native/JJ checkout.

## [1.17.63] - 2026-10-05

### Added

- Research and maintain product knowledge with `com knowledge list`, `read`, `add`, and `edit`. Filter by project, search documents, read Markdown or JSON, and save content from a file or standard input.
- Protect knowledge edits with the digest from the original document, so a concurrent update cannot be overwritten.

## [1.17.62] - 2026-10-01

### Added

- Sign into Verify test accounts in a fresh local Chrome window with `com verify browser-session --local-login`, then explicitly save the app session to the encrypted credential vault.
- Capture richer IndexedDB values through the verification browser storage format, with `--skip-indexed-db` for apps with large caches.

## [1.17.61] - 2026-10-01

### Changed

- Organize Composal help by workflow, with Verify, deployment, secrets, and app execution first, complete command descriptions, and yellow headings and cyan commands.
- Show resource or action help when API commands such as `com identity` and `com app` are called without arguments.
- Keep help plain for redirected output and `NO_COLOR`, and use Composal command names in API discovery hints.

## [1.17.60] - 2026-10-02

### Added

- Request and rerun GitHub PR verification with `com verify pull-requests`, and hand off CI previews pinned to the deployed PR head.

## [1.17.59] - 2026-10-01

### Fixed

- Keep Composal updates on the standard `release` feed and internal Vex updates on `vex-release`.
- Allow pre-split and 1.17.58 Composal installs to upgrade without a manual reinstall.

## [1.17.58] - 2026-10-01

### Changed

- Ship `com` as the focused Composal product CLI and `vex` as the internal source-control CLI, with separate installers and update feeds.
- Keep Git remote helpers in the Vex installation; Composal installs only `com`.

## [1.17.57] - 2026-10-01

### Added

- Capture a signed-in Chrome profile or local CDP session with `com verify browser-session`, or open an owner-controlled cloud browser and save its app session for future Verify runs.
- Enroll encrypted cloud passkeys and scoped browser authentication for Verify discovery and exploration.

## [1.17.56] - 2026-09-30

### Changed

- Default registry login, image contracts, image pushes, and Docker credential setup to `registry.composal.ai`. Explicit `--registry` overrides remain supported.

## [1.17.55] - 2026-09-30

- Renew expired or erased credentials automatically for hosted Git pull and push, while reusing healthy cached credentials.

## [1.17.54] - 2026-09-28

### Fixed

- Let Verify narrative sweep planning finish beyond the HTTP client's 30-second default timeout.

## [1.17.52] - 2026-09-28

### Fixed

- Submit Git-backed JJ changes without a repository-wide remote ref scan.

## [1.17.51] - 2026-09-28

### Added

- Import version 1 narrative Verify scenarios directly from YAML files, including browser journey intent and cited expectations.

## [1.17.50] - 2026-09-28

### Added

- Manage Verify cron schedules from `com verify schedules` and local MCP.

### Fixed

- Summarize sweep watch output without embedding live browser images.
- List evidence for URL-only sweeps without a repository.

## [1.17.49] - 2026-09-28

### Fixed

- Renew ordinary checkout credentials before they expire so `com status` can load repository state after long idle periods.
- Use the `com` command name in CLI update notices.

## [1.17.48] - 2026-09-28

### Fixed

- Accept profile slugs when creating previews and source-environment slugs when creating preview profiles.

## [1.17.47] - 2026-09-28

### Fixed

- Accept destination environment keys when deleting preview environment or profile secret bindings.

## [1.17.46] - 2026-09-28

### Fixed

- Accept preview profile slugs and names in `com hosting preview-profile-secret-binding` commands.

## [1.17.45] - 2026-09-28

### Fixed

- Complete `com pull --rebase` in Home checkouts without crawling unrelated Home history while retaining the previous snapshot.

## [1.17.44] - 2026-09-27

### Fixed

- Renew Home repository credentials before local commands so changes to the Home manifest do not interrupt ordinary work.
- Guide Home users to `com pull --rebase` or `com submit` when raw rebase or push cannot preserve repository authority.

## [1.17.43] - 2026-09-27

### Fixed

- Make `com deploy image --dry-run` preview the resolved request without creating a rollout.
- Show current AWS regions and volume limits in hosting CLI guidance.

## [1.17.42] - 2026-09-27

### Added

- Set up organization-scoped remote Docker builders with `com docker-builder setup`, including a local Docker context, automatic connection management, and direct pushes to `registry.composal.ai`.

## [1.17.41] - 2026-09-27

### Changed

- Refresh the bundled agent skill catalog from the latest master revision.
- Include the experimental Git and COM repository backend support from master.

### Fixed

- Publish the signed macOS `com` and Git helper aliases together with their versioned and latest downloads.

## [1.17.40] - 2026-09-27

### Fixed

- Automatically renew Home credentials before submitting or syncing changes using the saved CLI login.
- Use the current Composal CLI for release preparation and publication.

## [1.17.39] - 2026-09-26

### Fixed

- Allow bounded flat Home submissions with up to 4,096 objects while retaining the 32 MiB request limit.

## [1.17.38] - 2026-09-26

### Added

- Archive stale ephemeral `local_nvme` volumes with the explicit `vex volume archive --force-tombstone` recovery option.

## [1.17.37] - 2026-09-25

### Fixed

- Home checkpoint links follow local rewrites without downloading imported history after CLI commands.
- Status, log, diff, and show skip agent seal bookkeeping.
- Background freshness checks renew missing Home credentials and honor the selected `--repository` checkout.

## [1.17.36] - 2026-09-25

- Bound transcript API requests so a stalled metadata or finalization response releases the outbox drain for a later retry.

## [1.17.35] - 2026-09-25

- Bound and retry transcript object uploads so a stalled storage connection cannot hold an outbox drain indefinitely.

## [1.17.34] - 2026-09-25

- Upload missing transcript chunks concurrently so historical outbox drains complete faster without resending identical session content.

## [1.17.33] - 2026-09-25

- From a `com://` Git checkout, `com submit` commits working-tree changes, submits the review, and checks out a numbered `changes/N` branch for later patchsets.

## [1.17.32] - 2026-09-25

- Upload sanitized agent transcripts as reusable session chunks, retry large historical archives, and reclaim older delivered local archives while retaining the newest and rewrite-sensitive copies.

## [1.17.31] - 2026-09-25

- Fetch the Git transport route and issue its scoped credential in one request on a cold clone.

## [1.17.30] - 2026-09-25

- Resolve Git remotes through a single-repository lookup instead of loading the organization's full access catalog, and reuse routing hints for ten minutes.

## [1.17.29] - 2026-09-24

- Allow `vex repo-auth refresh` from linked workspaces when their shared repository credential expires.

## [1.17.28] - 2026-09-24

- Repair stale Home checkout credentials with `vex repo-auth refresh`, including invalid old routing metadata and changed Home membership.

## [1.17.27] - 2026-09-24

- Attach uploaded agent checkpoints to Changes from federated Home checkouts through the scoped API.

## [1.17.26] - 2026-09-23

- Let existing flat Home checkouts keep pulling after their last component is detached by adopting the standalone Home route while retaining historical component routes.

## [1.17.25] - 2026-09-23

- CI runners retry transient gateway, transport, deadline, and repository-routing saturation failures while cloning a workspace, without retrying repository or authorization errors.

## [1.17.24] - 2026-09-22

- `com magic-merge` resolves a three-way conflict as a Git merge driver. `com magic-merge --install-driver --gitattributes` registers it for one repository, `--global` for every repository on the machine. The driver tries ordinary line merge, then Mergiraf, and only then MagicMerge, so a conflict either side can resolve locally never reaches the network. This is the first macOS build to carry it: 1.17.22 and 1.17.23 published linux-amd64 only.
- `com setup` has an optional Magic Merge section that installs the global Git merge driver. `com magic-merge stats` shows local success and MagicMerge counts from `~/.composal` without using the network. `com magic-merge log` prints each MagicMerge resolution's folder, file, time, and diffs so an agent can inspect or replace the decision.

## [1.17.23] - 2026-09-20

- Preserve the original CI runner error when reporting the failed job also fails, and show the reporting failure alongside it. This keeps workspace preparation failures diagnosable during API interruptions.

## [1.17.22] - 2026-09-20

- Bound backend TLS handshakes by the configured connection deadline, so an unresponsive peer cannot leave CI checkout or repository discovery waiting indefinitely.
- `vex secrets --env <environment>`: address an environment's override layer of an app's secrets. `set`, `rotate`, `get`, `unset`, and `upload` then target that environment only; `list` and `env` show what that environment receives (app defaults with its overrides applied). Without `--env` the app defaults are used, so a local `vex secrets env --app <app>` keeps sandbox credentials while production carries live ones under the same slug.
- `vex secrets list --app` gains a `LAYER` column naming the environment of an override.
- Creating an app secret now grants it to the app's runtime identities, so the value reaches the next release without manual grants.


## [1.17.21] - 2026-09-19

- Add `com://` Git remotes and the `git-remote-com` helper, retaining compatibility with existing `vex://` remotes.
- Reuse checksum-verified downloads when retrying an interrupted CLI update.
- Keep the CLI and Git helper together when updating an installation linked into PATH.

## [1.17.20] - 2026-09-19

- Wait for a routed Git import destination to be prepared before uploading, reusing the same import while writer ownership is confirmed.

## [1.17.19] - 2026-09-19

- Introduce the Composal brand and the `com` command, keeping `vex` available for compatibility.
- Install from `https://dl.composal.ai/install.sh` and download CLI updates from `dl.composal.ai`.

## [1.17.18] - 2026-09-16

- Finish CI jobs promptly when the heartbeat thread is idle, while still waiting for any in-flight heartbeat before releasing the runner lease.

## [1.17.17] - 2026-09-16

- Preserve long dependency filenames in CI cache archives, including pnpm content hashes and Cargo registry paths. Reject malformed archives and isolate the new format from older caches; existing workflows refill their caches on the first run.

## [1.17.16] - 2026-09-15

### Fixed

- Restore declared `actions/cache` archives immediately before their steps on fresh CI workers, without relying on a manifest created later by the step itself. Requires the updated cache-request API.
- Report prefix archive restores as non-exact cache hits, preserving new-key save behavior, and reject truncated archive blocks.

## [1.17.15] - 2026-09-15

### Improved

- Repository imports upload original Git objects and refs to server-owned Git storage. The default acknowledgment waits for durable Git storage; `--wait` also waits for native conversion.
- Default CLI builds no longer include libgit2 or its vendored OpenSSL dependency. Server-side import conversion uses a separate worker build; local JJ interoperability retains gitoxide.

## [1.17.14] - 2026-09-13

### Improved

- Show shared merge-queue batch status in CLI queue output so adjacent changes can be followed through their common validation and publication.

## [1.17.13] - 2026-09-13

### Improved

- Enforce merge-queue batch execution deadlines locally, including stopping child processes when runner heartbeats are unavailable.
- Advertise deadline support when claiming batch work; older runners continue handling ordinary jobs without claiming deadline-bound batches.


## [1.17.12] - 2026-09-13

### Fixed

- Retry transient CI workspace archive download failures within the existing timeout, preserving the pinned lease and rejecting authorization failures immediately.

## [1.17.11] - 2026-09-13

### Improved

- Reduce submission latency by overlapping target checks with object uploads and sharing connection initialization across submit phases.
- Reuse validated submission targets and preserve unchanged stack parents when submitting Changes.

## [1.17.10] - 2026-09-12

### Added

- Request high-priority landing with `vex land --priority high`; the entire submitted stack or group retains dependency order.
- Manage branch CI concurrency through `vex repo branches concurrency`.
- Support isolated generated-file reconciliation on CI nodes, with bounded output uploads and no-network execution. This requires the supporting server rollout and remains disabled by default.

## [1.17.9] - 2026-09-11

### Added

- Start swarms from a goal, list them, watch their progress, and cancel them with `vex swarm`.
- Return swarm-specific exit codes for scripting and automation.

## [1.17.8] - 2026-09-11

### Added

- Manage automation connections, revision grants, provider subscriptions, and action approvals from the CLI.
- Create live workspaces with `vex clone --live`, and select a clone bookmark with `-b` / `--bookmark`.
- List and cancel execution runs, with orphaned runs expired automatically.

### Fixed

- Preserve explicit trunk selection and refresh federated Home state correctly.
- Recover deployment creation after a lost acknowledgement and retain complete CI node logs.
- Warn swarm workers when committing against a stale base.

## [1.17.7] - 2026-09-09

### Fixed

- Preserve pending changes and unsnapshotted edits when an existing woven Home checkout adopts federated components.
- Keep accepted Home objects readable after source packs are retired or local caches are pruned.

## [1.17.6] - 2026-09-09

### Improved

- Show live download percentage, bytes, average speed, and elapsed time during `vex update`, with explicit verification and installation phases.

### Fixed

- Allow downloads to continue without an overall time limit, regardless of connection speed; retain a timeout only for establishing the connection.
- Show underlying network errors when an update download fails.

## [1.17.5] - 2026-09-09

### Fixed

- Preserve an existing installation and report an error if either downloaded executable cannot start.
- Require accepted Apple notarization and verify both macOS executables before publication, while retaining bundled Git libraries for installation without Homebrew.

## [1.17.4] - 2026-09-09

### Fixed

- Bundle libgit2 in the CLI and Git helper so macOS downloads run without Homebrew libraries. Reject non-system dynamic libraries before signing macOS releases.

## [1.17.3] - 2026-09-08

### Changed

- Clone Home repositories faster by overlapping member metadata reads and sharing
  a bounded request budget across member file downloads.
- Keep setup integrations local to each project and show setup health and
  migration guidance.

### Fixed

- Home submit checks the accepted revision with a compact state read, avoiding
  full review-page queries before and after submission.
- Read Home-owned objects through their selected member repositories when the
  physical Home repository does not store those objects directly.

## [1.17.2] - 2026-09-08

### Fixed

- Clone and edit empty folder repositories without missing-tree errors or false
  concurrent-checkout warnings. Repeated status checks keep the working copy stable.
- Push folder repositories through their backing repository while preserving scoped
  credentials and the check that prevents overwriting newer remote history.

## [1.17.1] - 2026-09-08

### Fixed

- Capture and upload the calling Codex session when it commits in a new Git
  worktree, even when agent hooks still report the original checkout. Existing
  Git hooks pick up the fix after updating the CLI; no worktree registration
  or hook reinstall is required.

## [1.17.0] - 2026-09-08

### Fixed

- Git worktrees inherit transcript repository settings without sharing captured
  sessions or queues. Git hook installation and diagnostics use Git's actual
  hooks path; trailer opt-outs and local uninstall preserve sibling hooks.
- Git transcript uploads finish without waiting for a native attachment receipt.

### Added

- Inspect, sync, or uninstall transcript hooks across registered Git worktrees
  with `--all-worktrees`. Installation supports shared repository defaults,
  explicit `--scope worktree` overrides, and `--inherit` to restore defaults.


## [1.16.0] - 2026-09-07

### Added

- Discover saved conversations for a pull request, Change, or commit with
  `vex transcripts list`. Read messages with `vex transcripts read`, with
  pagination and optional tool events. Vex infers the repository from the
  current checkout when possible.
- Continue work from a saved transcript with `vex session continue`.
  `vex session resume --exact` resumes a local Codex conversation when its
  original state is available.
- Discover and read transcripts through local and hosted MCP tools. The shipped
  skills explain how to select checkpoints and continue reading older pages.
- Run commands against a deployed release with `vex exec`, including interactive
  terminal sessions.
- `vex billing` (roadmap 139): `status` prints the organization's package,
  subscription state, seats against the seat limit, trial and period end, and
  the draft-invoice estimate; `usage [--period current|previous]` prints the
  meter table with included, used, remaining, overage, and the projected
  pay-as-you-go cost; `portal` and `subscribe` print the Stripe Customer Portal
  and Checkout URLs for an owner. Every subcommand takes `--org` (public id,
  slug, or name), defaults to the organization of the current checkout, then
  to the configured default, and supports `--format json` / `--json`.
- A billing limit refusal from any command — `push`, `exec`, `deploy`
  included — now prints `Billing limit reached: <limit>` and `Upgrade: <url>`
  from the API's 402 `billing_limit_exceeded` body, with the upgrade path made
  absolute against the web origin (`VEX_WEB_BASE_URL` when set, otherwise
  inferred from the API base URL), and exits non-zero.
- Inspect signal integrations and inbound deliveries with `vex signals
  integrations`. Filter signals by source with `--source`.

### Changed

- User-level installation configures the shell PATH automatically.
- Agent hooks do less work before returning while preserving transcript capture.

### Fixed

- Transcript capture selects the exact agent session across workspaces and
  uploads correctly from secondary workspaces.
- Detached single-Change submissions retain their transcript attachments.
- Claude session identity is written after its environment file is created.
  Discarded session metadata is reported instead of silently ignored.
- Attached app commands handle lifecycle and streaming failures more reliably.
  Forced terminal mode rejects piped input with a clear error.


## [1.15.0] - 2026-09-04

### Added

- Transcripts now work in a plain `git clone` of a repository imported into
  Vex — no jj workspace and no `vex submit` required. `vex transcripts install`
  (and `vex setup`) in a git checkout writes the coding-agent hooks plus
  `post-commit` and `prepare-commit-msg` git hooks, and keeps the store under
  `.git/vex-agent-checkpoints`. Every commit made during a session seals a
  checkpoint at that commit's SHA, so the transcript is attached to the work
  without any extra command.
- Commits made during a session carry a `Vex-Session:` trailer naming the
  opaque session id, so `git log` shows the link with no Vex access. It is on
  by default; `vex transcripts install --trailers off` opts out and is
  remembered, so a later install never re-enables it.
- The repository is resolved from the checkout's `origin` remote and cached,
  so a fresh clone needs no addressing; `--repo <org>/<repo>` overrides it when
  the remote is unresolvable or imported by more than one organization.
- On the server, an imported repository's pull requests link sessions to the
  commits they produced — the commits on the PR that carry the trailer, the PR
  itself, and the commit that lands when the PR merges by any strategy. All of
  it appears on the organization's Sessions pages.
- `vex transcripts doctor` reports the store kind and location, the resolved
  repository, whether trailers are on, and the state of each git hook —
  including a hook that exists but is not Vex-managed.

### Changed

- `vex setup` wires a git checkout as well as a Vex workspace, installing the
  git hooks alongside the coding-agent hooks.
- `vex agent-checkpoints` is now `vex transcripts`. Checkpoints are the internal
  mechanism; Transcripts is what the feature is called everywhere you meet it,
  and `vex checkpoint` — which publishes a commit — already meant something else
  on the same help screen. `vex agent-checkpoints` stays a hidden alias for every
  subcommand indefinitely, because hook files written by earlier installs call it
  and are committed in repositories. `vex transcripts install` rewrites those
  hook files and the two git hook blocks to the new name in place, and
  `vex transcripts doctor` counts an old-name hook as installed and says how many
  still use the old command name rather than reporting it missing.
  `vex setup` takes `--with-transcripts` and `--no-transcripts`, with
  `--with-agent-checkpoints` and `--no-agent-checkpoints` kept as hidden aliases.

## [1.14.0] - 2026-08-29

### Added

- `vex change fold <CHANGE>` squashes a change into the change below it — the
  counterpart to `vex land`, which schedules it into the merge queue instead.
  The parent absorbs the content as a new patchset, the folded change closes as
  `folded` naming what absorbed it, and its descendants are reparented onto the
  parent, so a stack goes from N entries to N-1 with no review left behind still
  advertising itself as landable. `--into` asserts the parent so a stack that
  moved is not folded somewhere unintended, `--dry-run` reports the plan without
  writing, and `--message`/`--message-file` replace the description composed
  from both changes. The fold happens on the server, so the working copy still
  holds the folded change until `vex sync`.

## [1.13.1] - 2026-08-29

### Fixed

- `vex land`, `vex change show`, and the other Change commands work again.
  1.13.0 shipped before the Change review routes moved to their
  repository-scoped endpoints, so an installed 1.13.0 asked for a page the API
  no longer serves and got `404 not_found` back — `vex land` could not queue a
  Change at all.

## [1.13.0] - 2026-08-23

### Added

- `vex submit` and `vex sync` print a check-back hint when CI run history
  predicts one — `CI usually finishes by 14:32 (p95 14:36). Check: vex change
  ci #482` — so a submitter schedules one poll near the median instead of
  tight-polling. `--format json` carries the same data as an `expected_ci`
  object of durations and sample sizes; nothing is printed when the server has
  no history (or is older than this feature).

### Changed

- The normal `vex change show` output is now compact and includes current
  problems. It reports queue ejection, a base that needs a rebase, merge
  conflicts, and identifiers for checks that need attention. JSON output keeps
  its existing shape.
- `vex stack show` now reports whether landing through the tip is ready. Its
  member rows name their main issue, and its problems section includes landing
  requirements, merge conflicts, unavailable previews, and queue ejection.

## [1.12.0] - 2026-08-22

### Added

- `vex setup` installs the Vex setup, MCP, CI, deployment, identifier, and
  source control reference guides with the managed skill bundle, so agents can
  use that guidance offline.

### Changed

- Release builds tell noninteractive users to refresh an older managed skill
  bundle when the CLI contains a newer copy.
- The shipped skills document noninteractive conflict resolution and the
  snapshot boundary used for transcript capture.

### Fixed

- Conflict hints rename an indented `jj new` command to `vex new`, matching the
  command available in a Vex checkout.

## [1.11.1] - 2026-08-21

### Fixed

- `vex sync` restacks a checkout that has nothing to publish instead of failing
  with `Error: Empty revision set`. A clean working copy on a trunk that has
  moved is now refreshed and rebased onto the new trunk, and nothing is
  uploaded. `vex pull --rebase` shared the bug and is fixed with it.
- `vex sync` no longer refuses to run because a selected change has no
  description. An undescribed change is restacked like the rest of the stack and
  left out of the upload, so the one command that keeps a checkout current keeps
  working as soon as you start typing. `vex submit`, and any selection named
  with `-r`, still require a description.
- `vex push` publishes the objects it is about to move a ref onto when the
  checkout records a slug the catalog treats as an alias. An organization's Home
  is cloned as `main` and resolves to the canonical `home`, and the mismatch
  skipped the upload silently, so the push failed with `cannot resolve git/ref
  target …: object is missing or pending deletion` for a commit that had simply
  never been uploaded.

## [1.11.0] - 2026-08-20

### Added

- `vex setup` now configures this machine and the repository it is run in.
  Project skills go in `.agents/skills`. `--skill-scope global|local|both`
  chooses which skill trees to write (default `both` in a Vex checkout,
  otherwise `global`). A `generic` target covers Pi and other Agent Skills
  clients that load that shared tree (`--targets pi` and `--targets universal`
  still work).
- `--with-mcp` is the scripted way to enable MCP. Interactive setup starts with
  MCP off. Transcripts stay on by default in a Vex checkout;
  `--no-agent-checkpoints` omits them.

### Changed

- Windsurf is Devin: `--targets devin` (alias `windsurf`). Detection still
  accepts `Devin.app`, `Windsurf.app`, and leftover Windsurf config.
- Global skills are written once to `~/.agents/skills` rather than a per-client
  copy of the same tree. Claude Code in a checkout gets `.claude/skills/<skill>`
  as a relative symlink into `.agents/skills`.

## [1.10.0] - 2026-08-20

### Added

- `vex change list` takes `--limit N` (default 25) and prints how many changes
  it left out, instead of silently printing every change in the repository.
- The generated-resource commands — `vex app`, `env`, `desired-state`,
  `release`, `rollout`, `runtime`, `reconciler-tick`, `hosting`, `execution`,
  `identity`, `obs`, `artifact` — describe themselves in `--help`: the actions
  they accept, what each one does, and the arguments it needs.

### Changed

- `vex whoami` leads with the identity you asked for — name, email, user id,
  organization, and which repository the current checkout points at — rather
  than the full organization-policy dump. `--format json` is unchanged.
- Hints and errors inherited from jj now name `vex` as the command to run.
  Following one no longer lands you on `command not found` or a stock `jj` that
  refuses to open a Vex repository.
- `vex change list` asks the server for a page. The changes endpoint now
  returns the newest 25 by default instead of every matching change; use
  `--limit` for more.

### Fixed

- `vex describe`, `vex commit`, `vex split` and `vex squash` fail immediately
  with a message when there is no `-m` and no terminal to open an editor in.
  Run from an agent, a script, or CI they used to paint an editor into the pipe
  and hang.
- Revsets accept the raw-hex change id that Vex itself prints — from `vex
  change show --format json`, CI payloads, issue bodies — so pasting a Vex
  identifier back into `vex log -r` resolves instead of reporting that the
  change does not exist.
- `vex deploy logs` says which of the six things went wrong — unknown app,
  wrong allocation, expired logs, and so on — instead of collapsing them into
  `404: Not Found` or `502: Nomad request failed`.

## [1.9.1] - 2026-08-19

### Fixed

- `vex submit` from a Home checkout publishes one working-copy tree that can
  span every repository in that checkout. It no longer treats an unlanded
  previous Home change plus the current working copy as two submits, and no
  longer requires returning to the clone-time revision before starting the next
  Home change.
- `vex clone` of a federated Home no longer fails when a member repository
  contains `.gitmodules` or other Git submodule metadata.
- `vex clone` of a repository that contains empty files no longer fails checkout
  with `blob object is not finalized` for SHA-256 of empty bytes. The CLI
  synthesizes that implicit blob locally; jj-backend serves it the same way so
  older clients still clone.
- Hosted agent sandboxes clone a federated Home with a manifest-bound `vexhome_`
  credential instead of a raw repository access token, matching `vex clone`.
  The Blaxel runner floor is now the published 1.9.0 linux-amd64 CLI.

## [1.9.0] - 2026-08-17

### Added

- `vex submit` supports stacking a Git-mode branch (submitted from a plain `git
  clone`, no native Vex workspace) on top of another already-submitted Git-mode
  branch: pass `--target <parent-branch>` to create a genuinely stacked GitHub
  pull request — base is the parent's branch, not trunk — instead of a flat
  diff. See `/docs/submit-and-stacking`.
- `vex sync` gained `--restack`/`--no-restack` to control whether it rewrites
  the local stack when pulling the target, mirroring `gt sync`'s flag pair.

### Fixed

- A Git-mode submission rejected before any branch was claimed or PR touched
  (for example, `--target` naming an incompatible stack parent) no longer
  renders the misleading "Vex adopted the branch but the PR failed" message;
  it now surfaces the server's real rejection reason.

## [1.8.11] - 2026-08-14

### Fixed

- `vex pull` now refreshes flat federated Home repositories from their signed
  component snapshots without requesting forbidden raw access to the physical
  backing repository.
- `vex submit` prints `{origin}/{org}/change/{number}` (for example
  `https://vex.sc/roder/change/15`) instead of the Vex Home shortcut
  `/change/{number}`, which opens the wrong organization's review.

## [1.8.10] - 2026-08-14

### Fixed

- `changes/*` and `stacks/*` review refs are no longer immutable heads. They
  are in-flight patchset tips (`changes/832@vex`), so `vex edit` can rewrite
  them. Ordinary untracked remotes stay protected.

### Changed

- `vex submit`, `vex sync`, and `vex push` print what they are doing while
  objects upload and the review is created, including a live object-transfer
  line on a TTY, so a long submit no longer looks hung.

## [1.8.9] - 2026-08-13

### Fixed

- Home clones batch selected-snapshot metadata transfers while preserving the
  snapshot authorization boundary, so large federated repositories no longer
  fetch thousands of loose objects one request at a time.

## [1.8.8] - 2026-08-13

### Changed

- Agent checkpoint upload and export verify zlib hashes and the opaque
  session-id envelope. They no longer clone an already-scrubbed transcript
  and re-run the bundled secret scanner over every JSON string. Capture still
  scrubs fail-closed before anything is written to the outbox.
- Strings shorter than 8 bytes and payloads larger than the bundled scanner's
  1 MiB cap skip that scanner instead of blocking the session. Local
  credential, token, and private-key detectors still run.

### Fixed

- `vex setup doctor` and `vex session doctor` classify the local transcript
  outbox from manifests instead of decompressing and privacy-rescanning every
  outstanding archive. A mature checkout can hold hundreds of megabytes of
  already-scrubbed Codex transcripts; opening them made doctor appear to hang.

## [1.8.7] - 2026-08-13

### Fixed

- Private GitHub App imports now supply Git's expected fixed username and
  ignore unrelated machine credential helpers, so installation tokens clone
  repositories reliably.
- Eager Home clones fetch loose objects through verified presigned downloads
  before falling back to gRPC, so individual large files no longer exceed the
  gRPC message-size limit.

## [1.8.6] - 2026-08-13

### Fixed

- Clones fetch large manifests in bounded, retryable ranges, so composed Home
  repositories with substantial imported history no longer exceed the gRPC
  message-size limit.
- `vex submit` prints the canonical review URL `{origin}/change/{number}`
  instead of `/changes/{number}/browse`.

## [1.8.5] - 2026-08-12

### Fixed

- Agent checkpoint delivery now runs as one renewable machine-wide drain. A
  stale owner is replaced after its heartbeat expires, while concurrent Vex
  commands exit without multiplying privacy scans across repositories.
- Retrying an already-uploaded checkpoint no longer decompresses and
  privacy-rescans its local transcript just to attach the existing remote
  checkpoint to a commit.

## [1.8.4] - 2026-08-12

### Changed

- `vex setup` and `vex setup refresh` now trust the exact Vex-managed Codex
  hooks in the repository the command is configuring. Setup discovers each
  hook first and refuses to trust a modified, foreign, incomplete, or
  user-global hook, so the one-time approval prompt no longer interrupts a
  normal Vex checkout setup.

### Fixed

- Long agent sessions remain checkpointable and attributable across multiple
  Changes. Capture now accepts substantially larger transcript payloads while
  keeping interactive reads bounded, so a long-running agent's work continues
  to appear on its Change and in trunk History.

## [1.8.3] - 2026-08-11

### Added

- Failures now exit with a code that says which failure it was, so a script or
  agent can branch on the outcome instead of matching stderr prose. Previously
  every recoverable condition — a lost op-head race, an expired login, an
  unreachable API, a refused revset — exited 1, indistinguishable from a typo
  in a revset.

  | Code | Meaning | Recovery |
  | --- | --- | --- |
  | 10 | Not a Vex-backed checkout | Run inside a Vex checkout, or `vex clone` |
  | 11 | Not authenticated (401) | `vex login` |
  | 12 | API unreachable or 5xx | Retry |
  | 13 | Repository busy / rate limited | Retry after `Retry-After` |
  | 14 | Op-head CAS conflict | Rerun verbatim; files are untouched |
  | 15 | Working copy stale | `vex workspace update-stale`, then retry |
  | 16 | Not a fast-forward | `vex pull --rebase --dest <bookmark>` |
  | 17 | Revset selection refused | Scope or widen `-r` |
  | 18 | Land gates unmet | Wait for CI/approvals, or override |

  Codes 0, 1, 2, 3, and 255 keep their existing meanings, and an unclassified
  failure still exits 1 — a new code is never guessed. `vex repo import` keeps
  its own documented 0–7 scheme, which it also publishes as the `exit_code`
  field of its JSON events.

### Fixed

- `vex session doctor` now identifies captured agent sessions that never reached
  a checkpoint and prints an exact recovery command:
  `vex session attach --session <id> --revision <revision>`. Manual attachment
  accepts the harness session id directly and creates the missing checkpoint
  when necessary.
- Agent hooks route transcript capture through the repository that owns the
  tool's working directory, and large transcript imports finish in a detached
  process instead of being cut off when the invoking agent exits.
- Transcript attachments carry the JJ change id to the server. Change pages and
  trunk History can therefore find the producing session after the merge queue
  builds a new landing commit with a different commit id.

## [1.8.2] - 2026-08-11

### Changed

- Pulled Change and Stack refs read as `changes/595@vex` and `stacks/ABJY@vex`
  in the local view. They were recorded under the backend's canonical ref name,
  so every `vex status` and `vex log` line spelled the namespace twice —
  `refs/changes/595@vex` — in the one position that holds bookmark names, never
  ref names. The canonical server spelling is unchanged, and `refs/heads/changes/<n>`
  still expands to it on push. A checkout that pulled these refs with an earlier
  CLI keeps the old entries until its next `vex pull --refs changes|stacks|all`,
  which deletes them as it writes the renamed ones.

  Upgrading is the sharp edge, so it is worth knowing in advance: while some
  checkouts run this version and some do not, the local view flaps between the
  two spellings. A 1.8.1 or earlier binary does not recognise the bare names, so
  a plain `vex pull` against a view this release has already migrated deletes
  every bare entry at once — which reads exactly like data loss and is not.
  These refs are remote-only; a single `vex pull --refs changes` restores them.

## [1.8.1] - 2026-08-10

### Added

- `vex deploy logs` and `vex deploy allocation` no longer need a Nomad
  allocation id. Pass `--service` and `--environment` — or nothing at all in a
  repo with a deploy profile — and the server resolves the allocation currently
  serving them, preferring a live one and falling back to the most recent
  terminated one so a crashed service still answers. When the selectors match
  more than one service it refuses rather than guessing: reading `api` logs
  while debugging `jobs` is worse than an error. The allocation id still works
  when you have one.

### Fixed

- `vex change show` and `vex change log` were dropping most of what Rails
  publishes about a CI check. Only the name, status and required flag survived
  deserialization, so `--format json` reported a check with no job, run or
  pipeline id and nothing to open. Every published field now comes through,
  including timings and the reason a check could not be scheduled, along with
  the change's rolled-up `checks_status`.

## [1.8.0] - 2026-08-09

### Added

- CI runners stream a step's output while it runs. `vex node run` used to read a
  step's stdout and stderr to completion before uploading anything, so a long
  build reported nothing at all until it finished — a forty-minute `cargo test`
  was a blank log until the moment it ended. Output is now uploaded as it is
  produced, every 16 KB or two seconds, and the Vex web UI tails it. Segments
  always end on a line boundary so secret masking cannot be defeated by a token
  landing across two uploads.
- `VEX_SETUP_OFFLINE=1` skips the online Agent Skill publication entirely and
  keeps the bundle compiled into the CLI. `vex setup` is documented to work
  offline but always reached for `vex.sc` first; this makes that opt-out
  explicit, for air-gapped installs and for anywhere the network answer does not
  matter.
- `VEX_APPLICATIONS_DIR` overrides the applications directory harness detection
  reads, alongside the existing `CODEX_HOME`. It was the last detection input
  that nothing could redirect.

### Fixed

- `vex setup --yes --targets <harness>` installs for a harness you name even
  when the CLI finds no evidence it is installed. Naming a target is the
  clearest statement of intent there is; it previously installed nothing and
  still exited 0, so a scripted setup could silently do nothing at all.
- Terminal sessions no longer assume `/bin/zsh` exists. The login-shell fallback
  now picks the first shell actually present (`/bin/zsh`, `/bin/bash`, then
  `/bin/sh`), so a terminal opens on Linux hosts where zsh is not installed
  instead of failing to spawn.

## [1.7.0] - 2026-08-09

### Added

- `vex prune` finds and removes the residue a long-lived checkout accumulates:
  workspaces whose directory was deleted by hand, workspaces whose work has
  landed and that now hold only an empty commit, and empty undescribed commits
  left behind by sessions that went nowhere. It reports the plan and changes
  nothing by default; `--yes` takes all of it, `--interactive` opens a checkbox
  picker over the same plan, and `--format json` makes it machine-readable for
  an agent. Everything applies in one transaction, so `vex undo` reverses a
  whole prune. `--delete-files` is the only flag that touches the disk, and it
  runs last. Commits it cannot read are reported and never acted on.

### Fixed

- `vex dash` no longer dies when a commit in its revset cannot be read. A single
  object the backend returns but that fails the native-only decode used to abort
  the dashboard before it drew a frame; it is now a row carrying the error, the
  Revisions title counts them, and the rest of the graph loads. A revset walk
  that stops early — the 1000-commit cap, or an error mid-stream — now says so
  instead of silently returning a short list.

## [1.6.0] - 2026-08-09

### Added

- Roder is a capture adapter, so the Vex dashboard agent's sessions can attach to
  the commits they produce like any other harness. Roder is hosted rather than
  local: it installs no hook file here and has no provider transcript on this
  machine, so `vex agent-checkpoints doctor` reports it as `hosted` instead of
  counting zero hooks and calling that installed. The sandbox-side emitter that
  feeds it is not shipped yet, so nothing is captured through this path today.
- `vex session continue --agent` accepts `claude-code`, `cursor`, and `grok`
  alongside `codex`, so a transcript can be continued in whichever harness you
  actually have open. Each is launched with its own ask-before-acting default and
  is given access to the private handoff and nothing else; no permission-bypass
  flag is ever passed. `vex session resume` accepts the same values, but only
  Codex can resume a still-local native session exactly — the rest start from the
  sanitized handoff, which is what `continue` does.
- `vex session attach` with no arguments now lists the local sessions it could
  attach, newest first, with their titles. Finding the session ID was previously
  left to the reader.

### Fixed

- Grok transcripts reach the product. The upload path validated the adapter
  against its own `codex | claude | cursor` list, so every Grok checkpoint was
  captured, scrubbed, checkpointed and linked to a commit — and then failed
  before any network request, for every checkpoint it ever produced. Delivery is
  best-effort by design, so nothing surfaced it. The list is now derived from the
  harnesses Vex actually captures, so a new harness cannot be left out of it.
- `vex session attach` no longer attaches everything by default. With no
  `--session` it linked **every** checkpoint in the outbox that had no commit —
  1,859 of them on the machine this was found on, because per-turn lifecycle
  hooks legitimately leave that field unset — to a single revision, and a link
  cannot be corrected afterwards, so every genuinely later commit could then
  never be linked to those sessions. It now refuses and lists. `--all` still
  attaches in bulk, asks first, and takes `--yes` for scripts.
- One unhealthy checkpoint no longer discards the links already written for the
  others in the same `vex session attach` run.

## [1.5.1] - 2026-08-08

### Fixed

- Grok sessions are recorded as Grok. Grok merges hook files from every harness
  it is compatible with and does not read a project's `.grok/hooks/`, so it ran
  the Claude Code hook exclusively and every Grok session was captured as
  `claude-code` — with no model, no version, and no transcript, because Claude's
  extractor and transcript resolver both look in the wrong place. The harness is
  now read from Grok's own payload, so its model, reasoning effort, and native
  transcript are captured, and one session is recorded instead of a mislabelled
  twin. Sessions captured before this release keep their old label.
- Agent transcripts sync from a `vex ws create` workspace. `.jj/repo` is a
  pointer file rather than a directory in a workspace, so resolving the shared
  repository configuration through it always failed and every delivery attempt
  gave up — silently, because the drain runs detached. Capture had been working
  the whole time, so a workspace accumulated transcripts that could never upload
  or attach to a commit. `vex agent-checkpoints doctor` reported that store as
  unavailable rather than as full of undelivered work; it now reads the same
  store the capture path writes to.
- A Grok compaction no longer discards the turn's context. `PreCompact` is
  terminal for Grok, as it already was for Claude Code and Cursor.

## [1.5.0] - 2026-08-08

### Added

- `vex service create` adds a service to an existing app. The API endpoint
  already existed but nothing reached it — `vex service` was list/show/update
  only, so a second service (a cache, a worker) could only be added by writing
  the record directly. A created service is internal-only with auto-deploy off
  unless asked otherwise.
- `vex deploy` verbs accept the `#number` they print, so the id from `vex
  deploy list` can be pasted back into show/logs/cancel without reformatting.
- `vex dash` is a k9s-style infra console for watching hosted services and
  related platform state from the terminal.
- `vex bench clone --format json` reports `hydration_manifest_ms` and
  `hydration_walk_ms`, splitting the hydration phase into its server-side pack
  build and the local tree walk that feeds it.

### Fixed

- `install.sh` resolves `latest` through the CLI release registry — the same
  source of truth `vex update` uses — instead of the mutable `cli/latest/…` CDN
  alias. That alias tracks the dev channel and moving it forward was an optional
  release step, so it had drifted to **0.8.1 on macOS and 0.10.0 on Linux while
  1.4.0 was released for both**: every new user got a months-old CLI, and a
  different one per platform, while anyone who had run `vex update` was current.
  The alias has also been moved forward, and remains the offline fallback.
- `vex setup` ships a valid agent-skills bundle again after a packaging break
  left the installed skills unusable.
- Operator GC campaign tooling no longer treats a signed-plan inventory mismatch
  as a hard interlock: a pack set that moved between dry-run and apply is a
  normal repeat signal, not an operator halt.
- GC plan-scope assertions carry the per-kind collectable tallies the gate
  needs, and a permanently unprovable roll-up row no longer fails an otherwise
  good pass.

### Changed

- `vex hub` is now **`vex registry`**, matching `registry.vex.sc` (the registry
  stopped being "Vex Hub" when it moved off `hub.vex.sc`). `vex hub` still
  works as a hidden alias so existing scripts keep running.

## [1.4.0] - 2026-08-06

### Added

- `vex import git` supports `--standalone --slug <slug>` to provision a
  dedicated physical Vex repository and materialize at root `.` (cloneable as
  `<org>/<slug>`), in addition to the existing Home monorepo folder weave.
- Generic git sources accept local paths, `.git` directories, HTTP(S), and SSH
  remotes; clone uses ambient git credentials on the machine.
- Federated Home workflows: virtual-root clone/submit planning, and packing
  import objects as compressed VXPK packs for faster large git history imports.
- Tree and commit uploads during git import are pipelined with concurrent
  mapping writes so long imports spend less time waiting on the backend.

### Changed

- Local `pnpm dev:local` defaults jj-backend object storage to MinIO/S3 so
  list/purge/presign match production (`JJ_OBJECT_STORE_PROVIDER=valkey` remains
  available as an opt-in reduced path).
- Home monorepo submits that touch both `jj/` and other roots are accepted from
  a Home checkout without splitting into separate changes.

### Fixed

- Virtual-repository lands enqueue on the matching VR merge queue instead of the
  physical Home queue.
- Landing a monorepo Space no longer rewrites unchanged sibling folder tree ids,
  so Space-scoped history stays limited to commits that actually touch that tree.

## [1.3.1] - 2026-08-06

### Added

- Platform references and stacks are available through the CLI, including their
  canonical native-reference form.

### Changed

- Configuration-variable reclassification no longer rewrites the stored value.
- Queue entry commands accept a change number directly.
- GC plan JSON now preserves the plan's classification mode.

### Fixed

- `vex pull` recovers a stale `trunk()` alias instead of blocking the update.
- Pack-reclamation output reports successful reclaimed work correctly and
  treats an unreadable quarantine manifest as a real blocker.

## [1.3.0] - 2026-08-04

### Changed

- `vex submit` and `vex sync` now infer the review repository from the changed
  paths.
- `--repo` is now a checked override. Vex rejects it when the selected changes
  belong to a different repository.
- A selection containing changes from several repositories now fails before
  Vex mutates local or remote state.

## [1.2.5] - 2026-08-03

### Fixed

- An agent transcript no longer goes missing because *another* agent's session
  was unhealthy. When a commit sealed, one session that could not be
  checkpointed — a blocked privacy scan, an unreadable archive — aborted the
  whole batch, discarding the links already written for the healthy sessions.
  The commit then reported `No agent transcript attached to this change` and,
  seeing no checkpoints, skipped the upload retry, so a correctly captured
  transcript stayed on disk indefinitely. Checkouts shared by several agents at
  once were hit hardest. Each session is now handled independently.

### Changed

- `vex session doctor` and `vex agent-checkpoints sync` no longer re-verify
  checkpoints that are already delivered. The outbox keeps every checkpoint
  ever captured, and both commands were decompressing and re-scanning all of
  them on every run, so they slowed down as a checkout aged rather than with
  the work actually outstanding. On a store with ~1,800 delivered checkpoints,
  `session doctor` ran for over fourteen minutes without printing anything;
  it now finishes in about twelve seconds, and a sync that had eighteen
  checkpoints to send takes under a minute instead of twenty.
- `vex session doctor` now reports how much of its answer came from archives
  rather than manifests: `checked: 1875 (18 archives verified)`. Already
  delivered checkpoints are read from their manifest, so local corruption in a
  spent archive is no longer counted — Rails holds the authoritative copy, and
  `vex session doctor --remote` still reconciles against it.

## [1.2.4] - 2026-08-03

### Fixed

- A failed hosted Git clone now says what actually went wrong. When Vex's own
  clone endpoint is misrouted, Git reports `repository not found` against a
  hosted URL you never typed, which reads as "your repository is missing" when
  it means the service is misconfigured. `git clone vex://org/repo` and
  `vex git clone org/repo` now check the endpoint after a failure and say so
  explicitly, including that your repository and access are fine. A successful
  clone is unaffected — the check runs only once the transport has failed.

## [1.2.3] - 2026-08-03

### Added

- `vex submit -m "…"` (and `--message`) now describes the selected JJ revisions
  before uploading — the quick path for `vex describe -m "…" && vex submit` —
  and still seeds the initial rich-text Change description with the same text.
  Whitespace-only messages are rejected up front.

### Fixed

- `vex materialize --land` now reads the current hosted trunk before building
  its weave. If the trunk moves during the operation, the command rebuilds
  against the new tip instead of replacing existing trunk history.
- `vex materialize` now uploads its staged commits and file objects before it
  writes any refs. This fixes land failures under the default batch upload
  setting, including failures caused by copied file objects that were still
  local.

### Removed

- The `VEX_DURABILITY` durability lattice is gone (roadmap/088 Stage 9). It had
  been inert since Stage 7 made the operation log local: there is no queue for a
  deferred mode to defer into, so every operation is already durable before the
  command returns. `vex doctor` no longer prints the `durability` /
  `durability_note` fields. A `vex.json` that still carries `"durability"` keeps
  loading — the key is ignored, and rewriting the file simply drops it.

## [1.2.2] - 2026-07-31

### Fixed

- Agent sessions started in Cursor were captured twice, and the duplicate was
  attributed to Claude Code. Cursor also runs `.claude/settings.json` hooks, and
  capture trusted the hook file that invoked it over the payload, so one session
  was reported as two: the real Cursor session, and a Claude Code twin that
  carried no model or version and could never attach a transcript. Because the
  Claude-compatible hooks fire on every tool call, that empty twin usually won
  the commit attachment. The emitting harness is now read from the payload, which
  collapses the two into the single real session.

## [1.2.1] - 2026-07-30

### Fixed

- `vex land --dry-run` and `vex change log` printed a "Landing stopped" block
  for changes that never had a stopped landing, with every field of it blank.
  The server sends `attention: null` when there is nothing to report, and the
  CLI treated that JSON null as a present payload.

## [1.2.0] - 2026-07-30

### Added

- `vex land --dry-run` and `vex change log` now report why a landing stopped.
  Previously the CLI never read the server's attention payload at all, so an
  ejected landing surfaced only in the web UI. The block names the failing
  required checks and the conflicting file paths, says explicitly when no
  structured detail was recorded, and ends with the commands that dig further
  (`vex change log`, `vex queue status --format json`, `vex queue retry <id>`).
- `vex queue status --entry <id>` and `--change <n>` resolve those entries
  directly instead of hoping they fall inside the terminal-history window.

### Fixed

- `vex queue status` could not show a recently ejected entry. The terminal
  history was sorted by queue position rather than recency, so its limit kept
  the oldest entries and a landing that stopped minutes ago was unreachable no
  matter how it was queried. The window is now ordered by recency and is much
  deeper.

## [1.1.1] - 2026-07-29

### Fixed

- A source-built CLI reported no version to the backend at all. The
  `x-vex-cli-version` header added in 1.1.0 is only sent when the value fits the
  server's 64-character field, and a dev build's version is
  `X.Y.Z-<full 64-char commit>` — 70 characters — so the header was dropped
  entirely and the client was invisible. The effect was the opposite of the
  intent: released builds (CI, installs) reported fine, while source builds —
  what developers and agents actually run, and the likeliest place for an old
  client to hide — reported nothing. The commit suffix is now shortened to 12
  hex characters instead of the header being dropped, matching the short-sha
  convention already used for image tags and the release registry. The semver
  core is untouched, and a clean release version is still sent verbatim.

## [1.1.0] - 2026-07-29

### Added

- The CLI now sends its version to the backend as `x-vex-cli-version` gRPC
  metadata on every request. This exists to answer one question the platform
  previously could not: which CLI versions are actually running. Nothing about
  your repository is sent — only the version string this binary already prints
  for `vex --version`. It is attached in one place, adds no new requests, and is
  recorded server-side off the request path so it cannot slow a command down.

### Removed

- **`VEX_PUBLISH_OP_LOG` is gone.** It was documented as the compatibility
  escape that would restore the pre-1.0 publishing behaviour, and on a shipped
  1.0.x client it did not work — the client no longer had a publishing path and
  the server refused the old one regardless. An escape hatch that silently does
  nothing is worse than no escape hatch, because it is reached for during an
  incident, when discovering it is fake costs the most. If you have it set, it
  has not been doing anything; remove it.
- **`VEX_CLONE_SNAPSHOT_PACKS` is gone**, along with the snapshot-pack subsystem
  it controlled. Snapshot packs were a precomputed trunk-worktree closure chain
  embedded in the clone manifest; they had been disabled server-side since
  2026-07-24 and a production benchmark measured their contribution at exactly
  zero. Ordinary clone packs — which is what actually makes `vex clone` fast —
  are untouched and unaffected.

## [1.0.1] - 2026-07-28

### Fixed

- The freshness line no longer goes to stdout. In 1.0.0 it was appended to
  command output, so `vex log --no-graph -T commit_id` returned the 64-character
  commit id followed by `Refs: up to date with the server (...)` — 106 characters
  — silently corrupting scripts and any agent parsing templated output. The note
  is a status message about the repository, not part of a command's data, so it
  now goes to stderr with the rest of jj's hints, where a human still sees it.
  **Anyone scripting against 1.0.0 output should upgrade.**

## [1.0.0] - 2026-07-28

First major release. The operation log is now **local-only**: it lives in
`.jj/repo/` on the machine that produced it and is never uploaded, which is what
upstream jj intends ("operations and views are not meant to be exchanged between
repos or users"). Vex had been using the op log as its sync plane; refs are the
sync plane now. `vex undo`, `vex op log`, `vex op restore` and `--at-op` all keep
working exactly as before — they have always been local.

### Changed

- **Breaking: `vex push` is the publication verb.** Objects written by `vex
  commit` are staged durably on disk and uploaded by the next `vex push`, before
  any ref moves. Previously they were uploaded as a side effect of the operation
  publish during `commit`. A commit is still durable locally the moment it
  returns, but it is not on the server until you push.
- **Breaking: the client no longer publishes operations.** No `CommitOperation`
  call and no `Op`/`View` object upload happens on the default path. Servers keep
  accepting them for older clients during the compatibility window.
- `vex status` and `vex log` always show a freshness line with three distinct
  states — current, behind (naming `vex pull`), or unknown. "Unknown" is
  deliberately distinguishable from "current"; a failed or slow freshness probe
  never fails the command.
- Tracked bookmarks auto fast-forward using jj's own three-way merge against the
  last-known server target. A local bookmark that has moved is never
  fast-forwarded — it becomes a conflicted bookmark, as in jj. The working copy
  and `@` are never moved by this, and every advance is reported.
- `--durability` and `VEX_DURABILITY` are transitional and will be removed with
  the compatibility path.

### Added

- `vex checkpoint` publishes a commit as a ref under
  `vex/checkpoints/<agent-session>/<workspace>` without moving a bookmark, so an
  agent's work can be made visible to CI and to agent surfaces. CI opts in with an
  explicit `on: checkpoint:` workflow key, so a checkpoint never fires a bare
  `on: push:` workflow.
- `vex status --format json` exposes typed freshness fields so an agent can
  branch on data instead of parsing prose.
- `--no-refresh` (and its env equivalent) skips the freshness probe for scripting
  and benchmarks.

### Removed

- `vex debug publish` and the deferred publish queue it drained. Publication is
  `vex push`.
- The op-head conflict machinery, including its retry ladders. With no
  repository-global op-head compare-and-swap there is no such conflict to
  recover from, and the per-ref CAS on push is now the only conflict a user can
  encounter.

### Fixed

- The recurring "working copy is stale" / "sibling operation" lockup. Upstream
  jj's merge-based stale-working-copy recovery needs an op-heads store that can
  hold more than one head transiently; the old strict single-head CAS rejected
  that and forced a recovery-commit workaround. Local op heads hold several heads
  natively, so upstream's recovery path works again and the workaround is gone.
- Concurrent commands in two workspaces of one repository can no longer lose an
  operation head, and N concurrent readers of a divergent repository now produce
  one merge head instead of N.

## [0.18.0] - 2026-07-27

### Added

- `vex stack submit` accepts a stack-level Markdown PR description via
  `--message`, `--file`, or `--stdin`, and can clear an existing one with
  `--clear-description`. Repeatable `--attach ALIAS=PATH` uploads private proof
  assets referenced from the description as `vex-asset:<alias>`.

### Fixed

- `vex ws` resolves the organization from the repository when no default org is
  configured, instead of failing or guessing from an unrelated context.
- Agent checkpoint hooks are more resilient: they ignore the working copy while
  capturing, stop routine tool hooks from rescanning a growing transcript, and
  resume from the checkpoint that holds the most context rather than the latest
  upload by capture time.

## [0.17.1] - 2026-07-26

### Fixed

- `vex node run` now retries reporting a job's terminal result instead of
  giving up after one attempt. That report is the only record that a job
  finished, so a single transport error or a brief API interruption used to
  leave the lease dangling until the server's expiry reaper failed the job
  minutes later — discarding a build whose image had already been pushed. A
  repeat report answered by "lease is not active" is treated as already
  recorded rather than retried.

## [0.17.0] - 2026-07-26

### Added

- `vex rebase` now requires an explicit `-r`, `-s`, or `-b`. jj's default of
  `-b @` moves the whole branch containing `@`, which rewrites already-published
  commits into conflicts when the destination bookmark is stale, and it has no
  dry-run or confirmation in front of it. The rejection reports how many commits
  the default would have touched and points to
  `vex pull --rebase --dest <bookmark>`; pass `-b @` to opt back in.

### Changed

- Automatic stale-working-copy recovery now stops after two consecutive attempts
  within fifteen minutes. Recovering repeatedly against a degraded backend
  re-snapshots whatever is on disk each time, which can split one change across
  several commits or commit a half-written file. The refusal explains how to
  check backend health, recover manually, and undo a bad recovery from the
  operation log.
- Push and pull conflict errors now recommend `vex pull --rebase --dest
  <bookmark>` instead of a bare `vex rebase -d <bookmark>@vex`. The old hint
  named the exact command whose default sweeps in published commits.

## [0.16.1] - 2026-07-25

### Fixed

- `vex pull` now behaves like `jj git fetch` for tracked bookmarks: it merges each
  refreshed `<bookmark>@vex` into the local bookmark of the same name, so a
  fast-forward advances local `master` and real divergence becomes a conflicted
  bookmark. Pull previously marked every hosted ref as tracked but never carried
  the local bookmark, leaving local trunks silently stale — which made
  `vex rebase -d <bookmark>` aim at an old commit and, with jj's default `-b @`,
  rewrite already-published commits into conflicts.

### Changed

- `vex pull --update` is now only the working-copy move, since tracking carries
  the bookmark on every pull. Its refusal rules are unchanged for the working
  copy: it will not move over a description, uncommitted changes, or a working
  copy that is not a descendant of the target.

## [0.15.2] - 2026-07-25

### Fixed

- `vex repo import` no longer panics immediately after selecting repositories.
  Lease heartbeats now run independently of Tokio, matching the command
  executor used by the CLI.

## [0.15.1] - 2026-07-25

### Fixed

- A commit's agent transcript no longer disappears when the commit is
  rewritten. Checkpoints were attached to one immutable commit ID, but a rebase
  during non-fast-forward push recovery, a `vex land`, a squash, or a describe
  all replace that commit — leaving the attachment on a hidden commit that never
  lands, and the commit that did land with no provenance on History. Links now
  also record the jj change ID, which survives rewrites, and are re-pointed at
  the change's current commit after `vex commit` and after `vex push` so the
  outbox attaches the commit that actually exists.

## [0.15.0] - 2026-07-25

### Fixed

- `vex import git`, `vex import github`, and `vex space add` now import through
  native materialization instead of `git subtree add` plus a Git push. The old
  projection wrote Git-format commits and trees onto the target repository's
  trunk. Since that target defaults to the organization `home` — one physical
  repository shared by every virtual repository inside it — a single import
  could leave native clones of *every* folder failing while reading a tree
  object. The new path is the same engine the web import, GitHub onboarding, and
  `vex repo import` already used, so both surfaces now produce identical
  history.
- `vex materialize` and every other caller of the materialization engine refuse
  to weave onto a trunk tip that is a Git-format commit, instead of carrying
  those objects into the merge.

### Changed

- An import weaves the source default branch only. Non-default branches and
  tags are no longer projected into `imports/<slug>/*` — that projection was the
  Git-format write that corrupts a native trunk. The command names what it is
  leaving behind before it starts, and reports it as `skipped_branches` /
  `skipped_tags` under `--format json`.
- Imports no longer record Git import baselines. Native materialization writes
  the git-to-native commit identity map itself, which is what later sync reads.

## [0.14.1] - 2026-07-25

### Fixed

- A repository that was cloned and then only read no longer shows a frozen view.
  A clone keeps its workspace registration local until its first write folds it
  away, and until then op-head reads never asked the server anything — so work
  done by a teammate or an agent in another workspace was invisible
  indefinitely. Reads now fold that registration onto the current server head,
  which rejoins the server's history and makes everything published since the
  clone visible. Every failure path still falls back to the local view, so a
  read can become fresher but never fail.
- One op-head refresh per process now answers every caller in that process the
  same way. Previously the first caller fetched the server head and every later
  one silently fell back to the stale local head, which is how a freshly fetched
  head could be discarded within a single command.
- The end-of-command freshness refresh no longer gives up before it can finish:
  its budget was below a normal round trip, so it timed out every time and never
  recorded a server head.

## [0.14.0] - 2026-07-25

### Added

- `vex pull --update` fast-forwards the local bookmark and working copy to the
  bookmark it just pulled, instead of only refreshing `<bookmark>@vex`. It
  refuses without changing anything when the local bookmark is not an ancestor of
  the pulled target, when it is conflicted, or when the working copy holds a
  description or uncommitted changes.
- `vex pull -d/--dest <bookmark>` names the destination for `--update` and
  `--rebase`, following Sapling's split between what to pull and where to move.
  With a single pulled bookmark that bookmark is the destination; with none it is
  the repository trunk. `--update` also accepts Sapling's `-u`.
- `repo_pull` over MCP exposes the same `update` and `dest` parameters.

### Changed

- `vex pull --rebase` now actually pulls before it integrates: it refreshes the
  hosted bookmarks, reports that on stderr, and then rebases the current mutable
  stack onto the pulled target. Previously it delegated straight to `vex sync`,
  leaving the local `<bookmark>@vex` projection stale and taking its target from
  the control plane.
- `vex pull --rebase` is a pure graph operation and no longer requires diff
  descriptions or a review record, so it works on an in-progress stack. It
  previously failed with `diff <change> has no description` whenever the working
  copy was undescribed. Use `vex sync` when a submitted stack also needs its
  landed prefix removed and its review state reconciled.
- When the repository access catalog does not report a default branch (the usual
  case for an existing checkout authenticated with a cached token), `vex pull`
  now falls back to the repository's `trunk()` alias instead of failing to
  resolve a target.

## [0.13.0] - 2026-07-25

### Changed

- **Local-first durability is now the default.** A command returns once its
  operation is durable on local disk, and a background publisher moves it to the
  server; `push`, `pull`, `submit`, and `land` still flush the queue and confirm
  the server has everything before doing their own work. Working-copy snapshots
  no longer block on a round trip, so `vex status` on a dirty tree and `vex
  commit` return in local-disk time. Set `VEX_DURABILITY=sync` to restore the
  previous behaviour, where a command does not return until the server has
  acknowledged the operation.
- CI and other disposable machines (anything exporting `CI=true`, including Vex's
  own runners) default to `flush-on-exit` instead: the same deferred fast path,
  but the process will not exit with operations still queued, so a runner that is
  destroyed at the end of its job cannot lose work. `VEX_DURABILITY` overrides
  this.

### Fixed

- A repository whose queued operations diverged from the server now converges by
  itself. Both publish paths merge a moved server head and retry rather than
  asking you to reload and re-run the command, and a clone whose registration is
  still pending no longer hides the moved head from that merge — which previously
  left such a repository unable to publish at all until its marker files were
  removed by hand.

## [0.12.1] - 2026-07-25

### Fixed

- MCP server repo resolution now follows client workspace roots per call instead
  of a stale baked-in `--repo` path. Setup guardrails block invalid repo pins,
  and `vex setup doctor` reports them.

## [0.12.0] - 2026-07-25

### Added

- Local-first durability modes for the op log (`VEX_DURABILITY=local-first|flush-on-exit`;
  `sync` remains the default): mutations return after local durability and a background
  publisher drains the pending-publish queue with sequential per-operation CAS, so
  `vex status` on a dirty tree drops from ~1.1s to ~0.08s and clean `status`/`log`
  from ~0.16s to ~0.06s on a converged repo (op-head reads served locally, refreshed
  in the background without blocking).
- `vex debug publish` — force-drain the local-first publish queue and report the CAS
  outcome (`--dry-run` lists the queue).

### Changed

- Synchronous publishes now fail fast instead of freezing the repository: the inline
  op-head publish path is bounded (per-attempt request timeout 30s via
  `VEX_GRPC_REQUEST_TIMEOUT_MS`-family overrides, 2 attempts instead of 24), cutting the
  worst-case wedge from over two hours to about 90 seconds while holding the working-copy
  lock. A timed-out publish leaves files untouched; re-running the command publishes again.
- `vex push`, `vex pull`, `vex submit`/`sync`, and `vex land` flush the local publish
  queue before their server work (sync barriers), so deferred-mode operations are always
  server-visible before refs move.

## [0.11.1] - 2026-07-24

### Added

- `vex setup` now installs six focused agent skills (`vex`, `vex-stack`,
  `vex-apps`, `vex-deploy`, `vex-secrets`, and `vex-workspace`) from a single
  catalog with per-skill manifests and conflict detection.
- The interactive setup TUI preselects Skills, MCP, and Agent Context
  checkpoints, shows destination paths and state badges, and remembers
  deselections across runs. Non-interactive setup remains deterministic, and
  scripted `--yes` behavior is unchanged.
- `vex setup status` provides a per-target, per-plane overview. Setup doctor
  output is grouped by target with recovery commands, and `setup refresh` and
  `setup uninstall` support `--planes` scoping.

### Changed

- `vex setup doctor` distinguishes stale Vex-managed skills from user-modified
  skills and reports Codex trust gaps with exact, read-only remediation.
- Agent Context checkpoint hooks now warn instead of breaking the harness when
  `vex` is unavailable. Invocation-time self-healing repairs clobbered
  Vex-managed hooks, refreshes stale unmodified skills, and caches version
  nudges; set `VEX_NO_SELF_HEAL=1` to opt out.

## [0.10.1] - 2026-07-24

### Fixed

- `git clone vex://<org>/<repo>` now accepts Git's conventional URL form,
  where the organization is parsed as the URL authority. The explicit
  `vex://vex.sc/<org>/<repo>` form remains supported.

## [0.10.0] - 2026-07-24

### Added

- Vex releases now include `git-remote-vex`, enabling stock
  `git clone vex://vex.sc/<org>/<repo>` with catalog-resolved, short-lived
  repository authentication. `vex git clone <org>/<repo>` is also accepted as
  shorthand for the canonical hosted Git HTTPS projection.
- `vex repo import` now provides a session-backed GitHub App repository picker
  with keyboard selection, browser authorization continuation, resumable local
  clone/conversion/upload/landing, short-lived rotating credentials, per-item
  failure isolation and retry, and versioned JSON/JSONL output. Existing
  `vex repo <resource> <action>` commands remain API passthroughs, and
  `vex import github` remains available as the legacy compatibility flow.

## [0.9.1] - 2026-07-23

### Fixed

- `vex submit` and `vex sync` send compact JJ commit pointers rather than
  uploading full file diffs, allowing large stacks to be materialized by the
  server from pushed JJ objects.
- Stack submit output now includes a Vex Home review permalink such as
  `https://vex.sc/stack/19`.

## [0.9.0] - 2026-07-23

### Added

- `vex clone` now renders a per-stage progress timeline (Connect / Manifest /
  Transfer / Index / Hydrate / Publish / Checkout): each stage shows live
  detail while it runs (pack counts, bytes, transfer speed, hydrated objects,
  file counts) and leaves its final detail and duration in the terminal after
  the clone completes.
- `vex bench clone --format json` reports pack-phase timing counters
  (`pack_presign_wait_ms`, `pack_http_wait_ms`, `pack_download_ms`,
  `pack_unpack_ms`, `pack_loose_object_ms`).

### Changed

- Fresh clones build the commit index from the head operation's view instead
  of walking the full inherited operation log, cutting clone indexing from
  ~6.9 s to ~0.3 s on a 11k-commit repository. Historical operations index
  lazily on first use; `VEX_CLONE_FULL_INDEX=1` restores the exhaustive
  build.
- Historical view reads during full index builds are fetched concurrently
  (16-way) instead of one at a time.
- Clone pack/chunk fetch concurrency defaults retuned (8 packs x 16 chunks)
  for the new server pack shape (~16 MiB compressed packs, 2 MiB chunks);
  `VEX_CLONE_PACK_CONCURRENCY` / `VEX_CLONE_CHUNK_CONCURRENCY` still
  override.

### Fixed

- Output printed after the clone progress UI (such as `Set trunk()`) no
  longer lands at a stray column.
- The clone summary no longer reports "0 files" on reflink-only checkouts.

## [0.8.2] - 2026-07-22

### Added

- Hosted-app deployment config can be edited from the CLI: service visibility,
  config vars, and path rules.

### Changed

- `vex clone` is now strictly native: the checkout target resolves only through
  native bookmarks (the server-advertised default branch is authoritative), and
  native reads never traverse raw Git objects or `git/object/sha1/*` mappings.
  Use `vex git clone` for Git-format data. This removes the dominant checkout
  cost on converted repositories.
- If the advertised default branch has no native bookmark, `vex clone` now
  fails before checkout with an actionable error instead of silently falling
  back to Git refs.
- `vex bench clone --format json` reports new native-path counters
  (`native_trunk_resolutions`, `native_trunk_missing`,
  `git_compat_commit_decodes`, `git_compat_tree_decodes`,
  `git_mapping_names_resolved`, `git_mapping_rpcs`, `git_mapping_elapsed_ms`);
  any non-zero `git_*` counter on a native clone is flagged as a correctness
  regression.

### Fixed

- 0.8.1 regression: fresh native clones of repositories whose history includes
  Git-imported commits (including `vex/home`) failed during index build under
  the native-only contract. Index builds now skip non-native historical
  commits and truncate ancestry at the native/Git boundary; selected checkout
  targets still fail closed.
- `vex convert` / `vex materialize` can repair repositories whose views
  reference raw Git commits: conversion explicitly opts into Git-compatibility
  reads in memory (never persisted to `vex.json`).

## [0.8.1] - 2026-07-22

### Fixed

- Fresh signed macOS CLI release for the current Vex 0.8.1 source.

## [0.8.0] - 2026-07-22

### Added

- `vex setup` can now configure project-local Agent Context checkpoint hooks
  alongside Skills and MCP with `--with-agent-checkpoints` (alias
  `--with-agent-context`). Supported detected harnesses are Codex, Claude Code,
  and Cursor. Captures are scrubbed before local persistence or upload, attach
  to immutable Vex commits without rewriting them, and can be inspected or
  exported through `vex agent-checkpoints`.

### Fixed

- Claude Code checkpoints retain selected reasoning effort from current hook
  payloads and capture the direct session before a normal `vex commit`.

## [0.7.0] - 2026-07-20

### Added
- `vex docker setup` — one command to configure the local Docker daemon for the
  Vex registry, like `gcloud auth configure-docker`. By default it installs a
  `docker-credential-vex` credential helper (so tokens refresh automatically and
  are never written stale to `config.json`) and registers it for the registry;
  `--static` writes a classic base64 `auths` entry instead. Idempotent, with
  `--dry-run`, `--registry`, `--docker-config`, and `--bin-dir`.
- `vex secrets get --org` / `vex secrets env --org` — read org-scoped secrets
  (admin-only, audited), the counterpart to the existing app-scoped read.
- Org and app auto-detection for `vex secrets` when run inside a Vex repo: bare
  `--org` / `--app` (no value) resolve from the current folder, and with neither
  flag it defaults to the folder's app. Explicit ids still work everywhere.

### Changed
- The default registry is now `registry.vex.sc` (multi-region active-active across
  dc1/lon1/or1, Tigris-backed). `vex hub login` / `vex hub push` and the credential
  helper target it; `hub.vex.sc` still parses as a Vex host during the transition.

### Removed
- The `hub.vex.sc` registry hostname is discontinued; use `registry.vex.sc`.

## [0.6.1] - 2026-07-20

### Changed
- Vex CLI builds now reuse Cargo artifacts across local workspaces, Docker
  builders, and CI, reducing repeated dependency compilation.

## [0.6.0] - 2026-07-11

### Added
- `vex update` — self-updater for macOS/Linux that checks the CLI release
  registry, downloads the latest release binary, verifies its checksum, and
  atomically replaces the running executable.
- A background, off-main-thread check on startup for a newer release, cached
  locally; if one is available, the next `vex` invocation prints a one-line
  hint to update (release builds only; set `VEX_NO_UPDATE_CHECK=1` to disable).
- A real "release" build channel (`VEX_RELEASE=1`) that embeds a clean
  `X.Y.Z` version with no commit suffix, distinct from the commit-suffixed
  "dev" builds published on every push. Releases are registered in a new,
  immutable API-backed CLI release registry (`POST`/`GET /api/v1/cli_releases`)
  that rejects re-publishing an already-released version under a different
  commit.

### Changed
- The organization Home repository is now addressed as `<org>/home`. Existing
  bare-organization flows—including clone, convert, materialize, import,
  Space, and publish—now select Home while explicit `vex init` and `jj vex`
  targets remain explicit.
- Release builds compile the `jj/` source committed in the same Vex revision
  on every platform, so their embedded source identity is reproducible.

### Fixed
- Existing `<org>/main` remotes, checkouts, and stored repository configs keep
  working through the permanent compatibility address and resolve to the same
  repository identity as `<org>/home`.
- Repository-address catalog matching now accepts canonical and legacy Home
  metadata without creating duplicate physical entries, while Git branches and
  bookmarks named `main` remain unchanged.

## [0.5.0] - 2026-07-02

### Added
- Pack transfer is now parallel end to end: pack chunks download concurrently
  within each pack (`VEX_CLONE_CHUNK_CONCURRENCY`, default 8, on top of the
  existing 4-wide pack pool), over pooled HTTPS connections with connect/read
  timeouts (`VEX_HTTP_CONNECT_TIMEOUT_SECS` / `VEX_HTTP_READ_TIMEOUT_SECS`).
- Presigned direct object-store reads: when the server mints presigned URLs
  (`JJ_PRESIGN_GET_TTL_SECS`, on by default server-side), pack bytes download
  straight from object storage instead of riding the gRPC control path. Every
  presigned chunk is SHA-256-verified before use, response sizes are capped,
  and any failure falls back to verified gRPC transparently.
- Pack-resident metadata cache: clone metadata (commits, trees, ops, views —
  ~97% of unpacked objects) stays in per-pack payload files with an index
  instead of exploding into ~130k loose cache files, cutting clone cache-write
  time roughly in half. Blobs stay loose so copy-on-write checkout still works.
  Disable with `VEX_CACHE_PACK_RESIDENT=0`.
- Resumable transfers harden: corrupt transfer state self-heals, interrupted
  chunked downloads resume via truncate-to-state, and decode-poisoned
  transfers refetch cleanly.
- `vex bench clone` reports the new counters: `presigned_fetches`,
  `presigned_bytes`, `objects_pack_resident`, `loose_writes_avoided`,
  `chunk_fetch_concurrency`.

### Added
- Fast initial clone materialization (roadmap/032). Clones of snapshot-packed
  repos download the working tree as a few streamed snapshot packs instead of
  one RPC per file (vex/main: 2,930 per-file fetches → 0; cold clone 82.8s →
  ~28s), and repeat clones with a warm shared cache send `have` negotiation so
  the server skips already-held snapshot sets entirely
  (`VEX_CLONE_SNAPSHOT_PACKS=0` disables).
- Batched checkout hydration: lazy clones without snapshot coverage prefetch
  missing file/symlink blobs in bounded `GetObjectsInline` batches before
  checkout instead of one `GetObject` per file (`VEX_CLONE_HYDRATION=0`
  restores per-file fetching).
- Parallel + copy-on-write checkout: working-copy materialization uses a
  bounded writer pool (`VEX_CHECKOUT_WRITERS`, default min(8, cores)) and, on
  APFS/reflink filesystems with a same-volume cache, materializes files via
  `clonefile`/`FICLONE` (`VEX_CHECKOUT_REFLINK=0` disables).
- Clone pack prefetch downloads packs in parallel
  (`VEX_CLONE_PACK_CONCURRENCY`, default 4) over the same resumable chunked
  transfer; clone progress gained hydration and per-file materialization
  phases.
- `vex bench clone`: end-to-end clone benchmark with per-phase wall-clock
  attribution (connect / manifest / pack transfer / hydration / checkout) and
  client counters (per-file RPCs, pack chunks, hydrated objects, files/bytes
  written, reflinked files), text or `--format json`; supports `--samples`,
  `--dest`, `--keep`, and `--have <commit>` for incremental-transfer runs.

### Changed
- `vex clone` progress UI now shows a live detail line explaining what each
  phase is doing. Most importantly, while the server builds the clone manifest
  (cold cache) it shows `backend is building the clone manifest (cold cache) ·
  waited Ns` with a live counter instead of an opaque `0% Connecting`, and it
  surfaces transient backend errors it is retrying.
- `vex clone` now rides transient errors while fetching the clone manifest
  (edge 502 / backend restart / deadline) up to the max-wait instead of aborting
  after the short retry window.

### Fixed
- `vex clone` Ctrl+C (and `q`/`Esc`) during an in-progress clone now exits with
  an `clone interrupted` error instead of painting `100% ✓` while a detached
  worker kept running in the background. Clone failures are rendered in the
  progress block too.

## [0.3.1] - 2026-07-01

### Fixed
- `vex clone` working-copy materialization is now genuinely parallel. Blob reads
  during checkout were dispatched through a blocking `block_on` on the shared
  runtime, which stalled the single-threaded executor driving the concurrent
  checkout stream — collapsing the intended 32-way concurrency to one fetch at a
  time (≈one network round-trip per file). Object reads now run as spawned tasks
  and are awaited cooperatively, so up to `concurrency()` fetches are in flight at
  once. On a ~2,900-file clone of `vex/main` this turned a checkout that appeared
  to hang at "Connecting/Materializing" into a ~73s end-to-end clone.

## [0.3.0] - 2026-07-01

### Fixed
- `vex clone` no longer fails intermittently during working-copy checkout with
  "Failed to create parent directories … No such file or directory": the parallel
  checkout now retries the transient directory-creation race (observed on
  case-insensitive/APFS macOS clones) instead of aborting the whole clone.
- `vex clone` object and pack fetches survive a transient backend restart or edge
  blip. gRPC reads now retry with exponential backoff + jitter over a ~40s window
  (was a fixed ~2s), so a mid-clone 502 / "service currently unavailable" no
  longer aborts the clone. Tunable via `VEX_GRPC_RETRY_ATTEMPTS`,
  `VEX_GRPC_RETRY_BACKOFF_MS`, and `VEX_GRPC_RETRY_BACKOFF_CAP_MS`.

### Changed
- `vex clone` no longer holds one RPC open while the server builds a large clone
  manifest. It requests `accept_pending` and polls until the manifest is ready
  (tunable via `VEX_CLONE_MANIFEST_POLL_MS` / `VEX_CLONE_MANIFEST_MAX_WAIT_SECS`),
  so a cold manifest on a large repo can't trip the client/edge timeout.

### Added
- `vex materialize` — weave a source Git repo's full history into a native Vex
  trunk under a subpath (staged on a bookmark for review before landing);
  `--repo-token` lets the control plane authorize server-side runs directly.
- `vex stack land --squash` / `--rebase` — choose how an accepted stack lands on
  its target branch, overriding the repo's default landing method. `--squash`
  collapses each diff into a single clean commit on the current target tip;
  `--rebase` preserves the original commit message and author. The flags are
  mutually exclusive; omitting both falls back to the repository default.
- `vex ws` (alias `vex workspaces`) — create and manage local jj/vex workspaces
  under a single configurable root (default `~/.vex/workspaces/<org>/<name>`),
  driven by a `./.vex/workspace.toml` policy file. The default root lives
  *outside* the repo so per-workspace `node_modules`/`target` dirs don't sit in,
  or confuse tooling in, the parent working copy. `<org>` is the configured vex
  default-organization slug (falling back to the repo's directory name); `root`
  accepts a leading `~` (expands to `$HOME`) or a repo-relative path.
  - `vex ws create <name>` attaches a jj workspace and runs `on_workspace_create`
    hooks; `vex ws remove <name>` runs `on_workspace_remove` hooks, forgets the
    workspace, and deletes its files; `vex ws list` and `vex ws config` round it
    out (`vex ws config --init` scaffolds a starter policy file). The name is
    optional — omit it and a random `adjective-noun` name (e.g. `swift-otter`)
    is generated.
  - Hooks are ordered shell commands per event. Before each runs,
    `__WORKSPACE_DIR__`, `__WORKSPACE_NAME__`, and `__REPO_ROOT__` are
    substituted (and exported as `VEX_WORKSPACE_DIR` / `VEX_WORKSPACE_NAME` /
    `VEX_REPO_ROOT`) — e.g. to copy `.env` into a new workspace, or to symlink
    `target/` back to the main checkout so per-workspace Rust build caches don't
    each balloon to many GB.
  - When the workspaces root is configured *inside* the repo (a repo-relative
    `root`), `vex ws create` auto-ensures it is ignored before attaching the
    workspace: it appends the path to an existing `.gitignore` (or
    `.vexignore`/`.jjignore`), creating `.vexignore` when no ignore file exists.
    Idempotent; skip with `--no-ignore`. With the default outside-the-repo root
    this is a no-op (nothing in the repo to ignore).

## [0.2.6] - 2026-06-27

### Added
- `vex pat` — create, list, and revoke Personal Access Tokens from the CLI.
  `vex pat create --name <NAME> [--expires-in <DUR>]` prints the raw token to
  stdout (so it pipes into `vex secrets set`); `vex pat list` shows metadata
  only; `vex pat revoke <ID>` revokes. Backed by a new PAT-management API.

## [0.2.5] - 2026-06-26

### Fixed
- `vex clone` now checks out the server-registered trunk (the repository's
  `default_branch`) and seeds the repo-local `trunk()` revset to match, instead
  of guessing a local `main`/`master`/`trunk` bookmark and sometimes landing on
  an unrelated branch (e.g. an agent/feature branch).

## [0.2.4] - 2026-06-26

### Added
- `-v` is now a shorthand for `--version` (replaces clap's default `-V`).

### Changed
- `vex runner run` (the self-hosted runner) is now safe by default: it defaults to
  an isolated workspace (`~/.vex/runner/workspace`, configurable via the
  `vex.runner.workspace` config key) instead of the current directory, is off by
  default (`vex.runner.enabled`, with `--enable` for a one-off run), and refuses to
  operate on any repository outside its dedicated workspace.

## [0.2.3] - 2026-06-26

### Changed
- Maintenance release.

## [0.2.2] - 2026-06-26

### Changed
- Maintenance release; no functional CLI changes since 0.2.1.

## [0.2.1] - 2026-06-26

### Added
- Started this changelog and a `vex-cli-release` skill documenting changelog
  upkeep and the CLI release process.

_No functional CLI changes since 0.2.0._

## [0.2.0] - 2026-06-26

### Added
- `vex secrets` org/CI support: `--org <slug>`, `--ci`, and `--env-key <KEY>` on
  `set`/`list`/`unset` to manage org-scoped CI secrets via the identity secrets
  API. Secrets are referenced in workflow YAML as `${{ secrets.NAME }}` and
  injected into the declaring job's step environment at run time.
- The CI runner (`vex node run`) injects resolved per-step secrets into the step
  process environment and masks secret values out of captured step logs.
- Local-write mode for read-only CI workspace clones: the initial working-copy
  commit and operation log are written to the local cache instead of the
  backend, so a READ_ONLY runner token can check out without a backend write.

### Changed
- CI workspace clones use the shallow/lazy blob mode by default (metadata-only
  clone manifest; file blobs hydrate on demand), matching `vex clone`'s default
  and dropping CI clone size dramatically.
