Alpha test! Some parts are already working well, some parts are still being finished.
Sublicenses are access keys for a specific pack or mini-app created by that pack's author.
It can be a clicker, a bot, a tool, a helper, or a complete mini-app built for a specific task. The point is simple: you build your own product on top of EyeAuras and decide:
From a technical point of view, EyeAuras already allows very deep customization of these products. In practice, you can build something very close to a standalone application that already has automation, updates, protection, licensing, and similar infrastructure built in.
Example: a mini-app built on top of EyeAuras
You do not need a separate EyeAuras license in order to use sublicenses.
The platform is now free. Sublicenses exist for your paid packs and mini-apps.
To make onboarding easier, EyeAuras supports key-based login without a separate registration flow.
The user just clicks I have a key, pastes the key, and EyeAuras automatically creates an account for them. After that, they can use the pack like any other user.

On the pack page, authors now have a separate block related to licensing.
Sublicenses are designed around the idea that you, the pack author, distribute your keys however you want.
Right now EyeAuras provides the licensing infrastructure, but it does not provide built-in checkout or payment processing. That may change later, but at the moment there are both technical and legal questions around it.
In practice, common options are:
While sublicenses are still in alpha, key issuance still goes through me. The easiest way to reach me is via contacts, usually Discord.
After alpha, key issuance will become automatic. The basic flow will look like this:
15% commission, which means 85% stays with the authorThe result is simple: if you have not earned anything yet, you do not lose anything either.
This is where you configure how exactly licensing should behave for your pack.
Important: changes are not retroactive. If you have already issued keys with specific rules, those rules stay as they were. Users need to know that a purchased key will not change behind their back later.

This defines how license time is consumed.
Calendar is the classic model. A key is issued for a duration like a week or a month, and time keeps going on its own. If the program is closed, time still passes.
Consumed counts only the time while the user is actually using the program. If EyeAuras is closed, time does not pass.
The author can temporarily freeze licenses and stop time consumption.
This is useful if something breaks after an update and you need time to fix it. In that case you can freeze the keys, fix the issue, and then unfreeze them. Users do not lose time during downtime.
Important: for Calendar, this mode is still being finished. For Consumed, it should already work properly.
Every key has a certain number of sessions. By default it is usually 1.
What counts as a "session" is defined by you, the pack author:
EyeAuras does not invent what a session means for your product. It only tracks and maintains those sessions.
You can issue keys that become bound to a specific PC on first use.
If the user wants to use the pack on a different machine, they can:
For now this is primarily a list of issued licenses and their current state.
Later it will gain better search, filtering, and statistics.
This is useful for tracking online activity and understanding whether your product is currently being used.
The list is anonymized. You can see connection facts and technical license state, but not the actual identity of the user.
Later this will also include more growth and activity statistics.
Users do not get keys from EyeAuras itself. They get them from the pack author.
The flow is simple:
There are two common scenarios.
If the user already has an EyeAuras account, they can simply sign in and activate the key in their profile.

If the user does not have an account yet, they can click I have a key and sign in using only the key.

Both options are valid. The only difference is whether the user already has an account or EyeAuras creates one automatically during sign-in.
On the My Account page and right in the login window there is now a timeline of activated sublicenses.
There the user can see:

Users can also freeze their own license for an unlimited period of time.
While the license is frozen, time is not consumed.
The number of freezes is limited. The exact value is configured by the pack author, and by default it is usually 1.
From the sublicensing point of view, authors usually end up in one of two very different scenarios.
This is the simplest option.
In this case you usually do not need to invent anything special for login:
So you simply add the lease/request logic to your pack, while the user-facing login flow remains handled by EyeAuras itself.
This is the mini-app or near-standalone-app scenario.
This is usually the recommended approach for commercial products because you control the user experience better, and the pack logic and licensing logic are buried much deeper.
There are two sub-variants here:
The most secure format in the end is a fully custom UI.
If you have your own UI, there are two main options.
LoginWidgetThis is the fastest way if you have a Blazor window and do not want to build the login form yourself.
Just place this in your window:
<LoginWidget/>
That way the user can open the standard EyeAuras login flow right from your interface.
If you have your own ImGui / Blazor / WPF / any other interface, you can work directly through IEyeHubService.
In practice, the operations you usually need are:
PerformLogin(username, password) for standard login with username and passwordPerformLogin(licenseKey, licenseKey) for key login without a separate registration flowActivateLicenseKey(licenseKey) for attaching an extra key to an already logged-in accountActiveLicense for the current license stateConnectionState, ConnectedFor, DisconnectedFor for connection stateThe minimal flow looks like this:
var eyeHub = GetService<IEyeHubService>();
var userLicense = await eyeHub.PerformLogin(username, password);
var keyLicense = await eyeHub.PerformLogin(licenseKey, licenseKey); // key login
var updatedLicense = await eyeHub.ActivateLicenseKey(extraLicenseKey); // only for already logged-in user
Log.Info($"Current user: {eyeHub.ActiveLicense.Username}");
Log.Info($"Connection state: {eyeHub.ConnectionState}");
In practice this allows you to build your own login screen, your own profile page, your own connection state UI, and avoid showing the standard EyeAuras UI directly to the user.
If you already have a pack that uses sublicenses, read this section carefully.
The sublicense validation mechanism has changed a lot.
Previously you could just read the list of sublicenses from the current license, for example through ILicenseAccessor.ShareSublicenses.
Now, for modern EyeAuras builds, the correct model is different:
lease whose state changes over timeleaseIf you keep the old passive check and do not migrate to the new API, behavior will be as follows:
9298, compatibility mode may still make it work9298, the sublicense is no longer requested automaticallyShort version: for new packs and new client versions, the old approach is no longer enough.
If you want to publish or maintain packs for recent EyeAuras versions, migration to ISublicenseManager is mandatory.
Now you should use ISublicenseManager and request a lease.
Minimal example:
using var lease = GetService<ISublicenseManager>()
.Rent(new AuraShareId("S20260209165639iiQZB0NCruAb"));
lease.WhenChanged()
.Subscribe(x => Log.Info($"Lease changed: {new { x.IsGranted, x.Status, x.Message, x.LastUpdatedAt }}"));
The recommended reactive approach is to tie the subscription to ExecutionAnchors:
var lease = GetService<ISublicenseManager>()
.Rent(new AuraShareId("S20260209165639iiQZB0NCruAb"));
lease.WhenChanged()
.Subscribe(x =>
{
if (!x.IsGranted)
{
Log.Warn($"Sublicense is not granted yet: {x.Status} / {x.Message}");
return;
}
Log.Info("Sublicense granted, pack can continue working");
})
.AddTo(ExecutionAnchors);
Important details here:
Rent(...) is non-blocking and returns immediatelyPendingWhenChanged() fireslease.IsGranted == truelease itself is already bound to the script lifecycle by EyeAuras; .AddTo(ExecutionAnchors) above is for your subscriptionOne lease equals one logical session.
If you dispose the lease, that session is considered finished. When the script or pack stops, EyeAuras also releases those sessions automatically.
Rent(...) was calledCalling Rent(...) does not mean access is already granted.
The real check is lease.IsGranted and, if needed, lease.Status / lease.Message.
Each Rent(...) call is a separate session.
ILicenseAccessor.ShareSublicenses as the main mechanism anymoreYou can treat it as a legacy compatibility path, but not as the proper validation model for new packs.
The current licensing model tries to be as user-friendly as possible.
EyeAuras is not designed to make users lose access every time there is a short disconnect, reconnect, or client restart.
In practice, it works like this:
lease is not issued forever, only for a limited timeThere is another important case: crashes.
If the app or script crashes, the local lease may not be released in time, so for a while the server may think that session is still occupied. But for the user this should not turn into "everything died and nothing works anymore."
Because of Semi-Offline mode and the cached signed license, EyeAuras tries to restore already granted access after restart and keep the pack running while that offline grant is still valid.
So the expected behavior is:
lease againImportant limits of this mode:
For sublicenses, a small script that requests and checks the lease is basically mandatory. And if the product is paid, you usually want to hide that code as deeply as possible.
The recommended settings are:
PackDistributionPolicy = PackedOnlyPackScriptCompilationMode = BinariesOnlyPackScriptProtectionMode = PerformanceFirst or SecurityFirstWhat this gives you:
PackedOnly means the user only gets the packaged version of the packBinariesOnly means the script source is not distributed, only binariesPerformanceFirst / SecurityFirst add protection and obfuscation on top of thatTogether, this makes the licensing code much harder to inspect or tamper with.
More details are in C# Script Protection.
Important: at the moment this protection layer is still being tested. To enable it right now, you need access to the alpha group. Once the feature stabilizes, it will become available to everyone.
Even so, it is worth remembering: even with good packing and protection, the safest option is still a fully custom UI and mini-app approach.
Not every paid product needs to be a full mini-app with lots of code.
Sometimes the core functionality is mostly built from:
In that case, sublicenses are still usually implemented via a small C# script that starts together with the pack, rents the sublicense, and then passes the result into the rest of the logic.
There are two practical options here.
IsAuthenticated auraThe simplest path is to create a dedicated aura, for example IsAuthenticated, and keep a Fixed Value Trigger inside it.
Then your script watches the lease state and simply turns that aura on or off whenever the lease changes.
After that, the rest of the pack can use standard EyeAuras mechanisms:
AuraIsActiveEnabling ConditionThat way the licensing logic stays in one small script, while the rest of the automation can continue working almost exactly as before.
If you need to find the target aura from code, use the approach shown here: How to find an aura
If you prefer, the authorization state can live in a variable instead of a dedicated aura.
The idea is the same:
lease changes, it updates a variable like isAuthenticatedMore details about that approach are here: Variables
If your licensing logic lives directly inside your script, it makes sense to mark that script as private, so the user cannot edit or view that code.
Right now there is nothing special you need to "enable."
During alpha, key issuance still goes through me, so just message me.
Later you will be able to issue keys directly on the website without any manual setup in chat.
It is better if you already have a pack or a mini-app ready and it is clear what exactly you are distributing. If the product is private, that is also fine; a public page is not required.
Anywhere. EyeAuras does not limit your sales channel.
Common options are:
No. EyeAuras is now free.
The user pays only for your product, if you choose to sell access through sublicenses.
No, not retroactively.
New settings affect only new keys. Already issued keys should stay exactly as they were at the time of purchase.
Pending status meanIt means EyeAuras has already requested access, but the background license refresh has not finished yet.
This is usually a normal startup state.
Usually the current model tries to preserve already granted access and avoid bothering the user for small interruptions.
If there is a short disconnect, EyeAuras will try to continue working on the already signed license and resync with the server later.
If there is a crash, after restart the pack should usually continue working as long as the client still has a valid cached offline license for that access.
But the important detail is: this is Semi-Offline, not full offline. If the proper cache is missing, a fresh grant still has to come from the server.
Yes, if you want them to work reliably on newer EyeAuras versions.
If the pack still checks access the old way and never calls ISublicenseManager.Rent(...), a user with a valid purchased key may still fail to get access on modern clients.