Automatically adds or updates SPDX license and copyright headers in source files.
  • Python 99.8%
  • Makefile 0.2%
Find a file
2025-10-28 12:05:22 +04:00
.github chore(deps): update codecov/codecov-action action to v5 (#7) 2025-10-26 22:36:42 +04:00
python_license fix: keep space in template 2025-10-28 11:32:54 +04:00
tests fix: keep space in template 2025-10-28 11:32:54 +04:00
.gitignore ci: update ci 2025-10-26 19:18:20 +04:00
.licenseignore refactor: refactor code to be smaller 2025-10-26 18:00:15 +04:00
.pre-commit-config.yaml docs: update docs version 2025-10-28 11:57:25 +04:00
.pre-commit-hooks.yaml chore: add precommit hooks 2025-10-26 20:01:10 +04:00
.python-version feat: v0 2025-10-26 17:26:03 +04:00
LICENSE feat: v0 2025-10-26 17:26:03 +04:00
Makefile ci: update ci 2025-10-26 19:18:20 +04:00
NOTICE docs: project name in NOTICE file 2025-10-26 22:33:59 +04:00
pyproject.toml chore: bump version 2025-10-28 11:44:22 +04:00
README.md docs: update license command syntax in README 2025-10-28 12:05:22 +04:00
renovate.json chore: add renovate 2025-10-26 19:20:00 +04:00
uv.lock chore: bump version 2025-10-28 11:44:22 +04:00

Python License

PyPI version Python versions License Tests

One command to add SPDX license headers to all your source files. Works best with pre-commit hooks.

What It Does

Automatically adds SPDX-compliant license headers to your source files.

For Python files:

# SPDX-License-Identifier: Apache-2.0
# Copyright (C) 2025  Your Name

def your_code():
    pass

For JavaScript/TypeScript/Go/Rust:

// SPDX-License-Identifier: MIT
// Copyright (C) 2025  Your Company

function yourCode() {}

For CSS:

/*
 * SPDX-License-Identifier: Apache-2.0
 * Copyright (C) 2025  Your Name
*/

body { margin: 0; }

For HTML/Vue:

<!--
SPDX-License-Identifier: Apache-2.0
Copyright (C) 2025  Your Name
-->

<!DOCTYPE html>

Key Features

  • Supports 50+ file types including Python, JavaScript, TypeScript, Go, Rust, Java, C/C++, Swift, Kotlin, Ruby, Shell, SQL, Vue, and more
  • Custom notice templates for extended license information (e.g., AGPL, GPL notices)
  • Automatically updates copyright year ranges (e.g., 2023 becomes 2023-2025 when modified)
  • Check mode for CI/CD integration to ensure all files have headers
  • Respects .licenseignore and .gitignore files automatically
  • Preserves shebang lines in executable scripts
  • Handles multiple comment styles (hash, slash, dash, block comments)

Supported Languages

Hash comments (#): Python, Shell (bash/zsh/fish), Ruby, Perl, R, YAML, TOML, CMake

Slash comments (//): JavaScript, TypeScript, Go, Rust, Java, C/C++, Swift, Kotlin, C#, PHP, Scala, Objective-C, Gradle, Groovy, SCSS, Sass, Less

Dash comments (--): SQL, Lua, Haskell, Elm

Block comments: CSS (/* */), HTML/XML/SVG/Vue (<!-- -->)

Special files: Dockerfile, Makefile, Jenkinsfile, Vagrantfile, Rakefile, Gemfile, Podfile, Fastfile, CMakeLists.txt, and more

Installation

pipx install python-license

Or with pip:

pip install python-license

Usage

Command Line

Basic syntax:

license [options] <license-id> "<author>"

Examples:

# Check files without modifying (dry-run)
license --check Apache-2.0 "John Doe"

# Add/update headers in specific directory
license --fix MIT "Jane Smith" --dir src/

# Use custom ignore file
license --ignore-file .licenseignore --fix GPL-3.0 "ACME Corp"

# Process specific files only
license --fix Apache-2.0 "Your Name" file1.py file2.js

# Set custom copyright year
license --fix --year 2024 MIT "Your Company"

# Add extended notice (e.g., for AGPL, GPL licenses)
license --fix --notice-template NOTICE.template AGPL-3.0-or-later "Your Name"

Add to your .pre-commit-config.yaml:

repos:
  - repo: https://github.com/eznix86/python-license
    rev: v1.0.1
    hooks:
      - id: license-headers
        args: ['--check', 'Apache-2.0', 'Your Name']

For automatic fixing on commit:

repos:
  - repo: https://github.com/eznix86/python-license
    rev: v1.0.1
    hooks:
      - id: license-headers
        args: ['--fix', 'Apache-2.0', 'Your Name']

See .pre-commit-config.yaml for a complete example.

Options

Option Description
--check Check files without modifying (default mode)
--fix Add or update headers in files
--dir DIR Root directory to process (default: current directory)
--year YEAR Copyright year (default: current year)
--no-recursive Don't process subdirectories
--verbose, -v Show all processed files
--ignore-file FILE Path to ignore file (default: .licenseignore or .gitignore)
--notice-template FILE Path to notice template file to append after copyright
files Specific files to process (overrides --dir)

Notice Templates

For licenses that require extended notices (like AGPL, GPL), create a template file:

NOTICE.template:

This file is part of Your Project.

Your Project is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

See the LICENSE file for more details.

Then use it with:

license --fix --notice-template NOTICE.template AGPL-3.0-or-later "Your Name"

Result:

// SPDX-License-Identifier: AGPL-3.0-or-later
// Copyright (C) 2025  Your Name
//
// This file is part of Your Project.
//
// Your Project is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// See the LICENSE file for more details.

Ignore Files

Create a .licenseignore file to exclude specific files or directories:

# Ignore patterns (similar to .gitignore)
*.min.js
*.min.css
generated/*
vendor/
third_party/
build/
dist/

# Negate patterns (don't ignore these)
!important.min.js

If no .licenseignore exists, the tool automatically uses .gitignore patterns.

See .licenseignore for an example.

FAQ

Does it overwrite existing headers?

No, it intelligently updates them. If a file already has an SPDX header, it will:

  • Update the license identifier if changed
  • Update the copyright year range (e.g., 20232023-2025)
  • Preserve the existing header structure

The tool automatically manages copyright year ranges:

  • First added: Copyright (C) 2025 Your Name
  • After modification in 2026: Copyright (C) 2025-2026 Your Name
  • If already current: no change

Can I use it in CI/CD?

Yes! Use --check mode to fail the build if any files are missing headers:

# GitHub Actions example
- name: Check license headers
  run: license --check Apache-2.0 "Your Name"

This returns exit code 1 if any files need updating.

What files are excluded by default?

The tool automatically excludes common build artifacts and dependencies:

  • Version control: .git/, .svn/, .hg/
  • Dependencies: node_modules/, vendor/, third_party/
  • Build outputs: build/, dist/, target/, __pycache__/
  • Minified files: *.min.js, *.min.css
  • Lock files: *.lock, *.sum, go.mod
  • Config files: *.json, *.toml, *.yaml

Can I use custom SPDX license identifiers?

Yes! Use any valid SPDX license identifier. Common examples:

  • MIT
  • Apache-2.0
  • GPL-3.0-or-later
  • BSD-3-Clause
  • ISC

See SPDX License List for all valid identifiers.

Does it work with monorepos?

Yes! You can:

  • Run it on the entire repo
  • Use --dir to target specific packages
  • Use different .licenseignore files in different directories
  • Process specific files only

Contributing

Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.

Please make sure to update tests as appropriate.

License

This project is licensed under the Apache License 2.0.

See the NOTICE file for additional information.