Selling here
IndieLicense · open source

Sell license keys without running a server.

A small open-source library that signs and verifies license keys entirely on-device. No backend, no accounts, no phone-home. You generate the keys, we hand them to your buyers.

View on GitHub
Ed25519Signed and verified on-device0Servers to runMITOpen source, yours to forkOfflineIncluding first activation
Why this exists

Licensing should not become infrastructure.

You wrote a menu bar utility. Now you are being asked to run an activation server, keep it online forever, store customer records, and pay a monthly fee to a licensing SaaS that takes a cut of every sale. All of it so a text field can say “valid”.

A signature check does the same job, on the customer’s machine, for free, forever.

× An activation server you must keep alive
× A monthly bill that scales with your sales
× Customer records you never wanted to hold
A signed string, checked on the device
01

No server to run.

Keys are signed once, on your machine, and verified on the customer’s Mac. There is nothing to host, nothing to pay for monthly, and nothing that can go down at 3am and lock out your customers.

02

It works offline.

Activation is a signature check, not a network request. Your app works on a plane, behind a corporate firewall, and in ten years when you have moved on to something else.

03

No customer data leaves the Mac.

No accounts, no device fingerprints, no analytics, no activation limits. You cannot leak what you never collected — and privacy-minded Mac users notice.

04

You keep the keys. Literally.

You generate the keypair. Your private key never touches this store or anyone else’s infrastructure. If we vanished tomorrow, your licensing keeps working exactly as it does today.

How it works

Four steps, once.

1
Create your minting key
indielicense init — makes an Ed25519 keypair in a secure directory outside your repo. The public key goes in the app; the private key never leaves your machine.
2
Generate the Swift plumbing
indielicense integrate swift writes plain Swift files into your project — verifier, config, manager, and optional SwiftUI key entry and status badge. No SDK, no dependency to keep updated.
3
Mint a batch of keys
indielicense generate --count 500 writes keys.csv. Key ids continue across batches, so you can top up whenever you run low.
4
Upload the CSV
Drop it into your listing here as the key pool. We hand one key to each buyer at checkout and tell you when you are running low.
Key modes

Three ways to sell.

Chosen when you mint the batch, not baked into your app. You can mint a different mode tomorrow without shipping a new build.

Lifetime --mode lifetime
The app unlocks forever. No expiry, no update cutoff. The “$9, yours forever” key.
Updates --mode updates --updates-duration 365d
Unlocks forever, but only versions released within 365 days of activation are covered. After that they keep their current version or buy a renewal. This is the buy-once-with-12-months-of-updates model.
Trial --mode trial --expires 14d
Stops working 14 days after activation. For press, beta testers and “extend my trial” support requests.
The clock starts at activation, never at generation. A key holds a duration, not a date. Mint 500 trial keys today and they can sit unsold for six months — the countdown begins the first time a customer pastes one in.
Let your agent do it

Paste this into your coding agent.

It knows the library, the constraints, and the mistakes to avoid. Most apps are wired up in a single pass.

Paste into Claude Code from your project root — it will run the licensing interview with you. Paste into Codex. Pre-filled with sensible defaults for a single pass. Paste into Cursor’s composer. Includes .cursorrules entries to add.
Add IndieLicense to this macOS app so I can sell it with offline license keys.

Start here
- Repo: https://github.com/tarasowski/indielicence
- Read AI_INTEGRATION.md first — it is the copy-paste integration playbook.
- Read AGENTS.md — it contains mandatory security and repository rules. Follow them.
- SPEC.md describes the key format if you need it.

Run the licensing interview from AI_INTEGRATION.md with me before writing code.
Do not guess my answers. I need to decide: key mode (lifetime / updates /
trial), update window length, keyless trial days, and purchase URL.

Then do the work
1. Install the CLI: brew install tarasowski/tap/indielicense
2. indielicense init --product <id> --key-dir ~/Licensing/<id>
   The private key never enters the repo or the app bundle. Only the public
   key is embedded. Remind me to back up the key directory.
3. indielicense integrate swift --product <id> --key-dir ~/Licensing/<id> \
     --build-date <today> --output ./<App>/License --ui swiftui \
     --denylist bundled --trial <N>d --purchase-url <my store URL>
   This generates app-owned Swift files — LicenseVerifier, LicenseConfig,
   LicenseManager, and the SwiftUI activation/badge views. There is no SDK.
4. Wire LicenseManager into app launch. Gate paid features on
   license.hasFullAccess (licensed OR in keyless trial), not isLicensed.
5. Add LicenseBadgeView to the toolbar so trial state is always visible.
6. Embed the release build date as a source constant. Never read the
   executable's modification time — it is mutable after code signing.
7. Handle LicenseStore throw as an explicit storage-failure state. Never
   silently start a new activation window on a storage error.
8. Work through the LICENSE_INTEGRATION.md checklist it generates.

Constraints
- No networking, telemetry, or device fingerprinting. Validation is offline.
- Never overwrite existing files in the output directory.
- Treat any note text from a key as display data — SwiftUI text APIs only.

When done, show me the command to mint 500 keys and confirm where my private
key lives.

Free, MIT-licensed, and yours to fork.

We built it because we needed it, and we open-sourced it because licensing should not be a business model. Use it with this store, use it on your own site, use it with a competitor. It is yours either way.