LicenseKit
February 2026 → July 2026

In front of an empty repository, there's always that moment where you have to pick a licence. You vaguely know MIT is permissive and GPL obliges you to something, you copy what you saw elsewhere, and you move on. The tools I knew did generate a LICENSE file, but none of them explained what I had just signed.
LicenseKit is a command-line tool that helps you choose, understand and add the right open-source licence to a project.
npx @drosscend/licensekit
There was another, more personal motivation: I install dozens of tools like this one, and I wanted to be on the other side for once. To publish something anyone could run with a single command.
Understanding before generating
The tool shows what a licence permits, what it requires and what it excludes, in plain language rather than legalese.

It also compares two licences side by side, still the fastest way to grasp a difference. With MIT against GPL-3.0, you can see at a glance that both allow commercial use, but only the GPL requires documenting your changes and redistributing under the same terms.

Finally it generates the LICENSE file, filling in the author and year it works out on its own from the local Git configuration, and offers to update the license field of package.json along the way. You should never have to type in something the program can deduce.
The wizard, or my opinion encoded as points
The guided mode asks a few questions about the project, then ranks licences by relevance.
There's no intelligence behind it: it's a scoring matrix written by hand. Each answer adds or removes points from specific licences. Answering "library" favours MIT, Apache and the BSDs; answering "commercial project" docks the GPLs two points; "documentation" pushes CC0 up.
In other words, that ranking is my own convictions turned into weights. It's a reasoned opinion, not a truth, and I'd rather say so plainly. In the same spirit: the tool helps you understand and narrow things down, it doesn't replace legal advice.
Where the texts come from
The fourteen licences on offer aren't copied by hand. A script fetches their text and metadata from the GitHub API, then embeds them in the package.
What I did do manually is the categorisation: permissive, copyleft, weak copyleft, public domain. That classification structures the display and feeds the questionnaire. It doesn't exist in the source data.
Three dependencies, and that's it
An argument parser, an interactive prompt library, a bit of colour.
For a tool people run through npx without installing it, every dependency is a download on every run. A tool that takes ten seconds to start won't be run twice. Lightness isn't elegance here, it's a condition of use.
Internationalisation, on the other hand, was non-negotiable: everything is available in French and English, with system language detection and the option to force it with --lang. Translations live in separate files, so adding a language doesn't mean touching the code.
Moving to the author's side
This was my first npm package, and the publishing side taught me as much as the code.
The name first. Short names have long been taken, hence the scoped package, @drosscend/licensekit. Then the format: declaring the binary, building before publishing, curating the metadata so the npm page actually says something.
The part I find most interesting is the release pipeline. Pushing a tag is enough to trigger a release: the CI checks that the tag matches the version in package.json, runs the linter, the types and the ninety-two tests, builds the package and publishes it with a provenance attestation. All of it without a stored token, thanks to OIDC authentication between GitHub and npm. There is no npm secret in the repository, which is exactly what you want for an automated release.
The tool is built to reach beyond Node: manifest detection goes through an adapter registry, of which only one exists today, the package.json one. Adding Cargo.toml or pyproject.toml would take a file, not a redesign.
What re-reading revealed
Going back through the code to write this, I found two flaws.
The first: the comparison showed every limitation as absent. GitHub's data uses the tags liability and warranty, while my internal rules expected no-liability and no-warranty. The detail command went through an alias table, the comparison had forgotten it.
The second was sneakier, and it didn't come from the code. The pipeline called the TypeScript compiler without the version being pinned in the project, so it picked up whichever one was current. As long as TypeScript 5 was the latest release, all was well. The day TypeScript 7 shipped, publishing started failing on a project where not a single line had moved since February. The errors all traced back to one point: without Node's types, process.exit() no longer promised never to return, so the compiler could no longer infer that a variable was non-null after that check.
Both are fixed, dependencies are up to date, and tooling versions are now declared in the project. The lesson is simple: an unpinned dependency always ends up moving, including on a project you no longer touch.
Where the project stands
Written and published in two days, with Claude Code, on a deliberately closed scope: a tool that does one thing, completely.
I don't actively maintain it and I don't use it daily, but it lives its own life: around thirty downloads a month, from people I don't know. For a first package, that's enough to make you want to do it again.