> For the complete documentation index, see [llms.txt](https://docs-lunar.earthly.dev/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs-lunar.earthly.dev/release-notes/cli/2026.md).

# 2026

## v4.0.0 (2026-09-15) <a href="#cli-v4-0-0" id="cli-v4-0-0"></a>

### Features

#### Signing in from the CLI: `lunar login`, `lunar logout`, and `lunar whoami` <a href="#cli-personal-sign-in-commands" id="cli-personal-sign-in-commands"></a>

`lunar login` signs in to the Hub with a GitHub or GitLab account. The CLI asks the Hub which forge OAuth apps it accepts, runs that forge's sign-in flow — a device code to confirm in the browser, or an authorization page with PKCE on a `127.0.0.1` callback, which can also be completed by pasting the redirect URL back on a headless machine — and stores the resulting Hub session and forge token in the OS keyring, or in a `0600` `~/.lunar/credentials.json` where there is no keyring. `lunar login --list` prints the forge, host, client id, flow, and scopes of every provider the Hub accepts, and `--forge` and `--host` pick one when the Hub accepts more than one.

Every later command uses the stored session automatically and renews both it and the forge token behind it five minutes before they expire; when renewal is no longer possible the command says so and tells you to run `lunar login` again. `LUNAR_HUB_TOKEN` still wins wherever it is set, so the service token and CI credentials keep working unchanged, and having no credential at all is not an error for commands that need none. `lunar whoami` reports who the Hub takes the current credential for — a signed-in person, a CI job, or the service token — with the forge, host, source, and session expiry. `lunar logout` forgets the stored login for the Hub and revokes the forge token where it can: at the instance on GitLab, through the Hub on GitHub when the operator configured the app's client secret, and otherwise by printing the page on which to revoke it by hand.

See [Signing in to Lunar as yourself](/release-notes/product/2026.md#product-personal-sign-in).

* When `LUNAR_HUB_TOKEN` holds the OIDC token a GitHub Actions or GitLab CI job was issued — recognized by its asymmetric signature, which neither the Hub service token nor a Hub session has — the CLI now trades it once for a Hub session that lasts the job, uses that session for every Hub call, and passes it to the processes it starts, so the agent and scripts started by `lunar ci-tracer run` hold the session rather than a token the forge expires within minutes. An exchange the Hub refuses fails the command with an error naming the cause: a token whose audience or issuer the Hub does not accept, a Hub with no session key configured, or too many failed attempts from the caller. Against a Hub too old to support the exchange the CLI only warns and continues with the token as it was. Because the Hub vends a forge credential only to the service token, a job traced under a CI OIDC token must set `LUNAR_GITHUB_TOKEN` itself — `${{ github.token }}` on GitHub Actions — or the tracer runs with step attribution and `LUNAR_COMPONENT_INFER` disabled. See [CI job identity for GitHub Actions and GitLab CI](/release-notes/product/2026.md#product-ci-job-identity).
* `lunar login` against a GitLab host runs the device authorization grant first, so signing in works from a machine with no browser of its own: the CLI prints a URL and a user code to complete anywhere. GitLab never advertises the endpoint in its OIDC discovery document, so Lunar uses `/oauth/authorize_device` when discovery omits it, and falls back to the authorization-code grant with PKCE on a loopback redirect only when the instance predates GitLab 17.9 or the OAuth application has its device authorization grant turned off — new GitLab applications have it off by default. A client id the instance refuses outright is reported instead of being retried through the fallback. The GitLab application still needs the `http://127.0.0.1/callback` redirect URI so the fallback works, and `lunar login --list` now reports the GitLab flow as `device when the app allows it, else authorization code (PKCE)`. See [Signing in to Lunar as yourself](/release-notes/product/2026.md#product-personal-sign-in).
* `lunar hub permissions` prints the permission table the connected Hub applies: one row per permission with its scope, its `READ` or `WRITE` access, the GitHub and GitLab role it requires, and what a CI job may do with it (`no`, `own repo`, `own commit`, `cataloged repo`, `config repo, protected branch`, or `yes`), with `*` marking a role that the `authorization:` block of the installed Lunar configuration changed from its default. `--verbose` lists the Hub calls each permission governs, with the request fields the authorization checks read and that call's own CI value; `--all` adds the fixed `internal`, `authenticated`, and `public` permissions; `--output-json` prints the same table as JSON, naming the configuration version the overrides came from; and `--defaults` prints the table compiled into the CLI, which needs neither a Hub connection nor a credential. Reading the table from a Hub requires Lunar images 4.0.0 or later, which is where the Hub began serving it.
* `lunar hub pull --dry-run` now validates the configuration file the in-repo path on the URI names — `lunar hub pull github://acme-corp/lunar-repo/lunar-config.dev.yml@main --dry-run` loads that file plus its own `lunar-config.dev.d/` fragments — and a local argument may name the configuration file itself as well as a directory, so `lunar hub pull ./lunar-config.dev.yml --dry-run` checks a non-default entry point before it is merged; a path that names nothing, climbs out with `..`, is absolute, or resolves through a symlink outside the repository fails the validation instead of falling back to the root `lunar-config.yml`. See [Choosing which configuration file a Hub loads](/release-notes/product/2026.md#product-configuration-entry-point).
* `lunar setup bootstrap` can now deposit a GitLab token that is not bound to a group: pass `--gitlab-token` without `--gitlab-group` and the token is deposited host-wide, for every group on the instance, instead of one top-level group. The new `--gitlab-host` names that instance and takes a bare hostname — lowercased, with no scheme, port, or path — defaulting to `gitlab.com`; it is rejected together with `--gitlab-group`, because a group deposit is keyed by the group alone. Group deposits are otherwise unchanged: the same flags deposit the token under the same per-group slot, and only the error text for a half-supplied pair changes, to `--gitlab-group requires --gitlab-token`. See [Instance-wide GitLab tokens and token pools](/release-notes/product/2026.md#product-gitlab-host-wide-token-pools).
* `lunar sql credentials ls` lists the personal SQL API credentials the Hub has issued — login, forge, host, Postgres role, status (active, expired, revoked, or dropped), expiry, and last rotation — as a table, or as JSON with `--output-json`, and `lunar sql credentials revoke <login>` ends one person's SQL access by disabling their role and terminating its open sessions. Both commands talk to the Hub and are refused for a CI job credential. See [Per-person SQL API credentials](/release-notes/product/2026.md#product-per-person-sql-api-credentials).
* The CI Tracer again accepts a GitHub token of its own, in `LUNAR_GITHUB_TOKEN`, for the two things it cannot read from the job's environment: step attribution, which reads the workflow definition and the actions it uses, and the changed files behind `LUNAR_COMPONENT_INFER`. Both only ever ask about the repository being built, so in GitHub Actions set the variable to the job's own `github.token` and give the workflow `contents: read` and `pull-requests: read`; on Buildkite, which issues no per-job token, provision one. A tracer running on the Hub service token that sets nothing keeps using the GitHub credential the Hub vends, so existing pipelines are unchanged. When no credential is available at all, step attribution and changed-path component inference are skipped with a log line naming the variable, while tracing, collection, and collector execution continue unaffected.

### Improvements

* `lunar policy bypass-release`, `lunar policy bypass-pr`, and `lunar policy bypass-rm` no longer fail locally with "could not determine who is creating this bypass" when no actor can be inferred: when the CLI is authenticated as a logged-in person, it leaves `--actor` unset and the Hub records the login it authenticated, refusing an `--actor` that names anyone else; with the Hub's service token the CLI still fills the actor in from `GITLAB_USER_LOGIN`, `GITHUB_ACTOR`, or `USER`, and the Hub rejects the request when none of them is set, asking for `--actor`. The `--actor` help text on both commands now states which of the two applies. See [Verified bypass actors](/release-notes/product/2026.md#product-2026-09-15).
* `lunar policy bypass-ls` now names why a bypass is no longer in effect instead of calling every spent row `expired`: `status` reads `spent — PR #N was merged or closed` for a PR-gate bypass whose pull or merge request has finished, and `superseded — a later push moved PR #N past sha <sha>` for one pinned to a commit the head has moved past, keeping `revoked <when> by <who>` and `expired` for the cases they describe. A commit-bound bypass has no expiry clock, so it is no longer labelled as if it had one, and the `--active` help now states the four bounds the filter applies.
* `lunar hub pull --dry-run` no longer refuses to start without forge access: with no `LUNAR_GITHUB_TOKEN`, `LUNAR_GITLAB_TOKEN`, or configured Hub, plugins are cloned anonymously and each unpinned component's default branch is read straight from the remote with plain git, so validating a configuration that references only public repositories needs no setup at all. `lunar collector dev`, `lunar policy dev`, and `lunar cataloger dev` resolve default branches the same way, including for GitLab-hosted components when only a GitHub token is set. A private repository is still refused by the remote — the lookup fails with a credentials error instead of hanging on git's username prompt — and wildcard components, which need the forge API, still need a credential.
* `lunar hub pull --dry-run`, `lunar collector dev`, `lunar policy dev`, and `lunar cataloger dev` can now use the token the forge's own CLI is signed in with — `gh` for the host in `LUNAR_GITHUB_HOST` (`github.com` by default), `glab` for gitlab.com — so someone already authenticated to `gh` or `glab` can work with private and wildcard components without arranging a second credential. It is the last source consulted: `LUNAR_GITHUB_TOKEN` and `LUNAR_GITLAB_TOKEN`, then the token of a `lunar login` session, then the Hub-vended credential for a service-token caller, all take precedence, and a service-token caller never shells out to `gh` or `glab`. A forge CLI that is absent, signed out, failing, or slow to answer counts as no token rather than an error, and one invocation is cut off after 5 seconds. A token read this way serves only the CLI's own clones and forge API calls — it cannot sign anyone in to the Hub, which accepts only forge tokens issued to its own OAuth app. When no source yields a token, the error now reads `` run `lunar login`, set LUNAR_GITHUB_TOKEN, or authenticate `gh` `` (and the GitLab equivalent) instead of naming only the first two.
* An operation that genuinely needs a forge credential — expanding a wildcard component, resolving `lunar collector dev --pr`, or reaching a private repository — now fails with an error naming the credential for that component's own forge: sign in with `lunar login`, or set `LUNAR_GITHUB_TOKEN` for a GitHub host and `LUNAR_GITLAB_TOKEN` for a GitLab one. Previously a GitLab component was told to configure a GitHub connection, or reported only that no client was configured for its host.
* On a machine with a stored login, `lunar collector dev`, `lunar policy dev`, `lunar cataloger dev`, and `lunar hub pull --dry-run` now clone repositories, resolve default branches, expand wildcard component names, and read a `--pr` with the signed-in person's own forge token, instead of asking the Hub to vend a credential. `LUNAR_GITHUB_TOKEN` and `LUNAR_GITLAB_TOKEN` still take precedence where they are set, a forge the person is not logged in to falls through to the existing chain, and a machine with no stored login behaves exactly as before.
* `lunar sql connection-string` now returns a credential of your own when you are signed in with `lunar login`, and the shared SQL API connection string when the Hub service token is used; a CI job credential is refused. The connection string is still the only thing written to stdout, so piping it into `psql` or into a configuration file works as before, while a personal credential adds a note on stderr naming the Postgres role, when it expires, that re-running the command rotates it, and that a connection pooler in front of the SQL API only authenticates the role if it resolves users dynamically — PgBouncer `auth_query` rather than a static user list. See [Per-person SQL API credentials](/release-notes/product/2026.md#product-per-person-sql-api-credentials).
* On a GitHub Actions `pull_request` event, the CI Tracer now reads the pull request's head commit and base branch from the event payload the runner writes for the job, instead of asking the GitHub API for the workflow run, and falls back to that API call only when the payload is missing or carries neither.
* The CI Tracer now installs its configuration from Lunar Hub instead of cloning the configuration repository and every `uses:` plugin repository, so a traced job no longer needs access to those repositories. The Hub serves only what the job needs — the components of the repository being traced, the collectors whose CI hooks apply to it, and each of those collectors' code — so a CI workload no longer receives policies, catalogers, or other repositories' components. Where the tracer cannot read the repository from its own environment, which is the case when it wraps a self-hosted runner and starts before any job exists, it installs the whole configuration exactly as before. Against a Hub that does not yet serve the configuration, the tracer falls back to cloning.

### Bug fixes

* A Hub host given as a URL now works instead of failing with `too many colons in address`: the `lunar` CLI and the CI Tracer strip an `http://` or `https://` prefix, a trailing slash, and surrounding whitespace from the resolved host, and bracket an unbracketed IPv6 literal, applying the same treatment to `--hub-host`, `LUNAR_HUB_HOST`, and the `hub.host` field of the Lunar configuration. A value that cannot be interpreted — one carrying a path, query, fragment, credentials, an unrecognized scheme, or a port, since the gRPC and HTTP ports have their own settings — now fails the command with an error naming the problem, the setting the value came from, and the bare host name to use instead, except under `--no-hub` or `LUNAR_NO_HUB`, where the host is ignored. Any host that already worked is left byte-identical.
* Running `lunar hub pull --dry-run` twice against the same configuration commit — for example validating a repository's development and production configuration files in one CI job — no longer fails the second run with `config validation failed: ... configuration already exists`. The throwaway draft the first run leaves behind, which is keyed by the configuration repository's commit alone, is now replaced rather than treated as a conflict.

## v3.18.0 (2026-08-26) <a href="#cli-v3-18-0" id="cli-v3-18-0"></a>

### Features

* `lunar policy ok-release` now prints the Hub-rendered verdict block verbatim when the Lunar configuration sets `customization.ok_release_template`, in place of the built-in summary line and the failing and bypassed check lists; when no template is configured, or the Hub cannot render one, the command prints its built-in output as before. Only the printed block changes — the verdict, the exit code, the polling progress messages, and `lunar policy ok-pr` are unaffected. See [Customizing the `ok-release` verdict output](/release-notes/product/2026.md#product-2026-08-25).

### Improvements

* `lunar policy ok-release` and `lunar policy ok-pr` no longer print the command's usage and flag list when they fail after their arguments have been parsed — an invalid component ID, an expired timeout, or an authentication failure — so the error and its remedy stay at the end of a CI log instead of being scrolled off by help text.
* `lunar policy ok-release` and `lunar policy ok-pr` now fail on the first response saying Lunar Hub has no component by that name, instead of polling every interval until `--timeout` — ten minutes by default — for the same verdict. Nothing in the run being gated creates a component, so waiting could not change the answer; the error names the invalid component ID and points at the Lunar catalog the name has to come from. An unknown component stays fatal under every `--fail-open` mode, and a component that exists but has not finished evaluating still polls to `--timeout` as before.

### Bug fixes

* The CI Tracer now selects a component whose declared repository identity differs in letter case from the identity the CI environment reports: host, owner, and repository name are compared case-insensitively when matching components to the repository the job runs in, when resolving the names listed in `LUNAR_COMPONENT`, and when falling back to a single component named after the repository. Previously a component authored as `github.com/Acme/Api` in a checkout the Git platform reports as `acme/api` matched nothing, so the job ran collectors for no component and collected nothing, without an error. A monorepo component's subdirectory path is still matched case-sensitively, because it is a file path, and branch matching is unchanged. See [Case-insensitive repository identity matching](/release-notes/product/2026.md#product-2026-08-19).

## v2.12.0 (2026-08-11) <a href="#cli-v2-12-0" id="cli-v2-12-0"></a>

### Improvements

* `lunar policy ok-release` and `lunar policy ok-pr` now print a loud warning when running in CI without a detectable workflow run ID — for example when `GITHUB_RUN_ID` is absent and `--workflow-id` was not passed — explaining how to pass `--workflow-id`; previously the gate silently blocked until its timeout.

## v2.11.0 (2026-08-07) <a href="#cli-v2-11-0" id="cli-v2-11-0"></a>

### Features

* `lunar setup bootstrap` now accepts `--gitlab-group` together with `--gitlab-token` to deposit a GitLab group access token — run once per top-level group — and `--github-owner` to deposit per-organization GitHub App keys for multi-organization installs. At least one Git platform credential is now required: `--github-app-pem`, the GitLab pair, or both. Existing single-organization GitHub invocations are unchanged.

## v2.10.0 (2026-08-04) <a href="#cli-v2-10-0" id="cli-v2-10-0"></a>

### Features

* `lunar policy ok-release` and `lunar policy ok-pr` accept a new `--fail-open` flag to exit successfully instead of blocking when no verdict can be obtained: a bare `--fail-open` covers an unreachable Hub, and `--fail-open=timeout` or `--fail-open=both` extend it to gate timeouts (the value must be attached with `=`). Authentication failures and an unknown component name stay fatal under every mode — a typo in a component name cannot silently pass — and a gate whose checks genuinely fail still blocks.
* `lunar policy bypass-release` and `lunar policy bypass-pr` record a time-bound override of a component's release or PR/MR merge gate, `lunar policy bypass-ls` lists a component's bypasses — including expired and revoked ones — and `lunar policy bypass-rm` revokes one early. `--reason` is recorded with the bypass, `--for` sets its duration, and `--sha`, `--pr`, and `--policy` narrow its scope; in CI, when neither `--sha` nor `--pr` is given, the bypass is scoped to the commit taken from `GITHUB_SHA` or `CI_COMMIT_SHA`. See [Break-glass gate bypasses](/release-notes/product/2026.md#product-break-glass-gate-bypasses).
* The new `lunar queue` commands inspect and clear the Hub's queue of script runs: `lunar queue status` shows how many runs are queued by script type, and `lunar queue clear <collectors|policies|catalogers|all>` deletes queued runs — useful for recovering from a misconfiguration that filled the queue with work that can only fail and retry. Without `--yes`, `queue clear` prints what it would remove without deleting anything, and runs that are already executing are never deleted.

### Improvements

* The CI Tracer now fetches the component catalog from the Hub only when a CI job names a component, caches it per repository, and asks only for changes since its last fetch, removing redundant Hub round-trips on every run. The new `LUNAR_CATALOG_FULL_REFRESH_PERIOD` variable (default `15m`) bounds how long a missed change can leave the cached catalog stale; `0` disables the periodic full refresh.

## v2.8.0 (2026-07-29) <a href="#cli-v2-8-0" id="cli-v2-8-0"></a>

### Bug fixes

* Fetching scripts from a public repository under an owner with no configured SCM credentials no longer emits a warning per reference: the designed anonymous-access fallback is logged at debug level, so a `lunar collector dev` run over a configuration referencing dozens of public plugin scripts no longer prints a wall of warnings that reads like a failure. A private repository under an unconfigured owner still fails loudly, with the error naming the missing credentials. See [Public repositories without a GitHub App](/release-notes/product/2026.md#product-2026-05-27).
* `lunar collector dev` and `lunar cataloger dev` now run code collectors from the component's subdirectory for monorepo components — the same working directory the Hub uses — instead of the repository root, so a collector no longer behaves differently in local development than in production. With `--component` the subdirectory must exist at the checked-out ref, and with `--component-dir` pointing inside a monorepo the component name (and `LUNAR_COMPONENT_ID`) now includes the subdirectory exactly as the Hub names it.
* An interrupted `lunar collector dev`, `lunar policy dev`, or `lunar cataloger dev` run no longer poisons every later run with `failed to install draft config: ... configuration already exists`. The throwaway draft configuration such a run leaves behind is now replaced on the next run instead of blocking it, so no manual deletion under `~/.lunar/drafts/` (or `lunar clear-cache`) is needed to recover.
* `lunar policy ok-release` and `lunar policy ok-pr` no longer fail on a transient connection error partway through their poll. When the Hub becomes briefly unreachable after the poll has already reached it — for example during a load-balancer blip under load — the command now prints `temporarily unable to reach remote server; retrying...` and keeps polling until `--timeout` instead of aborting the gate. A server that is unreachable from the very first call, or any non-transient error, still fails immediately.

## v2.7.0 (2026-07-21) <a href="#cli-v2-7-0" id="cli-v2-7-0"></a>

### Improvements

* `lunar collector dev`, `lunar policy dev`, `lunar cataloger dev`, and `lunar hub pull --dry-run` now work with GitLab-hosted components and plugins: set the new `LUNAR_GITLAB_TOKEN` environment variable (or let a configured Hub supply the credentials), and the CLI routes clone authentication, default-branch resolution, and wildcard component expansion to the matching SCM for each host, including GitLab's nested namespaces. With `--component-dir`, the component name is now derived from the checkout's actual remote host instead of the configured GitHub host.

### Bug fixes

* Fetching the component catalog from the Hub no longer fails with a gRPC `ResourceExhausted` error on very large catalogs: the maximum gRPC message size between the CLI, the CI Tracer, and the Hub is raised from 4 MB to 16 MiB, so the CI Tracer's periodic catalog refresh keeps working on installations with tens of thousands of components.

## v2.6.2 (2026-07-17) <a href="#cli-v2-6-2" id="cli-v2-6-2"></a>

### Features

* The new `lunar setup bootstrap` command performs the secret-deposit step of a Lunar Dedicated install: it generates the workload encryption key and the webhook secret, and deposits them together with the GitHub App private key (`--github-app-pem`) into the dedicated account's secret drop in AWS Secrets Manager, encrypted with the install's CMK. It requires `--tenant` and `--region` from the coordinates packet, and can deposit cross-account by assuming the write-only deposit role with `--deposit-role-arn` and `--external-id` (which must be given together), so the secrets never pass through Earthly's systems. Re-runs are safe: the generated encryption key and webhook secret are write-once and never overwritten, while the GitHub App key is updated on every run, so rotating it is just a re-run. The generated webhook secret is printed exactly once — on the run that deposits it — to be set in the GitHub App's "Webhook secret" field.

### Bug fixes

* `lunar` and the CI Tracer now place their state, cache, and config directories under a writable temp-based path when running as a non-root user whose home directory is unset or resolves to the filesystem root, instead of failing with `mkdir /.lunar: permission denied`; a usable home directory still resolves to `~/.lunar/` as before.

## v2.6.1 (2026-07-16) <a href="#cli-v2-6-1" id="cli-v2-6-1"></a>

### Breaking changes

* The `lunar grafana deploy-dashboards` command is removed. Lunar's Grafana dashboards, datasources, and panel plugins are now installed by the `ghcr.io/earthly/lunar-dashboards` deploy image — the Helm chart runs it automatically on install and upgrade, and the same image can be run directly with Docker or Podman against a Grafana you operate yourself — so no local CLI step or container runtime is involved in dashboard deployment anymore.

### Improvements

* `lunar sql connection-string` accepts a new `--grafana` flag that prints the connection string for the read-only Grafana datasource role instead of the SQL API one.

### Bug fixes

* The CI Tracer now detects scheduled runs — `GITHUB_EVENT_NAME=schedule` on GitHub Actions, `BUILDKITE_SOURCE=schedule` on Buildkite — and records their collections as periodic re-collections rather than CI collections pinned to the checked-out commit, so a scheduled pipeline no longer replaces the component's latest data with its own partial results. See [Scheduled CI runs no longer overwrite component data](/release-notes/product/2026.md#product-2026-07-16).

## v2.6.0 (2026-07-09) <a href="#cli-v2-6-0" id="cli-v2-6-0"></a>

### Features

* `lunar-config.yml` can now be validated before merge: `lunar hub pull --dry-run <repo>` runs the Hub's own load-and-validate pipeline — including `uses:` plugin resolution and component repository checks — without applying anything, exiting non-zero on validation errors; it needs GitHub access but no Hub connection, so it can run as a CI check on pull requests. A companion `lunar config schema` command prints a JSON Schema for editor autocomplete.

### Bug fixes

* Fixed a CI/CD Tracer deadlock while configuring signal-heavy traced processes that could hang a build indefinitely and hold its runner until the CI timeout. The deadlock surfaced most often when the Hub was unreachable.

## v2.5.0 (2026-07-08) <a href="#cli-v2-5-0" id="cli-v2-5-0"></a>

### Features

* New `lunar grafana deploy-dashboards` command installs Lunar's Grafana dashboards, datasources, and panel plugins into a Grafana instance you operate (self-hosted or Grafana Cloud). The Grafana endpoint and credentials are supplied by the Hub, the dashboard version is matched to the running Hub automatically, and a Docker or Podman runtime is required locally.

### Improvements

* The Hub gRPC and HTTP ports now default to 443 when not configured, and `lunar ci-tracer run` forwards the resolved Hub connection settings to the tracer process. A CI runner configured with only `LUNAR_HUB_HOST` previously failed the Hub-configured check and could silently run without instrumentation.
* `lunar collector dev` and `lunar policy dev` now work when the Lunar config is split across `lunar-config.d/` files, and fully local runs (`--component-dir` together with `--script`) no longer require GitHub or Hub credentials. Credential errors in the remaining modes now explain what to configure.

### Bug fixes

* The CI/CD Tracer now classifies Node.js-based GitHub Actions launched through a shebang entrypoint as steps; such actions were previously attributed as commands of the preceding step.
* Fixed `sudo` failing inside traced builds with `The "no new privileges" flag is set`: the CI/CD Tracer no longer sets `no_new_privs` on traced processes that hold `CAP_SYS_ADMIN`. Running `sudo` or other setuid binaries under tracing requires a self-hosted runner running as root with `CAP_SYS_ADMIN`; on runners without the capability the previous behavior is unchanged.

## v2.4.0 (2026-06-23) <a href="#cli-v2-4-0" id="cli-v2-4-0"></a>

### Security

* Updated high-severity Go dependencies (`golang.org/x/crypto`, `golang.org/x/net`, `golang.org/x/sys`, `github.com/jackc/pgx/v5`) to patched versions in the `lunar` CLI and CI/CD Tracer build.

## v2.3.2 (2026-06-19) <a href="#cli-v2-3-2" id="cli-v2-3-2"></a>

### Bug fixes

* Fixed collectors failing with `Hub connection details not provided` when a collector image carrying CLI v2.2.0 or later runs against a Hub older than 2.3.1: `lunar collect` inside a collector now falls back to the legacy stdout output those Hubs expect. Out-of-band `lunar collect --component` invocations still submit to the Hub directly.

## v2.3.1 (2026-06-19) <a href="#cli-v2-3-1" id="cli-v2-3-1"></a>

### Migrations and upgrade notes

* The CI/CD Tracer's GitHub Action now lives at `earthly/lunar-ci-tracer` (renamed from `earthly/lunar-ci-action`) — update workflow references to the new name. The separate `lunar-ci-agent-dist` binary distribution is retired: install the tracer through the `lunar` CLI with `lunar ci-tracer run` or `lunar ci-tracer install`.

### Bug fixes

* Pull-request checks now post on GitHub Enterprise Server: the CI/CD Tracer records the repository's GitHub host with each CI collection, so the Hub posts the resulting checks against the right GitHub instance. See [GitHub Enterprise Server and multi-organization support](/release-notes/product/2026.md#product-github-enterprise-server-support).

## v2.3.0 (2026-06-19) <a href="#cli-v2-3-0" id="cli-v2-3-0"></a>

### Features

* New `lunar ci-tracer install` command downloads and caches the CI/CD Tracer through the Hub without running it, for warming the cache at build time — for example when baking a runner image.
* The CI/CD Tracer now supports Buildkite. Start it from a Buildkite agent `command` hook to trace builds and run CI collectors; runs are collected even though Buildkite exposes no job or step boundaries, and setting `LUNAR_COMPONENT_INFER=true` enables changed-path attribution for monorepo builds. See [Buildkite support](/release-notes/product/2026.md#product-buildkite-support).
* The CI/CD Tracer resolves the GitHub host from the run environment (`GITHUB_SERVER_URL` on GitHub Actions, or the git remote on Buildkite), so runs on GitHub Enterprise Server repositories are attributed to the right component with no extra configuration; `LUNAR_GITHUB_HOST` remains available as an override. See [GitHub Enterprise Server and multi-organization support](/release-notes/product/2026.md#product-github-enterprise-server-support).

## v2.2.0 (2026-06-17) <a href="#cli-v2-2-0" id="cli-v2-2-0"></a>

### Features

#### Unified CLI and CI/CD Tracer releases <a href="#cli-unified-cli-tracer-release" id="cli-unified-cli-tracer-release"></a>

The `lunar` CLI and the CI/CD Tracer (previously called the CI agent) now release together under a single version. There is no separate `lunar-ci-agent` binary to install: the CLI fetches, verifies, and caches the tracer through your Hub on first use, and later runs reuse the cache.

Start the tracer with the new `lunar ci-tracer run` command. It resolves the tracer version pinned into the CLI at build time (override with `--version`), downloads the binary through the Hub on a cache miss, verifies its digest, and caches it under `~/.lunar/bin` (override with `LUNAR_BIN_DIR`). All other arguments are forwarded to the tracer unchanged.

Version numbering continues above both earlier release lines — the CLI was at v2.0.0 and the CI agent at v2.1.3 — which is why there is no v2.1.0.

* New `--component <github.com/owner/repo>` and `--sha <commit>` flags let `lunar collect` run outside a traced CI job — for example in a CD pipeline — to attach additional component JSON to an existing component at a specific commit. The flags fall back to `LUNAR_COMPONENT_ID` and `GITHUB_SHA` when unset, and an optional `--pr` associates the write with a pull request. See [Out-of-band collection](/release-notes/product/2026.md#product-out-of-band-collection).

### Improvements

* When `LUNAR_COMPONENT_INFER=true` is set, changed-path component inference on GitHub Actions now covers push events as well as pull requests, so a monorepo build on the default branch is attributed to the components whose files actually changed. See [Monorepo support: path-scoped components](/release-notes/product/2026.md#product-monorepo-path-scoped-components).
* `lunar` commands and the CI/CD Tracer automatically retry Hub requests interrupted by a brief Hub outage, such as a rolling restart during an upgrade, instead of failing the operation.
* The CI/CD Tracer resolves component default branches only for the repository it is tracing, instead of for every component at startup. This reduces GitHub API usage on busy runners and fixes Lunar config sync failures caused by exhausting the GitHub App rate limit.

### Bug fixes

* The CI/CD Tracer now bounds the Hub and GitHub API calls made from its tracing loop with timeouts, and job cancellation interrupts them. A stalled call could previously freeze the traced build or leave an orphaned tracer occupying a self-hosted runner after the job was cancelled.
* Fixed a CI/CD Tracer deadlock triggered when a traced process exited while the tracer was still configuring it. The wedged tracer could leave a self-hosted runner reporting online while no longer running jobs.
* The CI/CD Tracer no longer logs a warning for every fault signal seen in traced processes — managed runtimes such as the JVM, Go, and Node.js raise and handle these signals as part of normal operation. A crash is now reported only when a fault signal actually terminates the traced process.

## v2.0.0 (2026-05-17) <a href="#cli-v2-0-0" id="cli-v2-0-0"></a>

### Features

* The new `lunar licence` command group extracts Hub bootstrap artifacts from a licence JWT locally, before any Hub is running in the cluster: `lunar licence verify` validates the licence against the trust list embedded in the binary and prints a summary; `lunar licence pull-secret` generates a Kubernetes `imagePullSecret` manifest for pulling Lunar images from `ghcr.io` (with `--namespace`/`-n`, `--name`, and `--out`/`-o`); and `lunar licence registry-token` prints the GHCR pull token for use with `docker login`. All subcommands accept `--licence-file`, or the `LUNAR_LICENCE_FILE` environment variable.

### Improvements

* The CI/CD Tracer continues running when Hub-backed startup setup fails — fetching runtime logging configuration or completing the initial sync — instead of aborting the CI job; set `LUNAR_STRICT_MODE=true` to keep the previous fail-closed startup behavior.

### Bug fixes

* `lunar collector dev --component` checks out the branch configured for the component in the Hub catalog instead of always using the repository's default branch, and validates that the component exists in the catalog.
* The CI/CD Tracer retries its update checks while Lunar Hub has no current configuration published, instead of proceeding and later surfacing confusing "manifest not found" errors during observation.

## v1.1.2 (2026-05-07) <a href="#cli-v1-1-2" id="cli-v1-1-2"></a>

### Breaking changes

* The CI/CD Tracer no longer accepts a GitHub personal access token for runtime authentication: the `LUNAR_GITHUB_TOKEN` runtime path is removed, and the tracer always uses GitHub App installation tokens vended by Lunar Hub, which was already the default path. Remove `LUNAR_GITHUB_TOKEN` from tracer environments; a Hub connection is now required for GitHub API access.

### Features

* The new `lunar diagnose bundle` command captures a self-contained troubleshooting snapshot of a deployed Lunar stack — descriptions and logs for every Lunar pod plus database statistics — packaged as a single `tar.gz` for sharing with support.

### Improvements

* CLI commands that take a component name — `lunar collector dev`, `lunar policy dev`, `lunar component get-json`, `lunar policy ok-release`, and `lunar policy ok-pr` — fall back to the `LUNAR_COMPONENT_ID` environment variable when no flag or argument is given.
* `lunar hub pull` no longer runs global catalogers automatically on every configuration sync; pass the new `--rerun-catalogers` / `-t` flag to opt in, mirroring the existing `--rerun-code-collectors` / `-l` flag. Per-component catalogers are unaffected and keep firing on their own hooks.
* The new `LUNAR_INSTALL_FILE_MAX_DISK_SIZE` setting (for example `200m` or `5gb`) caps the disk space used by locally cached Lunar configuration versions, pruning the oldest unused versions first; the default `0` leaves size-based pruning disabled.
* The CI/CD Tracer now handles attaching to a CI job that is already running — for example when launched as a step inside a GitHub Actions job — initializing from the current step instead of dropping all events, and it reports readiness only after its initial configuration sync with Lunar Hub succeeds.

### Bug fixes

* The CI/CD Tracer starts and idles when Lunar Hub has no configuration installed yet, instead of exiting with a startup sync failure and leaving the CI runner untraced.
* The CI/CD Tracer correctly traces GitHub code scanning runs that use the `dynamic` event type, including step resolution for CodeQL default-setup workflows whose definitions are not committed to the repository.
* The CI/CD Tracer no longer fails to initialize on GitHub-hosted runners: step scripts under the hosted runners' `work/_temp/` path are now recognized, where previously only the self-hosted `_work/_temp/` layout was detected.
* CI/CD Tracer startup update checks are now properly cancelled when their timeout fires (configurable via `LUNAR_UPDATE_CHECK_TIMEOUT`, default 5m), and attaching to an already-running process no longer logs misleading error and warning messages for expected mid-job attach conditions.

## v1.1.1 (2026-03-26) <a href="#cli-v1-1-1" id="cli-v1-1-1"></a>

### Improvements

* `lunar policy ok-release` and `lunar policy ok-pr` print which policy checks are blocking and their status, instead of only reporting that the component is unable to release or merge.
* `lunar policy ok-release` and `lunar policy ok-pr` poll until policy results are complete instead of returning a one-shot answer that could report failure before workflows and collectors had finished; polling is configurable with `--poll-interval` (default 10s) and `--timeout` (default 10m), and the commands print what they are still waiting on.
* A new `--ready-file` option makes the CI/CD Tracer create a file once tracing is active when attaching to a running process with `--pid`, so wrapper scripts can wait for tracing to start instead of polling `/proc`.
* `lunar` and the CI/CD Tracer now default their state, cache, and config directories to user-level paths under `~/.lunar/` when running as a non-root user, instead of system paths such as `/var/lib/lunar`; explicit overrides like `LUNAR_STATE_DIR` still take precedence.

## v1.1.0 (2026-03-19) <a href="#cli-v1-1-0" id="cli-v1-1-0"></a>

### Improvements

* `lunar collect` has a new `--array-append` flag that wraps the collected value in a single-element array; arrays at the same path are concatenated during the Component JSON merge, so repeated collector invocations can accumulate list values.
* `lunar collector dev` and `lunar policy dev` can now run directly inside a plugin directory (one containing `lunar-collector.yml` or `lunar-policy.yml`) without requiring a repository with a full `lunar-config.yml` setup.
* Collectors running on CI command hooks (`ci-before-command`, `ci-after-command`) now inherit the full environment of the traced CI process instead of a minimal sandbox, so variables such as `PATH` and `JAVA_HOME` set during CI steps are visible to collector scripts.

### Bug fixes

* The CI/CD Tracer terminates and reaps any remaining traced child processes when the root traced process exits, instead of leaving them ptrace-stopped.
* The CI/CD Tracer resolves steps from reusable workflow references, fixing "job not found in workflow definition" step-resolution failures in GitHub Actions jobs that call another workflow via `uses:`.
* The CI/CD Tracer detects shebang scripts during process tracing, so a tool like `npm` is reported as the command binary instead of its interpreter (`node`) in `binary.name` hook matching and `LUNAR_CI_COMMAND_BIN`.
* The CI/CD Tracer no longer fails to parse GitHub Actions workflow definitions that set a step's `env` to a runtime expression such as `${{ fromJSON(inputs.envs) }}`.

## v1.0.11 (2026-02-22) <a href="#cli-v1-0-11" id="cli-v1-0-11"></a>

### Security

* Git access tokens no longer appear in debug logs: git commands authenticate through the process environment instead of embedding the token in clone and remote URLs.

### Features

* The new `--component-dir` flag points `lunar collector dev` at a local directory as the target repository, instead of cloning the component's repo.
* The new `--config` option on `lunar collector dev` and `lunar policy dev` loads the Lunar config from a remote Git repository, accepting both `github.com/org/repo` and `github://org/repo@branch` forms.
* Collector command hooks support advanced matching of traced commands: exact or pattern-based binary matching (`name_pattern`, `dir_pattern`), positional and flag-based argument matchers (including both `--flag=value` and `--flag value` forms), and environment variable matchers.
* The new `--no-hub` option makes the Hub connection optional, so `lunar collector dev` and `lunar policy dev` can run without a configured Hub.
* Plugin scripts can be addressed with dot notation in dev commands — `myplugin.mycollector` selects one collector or policy, and passing just the plugin name runs all of the plugin's collectors or policies in a single invocation.
* The new `lunar secret` commands manage the secrets that collectors, policies, and catalogers use, storing values on the Hub at runtime instead of requiring them in the Hub's environment configuration.
* The new `lunar version` command prints the CLI version and the source commit it was built from.

### Improvements

* `lunar collector dev` resolves the component name and exposes it to the collector script's environment.
* Plugins referenced from directories outside the config repository — including symlinked paths — now install correctly in dev mode.
* Git clones are cached across plugin installs for faster repeated installs, draft (local dev) installs are no longer cached, and stale cached clones are purged periodically.
* `lunar hub pull` reports the full output of failed install commands, instead of a truncated error.
* Dependency installation is skipped for scripts that specify a container image, since the image already provides their dependencies.

### Bug fixes

* Fixed a permission-denied error when plugin installation copied directories with restrictive (read-only) permissions; failed partial copies are also cleaned up instead of blocking the next attempt.
* The `.git` directory is no longer copied during plugin installation, avoiding file-permission errors it used to cause.
* Referencing a non-existent local or remote plugin path in `uses` now produces a clear validation error instead of failing obscurely.

## v1.0.9 (2026-01-15) <a href="#cli-v1-0-9" id="cli-v1-0-9"></a>

### Improvements

* Release binaries are about 13% smaller: debug symbols are now stripped at build time.

## v1.0.8 (2026-01-15) <a href="#cli-v1-0-8" id="cli-v1-0-8"></a>

### Breaking changes

* The CI/CD Tracer binary (`lunar-ci-agent-linux-amd64`) is no longer attached to `lunar-dist` releases; it is published through its own release channel from this release onward. Update any automation that downloads the tracer binary from `lunar-dist`.

## v1.0.7 (2026-01-14) <a href="#cli-v1-0-7" id="cli-v1-0-7"></a>

### Features

* Releases now include a Linux arm64 build of the `lunar` CLI (`lunar-linux-arm64`), alongside the existing Linux amd64 and macOS (Apple silicon) binaries.

## v1.0.6 (2026-01-13) <a href="#cli-v1-0-6" id="cli-v1-0-6"></a>

### Breaking changes

* Collector, policy, and plugin names may no longer contain dots; configurations using dotted names are rejected when the Lunar config is loaded. The dot is reserved as the plugin/script separator.
* The deprecated `lunar-ci-agent install <config-URI>` command is removed; the CI/CD Tracer performs an initial configuration update check at startup instead, so a separate install step is no longer needed.

### Features

* `lunar collector dev` and `lunar policy dev` fetch the secrets a script needs from the Hub; a new `--secrets` flag supplies overrides or extra values.
* Collectors can now run at CI step boundaries on GitHub Actions using the new `ci-before-step` and `ci-after-step` hook types.

### Improvements

* `lunar collector dev` sets additional common environment variables for the collector script, bringing the local execution environment closer to what collectors receive in CI runs.
* `lunar collector dev` and `lunar policy dev` show a spinner with progress information about what is happening in the background.
* Collector and policy name resolution is more consistent — plugin names take part in resolution with fixed precedence — and name conflicts are detected with clearer error messages.
* The CI/CD Tracer now starts and runs without a locally installed Lunar configuration, picking it up automatically once the periodic update fetches it.
* CI step detection on GitHub Actions now accounts for composite actions, pre/post hooks, and conditional steps.

### Bug fixes

* The CI/CD Tracer no longer duplicates collector runs when several traced commands complete in a row.
* Collections from GitHub Actions matrix builds are now attributed to the correct matrix job instance instead of being conflated under the job's logical name.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs-lunar.earthly.dev/release-notes/cli/2026.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
