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.
Options
Section titled "Options"| Option | Type | Required | Default | Description |
|---|---|---|---|---|
lines | integer (>= 1) | 20 | Number of leading lines to consider. | |
pattern | string | yes | Rust 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.
Example
Section titled "Example"A source file missing its copyright header
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✓
fn a() {}// Copyright 2026// SPDX-License-Identifier: Apache-2.0fn b() {}With this .alint.yml:
version: 1rules: - id: copyright-header kind: file_header paths: "src/**/*.rs" pattern: "(?s)Copyright" lines: 3 level: erroralint check reports:
--- 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 failingEvery source file carries the header
Section titled "Every source file carries the header"This repository is compliant:
- src/
- src/a.rs✓
- src/b.rs✓
// Copyright 2026fn a() {}// Copyright 2026// SPDX-License-Identifier: Apache-2.0fn b() {}With this .alint.yml:
version: 1rules: - id: copyright-header kind: file_header paths: "src/**/*.rs" pattern: "(?s)Copyright" lines: 3 level: erroralint check reports:
v All 1 rule(s) passed.