Skip to content

file_header

The first N lines must match a regex (line-oriented). For a byte-level prefix check, prefer file_starts_with.

A leading UTF-8 BOM is not part of the header: the lines are read after it, which is where both fixes insert the header, so a ^-anchored pattern matches a BOM file and the fix converges.

The N lines are matched as one string, newlines included, so ^ matches at the start of the first line and $ only at the end of the block, after the last line's newline. ^// Copyright checks line 1; (?m)^// SPDX-License-Identifier: accepts the line anywhere in the first N. See Regex patterns and anchors.

Fix: file_prepend — inject declared content at the top, at BOF (after any UTF-8 BOM, which it preserves). Blind to a shebang / XML declaration (it would push either off line 1) -- use insert_header when that matters.

Fix: insert_header — the position-aware alternative to file_prepend (same content / content_from): inserts the header AFTER a leading UTF-8 BOM, shebang (#!...), or XML declaration (<?xml ...?>), so it never displaces a line that must stay first (a kernel reads a shebang only on line 1; an XML parser needs the declaration first). For a file with none of those prefixes it inserts at BOF, exactly like file_prepend. Safe by default (the insertion point is the one canonical header spot and the content is inert -- at least as safe as the Safe file_prepend it refines, and safer on a file with a shebang / XML declaration); demoted to a suggestion from an untrusted remote extends: (the header bytes are ruleset-authored). Its idempotency guard anchors on both the insertion point and the file top, so a repeated fix is a guaranteed no-op even when the header content itself begins with a #! / <?xml prefix. Because the header can land below line 1, the rule's pattern must be able to match below the first line: use an unanchored pattern (or (?m)); a ^-anchored pattern that only matches line 1 cannot be satisfied once the header sits under a shebang.

OptionTypeRequiredDefaultDescription
linesinteger (>= 1)20Number of leading lines to consider.
patternstringyesRust regex. The first lines lines of each file in scope must match. They are one string, newlines included, so ^ and $ anchor to the block's start and end unless the pattern turns on (?m).

Plus the common paths, level, id, when, scope_filter, fix, and expect_matches fields. This table is generated from the JSON Schema; option types and defaults are authoritative.

Section titled "A source file missing its copyright header"

The rule fires on this repository:

  • src/
  • src/a.rs

    ✗ error copyright-header

    1:1 first 3 line(s) do not match required header /(?s)Copyright/

  • src/b.rs✓
src/a.rs
fn a() {}
src/b.rs
// Copyright 2026
// SPDX-License-Identifier: Apache-2.0
fn b() {}

With this .alint.yml:

version: 1
rules:
- id: copyright-header
kind: file_header
paths: "src/**/*.rs"
pattern: "(?s)Copyright"
lines: 3
level: error

alint check reports:

Terminal window
--- src/a.rs -------------------------------------------------------------------
x error copyright-header
1:1 first 3 line(s) do not match required header /(?s)Copyright/
Summary (1 violation):
x 1 error
0 passing * 1 failing

Every source file carries the header

Section titled "Every source file carries the header"

This repository is compliant:

  • src/
  • src/a.rs✓
  • src/b.rs✓
src/a.rs
// Copyright 2026
fn a() {}
src/b.rs
// Copyright 2026
// SPDX-License-Identifier: Apache-2.0
fn b() {}

With this .alint.yml:

version: 1
rules:
- id: copyright-header
kind: file_header
paths: "src/**/*.rs"
pattern: "(?s)Copyright"
lines: 3
level: error

alint check reports:

Terminal window
v All 1 rule(s) passed.