LicenseOps (lops)
A fast CLI tool to check, fix, and migrate license headers across 50+ languages. Supports SPDX, REUSE, Apache/GPL boilerplates, and custom templates. Built for CI pipelines, pre-commit hooks, and local development.
Why "LicenseOps"? — "License" says what it manages, "Ops" signals it's an operational tool built for automation — CI pipelines, pre-commit hooks, workflows. The CLI binary is
lops(LicenseOps) — 4 characters, fast to type, same pattern as Kubernetes →kubectl, Terraform →tf.
Features
- Check, Fix, Remove — validate headers, auto-add/replace them, or strip them entirely
- Multiple formats — SPDX short (1-line and 2-line), REUSE, Apache 2.0 boilerplate, GPL/LGPL/AGPL boilerplate, custom templates
- 50+ languages — correct comment syntax for Go, Rust, Python, JavaScript/TypeScript, Java, C/C++, Shell, YAML, CSS, HTML, SQL, and many more
- SPDX expressions —
Apache-2.0 OR MIT,GPL-3.0-only WITH Classpath-exception-2.0 - Smart handling — preserves shebangs and Python encoding declarations, skips generated files and binaries
- Gitignore-aware — respects
.gitignorepatterns automatically - Cross-format migration — switch from one header format to another without manual cleanup; old headers are fully detected, stripped, and replaced
- Parallel processing — files are processed concurrently for fast execution on large codebases
- Structured output —
--output jsonand--output sariffor CI tooling and GitHub Code Scanning - CI-ready — exit codes 0/1/2/3,
--dry-run,--diff, Docker image, GitHub Actions compatible - Zero config viable — works with just
lops check -l MIT -o "Your Name" .
Installation
Binary
Download the binary for your platform from Releases:
- macOS (Apple Silicon)
- macOS (Intel)
- Linux (x64)
- Linux (ARM)
curl -sSL https://github.com/licenseops/licenseops/releases/latest/download/licenseops_darwin_arm64.tar.gz | tar xz
sudo mv lops /usr/local/bin/
curl -sSL https://github.com/licenseops/licenseops/releases/latest/download/licenseops_darwin_amd64.tar.gz | tar xz
sudo mv lops /usr/local/bin/
curl -sSL https://github.com/licenseops/licenseops/releases/latest/download/licenseops_linux_amd64.tar.gz | tar xz
sudo mv lops /usr/local/bin/
curl -sSL https://github.com/licenseops/licenseops/releases/latest/download/licenseops_linux_arm64.tar.gz | tar xz
sudo mv lops /usr/local/bin/
Go install
go install github.com/licenseops/licenseops/cmd/lops@latest
Docker
# Latest stable release
docker run --rm -v "$PWD":/src -w /src ghcr.io/licenseops/licenseops:latest check
# Pinned to exact version
docker run --rm -v "$PWD":/src -w /src ghcr.io/licenseops/licenseops:0.2.0 check
# Latest development build (tracks main branch)
docker run --rm -v "$PWD":/src -w /src ghcr.io/licenseops/licenseops:latest-dev check
Quick Start
Initialize a config file (interactive):
lops init
Or check compliance directly:
lops check -l Apache-2.0 -o "Acme Corp" .
Fix headers:
lops fix -l Apache-2.0 -o "Acme Corp" .
Preview changes as a unified diff:
lops fix --diff
Remove all headers:
lops remove --dry-run # preview first
lops remove # then remove
Config file — create .licenseops.yaml in your project root (or use lops init):
license: Apache-2.0
copyright-holder: 'Acme Corp'
exclude:
- 'vendor/**'
- '**/*.pb.go'
Then simply:
lops check
lops fix
Header Formats
| Format | Config value | Description |
|---|---|---|
| SPDX 2-line | spdx (default) | // Copyright 2026 Acme Corp + // SPDX-License-Identifier: Apache-2.0 |
| SPDX 1-line | spdx (no owner) | // SPDX-License-Identifier: MIT |
| REUSE | reuse | // SPDX-FileCopyrightText: 2026 Acme Corp + // SPDX-License-Identifier: MIT |
| Apache 2.0 | apache-long | Full 14-line Apache boilerplate |
| GPL/LGPL/AGPL | gpl-long | Full GNU boilerplate (auto-selects GPL, LGPL, or AGPL) |
| Custom | custom | User-defined Go template file |
See Header Format Comparison for side-by-side examples.
CLI Flags
-l, --license SPDX license identifier or expression
-o, --owner copyright holder
-f, --format header format (spdx, reuse, apache-long, gpl-long, custom)
-y, --year copyright year
-c, --config config file path (default: .licenseops.yaml)
-v, --verbose show status of every file
--dry-run preview changes without modifying files (fix/remove)
--diff show unified diff of changes (fix, implies dry-run)
--excluded-only invert scan; process only files matching exclude
patterns from your config (remove only)
--output output format: text (default), json, sarif
Precedence: CLI flags > config file > defaults
Exit Codes
| Code | Meaning |
|---|---|
| 0 | All files compliant / all files fixed |
| 1 | Non-compliant files found |
| 2 | Runtime error |
| 3 | Partial failure (some errors and some non-compliant) |
Next Steps
- Getting Started — install and add headers in 3 minutes
- Configuration Guide — full config file reference, CLI flags, and merge rules
- Header Formats — side-by-side format comparison to choose the right one
- Use Cases — 12 real-world scenarios with example configs
- CI Integration — GitHub Actions, GitLab CI, pre-commit, Docker
- Supported Languages — all 50+ file types and comment styles
- FAQ & Troubleshooting — common questions and error resolution
License
Apache-2.0 — see LICENSE