CLI ยท commit 7783df8

headerkit

License & copyright header manager for polyglot repos

Download headerkit.zip
Quickstart
unzip headerkit.zip && cd headerkit
uv venv .venv && uv pip install -p .venv/bin/python -e '.[dev]'
.venv/bin/python -m pytest -q

headerkit

headerkit keeps license and copyright headers correct across polyglot repositories. It adds missing headers, repairs outdated copyright years from git history, detects files that declare the wrong license, and fails CI when a header drifts. It understands 43 languages, including shebangs, encoding lines, XML prologs, PHP open tags, doctypes, Go build tags and Python docstrings, and it never touches generated, vendored or binary files.

Features

Install

uv venv .venv && uv pip install -p .venv/bin/python -e '.[dev]'
source .venv/bin/activate    # or call .venv/bin/headerkit directly

Requires Python 3.12+ and git (for year logic). The only dependency is click.

Quickstart

./examples/make_sample_repo.sh /tmp/sample   # a polyglot repo with planted problems and dated history
cd /tmp/sample
headerkit check          # exit 1, lists every problem
headerkit fix            # repair everything that is safe to repair
headerkit check          # exit 1: only src/Main.java (wrong license) remains; see `fix --relicense` below

In your own repository run headerkit init --license MIT --owner "Your Name", edit headerkit.toml, then headerkit check.

Usage

Global options (before the command): -C/--root DIR (project root, default .) and -c/--config FILE. Every command except init accepts optional PATHS to restrict the scan to files or directories. The output below was captured on the sample repo built by examples/make_sample_repo.sh.

check

$ headerkit check
Makefile:1: missing: no license header
    hint: run `headerkit fix` to add a MIT header
Tool.cs:1: missing: no license header
    hint: run `headerkit fix` to add a MIT header
config/pom.xml:1: missing: no license header
    hint: run `headerkit fix` to add a MIT header
public/index.php:1: missing: no license header
    hint: run `headerkit fix` to add a MIT header
scripts/build.rb:1: missing: no license header
    hint: run `headerkit fix` to add a MIT header
scripts/deploy.sh:2: malformed: license notice detected as MIT but there is no SPDX-License-Identifier line
    hint: run `headerkit fix` to rewrite the header in SPDX form
scripts/deploy.sh:5: outdated-year: copyright has 2020, git history says 2023
    hint: run `headerkit fix` to update the years
sql/schema.sql:1: missing: no license header
    hint: run `headerkit fix` to add a MIT header
src/Main.java:1: wrong-license: header declares GPL-3.0-or-later, expected MIT
    hint: run `headerkit fix --relicense` if the file really is relicensed, or add a [[override]] for its path
src/app.py:1: missing: no license header
    hint: run `headerkit fix` to add a MIT header
src/db.go:1: missing: no license header
    hint: run `headerkit fix` to add a MIT header
src/lib.rs:1: malformed: header has no SPDX tag or recognised license notice
    hint: run `headerkit fix` to add `MIT`
src/server.js:1: missing: no license header
    hint: run `headerkit fix` to add a MIT header
src/shared.py:1: missing-owner: no copyright line for Acme Robotics Ltd
    hint: run `headerkit fix` to add it
src/util.py:1: outdated-year: copyright has 2019, git history says 2019-2024
    hint: run `headerkit fix` to update the years
web/index.html:1: missing: no license header
    hint: run `headerkit fix` to add a MIT header
web/style.css:1: missing: no license header
    hint: run `headerkit fix` to add a MIT header
18 files checked, 16 with issues (17 problems)

Formats: --format text|json|github|sarif. GitHub annotations look like:

::error file=Makefile,line=1,title=headerkit HK001::no license header. run `headerkit fix` to add a MIT header
::error file=Tool.cs,line=1,title=headerkit HK001::no license header. run `headerkit fix` to add a MIT header
::error file=config/pom.xml,line=1,title=headerkit HK001::no license header. run `headerkit fix` to add a MIT header

Exit codes: 0 clean, 1 problems found, 2 usage or configuration error.

fix

$ headerkit fix
fixed Makefile (missing)
fixed Tool.cs (missing)
fixed config/pom.xml (missing)
fixed public/index.php (missing)
fixed scripts/build.rb (missing)
fixed scripts/deploy.sh (malformed, outdated-year)
fixed sql/schema.sql (missing)
skipped src/Main.java: header declares GPL-3.0-or-later, expected MIT (use --relicense or an [[override]])
fixed src/app.py (missing)
fixed src/db.go (missing)
fixed src/lib.rs (malformed)
fixed src/server.js (missing)
fixed src/shared.py (missing-owner)
fixed src/util.py (outdated-year)
fixed web/index.html (missing)
fixed web/style.css (missing)
15 files changed, 1 skipped

src/Main.java declares GPL-3.0-or-later in an MIT project, so it is reported and left alone. After reviewing it, --relicense replaces it:

$ headerkit fix --relicense
fixed src/Main.java (wrong-license)
1 files changed, 0 skipped

Changes are minimal. A stale year is edited in place, and a free-form permission notice is replaced by the SPDX form:

diff --git a/scripts/deploy.sh b/scripts/deploy.sh
--- a/scripts/deploy.sh
+++ b/scripts/deploy.sh
@@ -1,8 +1,6 @@
 #!/bin/sh
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software, to deal in the Software without restriction.
-#
-# Copyright 2020 Acme Robotics Ltd
+# Copyright 2020-2023 Acme Robotics Ltd
+# SPDX-License-Identifier: MIT

 set -eu
 echo "deploying"
diff --git a/src/util.py b/src/util.py
--- a/src/util.py
+++ b/src/util.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2019 Acme Robotics Ltd
+# Copyright (c) 2019-2024 Acme Robotics Ltd
 # SPDX-License-Identifier: MIT

 def greet(name: str) -> str:

--dry-run lists what would change without writing. Afterwards:

$ headerkit check
src/Main.java:1: wrong-license: header declares GPL-3.0-or-later, expected MIT
    hint: run `headerkit fix --relicense` if the file really is relicensed, or add a [[override]] for its path
18 files checked, 1 with issues (1 problems)

report

$ headerkit report
Scanned 18 files (skipped: excluded 2, generated 1, unsupported 1)

Licenses by SPDX identifier
  MIT                                   3
  GPL-3.0-or-later                      1
  Apache-2.0 (notice, no SPDX tag)      1
  MIT (notice, no SPDX tag)             1
  (copyright only, no license text)     1
  (no header)                          11

Languages
  python 3, makefile 1, csharp 1, xml 1, c 1, php 1, ruby 1, shell 1, sql 1, java 1, go 1, typescript 1, rust 1, javascript 1, html 1, css 1

Files lacking an SPDX tag (14)
  Makefile
  Tool.cs
  config/pom.xml
  legacy/old.c
  public/index.php
  scripts/build.rb
  scripts/deploy.sh
  sql/schema.sql
  src/app.py
  src/db.go
  src/lib.rs
  src/server.js
  web/index.html
  web/style.css

Conflicts (1)
  copyleft license GPL-3.0-or-later inside a project licensed MIT

report --format json gives the same data as JSON. --fail-on-conflict exits 1 if conflicts exist (copyleft inside a permissive project, GPL-2.0-only mixed with Apache-2.0 or GPL-3.0).

strip

headerkit strip [--dry-run] [PATHS] removes detected license headers and the blank line that followed them.

Configuration

[headerkit]
license = "MIT"
style = "spdx"                 # or "notice"
owner = ["Acme Robotics Ltd"]  # one or several holders
project = "Acme Toolkit"
year_mode = "git"              # or "fixed" with year = "2020-2024"
exclude = ["docs/**"]

[[override]]
glob = "legacy/**"
license = "Apache-2.0"
style = "notice"

All keys, glob rules, templates and output formats are described in docs/configuration.md.

Architecture

Module Responsibility
src/headerkit/languages.py Language registry and detection by name, extension and shebang.
src/headerkit/header.py Preamble handling, locating and parsing the existing header, copyright-line parsing, comment rendering.
src/headerkit/licenses.py Short notice templates, license signatures, SPDX expression helpers.
src/headerkit/config.py TOML config, per-path rule resolution, glob matching.
src/headerkit/years.py Git history year ranges (rename-aware) and the year provider.
src/headerkit/engine.py analyze, fix and strip.
src/headerkit/scan.py File discovery and skip rules.
src/headerkit/report.py License inventory and conflict detection.
src/headerkit/output.py Text, JSON, GitHub and SARIF formatters.
src/headerkit/cli.py Click commands.

Algorithms and worked examples: docs/design.md.

Tests

.venv/bin/pytest -q

132 tests: golden insertion files per language and licence style (tests/golden/), git-history year ranges against temporary repositories (renames, subdirectory roots), idempotency, license detection, config validation and CLI behaviour end to end.

Limitations

License

MIT, see LICENSE.