Whose code is it anyway?
Every project borrows: a template, a snippet, a font, a logo, three hundred packages. Learn what each one lets you do and what it asks in return, one real licensing mistake at a time, in one small open source project.
prettyout 2.1.0 MIT tables colorwheel 1.4.0 GPL-3.0-only colour ✗ not permissive click-lite 3.0.2 BSD-3-Clause commands Starling is MIT. Packages it ships that are not permissive: 1 colorwheel 1.4.0: GPL-3.0-only, pulled in by prettyout
Robin asked for one MIT package. It brought a GPL one along, two levels down, inside an app Robin ships as MIT. Chapter 07 finds a way out that keeps the coloured tables.
From your first LICENSE to the AGPL
A license is permission in writing, with conditions. Each chapter takes one kind of permission, shows a project that broke its conditions, and fixes it.
- 01No license, no permissionWhy public code is still all rights reserved, and how to add a license with the exact text and a real copyright line.
- 02One license, three placesLICENSE, the README and every manifest, saying the same thing in SPDX identifiers that tools understand.
- 03Borrowing properlyKeeping a template's notice, and the four things Apache-2.0 asks when you copy and change its code.
- 04Assets and trademarksLicenses for fonts, icons and images, and how to show another product's logo without claiming its endorsement.
- 05What you shipPermissive, copyleft and source-available dependencies, and the GPL package hiding two levels down.
- 06Copyleft over the networkWhat the AGPL adds for web services, when it applies, and how to offer the source of the version you run.
Can I use it?
You found some code you want. Pick its license and your project's license, and see whether they combine, and on what conditions.
- Green means yes: keep the notices.
- Blue means yes, with conditions to follow.
- Red means no, not as things stand.
The same table as nest compat in the lab, for the common case of distributing the combined code. It is a guide, not legal advice.
No
GPL-3.0 code in an MIT project
Distributing it would make the whole work GPL-3.0. Only if you relicense your project.
GPL-3.0 code, into every license
- MITNo
- Apache-2.0No
- MPL-2.0No
- GPL-2.0-onlyNo
- GPL-3.0Yes
- AGPL-3.0Yes
Eight chapters, eight mistakes
Each chapter explains one idea in depth, then hands you a small project that gets it wrong in exactly that way. You fix it, and the checker reads the project like a scanner would.
- 01No license, no permissionCase: The repo nobody could usecopyright, choosing a license15 min
- 02One license, three placesCase: Three answers to one questionSPDX ids, manifests, README15 min
- 03Keep their nameCase: The name that went missingMIT's condition, templates, forks15 min
- 04Copying Apache codeCase: The file that forgot where it came fromApache-2.0, NOTICE, stated changes20 min
- 05Fonts, icons and imagesCase: The font with no papersOFL, icon sets, Creative Commons15 min
- 06Names and logosCase: The partner nobody signed uptrademarks, logos, endorsement15 min
- 07What you shipCase: The copyleft two levels downdependencies, copyleft, CI gates20 min
- 08Copyleft over the networkCase: The fork that hid its sourceAGPL, network use, source offers20 min
Run it, fix it, prove it
Every case is a folder: a tiny project with one licensing mistake in it. Nothing to install beyond uv. Here is case 02 from start to finish.
- 1Run ituv run python -m nest run 2
✗ README's License section names MIT, LICENSE is Apache-2.0 ✗ pyproject.toml: "MIT License" is not an SPDX identifier (use "MIT") ✗ web/package.json says ISC, LICENSE is Apache-2.0
One license file, three different answers around it.
- 2Fix itpyproject.toml, web/package.json
- license = "MIT License" + license = "Apache-2.0" - "license": "ISC" + "license": "Apache-2.0"
LICENSE is the truth. Bring the descriptions into line.
- 3Prove ituv run python -m nest check 2
PASS pyproject.toml declares the SPDX id Apache-2.0 PASS web/package.json declares Apache-2.0 PASS the README's License section names Apache 2.0, and only that
Every place names the same license, in words tools understand.
Four commands to the first case
You need git and uv. uv installs Python 3.13 for you, and the lab uses the standard library only. No accounts, no API keys, no Docker.
Then scan your own projects
The scanner from the lab works on any folder: it reads LICENSE, the README and every manifest, and tells you where they disagree.
uv run python -m nest scan ~/code/your-projectgit clone https://github.com/jars-demo/licensing-demo.git cd licensing-demo/lab uv sync uv run python -m nest run 1
The checklist
Ten rules, one per idea in the workshop. The last chapter ends with the same list.
- 01
Every repository gets a license file with the exact, canonical text. No license means no permission.
- 02
Fill in the copyright line with a real name and year, and leave every other word alone.
- 03
Declare the same license in
LICENSE, the README and every manifest, as an SPDX identifier. - 04
When you build on someone's code, keep their copyright notice. Add your name; never replace theirs.
- 05
Copying Apache-2.0 code: ship the license, keep the headers, say what you changed, and carry their NOTICE lines.
- 06
Fonts, icons and images have licenses. Ship each license next to the asset it covers.
- 07
A license never grants a trademark. Use other products' names and logos to say what you work with, never to claim endorsement.
- 08
Read the license of every dependency you ship, including the ones two levels down, and check them in CI.
- 09
GPL code in something you distribute makes the whole thing GPL. AGPL code you change and run online must offer its source.
- 10
Only the owner can change a license. When in doubt, ask the author, and for anything that matters legally, ask a lawyer.