# Licensee answers one question: which licence is this, and has it been changed

> Licensee is a Ruby gem and CLI that reads LICENSE files, package manifests and READMEs, then works out which SPDX licence a project is under and whether the text has been modified. It is built for compliance work, where the difference between MIT and a modified MIT is the whole question.

**licensee/licensee** — Ruby gem & CLI to detect a project's open source license (SPDX) from LICENSE files, package manifests, and READMEs

- Repository: https://github.com/licensee/licensee
- Website: https://licensee.github.io/licensee/
- Stars: 917 · Forks: 349
- Language: Ruby
- License: MIT
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/licensee-licensee

## Three questions the tool was built to answer

The README states the problem in three bullets, and they are worth quoting because they define the scope precisely.

You have got an open source project. How do you know what you can and can't do with the software? You have got a bunch of open source projects, how do you know what their licenses are? And you have got a project with a license file, but which license is it, and has it been modified?

The third question is the one that separates Licensee from a filename sniffer. Almost every repository has a file called LICENSE, and it is often a copy of a known licence with the copyright holder's name filled in, sometimes with an extra clause added, sometimes with the year changed. Reading the name of the file tells you nothing. Reading the text and comparing it against known licences tells you a lot.

The audience follows from the questions. This is for people who need to know the licensing status of software they did not write: a compliance team triaging a dependency list, an open source program office checking attribution, or a developer who has found a licence file and cannot tell which licence it is.

The project description says it detects a project's open source license, SPDX, from LICENSE files, package manifests and READMEs. The SPDX identifier matters because it is the machine-readable vocabulary that compliance tooling expects, and a tool that outputs a SPDX expression can feed straight into the rest of your pipeline.

## The matcher order: copyright notice, exact match, then Dice coefficient

Licensee automates the process of reading LICENSE files and compares their contents to known licenses using several strategies, which the project calls Matchers. It attempts to determine a project's license in a defined order, and the order matters more than any single matcher.

The first rule is the unusual one. If the license file has an explicit copyright notice and nothing more, for example Copyright (c) 2015 Ben Balter, Licensee assumes the author intends to retain all rights, and thus the project isn't licensed. That is a legalistic default, and a defensible one: a bare copyright notice grants nothing, so reporting it as unlicensed is the honest answer rather than guessing at MIT.

The second rule is exact match. If the license is an exact match to a known licence, and if stripping away whitespace and copyright notice might get lucky, direct string comparison in Ruby is cheap. The implementation detail is in the README and it is a good one: exact match first because it is cheap, and it gives an unambiguous answer when it succeeds.

The third rule is the fallback, and the README calls it a fancy math thing called the Sørensen-Dice coefficient, which it says is really good at calculating the similarity between two strings. By calculating the percent changed from the known licence to the license file, you can tell that a given licence is 95% similar to the MIT licence, with 5% likely representing legally insignificant changes to the license text.

The key design decision is that the fallback reports a number rather than a verdict. It does not say this is MIT with modifications. It says this is 95% similar to MIT, and leaves the judgement about whether that 5% matters to whoever is responsible for the decision.

## Installing the gem, or running it from source on Windows

There are three installation routes, and the README gives each one.

To use the latest released gem from RubyGems:

```bash
gem install licensee
```

To use Licensee programmatically inside your own Ruby project, you add the gem to your project's Gemfile. To run Licensee directly from source:

```bash
gem install bundler
bundle install
bundle exec bin/licensee
```

The Windows case has its own line, because the Ruby interpreter has to be named explicitly there.

```bash
bundle exec ruby bin\licensee
```

The optional piece is the rugged gem, and it changes what the tool can do. By default, Licensee scans projects using the filesystem. If you want to scan bare Git repositories or repositories without a working tree, for example on a Git server, you install rugged, which provides Ruby bindings for libgit2.

```bash
gem install rugged
```

Or you add it to your Gemfile alongside Licensee.

```ruby
gem 'rugged'
```

The behaviour change is graceful. When rugged is available, Licensee.project will use it automatically, and if rugged is not installed, Licensee falls back to filesystem-based scanning transparently. That is the right design for an optional dependency, because a compliance tool that fails to start because a native extension is missing is worse than one that scans less thoroughly.

The one caveat is that rugged is a native extension and requires cmake and openssl to build. The README notes these are available through a package manager on most systems, for example apt install cmake libssl-dev or brew install cmake openssl.

If you would rather not manage Ruby dependencies at all, there is a Dockerfile, and the three commands are short.

```bash
git clone https://github.com/licensee/licensee && cd licensee
docker build . --tag licensee
docker run licensee [COMMAND]
```

The image is built from ruby:4.0.7 with cmake installed and an entrypoint of bundle exec ./bin/licensee, so the container is just the CLI with no arguments.

## Gem repository scanning is opt-in for a reason

The filesystem default and the rugged path are not equivalent, and the difference is worth understanding before you point the tool at a Git server.

Filesystem scanning means the tool reads the files in a working directory. That covers the ordinary case of checking out a repository and looking at it, and it works with any directory of files, whether or not it is a Git repository at all.

Rugged scanning means the tool reads the Git object database directly through libgit2 bindings. That is what lets it handle bare repositories, where there is no working tree to read, and it is what you need when the thing you want to inspect lives on a Git server rather than on someone's laptop.

This matters for one specific workflow that compliance teams actually run: auditing a server-side Git hosting instance rather than a mirror of it. There is no checkout to read, so the filesystem path finds nothing, and without rugged the tool silently has less to work with.

The README's phrasing is worth noting. It calls Git repository scanning optional, and the fallback is transparent, which means the same command produces a result in both cases. What changes is the coverage, and a result derived from a filesystem scan of a checked-out repository will have been derived from whatever the checkout contains.

The Docker image is worth a second look for this reason. It does a git init in the working directory and copies the whole source tree in, so it is set up to scan a filesystem. If your bare repository workflow needs rugged, you would be building your own image on that basis rather than using the shipped one.

## Semver and the pessimistic constraint, plus what the docs folder holds

The README's versioning section is short and specific. This project conforms to semver, and as a result of this policy you can and should specify a dependency on this gem using the Pessimistic Version Constraint with two digits of precision.

```ruby
spec.add_dependency 'licensee', '~> 1.0'
```

That means your project is compatible with licensee 1.0 up until 2.0. You can also set a higher minimum version.

```ruby
spec.add_dependency 'licensee', '~> 1.1'
```

The release history supports taking that advice seriously. The listed versions are v10.1.0 released 2026-08-07, v10.0.0 on 2026-05-05, and v9.20.0 also on 2026-05-05. The jump from a 9.x line to a 10.0.0 major is the kind of break that a pessimistic constraint is designed to catch, and the two releases on the same day in May suggest a coordinated transition rather than an accident.

The documentation lives in a docs/ folder in the repository, and the README lists four entry points. usage.md has instructions for using Licensee. customizing.md covers customizing Licensee's behavior. CONTRIBUTING.md has contribution and development instructions. And what-we-look-at.md has more information about what Licensee looks at, or doesn't, and why.

That last document is the one to read first if you are evaluating the tool for compliance work, because it defines the detection surface. The README says the tool reads LICENSE files, package manifests and READMEs, but the details of what it inspects in each of those, and what it deliberately ignores, live in that document.

The repository layout also shows the tool's structure: lib/ for the implementation, bin/ for the executable, spec/ for the RSpec suite with a .rspec file and a .rubocop.yml, a pre-commit-config.yaml, and a vendor/ directory. The gemspec is licensee.gemspec and the Gemfile is at the root.

## What the similarity score does not decide for you

The tool's output is a number and an identifier, and the gap between those two things is where the legal risk lives.

A Dice coefficient of 95% against MIT means the text differs from MIT in a way that scores as five percent change. The README says such a difference is likely representing legally insignificant changes to the license text. Likely is doing real work in that sentence. A five percent change is also what you get from adding a nontrivial clause, and the tool cannot tell the two apart. It measures text similarity, and it does not have a model of what a licence clause means.

That is why the first matcher exists. A bare copyright notice produces a definite answer, unlicensed, because the intent is unambiguous. A near-match produces an ambiguous one, and the library refuses to resolve it for you.

So the correct way to use Licensee is as triage. It tells you which files in a repository to read, and it tells you how far each candidate licence is from the text you have. A person then reads the five percent that differs and decides.

The README does not present the tool as giving legal advice, and it does not need to, because it is honest about the shape of its own output. But the words likely representing legally insignificant changes are a description of the common case, not a guarantee, and an automated pipeline that treats a similarity score as a licence determination inherits that gap without noticing.

Two further limits are visible in the repository rather than the README. The licence of Licensee itself is MIT, with a LICENSE.md at the root, and the project carries an OpenSSF Scorecard badge and an OpenSSF Best Practices badge alongside a CI badge and a PRs Welcome badge. Those are signals about how the project is maintained, not about the output it produces.

## Conclusion

Adopt Licensee if you need to answer, repeatedly and automatically, what licence a repository is under, especially if your compliance work depends on telling a stock MIT licence apart from a modified one. Do not adopt it as a legal opinion, because it reports similarity, not legal meaning, and a high similarity score is not a lawyer's conclusion. Before you wire it into a pipeline, read what-we-look-at.md in the docs folder to learn which files it inspects, and remember that bare repositories need the rugged gem installed before the tool will scan them.

## FAQ

### How do I install Licensee?

Install the released gem with gem install licensee. To run it from source, install bundler, run bundle install, then bundle exec bin/licensee, or bundle exec ruby bin\licensee on Windows. There is also a Dockerfile, so you can build and run the CLI in a container.

### How does Licensee decide which licence a project uses?

It tries three matchers in order. A license file containing only an explicit copyright notice means the project is treated as unlicensed. Then it tries an exact match against known licences after stripping whitespace and copyright notices. Failing that, it computes the Sørensen-Dice coefficient and reports the percentage similarity to each known licence.

### What is Licensee for?

It automates the process of reading LICENSE files and comparing their contents to known licenses, so you can find out what licence a project is distributed under and whether the licence text has been modified. It is used for compliance and dependency triage.

### Can Licensee scan bare Git repositories?

Yes, if you install the rugged gem, which provides Ruby bindings for libgit2. When rugged is available, Licensee.project uses it automatically, and without it Licensee falls back to filesystem-based scanning transparently. Rugged is a native extension and needs cmake and openssl to build.

### Does a Licensee similarity score mean a project is unmodified MIT?

No. The tool reports how similar the text is to a known licence, for example 95% similar to MIT with 5% likely representing legally insignificant changes. That describes the common case rather than a legal determination, so the differing text needs reading.

### How should I depend on the Licensee gem?

The project conforms to semver, so the README advises the pessimistic version constraint with two digits of precision, for example spec.add_dependency 'licensee', '~> 1.0', which is compatible from 1.0 up until 2.0.

## Sources

- [licensee/licensee on GitHub](https://github.com/licensee/licensee)
- [License: MIT](https://github.com/licensee/licensee/blob/main/LICENSE)
- [Project website](https://licensee.github.io/licensee/)
- [README](https://github.com/licensee/licensee/blob/main/README.md)
- [Releases](https://github.com/licensee/licensee/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/licensee-licensee
