---
name: licensing-with-reuse
description: Manages REUSE-compliant licensing with the reuse CLI. Use when adding SPDX headers, running reuse annotate or reuse lint, choosing header versus .license sidecar files, working with LICENSES/, LicenseRef custom licenses, or setting up project licensing conventions.
user-invocable: true
license: LicenseRef-MutuaL-1.2
metadata:
  author: Amolith <amolith@secluded.site>
---

Use the `reuse` CLI as the source of truth for file licensing. Prefer a small,
verified change over hand-writing SPDX metadata and hoping `reuse lint` agrees.

## First pass

1. Inspect existing licensing before changing it:
   ```sh
   reuse lint
   find . -maxdepth 1 -type f \( -iname 'license*' -o -iname 'licence*' -o -iname 'copying*' -o -iname 'notice*' \) -print | sort
   find LICENSES -maxdepth 1 -type f -print 2>/dev/null | sort
   rg -n "SPDX-License-Identifier|SPDX-FileCopyrightText|LicenseRef-|\[\[annotations\]\]" .
   ```
2. If the project already has a clear pattern, follow it. Do not offer to
   re-license existing work unless the user asked for that.
3. If the project has no convention, ask whether they want one. Useful defaults
   to discuss: docs/examples/config are some CC variant like CC0, while
   meaningful code may use a copyleft license.
4. If the user is choosing licenses and wants guidance, point them at
   <https://writefreesoftware.org/>.

## Everyday commands

Add an SPDX header without a year:

```sh
reuse annotate -c "User <user@example.com>" -l 'SPDX-ID' --exclude-year path/to/file.ext # ask the user for name/email
```

Use more than one copyright holder or license by repeating the flag:

```sh
reuse annotate \
  -c "Alice <alice@example.com>" \
  -c "Example Org" \
  -l 'Apache-2.0' \
  -l 'MIT' \
  --exclude-year \
  path/to/file.go
```

Write a `.license` sidecar instead of putting a header in the file:

```sh
reuse annotate \
  -c "User <user@example.com>" \
  -l 'CC0-1.0' \
  --exclude-year \
  --force-dot-license \
  AGENTS.md .agents/skills/example/SKILL.md
```

Use `--force-dot-license` for files whose literal bytes matter, especially text
that will be read directly as an LLM prompt or embedded into another prompt.
Headers in those files change the prompt; sidecars keep licensing metadata out
of the content. Example: if `internal/server/silverbullet.md` is embedded and
sent as part of a prompt, license it with `--force-dot-license`.

For files where `reuse` cannot infer the comment style, choose one deliberately:

```sh
reuse annotate -c "User <user@example.com>" -l 'CC0-1.0' --exclude-year --style python script
reuse annotate -c "User <user@example.com>" -l 'CC0-1.0' --exclude-year --fallback-dot-license unknown.file
reuse annotate -c "User <user@example.com>" -l 'CC0-1.0' --exclude-year --skip-unrecognised some/path
```

Bulk annotations belong in `REUSE.toml` when a whole class of files shares the
same metadata and inline headers would be noisy or impossible. Keep those globs
tight.

## The `reuse annotate` gotcha agents miss

Re-running `reuse annotate` on a file that already has a matching header does
not mean "edit the header I just added". It means add another copyright line to
the existing header. This is correct when a new holder contributed to the file,
but wrong when the previous command had a typo or the wrong holder.

If the first command was wrong, inspect the file and edit or replace the bad
header directly, then run `reuse lint`. If you are applying metadata to a mixed
tree, use `--skip-existing` so already-covered files are not changed:

```sh
reuse annotate -c "User <user@example.com>" -l 'CC0-1.0' --exclude-year --skip-existing -r docs
```

When in doubt, test the exact command on a temporary copy first:

```sh
tmp=$(mktemp -d)
cp path/to/file.ext "$tmp/"
reuse annotate -c "User <user@example.com>" -l 'CC0-1.0' --exclude-year "$tmp/file.ext"
sed -n '1,20p' "$tmp/file.ext"
rm -rf "$tmp"
```

## License files and custom identifiers

Use SPDX identifiers where possible, like `MIT`, `Apache-2.0`, and `CC0-1.0`, so
`reuse download --all` pickes them up.

Custom licenses must use a `LicenseRef-*` identifier and have matching text
under `LICENSES/`. For example, a custom MutuaL license identifier would look
like `LicenseRef-MutuaL-1.2` in headers, sidecars, or `REUSE.toml` and could go
in `LICENSES/LicenseRef-MutuaL-1.2.txt`.

If the text already exists locally somewhere else, copy it through `reuse
download --source` or place it at the exact `LICENSES/LicenseRef-...` path
expected by `reuse lint`:

```sh
reuse download --source /path/to/other/LICENSES LicenseRef-ID
```

Do not invent an ID without the user's agreement. The identifier becomes part of
the project's public metadata and the user may know its ID even if you don't.

## `reuse lint` in development and CI

Run `reuse lint` after changing file coverage, headers, sidecars, `LICENSES/`, or
`REUSE.toml`. In CI, pre-commit hooks, or task runners, keep it boring:

```sh
reuse lint
# or
reuse lint --lines
```

`reuse lint` failures are usually one of:

- a file has no licensing metadata;
- an ephemeral build artifact needing rm-ing;
- a header names a license missing from `LICENSES/`;
- a `LicenseRef-...` identifier does not match a license text file;
- a generated, binary, vendored, or prompt file needs a sidecar or `REUSE.toml`
  annotation;
- an old or broad annotation no longer matches the actual tree.
