Skip to content
Latchkey home
Documentation menu

Latchkey CLI changelog

What each release of the Latchkey CLI added, changed and fixed, newest first, from 0.3.0 on.

In short

  1. Every Latchkey CLI release from 0.3.0 on, newest first, with what it added, changed and fixed.
  2. latchkey version prints the version you have, and npm install -g @latchkeydev/cli upgrades to the newest.

Each entry lists what a release of the Latchkey CLI (@latchkeydev/cli and the standalone latchkey binaries) changed for you and your coding agents, dated the day it was published, in UTC. Run one-off jobs from the CLI describes the commands as they work today.

0.17.0#

Released 2026-11-13.

Added#

  • latchkey workflows rerun <run-id> --repository <owner/name> runs the jobs of a Latchkey CI run that did not pass again, with every job that needs one of them, as a new attempt of the same run at the same commit, and prints the attempt and the run's page. Every other job that passed is not run or billed again, and the command does not wait for the attempt. A job bound to an environment that needs an approval waits for one, unless it is held in a trial run or a pipeline on trial, or its environment does not accept the run, and the command names those environments on stderr, as far as Latchkey can still read them from an earlier attempt. With --output json it prints one object with run_id, attempt, allocated, run_url and waits_for_approval, and code RERUN_NEEDS_APPROVAL with its sentence in message when that list names any. A refusal prints its sentence on stderr and exits 1. It needs a key with runs:control.
  • latchkey workflows cancel <run-id> --repository <owner/name> cancels every job of a Latchkey CI run's current attempt that has not finished, through the one cancel path latchkey cancel uses, and the jobs it had not created yet are never created. It prints the attempt and the run's page, and with --output json one object with run_id, attempt, cancel_requested, not_created and run_url. A refusal prints its sentence on stderr and exits 1. It needs a key with runs:control.
  • latchkey run and latchkey preflight now say on stderr when the batch a job is started under, by --batch or LATCHKEY_BATCH, has no budget, with the command that sets one (latchkey budget set <batch> <dollars>), and the job still starts. Nothing is said when Latchkey could not read the budget or the batch's spend, since the batch may still have a budget, and latchkey preflight --batch-budget never says it. With --output json, latchkey run prints no line: the created event's new batch_budget_status reads set, none or unread, and is null when the job has no batch.

Changed#

  • The bundled skill now covers latchkey workflows rerun and latchkey workflows cancel, and the MCP tools rerun_run and cancel_run, where it said no latchkey command takes a run id and no key can cancel a whole run.
  • The bundled skill now says a heals entry below stage 3 with category flaky_test is self-heal's flaky-test re-run, which ran the failed step again unchanged, so its outcome fixed means the re-run passed, not that anything was fixed.

Fixed#

  • latchkey workflows --help and the bundled skill now say a job that latchkey workflows run starts and that is bound to an environment that needs an approval waits for one, unless it is held in a trial run or a pipeline on trial, or its environment does not accept the run, where they made a trial run the only exception.

0.16.0#

Released 2026-11-11.

Added#

  • latchkey preflight --workflow <file> --repository <owner/name> runs the jobs of one workflow file, as Latchkey compiles it, on your working tree as it is now, before you commit or push it. The repository is packed whole, from its top level, by the rules of latchkey run, and the change is measured against the merge base of HEAD and the default branch origin/HEAD names, as this clone last fetched it. Before any runner starts, each job is judged: it runs as written, it runs its dry run, it is skipped by its own condition or for a job it needs, it fails before it starts, or it is not run, with a reason, such as a job that reads a secret, since a preflight is handed none. A preflight paints no check, opens no pull request, starts no self-heal and saves no cache entry. It exits 0 only when no job failed, none was left not run, and a job ran, and 195 only when it left a job not run, or ran no job, and every job it ran passed or was skipped by its own condition or for a job it needs; latchkey preflight --help lists the rest. With --output json it prints one object once its run has ended. When git cannot say what the change is, it is refused with CLI_GIT_UNREADABLE and nothing is sent. It needs a key with jobs:run, and a repository connected to Latchkey CI.

Changed#

  • latchkey wait can now print that self-heal judged step 3's failure flaky and re-ran the step unchanged, then it passed, or that it re-ran step 3 unchanged in case its failure was flaky, then the re-run did not make the step pass, where it said self-heal fixed the step or could not fix it, and the Self-heal row of latchkey status can say the same.
  • The bundled skill now covers latchkey preflight, including the run it answers, which latchkey workflows list never lists, and says a job's own check, such as Latchkey / ci.yml / test, can show as queued or in progress while its job waits or runs, where it said Latchkey writes no pending check.
  • A key that starts with lk_dev_ is from Latchkey's dev environment and is no longer sent to the prod API (api.latchkey.dev or latchkey.dev): the command stops before anything is sent and exits 1 with CLI_API_KEY_WRONG_ENVIRONMENT. A key that starts with neither lk_live_ nor lk_dev_ still only warns.

Fixed#

  • When latchkey run reads the files git tracks, it now sets git's filesystem monitor empty, not false: a git before 2.36 runs false as a program found on PATH, where a relative entry can find one in the repository being packed. A directory named git on PATH no longer stops that read, and on Windows every variable whose name starts with GIT_ or LATCHKEY_, in any case, is kept out of git's environment.
  • The README and the bundled skill now give the compressed size ceiling as 200 MiB, the bound the CLI has always held, where they said 200 MB.
  • The bundled skill now says a job held in its workflow file's concurrency: group (JOB_HELD_IN_GROUP) can end without starting if a newer run joins the group first, where it said it ends without starting: the newer run cancelled before Latchkey ends the held job leaves it waiting.
  • An API key from --token, LATCHKEY_TOKEN or the saved config is now trimmed of the spaces, tabs and line breaks around it before it is checked and sent, and latchkey login --token saves it trimmed, or stops with Empty API key. and exits 2 when the key is only whitespace, where it exited 1. A key ending in a line break, such as a LATCHKEY_TOKEN set with a trailing newline, no longer stops the command with invalid authorization header, and an lk_live_ key with whitespace before it no longer draws the warning that it does not start with lk_live_.

0.15.0#

Released 2026-11-09.

Added#

  • latchkey workflows list --repository <owner/name>, with --commit <sha> or --pr <number>, lists the Latchkey CI runs of a commit, named by its full id, or of a pull request over the last 90 days, newest first. With --output json it prints one object with repository, runs and truncated, each run the object the MCP tool get_run_status answers. With more than 50 runs it exits 1 with LIST_TRUNCATED, unless --allow-truncated takes the newest 50. It needs a key with jobs:read.
  • latchkey wait --commit <sha> and latchkey wait --pr <number>, with --repository <owner/name>, wait on Latchkey CI runs instead of jobs: the runs at a commit, named by its full id, or a pull request's runs at its newest commit. When the runs end it prints a table of them and exits 0 if each one succeeded or was skipped, 1 otherwise, and with --output json it prints one run_ended event per run, then a summary event. It exits 194 with RUN_NOT_EXPECTED when the repository is not connected to Latchkey CI, or when every run it follows ended with no job because no workflow file matched, and 197 with RUN_WAIT_LIMIT_REACHED when its last look before it gave up met Latchkey's limit on the waits it holds for a workspace at once.

Changed#

  • Before a command sends its key, it prints Latchkey API: <host> on stderr, naming the host the key goes to, once a process and in json mode too, so a key pointed at the wrong environment shows before anything answers. On latchkey run and latchkey watch, --quiet leaves it off.
  • The bundled skill now covers finding the runs of a commit or a pull request with latchkey workflows list and latchkey wait --commit or --pr, and with the MCP tools list_runs and wait_run.
  • latchkey watch --help now gives the exception the bundled skill already gave: on GitHub Actions, the one re-run of a failing test that Latchkey allows while the workflow has an open flaky-test finding is not escalated when Latchkey could read the failing tests from the test runner's report and the re-run failed the same way, so the run surfaces once, under its one id.

0.14.0#

Released 2026-11-06.

Changed#

  • latchkey migrate plan now prints a pipeline already on trial as On trial, where it printed Stays, and the help no longer says latchkey migrate apply needs the repository in advisory mode: it needs the repository connected to Latchkey CI. Latchkey opens such an apply for any version of the CLI. The bundled skill's refusals of migrate apply now name a plan that moves a pipeline already on trial, in place of a repository not in advisory mode.
  • latchkey watch --help and the bundled skill now say latchkey watch polls the failures self-heal recorded but did not fix and hands off the first new failure of each job (of each run on Latchkey on GH), and that a failure whose step self-heal refused to read carries no root cause or failing file. The prompt it hands your agent now says self-heal recorded the failure but did not fix it, and that get_failure_bundle returns what Latchkey kept of it. Only the words changed: watch picks the failures it hands off by the same rule as 0.13.0, from the list Latchkey returns to any version of the CLI.

0.13.0#

Released 2026-11-04.

Added#

  • latchkey list --state active lists only the jobs still on their way: every queued, provisioning or running job, up to 100, newest first, however many newer jobs have finished. --batch narrows it, and --before and --limit are refused, since it is read whole rather than a page at a time. With --output json it prints jobs and truncated, true when more than 100 were on their way, and in text a line on stderr says so. A Latchkey API that cannot read the jobs still on their way would answer with jobs in every state, so it is refused with CLI_LIST_FILTER_UNSUPPORTED and nothing is listed. --state all, the default, lists every job as before.

Changed#

  • The bundled skill now covers reading what is still on its way with latchkey list --state active, and its CLI_LIST_FILTER_UNSUPPORTED row names --state active.

0.12.0#

Released 2026-11-04.

Changed#

  • When latchkey run refuses an empty directory, it now says what to do: run from your project's directory, or pass --no-context for a command that needs no files. The bundled skill's CLI_CONTEXT_EMPTY row names the flag too.
  • With --output json, latchkey list, latchkey batch show and latchkey status always hold run_id, the Latchkey CI run a job belongs to, and served_by, how it got its runner (warm, parked or cold_start), each null when Latchkey sends none. A CLI from 0.4.0 on already prints both when Latchkey sends them, and the text output has not changed.
  • The bundled skill now says to split a suite through the package's own test script (npm test -- --shard=2/4), so every shard runs the package's pretest steps as CI does. It also covers moving to Latchkey CI: a run reads only the secrets set in Latchkey, never a GitHub secret of the same name, so an owner or admin carries them over before the switch pull request merges, and once it merges, a moved pipeline is read from the commit's Latchkey checks, get_run_status or latchkey list, because GitHub Actions no longer runs it.
  • The bundled skill now names merge_group among the events a workflow file runs on: each group a merge queue builds, matched on the branch the group targets.

0.11.0#

Released 2026-11-03.

Changed#

  • latchkey migrate plan now says a moving job bound to an environment waits for an owner or admin to approve it once its pipeline runs live, where it used to say in a live run. In a repository on Latchkey CI, a pipeline runs on trial, even inside a live run, while the GitHub Actions file it replaces is still at the commit.
  • The bundled skill now says that failure_explanation names the first step that failed, and that step's exit code when it has one, on a workflow-file job that failed with failure_reason null, and that output the CLI cannot write never changes its exit code. It also covers pipelines on trial inside a live run: what advisory: does in their jobs, the failure_explanation starting Held on trial: of a held job, list_trial_verdicts naming in workflow_path the pipeline on trial each entry compares, and get_run_status saying in trial why some of a run's pipelines ran on trial.

Fixed#

  • A full disk under a redirected stdout or stderr no longer makes the CLI exit 1, which reads as a failed job: when either stream cannot be written, the CLI exits with the code it would have given. It drops the rest of its stdout and, unless the reader went away (| head), says so once on stderr, and it drops what it cannot write to stderr without a word. A log it could not write is still on the job, and latchkey logs <id> reads it again.

0.10.0#

Released 2026-11-02.

Added#

  • latchkey workflows run <workflow> --repository <owner/name> starts a run of a Latchkey CI workflow file that declares on: workflow_dispatch, at the repository's default branch or at the branch or tag --ref names, with the file's inputs given as --input <name=value>. It prints a link to the run's page without waiting for the run, and running it again starts a second run, billed as its own. The key needs the workflows:run scope. An input is recorded on the run and shown on its page, and a job's log does not hide it, so never put a token or password in one.
  • latchkey budget set <batch> <dollars> --max-concurrent <n> limits how many of a batch's jobs run at once, a whole number from 1 to 1000. The rest wait in the queue and start as the batch has room. An API key can set a batch's first limit or lower it, never raise or remove it, and latchkey budget show prints the limit.

Changed#

  • latchkey status shows a Self-heal row for each self-heal attempt on the job that fixed a failure or could not, and latchkey run and latchkey wait print each as a line after the job's outcome. When self-heal's agent reported a fix but the job ended without passing, the line says the fix was reported, not made. With --output json, run's complete event and wait's ended and summary events carry the job's heals list as status prints it.
  • The bundled skill now covers starting a workflow file with latchkey workflows run or the run_workflow MCP tool, pacing a burst of jobs with its batch's limit, why a batch job can wait behind Latchkey CI jobs near the workspace's limit, reading heal records and trial verdicts over MCP (list_heals, get_heal and list_trial_verdicts), splitting a test suite across matrix legs, and what self-heal reads from an uploaded working tree.
  • The npm package's homepage is now the Latchkey CLI documentation page, and its README links this changelog.

0.9.0#

Released 2026-10-28.

Added#

  • latchkey oidc request-token --audience <audience> gets a short-lived identity token for your cloud from inside a job of a Latchkey CI run. It prints the token, or with --out <file> writes it to a file only its owner can read. Like latchkey cache, it talks to the job's runner and needs no API key.
  • latchkey validate <file> checks a workflow file the way Latchkey compiles it for a run, without starting anything. A refused file prints its first refusal with its line; a file that compiles prints its jobs and the most one run of the file can cost at list rates. It exits 0 when the file compiles and 1 when it is refused.

Changed#

  • The standalone binaries now embed Node 24, so the macOS binaries need macOS 13.5 or newer. On older macOS, install with npm.
  • latchkey environments list adds an Approval column saying whether an environment's jobs wait for an owner or admin to approve them.
  • latchkey migrate plan says when a moving job bound to an environment will wait for an approval in a live run, and, for a pipeline that stays on GitHub Actions but runs after one that moves, whether it stops running or runs less often once the switch pull request is merged.
  • A batch named . or .. alone is refused by every command that takes a batch name (exit 2).

Fixed#

  • An --env variable named __proto__ is now sent with the job instead of being dropped.

0.8.0#

Released 2026-10-27.

Changed#

  • A batch name can no longer hold / or %. latchkey run, latchkey list and latchkey wait now refuse one, including one set in LATCHKEY_BATCH, before reaching Latchkey (exit 2), as latchkey budget and latchkey batch show already did.

0.7.0#

Released 2026-10-26.

Changed#

  • latchkey migrate plan marks a step whose dry-run command the plan refused: its "Needs a person" line gives the reason, and the item stays open until you answer with a command the workflow file can run.
  • The answers file for latchkey migrate plan --answers <file> can give a dry_run answer with a dry_run_command, which the plan writes as a trial-run step in place of the answered one.
  • The bundled skill now covers trial runs (advisory: on jobs and steps), concurrency: groups in workflow files, and the latchkey/artifact-upload and latchkey/artifact-download steps.

0.6.0#

Released 2026-10-24.

Added#

  • latchkey wait waits until the jobs you name, or every job of a batch with --batch <name>, have ended, printing each outcome as it ends and then a table of state, exit code, run time, cost and batch. It exits 0 only when every job exited 0, and Ctrl-C stops the wait, never a job.
  • latchkey batch show <name> shows one batch: its budget, what its jobs have cost at list rates, its jobs by state and why its queued jobs wait. latchkey budget show <batch> prints the budget and spend alone.
  • latchkey environments list --repository <owner/name> lists the branches each environment of a repository accepts.
  • latchkey list takes --batch <name> for one batch's jobs and --before <value> to page further back, shows a COST column, and latchkey status shows a finished job's cost.
  • When a newer CLI is out, a command printing text says so on stderr, at most once a day and never in CI. Set LATCHKEY_NO_UPDATE_NOTICE to turn it off.

Changed#

  • Inside a git work tree, latchkey run packs every file git tracks, even one a .gitignore pattern matches, as a fresh clone would have it. The credential deny list, --exclude and .latchkeyignore still apply, and --no-git-index packs by the .gitignore files alone.
  • Every refusal carries a code. With --output json, a refused command prints one object with its code, and the bundled skill lists every code.
  • latchkey run refuses a leading bash -c or sh -c (exit 2), since that shell would run only the first word of its script. Pass the script as one quoted argument instead.

0.5.0#

Released 2026-10-24.

Added#

  • latchkey artifact upload and latchkey artifact download pass files between the jobs of one Latchkey CI run. A failed upload or download exits 1, so the step fails, and an upload leaves out dot-files such as .env unless you pass --include-hidden-files.
  • latchkey migrate plan <owner/name> reads a repository's GitHub Actions workflow files and prints its plan for moving to Latchkey CI, with each item that needs your answer. latchkey migrate apply opens the one pull request that adds the Latchkey CI workflow files, and latchkey migrate status shows where it stands.
  • latchkey steps lists the Latchkey steps a workflow file can name with uses: latchkey/<name>@<version>, with their inputs and defaults.

Changed#

  • A job whose run an owner or admin rejected for its environment exits 130 from latchkey run and latchkey logs --follow, as a stop rather than a failure to fix.

0.4.1#

Released 2026-10-19.

Fixed#

  • The help text, README and bundled skill now match how 0.4.0 behaves: the exit codes list skipped (exit 1), logs stay readable for 7 days from when the job started, and latchkey cache works only inside a Latchkey CI job or a latchkey run job.
  • latchkey budget set help says an API key can set a batch's first budget up to the workspace's spend limit, and that an owner or admin raises a budget on the Billing page.

0.4.0#

Released 2026-10-19.

Added#

  • latchkey run --context <dir> packs another directory instead of the current one, and --exclude <pattern> holds paths back without editing a file. No --exclude pattern can ship a file the credential deny list blocks.
  • latchkey run --budget <dollars> stops a job once it has cost that much (exit 3), and --batch <name> or LATCHKEY_BATCH puts jobs in a batch.
  • latchkey budget set <batch> <dollars> caps a batch. A latchkey run refused at its batch's budget exits 193 and creates no job.
  • latchkey cache restore and latchkey cache save restore and save a cache entry from inside a job. No cache condition fails the job.
  • latchkey secrets set <name> sets a secret a workflow step can read, for the workspace or one repository. The value comes from a pipe or a hidden prompt, never the command line.

Changed#

  • latchkey run prints a link to each job's page in the dashboard, and latchkey watch links a failure to its Latchkey run page.
  • latchkey status shows more when Latchkey sends it: running and queued jobs against the workspace's limit, the jobs ahead of a queued job and why it waits, the cost so far, its batch, key and budget, when it last wrote output, and what ended it. latchkey list adds BATCH and KEY columns.
  • --timeout accepts up to 3 hours, and a job's logs stay readable for 7 days from when it started.
  • latchkey run --detach exits with the job's mapped code when the submit already ended the job, a skipped job exits 1, and every --output json event carries at.

Fixed#

  • Text from Latchkey that reaches your terminal is stripped of control, text-direction and invisible format characters, and a failure reason a job reported itself is shown as the job's own words.

0.3.0#

Released 2026-08-15.

Added#

  • latchkey list lists your workspace's recent jobs, newest first, including the ones still running, so you can recover a job id that scrolled away.

Changed#

  • latchkey watch also reports latchkey run jobs that self-heal recorded but did not fix, and every failure it prints carries its root cause and failing file when one was recorded.

Fixed#

  • When the log tail of latchkey run or latchkey logs --follow gives up after repeated network errors, the CLI checks the job once more and exits with its own code if it finished, where it used to exit 1.
  • The log tail catches up faster on a backlog of colored or non-ASCII output.