License and Legal
Licensing decisions are cheap before the first external contribution and expensive after. Get this right early.
This skill provides engineering guidance, not legal advice. For relicensing a project with outside contributors, employer IP questions, trademark disputes, or anything with money attached, tell the user to consult a lawyer. Say it once, clearly, then give the best engineering answer you can.
Choosing a license
Ask what the user actually wants, in this order:
Do you want maximum adoption, including inside proprietary products? → MIT (shortest) or Apache-2.0 (adds an explicit patent grant + trademark clause). Apache-2.0 is the better default for anything with patent surface or corporate contributors. MIT is the better default for small libraries where brevity matters.
Do you want modifications to your code returned to the commons, but allow linking from proprietary software? → MPL-2.0 (file-level copyleft) or LGPL-3.0 (library-level, more restrictive in practice).
Do you want anything built on this to also be open source? → GPL-3.0. Understand the cost: many companies have blanket policies against GPL dependencies, so adoption drops sharply.
Same as 3, but the software will be run as a network service? → AGPL-3.0. Closes the "SaaS loophole." Adoption cost is even higher; some companies ban it outright.
Do you want to prevent competitors from offering it as a hosted service? → BSL 1.1, Elastic License 2.0, or SSPL. Be explicit with the user: these are not open source by the OSI definition. Do not call a BSL project "open source" — the community reaction to that mislabeling is consistently harsh. "Source-available" is the accurate term.
Defaults worth stating: Apache-2.0 for most new projects, MIT for small libraries, AGPL-3.0 if the business model is hosting, and honesty if the answer is source-available.
Ecosystem gravity
Fighting your ecosystem's convention costs adoption. Rust and Go lean permissive
(Rust commonly dual-licenses MIT OR Apache-2.0); npm skews MIT; Python is mixed but
permissive-leaning; the Linux kernel world is GPL-native. Match unless you have a
reason.
Compatibility
Direction matters — you can flow permissive into copyleft, never the reverse.
| Your license | Can include MIT/BSD | Apache-2.0 | MPL-2.0 | GPL-3.0 | AGPL-3.0 |
|---|---|---|---|---|---|
| MIT | Yes | Yes¹ | No² | No | No |
| Apache-2.0 | Yes | Yes | No² | No | No |
| MPL-2.0 | Yes | Yes | Yes | No | No |
| GPL-3.0 | Yes | Yes | Yes | Yes | No |
| AGPL-3.0 | Yes | Yes | Yes | Yes | Yes |
¹ You must preserve Apache-2.0's NOTICE file and attribution.
² MPL-2.0 files stay MPL-2.0; you may combine, but you cannot relicense those files.
Known trap: Apache-2.0 is incompatible with GPL-2.0-only (patent clause), though it is fine with GPL-3.0. If a project is GPL-2.0-only, Apache-2.0 dependencies are a problem.
Applying the license
# 1. Full license text at the repo root, verbatim, filename LICENSE (no extension)
curl -sL https://raw.githubusercontent.com/licenses/license-templates/master/templates/apache.txt -o LICENSE
# Fill in year and copyright holder in the Apache-2.0 appendix.
# 2. Declare it in the package manifest
# package.json: "license": "Apache-2.0"
# pyproject.toml: license = "Apache-2.0"
# Cargo.toml: license = "MIT OR Apache-2.0"
# 3. SPDX headers on source files (optional but increasingly expected)
# // SPDX-License-Identifier: Apache-2.0
Copyright line guidance: Copyright <year> <entity> where entity is you, your
company, or "The Authors". The last form scales — it avoids editing every
header when contributors join, and pairs with an AUTHORS file. Do not maintain
per-file per-contributor copyright lists; Git already tracks that.
Use reuse lint (REUSE spec) if the project needs machine-verifiable compliance.
Contribution mechanics: DCO vs CLA
| DCO | CLA | |
|---|---|---|
| Mechanism | Signed-off-by: in commit (git commit -s) |
Contributor signs a document once |
| Says | "I have the right to submit this" | Grants the project rights, sometimes copyright |
| Friction | Low | High — blocks first PRs, needs a bot and storage |
| Enables relicensing later | No | Yes (if it grants that) |
| Use when | Almost always | A foundation requires it, or you need relicensing rights |
Default to DCO. Enforce with the DCO GitHub App.
Add to CONTRIBUTING.md:
By contributing, you certify the Developer Certificate of Origin. Sign commits with
git commit -s.
Adopt a CLA only with a concrete reason. Contributors are increasingly suspicious of CLAs that assign copyright — the "we might relicense later" subtext is read correctly. If you do use one, prefer a license-grant CLA over a copyright-assignment CLA, and say in plain language what it allows.
Vendoring third-party code
Every time code is copied in:
- Confirm the license permits it and is compatible (table above)
- Keep the original license file next to the code:
third_party/<name>/LICENSE - Record origin and commit SHA in a header or
third_party/README.md - Add the notice to your
NOTICEfile if your license or theirs requires attribution - Never strip copyright headers — this is the fastest way to a legitimate complaint
Do the same for AI-generated code whose provenance you cannot establish: if it looks like a verbatim reproduction of a known implementation, treat it as vendored code and find the source.
Dependency license audit
npx license-checker --summary # npm
pip-licenses --format=markdown # Python
cargo deny check licenses # Rust (config in deny.toml)
go-licenses report ./... # Go
Run this in CI for any project with commercial users. A GPL dependency arriving via a transitive upgrade into an MIT-licensed library is a real incident, and it is silent until someone's legal team finds it.
Relicensing an existing project
Hard, in proportion to contributor count. The mechanics:
- Sole author, no external contributions → change it, note it in
CHANGELOG.md. Old released versions remain under the old license permanently; you cannot revoke. - External contributors, no CLA → you need permission from every contributor
holding copyright in surviving code. Enumerate them:
Open a tracking issue, get explicit written consent, remove or rewrite code from anyone unreachable. Projects have taken years on this.git log --format='%aN <%aE>' -- <paths> | sort -u - CLA with relicensing rights → you likely already have the right. Read the CLA.
Going permissive → restrictive (MIT → AGPL/BSL) is legally simpler but socially costly; expect a fork of the last permissive commit. Plan the communication before the commit, and be honest about the business reason. Users forgive a stated commercial motive far more readily than a rationalization.
Answering "can I use this?"
When asked about a third-party project, check LICENSE (not the README badge, which
is often stale), then:
- Permissive (MIT/BSD/Apache) → yes, including commercially; preserve notices, and
for Apache-2.0 preserve
NOTICE. - MPL → yes; modifications to MPL files must stay open.
- GPL → yes if what you distribute is also GPL. Internal-only use is unrestricted.
- AGPL → same, and network use counts as distribution.
- BSL/SSPL/Elastic → read the actual terms; usually fine except for hosting it as a competing service. Check the change date on BSL — it converts to open source.
- No license file → you have no rights beyond viewing. Ask the author to add one; many will. Do not assume "it's on GitHub so it's free".
Anti-patterns
- No LICENSE file. Default copyright applies: all rights reserved.
- Calling BSL/SSPL "open source". It is not, per the OSI definition.
- License in README only. Tooling reads
LICENSEand the package manifest. - Mismatched declarations.
package.jsonsays MIT,LICENSEsays Apache-2.0. This gets found by automated scanners and looks careless. - Copyright assignment CLA for a small project. Maximum friction, minimum benefit.
- Assuming permissive means no obligations. MIT requires preserving the notice;
Apache-2.0 requires
NOTICEpropagation.