> ## Documentation Index
> Fetch the complete documentation index at: https://site.aspect.build/llms.txt
> Use this file to discover all available pages before exploring further.

# aspect buildifier

> Migrate the Rosetta buildifier task to aspect buildifier with format.alias() in config.axl, using buildifier_prebuilt to format Bazel Starlark files.

The legacy Rosetta `buildifier` task ran a Bazel target (defaulting to `//:buildifier.check`) that invoked [buildifier](https://github.com/bazelbuild/buildtools) in check mode against the workspace's Starlark files, surfacing lint warnings and formatting diffs as CI annotations.

There are two ways to replace it with Aspect CLI tasks:

1. **config.axl alias (recommended)** — register `aspect buildifier` as a first-class CLI command via a `format.alias()` declaration in `.aspect/config.axl`. No BUILD target needed, no `rules_lint` dependency.
2. **BUILD target approach** — declare a Starlark-only `format_multirun` target and point `aspect format` at it via `--formatter-target`.

## What changed

| Area            | YAML-configured tasks                                                                                                                      | Aspect CLI tasks                                                                                                                                                              |
| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Invocation      | `rosetta run buildifier`                                                                                                                   | `aspect buildifier` (config.axl alias) or `aspect format --formatter-target=//tools/format:format-starlark` (BUILD target approach)                                           |
| Check target    | `target:` (default `//:buildifier.check`)                                                                                                  | `formatter_target` default set in config.axl, or passed via `--formatter-target` on the CLI                                                                                   |
| Fix target      | `fix_target:` (default `//:buildifier`)                                                                                                    | Both approaches run the fix target by default; the legacy "check then suggest fix" annotation is replaced by `aspect format`'s pre/post-snapshot diff flow                    |
| Lint warnings   | Surfaced as a separate annotation pointing at [`buildtools/WARNINGS.md`](https://github.com/bazelbuild/buildtools/blob/master/WARNINGS.md) | Not surfaced separately — buildifier's `-mode=fix` applies what it can fix; warnings appear in `aspect format`'s output and the unified format check-run                      |
| Diff archival   | Reused the legacy `format` task's diff handling when invoked via `bazel run`                                                               | `aspect format --upload-format-diff` archives the patch as `format.patch` via `ArtifactsTrait`. See [aspect format → Diff archival](/docs/cli/migration/format#diff-archival) |
| Soft-fail       | `soft_fail: true` downgraded the failure to a warning                                                                                      | `--soft-fail`. See [aspect format → Soft-fail](/docs/cli/migration/format#soft-fail)                                                                                          |
| Ignore patterns | n/a                                                                                                                                        | `--ignore-pattern` (repeatable). See [aspect format → Ignore patterns](/docs/cli/migration/format#ignore-patterns--workspace-awareness)                                       |

***

## config.axl alias approach (recommended)

This approach registers `aspect buildifier` as a real CLI command by declaring a `format.alias()` in `.aspect/config.axl`. It does **not** require a BUILD target or a `rules_lint` dependency — only `buildifier_prebuilt`.

### Setup

**`MODULE.bazel`:**

```python theme={null}
bazel_dep(name = "buildifier_prebuilt", version = "8.5.1.2")  # or newer
```

**`.aspect/config.axl`** (create if it doesn't exist):

```python theme={null}
load("@aspect//format.axl", "format")

buildifier = format.alias(
    defaults = {
        "formatter_target": "@buildifier_prebuilt//buildifier",
        # buildifier_binary is a symlink to the raw Go binary; it does not
        # switch to $BUILD_WORKING_DIRECTORY on its own, so we run it in
        # the user's cwd to make relative paths resolve.
        "run_in_cwd": True,
        # Fires only when the format task would otherwise pass zero files
        # to the formatter (e.g. `--scope=all`, or a `--scope=changed` run
        # that degraded because no changed files matched). The bare
        # buildifier binary needs `-r .` to walk the tree on its own. Inert
        # whenever a file list is passed, so `--scope=changed` (the default)
        # and per-file invocations are unaffected.
        "formatter_args_for_tree_walk": ["-r", "."],
        "include_patterns": [
            "**/BUILD",
            "**/BUILD.bazel",
            "**/MODULE.bazel",
            "**/*.MODULE.bazel",
            "**/WORKSPACE",
            "**/WORKSPACE.bazel",
            "**/*.axl",
            "**/*.bzl",
        ],
    },
    summary = "Format Starlark files using buildifier.",
)

def config(ctx: ConfigContext):
    ctx.tasks.add(buildifier)
```

`format.alias()` creates an `aspect buildifier` command pre-configured with a `formatter_target` and `include_patterns`. Running `aspect buildifier` is equivalent to running `aspect format` with those defaults baked in — only Starlark files are touched, no other formatters run.

<Note>
  `ctx.tasks.add(buildifier)` registers the alias as a CLI command. Until that line is present, `aspect buildifier` won't exist.
</Note>

<Warning>
  **`--scope=all` covers a narrower file set than `--scope=changed`.** In `--scope=all` the format task hands off discovery to buildifier's `-r .` tree walk, which recognizes only `BUILD`, `BUILD.bazel`, `MODULE.bazel`, `WORKSPACE`, `WORKSPACE.bazel`, `*.bzl`, `*.star`. Files matching the alias's `include_patterns` but not on buildifier's list — notably `*.axl`, `*.MODULE.bazel` — are **silently skipped**. The default `--scope=changed` passes the changed file list to buildifier positionally and is unaffected.

  See [aspect buildifier → Run it locally](/docs/cli/tasks/buildifier) for details.
</Warning>

### CI configuration

Add a dedicated `buildifier` job alongside your other Aspect CLI tasks. If your repo also runs `aspect format` for other languages, run both jobs in parallel — they don't overlap because `include_patterns` in the alias limits buildifier to Starlark files.

<CodeGroup>
  ```yaml GitHub Actions theme={null}
  jobs:
    buildifier:
      runs-on: [self-hosted, aspect-workflows, aspect-default]
      permissions:
        id-token: write
      steps:
        - uses: actions/checkout@v6
        - uses: aspect-build/setup-aspect@2306377a61c45954ab2df7c7311698b109364352 # v2026.26.9
          with:
            aspect-api-token: ${{ secrets.ASPECT_API_TOKEN }}
        - name: Buildifier
          run: aspect buildifier --task:name buildifier
  ```

  ```yaml Buildkite theme={null}
  steps:
    - key: buildifier
      label: ":hammer_and_wrench: Buildifier"
      plugins:
        - aspect-build/setup-aspect#1d5768c5d28b72bf523b4722fc9177d2cc2d85c7: ~ # v2026.26.8
      command: aspect buildifier --task:name buildifier
      agents:
        queue: aspect-default
  ```

  ```yaml GitLab theme={null}
  include:
    - component: $CI_SERVER_FQDN/aspect-build/setup-aspect-gitlab-component/setup@2026.26.8

  buildifier:
    extends: .setup-aspect
    tags: [aspect-workflows, aspect-default]
    rules:
      - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
    script:
      - aspect buildifier --task:name buildifier
  # Set ASPECT_API_TOKEN as a masked CI/CD variable in Settings → CI/CD → Variables.
  ```

  ```yaml CircleCI theme={null}
  version: 2.1

  orbs:
    setup-aspect: aspect-build/setup-aspect@2026.26.10

  jobs:
    buildifier:
      machine: true
      resource_class: circleci-org/aspect-default
      steps:
        - checkout
        - setup-aspect/setup
        - run:
            name: Buildifier
            command: aspect buildifier --task:name buildifier
  # Set ASPECT_API_TOKEN as a project environment variable or context secret.
  ```
</CodeGroup>

***

## BUILD target approach

Use this approach if you prefer to keep buildifier wired through a Bazel target in `tools/format/BUILD.bazel`.

### Wiring buildifier into your formatter target

The default formatter target is `//tools/format:format`. Add `starlark =` to its `format_multirun` invocation, pointing at a buildifier binary from [`buildifier_prebuilt`](https://registry.bazel.build/modules/buildifier_prebuilt):

**`MODULE.bazel`:**

```python theme={null}
bazel_dep(name = "buildifier_prebuilt", version = "8.5.1.2")  # or newer
bazel_dep(name = "aspect_rules_lint", version = "...")  # required for format_multirun
```

**`tools/format/BUILD.bazel`:**

```python theme={null}
load("@aspect_rules_lint//format:defs.bzl", "format_multirun")

format_multirun(
    name = "format",
    starlark = "@buildifier_prebuilt//:buildifier",
    # ...other languages your repo formats:
    # rust = "@rules_rust//tools/upstream_wrapper:rustfmt",
    # go = "@aspect_rules_lint//format:gofumpt",
    # javascript = ":prettier",
)
```

That's the whole switch in the common case — `aspect format` will now run buildifier on Starlark files as part of its normal flow. No new task wiring, no new CI step required.

<Note>
  The legacy task's `target` and `fix_target` (`//:buildifier.check` / `//:buildifier`) are no longer used. `format_multirun` produces both the fix target (`//tools/format:format`) and a check-only sibling (`//tools/format:format.check`) automatically; `aspect format` invokes the fix target and decides pass/fail by diffing the working tree before and after. You can delete the old labels once nothing references them.
</Note>

### Running buildifier as a dedicated task

Some repos want buildifier on its own CI step — a fast Starlark-only check that runs in parallel with (and finishes well before) the bigger language formatters. The legacy `buildifier` task gave that for free.

The new pattern: **declare a second `format_multirun` target that only sets `starlark =`**, then point a dedicated `aspect format` invocation at it via `--formatter-target`. The default formatter target in `tools/format:format` keeps every other language; the Starlark-only target lives alongside it.

**`tools/format/BUILD.bazel`:**

```python theme={null}
load("@aspect_rules_lint//format:defs.bzl", "format_multirun")

format_multirun(
    name = "format",
    starlark = "@buildifier_prebuilt//:buildifier",
    # ...other languages...
)

format_multirun(
    name = "format-starlark",
    starlark = "@buildifier_prebuilt//:buildifier",
)
```

Then in your CI, run two `aspect format` steps in parallel — one for buildifier and one for everything else. Use `--task:name` to give each a distinct status check name, and `--ignore-pattern` to keep them from doing duplicate work:

<CodeGroup>
  ```yaml GitHub Actions theme={null}
  jobs:
    buildifier:
      runs-on: [self-hosted, aspect-workflows, aspect-default]
      permissions:
        id-token: write
      steps:
        - uses: actions/checkout@v6
        - uses: aspect-build/setup-aspect@2306377a61c45954ab2df7c7311698b109364352 # v2026.26.9
          with:
            aspect-api-token: ${{ secrets.ASPECT_API_TOKEN }}
        - name: Buildifier
          run: |
            aspect format \
              --task:name buildifier \
              --formatter-target=//tools/format:format-starlark

    format:
      runs-on: [self-hosted, aspect-workflows, aspect-default]
      permissions:
        id-token: write
      steps:
        - uses: actions/checkout@v6
        - uses: aspect-build/setup-aspect@2306377a61c45954ab2df7c7311698b109364352 # v2026.26.9
          with:
            aspect-api-token: ${{ secrets.ASPECT_API_TOKEN }}
        - name: Format (non-Starlark)
          run: |
            aspect format \
              --task:name format \
              --ignore-pattern='**/*.bzl' \
              --ignore-pattern='**/BUILD' \
              --ignore-pattern='**/BUILD.bazel' \
              --ignore-pattern='**/MODULE.bazel' \
              --ignore-pattern='**/WORKSPACE' \
              --ignore-pattern='**/WORKSPACE.bazel'
  ```

  ```yaml Buildkite theme={null}
  steps:
    - label: ":hammer_and_wrench: Buildifier"
      plugins:
        - aspect-build/setup-aspect#1d5768c5d28b72bf523b4722fc9177d2cc2d85c7: ~ # v2026.26.8
      command: >-
        aspect format
        --task:name buildifier
        --formatter-target=//tools/format:format-starlark
      agents:
        queue: aspect-default

    - label: ":hammer_and_wrench: Format"
      plugins:
        - aspect-build/setup-aspect#1d5768c5d28b72bf523b4722fc9177d2cc2d85c7: ~ # v2026.26.8
      command: >-
        aspect format
        --task:name format
        --ignore-pattern='**/*.bzl'
        --ignore-pattern='**/BUILD'
        --ignore-pattern='**/BUILD.bazel'
        --ignore-pattern='**/MODULE.bazel'
        --ignore-pattern='**/WORKSPACE'
        --ignore-pattern='**/WORKSPACE.bazel'
      agents:
        queue: aspect-default
  ```

  ```yaml GitLab theme={null}
  include:
    - component: $CI_SERVER_FQDN/aspect-build/setup-aspect-gitlab-component/setup@2026.26.8

  buildifier:
    extends: .setup-aspect
    tags: [aspect-workflows, aspect-default]
    rules:
      - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
    script:
      - aspect format --task:name buildifier --formatter-target=//tools/format:format-starlark

  format:
    extends: .setup-aspect
    tags: [aspect-workflows, aspect-default]
    rules:
      - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
    script: |
      aspect format \
        --task:name format \
        --ignore-pattern='**/*.bzl' \
        --ignore-pattern='**/BUILD' \
        --ignore-pattern='**/BUILD.bazel' \
        --ignore-pattern='**/MODULE.bazel' \
        --ignore-pattern='**/WORKSPACE' \
        --ignore-pattern='**/WORKSPACE.bazel'
  # Set ASPECT_API_TOKEN as a masked CI/CD variable in Settings → CI/CD → Variables.
  ```

  ```yaml CircleCI theme={null}
  version: 2.1

  orbs:
    setup-aspect: aspect-build/setup-aspect@2026.26.10

  jobs:
    buildifier:
      machine: true
      resource_class: circleci-org/aspect-default
      steps:
        - checkout
        - setup-aspect/setup
        - run:
            name: Buildifier
            command: aspect format --task:name buildifier --formatter-target=//tools/format:format-starlark

    format:
      machine: true
      resource_class: circleci-org/aspect-default
      steps:
        - checkout
        - setup-aspect/setup
        - run:
            name: Format
            command: |
              aspect format \
                --task:name format \
                --ignore-pattern='**/*.bzl' \
                --ignore-pattern='**/BUILD' \
                --ignore-pattern='**/BUILD.bazel' \
                --ignore-pattern='**/MODULE.bazel' \
                --ignore-pattern='**/WORKSPACE' \
                --ignore-pattern='**/WORKSPACE.bazel'

  workflows:
    ci:
      jobs:
        - buildifier
        - format
  # Set ASPECT_API_TOKEN as a project environment variable or context secret.
  ```
</CodeGroup>

The same split generalizes — declare one `format_multirun` per group of formatters you want as a separate CI step (e.g. one for Starlark, one for JavaScript/TypeScript/CSS via Prettier, one for everything else), and use `--ignore-pattern` on the catch-all step to avoid re-formatting files the dedicated step already handled.

<Note>
  Pinning `--formatter-target` for a dedicated buildifier step at the **CLI flag** level — rather than in `.aspect/config.axl` — is intentional. `config.axl` is global to all `aspect format` invocations, so setting `formatter_target` there would also redirect your default `aspect format` (the one developers run locally). Per-CI-step overrides belong on the CLI. (This constraint does not apply to the config.axl alias approach, which registers a separate `buildifier` command rather than overriding `format`.)
</Note>

***

## Lint warnings: use `aspect lint`

The legacy task surfaced buildifier's lint warnings (the `--lint=warn` output that lists rule violations like `module-docstring`, `name-conventions`, etc.) as a dedicated annotation pointing at [`buildtools/WARNINGS.md`](https://github.com/bazelbuild/buildtools/blob/master/WARNINGS.md).

In the new world, that lives in `aspect lint`, not `aspect format`. `format_multirun` (and the config.axl alias) runs buildifier in fix mode and auto-applies what it can; warnings buildifier won't auto-fix don't surface as a status check from `aspect format`. To gate on those warnings, wire buildifier in as a [rules\_lint](https://github.com/aspect-build/rules_lint) lint aspect and run it from `aspect lint`.

**`tools/lint/linters.bzl`:**

```python theme={null}
load("@aspect_rules_lint//lint:buildifier.bzl", "lint_buildifier_aspect")

buildifier = lint_buildifier_aspect(
    binary = Label("@buildifier_prebuilt//:buildifier"),
    # warnings = "all",  # default; or pass a comma-separated allowlist
)
```

By default the aspect visits `bzl_library` targets. To lint `BUILD.bazel`, `MODULE.bazel`, or other Starlark files, add `tags = ["starlark"]` (or `tags = ["lint-with-buildifier"]`) to a target listing them in `srcs`:

```python theme={null}
filegroup(
    name = "starlark_files",
    srcs = ["BUILD.bazel", "MODULE.bazel"],
    tags = ["starlark"],
)
```

Then add `//tools/lint:linters.bzl%buildifier` to your `aspect lint` invocation — either as `--aspect` on the CLI or in `.aspect/config.axl`. See [the `aspect lint` migration guide](/docs/cli/migration/lint) for the wiring details. Output is SARIF, deduplicated and (on GitHub Actions, by default) posted as PR comments by the `GithubLintComments` feature.

**Recommended split:**

| Concern                                | Task                                                             | Mode                                |
| -------------------------------------- | ---------------------------------------------------------------- | ----------------------------------- |
| Auto-applied formatting + simple fixes | `aspect buildifier` or `aspect format` (Starlark via buildifier) | `--lint=fix` (in-place edits)       |
| Warnings that need human attention     | `aspect lint --aspect=…%buildifier`                              | `--lint=warn` (SARIF + PR comments) |

This is the same split rules\_lint uses for every other Starlark-aware tool — formatting in `format_multirun`, diagnostics in the lint aspect — so the buildifier wiring matches the rest of your linters.
