> 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/install/lunar-ci-agent/buildkite.md).

# Buildkite

Lunar instruments Buildkite with two pieces:

1. A Buildkite agent **`command` hook** (`command` is Buildkite's agent-hook type) that wraps each command with Lunar tracing, so collectors run and their data is attributed to your components.
2. A Buildkite **Notification Service webhook** to Lunar Hub, so Lunar Hub knows a build ran and CI-dependent policies wait for it instead of finalizing early.

{% hint style="info" %}
Lunar listens to **two** webhooks that drive different things: your **source-control (SCM)** webhook carries source events (push / pull request) and owns component identity, while the **Buildkite** webhook reports that a build ran so CI-dependent policies wait for it. Buildkite is the CI layer; your SCM is the source host — Buildkite tracing works against the source host your components are already registered with.
{% endhint %}

## Setup

### Step 1 — Agent command hook (tracing)

On your Buildkite agent, add a `command` hook (in the agent's `hooks/` directory) that exports the Lunar configuration and runs `lunar ci-tracer run` to trace the build's command:

```bash
# hooks/command
set -e

export LUNAR_CI_TYPE=buildkite
export LUNAR_RUN_CMD="bash -c \"$BUILDKITE_COMMAND\""
export LUNAR_HUB_HOST=hub.example.com
export LUNAR_HUB_TOKEN="$LUNAR_HUB_TOKEN"

lunar ci-tracer run
```

The `lunar` CLI installs the CI tracer on first use and caches it, so no separate agent binary needs to be installed on the runner. Source-control credentials (used for changed-file inference) are fetched from Lunar Hub, so no GitHub token is needed on the runner.

The Hub host and ports resolve in order: explicit `LUNAR_HUB_*` env vars, then the `hub:` block of a `lunar-config.yml` the runner can read, then a default of `443` for both gRPC and HTTP. Set `LUNAR_HUB_GRPC_PORT` / `LUNAR_HUB_HTTP_PORT` only for a Hub on non-default ports that isn't declared in a manifest. See the [Configuration Reference](/install/lunar-ci-agent/agent-config.md) for the full set of `LUNAR_*` variables.

### Step 2 — Notification Service webhook (build status)

Without the webhook, Lunar Hub never learns a Buildkite build happened, so CI-dependent policies would finalize before the build's data lands. In Buildkite, go to **Organization Settings → Notification Services → Add → Webhook** (the service is org-level, not per-pipeline) and configure it so Lunar Hub records each build:

* **URL**: `https://<your-hub-host>/webhooks/buildkite`
* **Token**: set a shared token and configure Lunar Hub with `HUB_BUILDKITE_WEBHOOK_TOKEN` to the same value. Lunar Hub verifies the `X-Buildkite-Token` header on every request; an unset token rejects all requests.
* **Events**: `build.scheduled`, `build.running`, `build.finished`.

{% hint style="warning" %}
The webhook endpoint must be reachable from Buildkite's servers, so it's exposed to the public internet — the same posture as your SCM webhook endpoint. Keep it behind TLS and rely on the shared `X-Buildkite-Token` for authentication; Lunar Hub rejects every request whose token doesn't match.
{% endhint %}

Lunar Hub creates a workflow-run record per build, associates it with the build's commit (and pull request, for PR builds), and re-evaluates CI-dependent policies when a build finishes.

## Component attribution

Lunar reads the standard `BUILDKITE_*` environment to attribute collected data to components. In a monorepo, set one of the following in your pipeline so a build maps to the right subdirectory component (see [Components](/configuration/lunar-config/components.md)):

* `LUNAR_COMPONENT` — name the component(s) explicitly (comma-separated).
* `ciPipelines` on the component — matches the Buildkite **pipeline name**.
* `LUNAR_COMPONENT_INFER=true` — infer from changed paths (PR builds) or the working directory.

## Scope and limitations

* **Command-level** collection is supported (`ci-before/after-command` hooks). Job- and step-level scopes are not yet collected by Lunar.
* **Changed-path** component inference resolves for **pull-request** builds; push builds fall back to working-directory inference (Buildkite provides no prior-commit SHA to diff against).
* **One CI provider per repo** — the first Buildkite build marks the repo as Buildkite-driven, and any other CI provider's doneness probe then skips it. Running two CI providers against the same repo isn't supported.


---

# 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/install/lunar-ci-agent/buildkite.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.
