Modalità CLI compatibile con l’AI Server
A partire da Babel Licensing 11.8, la riga di comando lic può emettere un flusso di output strutturato e leggibile dalle macchine, adatto alle pipeline di CI, ai sistemi di gestione degli ordini e agli agenti AI, come la modalità introdotta nell’offuscatore con la 11.7.
L’output di testo predefinito di lic non cambia e resta pienamente compatibile con le versioni precedenti: gli script esistenti non richiedono modifiche.
La modalità compatibile con l’AI si attiva con tre opzioni globali:
--format=text|json|ndjsonseleziona il formato del canale di output--quiet(alias-q) sopprime il banner del logo e termina subito con un errore davanti alle richieste interattive--strict-exitattiva i codici di uscita semantici
Quando è selezionato --format=json o --format=ndjson, stdout trasporta il flusso strutturato e i messaggi leggibili dalle persone vengono indirizzati su stderr, così i due canali non si mescolano mai.
--format è anche l’opzione che seleziona il formato di output della licenza (xml, serial, base32, ascii). I due insiemi di valori sono disgiunti, quindi i due significati possono comparire nella stessa riga di comando: lic MyApp.dll --format base32 --format json.
Opzioni
—format <format>
Seleziona il formato di output usato su stdout. Valori ammessi:
| Valore | Descrizione |
|---|---|
text | Predefinito. L’output di console tradizionale, leggibile dalle persone. |
json | Un unico documento JSON, accumulato in un buffer e scritto al termine dell’esecuzione (o con --help / --version). È la scelta migliore quando stdout viene salvato in un file o inviato tramite pipe a un consumer JSON. |
ndjson | JSON delimitato da caratteri di nuova riga. Un evento per riga, scritto non appena viene prodotto. È la scelta migliore per i consumer in streaming, i sistemi di raccolta dei log e gli agenti in esecuzione. |
lic MyApp.dll --keyfile keys.pem --sign --expiredate 365 --format json > result.json
lic MyApp.dll --keyfile keys.pem --sign --format ndjson | jq -c 'select(.level=="error")'Con json o ndjson il banner del logo viene soppresso a prescindere da --logo, in modo che il primo byte su stdout sia JSON valido.
—quiet (-q)
Sopprime il banner del copyright e ogni richiesta interattiva. L’unica richiesta interattiva di lic è la password di un file di chiavi PFX: con --quiet, se manca --keypwd il comando termina con un errore esplicito invece di restare in attesa di input, e questo rende l’opzione sicura per le esecuzioni non presidiate sui runner di CI, nei container e da parte di agenti.
lic MyApp.dll --quiet --keyfile signing.pfx --keypwd "$KEY_PWD" --sign--quiet è indipendente da --format: puoi combinarlo con l’output text per mantenere log leggibili dalle persone senza il banner.
—strict-exit
Attiva per il processo i codici di uscita semantici. Senza questa opzione, lic mantiene il contratto tradizionale, in cui 0 indica il successo e 1 qualsiasi errore.
| Codice di uscita | Costante | Significato |
|---|---|---|
0 | success | Il comando è terminato senza errori. |
10 | invalidArguments | Non è stato possibile interpretare la riga di comando, oppure conteneva un valore non valido (per esempio un’opzione sconosciuta). |
20 | inputNotFound | L’assembly, il file di licenza o un altro file di input obbligatorio non è stato trovato. |
30 | processingFailure | L’elaborazione della licenza non è riuscita: generazione, aggiornamento, oppure una firma che non ha superato la verifica. |
40 | licensingFailure | La licenza di Babel Licensing dello strumento stesso è mancante, non valida o scaduta. |
50 | keyOrSigningFailure | Non è stato possibile caricare un file di chiavi o un contenitore di chiavi, oppure un’operazione crittografica non è riuscita. |
I numeri sono gli stessi della tabella --strict-exit dell’offuscatore, quindi un solo chiamante può pilotare babel e lic con un’unica tabella dei codici di uscita; l’unica differenza è che il codice 30 indica qui l’elaborazione della licenza e lì l’offuscamento. La classificazione è riportata anche come exitReason nel risultato JSON, anche quando --strict-exit non è attivo.
lic MyApp.licenses --verify --keyfile keys.pem --strict-exit --quiet
echo "exit=$?"Schema: lic.cli.v1
Tutti i payload strutturati contengono "schema": "lic.cli.v1" e un kind che indica di che documento si tratta: event, result, help o version. Lo schema ricalca babel.cli.v1 dell’offuscatore ma ha una versione separata, perché i due strumenti espongono insiemi di opzioni diversi. All’interno di una versione principale dello schema sono ammesse le modifiche additive; le modifiche incompatibili comportano un nuovo nome dello schema.
Record di evento
Ogni messaggio emesso mentre un’esecuzione è in corso viene associato a un evento:
{
"schema": "lic.cli.v1",
"kind": "event",
"ts": "2026-09-03T06:31:54.1686900Z",
"level": "info",
"message": "License saved to 'MyApp.licenses'"
}| Campo | Tipo | Note |
|---|---|---|
ts | string (ISO 8601, UTC) | Data e ora in cui l’evento è stato prodotto. |
level | debug | info | warning | error | Gravità . |
code | string | Codice di diagnostica, presente solo quando il messaggio ne ha uno. |
message | string | Messaggio leggibile dalle persone. |
data | object | Payload strutturato facoltativo, presente solo quando è associato all’evento. |
Envelope del risultato
—format=json
Al termine dell’esecuzione viene scritto su stdout un unico oggetto JSON. Contiene il riepilogo dell’esecuzione e tutti gli eventi accumulati nel buffer durante l’esecuzione:
{
"schema": "lic.cli.v1",
"kind": "result",
"exitCode": 0,
"exitReason": "success",
"elapsedMs": 133,
"warnings": 0,
"errors": 0,
"events": [
{ "schema": "lic.cli.v1", "kind": "event", "ts": "2026-09-03T06:31:54.1686900Z", "level": "info", "message": "License saved to 'MyApp.licenses'" }
]
}Un’esecuzione non riuscita riporta la classe dell’errore in exitReason e l’errore tra gli eventi. Qui l’assembly di input non esisteva:
{
"schema": "lic.cli.v1",
"kind": "result",
"exitCode": 20,
"exitReason": "inputNotFound",
"elapsedMs": 34,
"warnings": 0,
"errors": 1,
"events": [
{ "schema": "lic.cli.v1", "kind": "event", "ts": "2026-09-03T06:30:27.4366510Z", "level": "error", "message": "Error: The specified file '/build/missing.dll' was not found." }
]
}—format=ndjson
Ogni evento viene scritto non appena è prodotto, su una riga a sé. Dopo l’ultimo evento viene aggiunta una riga finale con il risultato, senza l’array events, perché gli eventi sono già stati trasmessi:
{"schema":"lic.cli.v1","kind":"event","ts":"2026-09-03T06:31:54.3357790Z","level":"info","message":"License saved to 'MyApp.licenses'"}
{"schema":"lic.cli.v1","kind":"result","exitCode":0,"exitReason":"success","elapsedMs":141,"warnings":0,"errors":0}| Campo | Tipo | Note |
|---|---|---|
exitCode | integer | Codice di uscita numerico effettivamente restituito dal processo (tradizionale o semantico, a seconda di --strict-exit). |
exitReason | string | Token di classificazione stabile. Riflette sempre la classe semantica, anche senza --strict-exit. |
elapsedMs | integer | Durata totale in tempo reale, in millisecondi. |
warnings | integer | Numero di eventi di livello warning. |
errors | integer | Numero di eventi di livello error. |
events | array | Presente in modalità json; omesso in ndjson. |
—help leggibile dalle macchine
lic --help --format=json emette una descrizione completa di ogni opzione pubblica, adatta agli strumenti che devono esaminare l’interfaccia della CLI: completamento automatico della shell, agenti AI, generatori di documentazione.
{
"schema": "lic.cli.v1",
"kind": "help",
"version": "12.0.0.0",
"usage": "lic.exe <assembly|licensefile> [<other assemblies>...] [options]",
"options": [
{
"name": "trial",
"aliases": [],
"description": "Add or update trial license restriction",
"args": "<key=value>",
"argRequired": true,
"argOptional": false,
"negatable": false,
"incremental": false,
"container": "hash",
"type": "string",
"group": "- License Restrictions -",
"details": "Set trial restriction properties entering key-value pairs:\n\nid=<id> Restriction id\nexpire=<date> Set expiration date\ndays=<n> Set number of trial days\n..."
}
]
}| Campo | Significato |
|---|---|
name, aliases | Il nome dell’opzione e le sue grafie alternative, comprese le forme negate e gli alias di una sola lettera. |
args | Il segnaposto dell’argomento come compare nella sintassi d’uso, oppure vuoto per un’opzione senza argomento. |
argRequired, argOptional | Indica se l’opzione accetta un argomento obbligatorio o facoltativo. |
negatable | Indica se l’opzione accetta il prefisso no. |
container | scalar per un valore singolo, array per un’opzione ripetibile, hash per le coppie key=value. |
type | string o integer. |
group | La sezione dell’output della guida a cui appartiene l’opzione. |
details | La descrizione estesa, lo stesso testo stampato da lic --help <option>. |
È supportata anche una forma limitata a una sola opzione: lic --help trial --format=json emette lo stesso envelope, che contiene solo l’opzione trial. Le opzioni nascoste e interne non vengono mai restituite.
—version leggibile dalle macchine
lic --version --format=json emette le informazioni su prodotto, versione, runtime e piattaforma:
{
"schema": "lic.cli.v1",
"kind": "version",
"product": "Babel Licensing",
"version": "12.0.0.0",
"fileVersion": "12.0.0.1",
"runtime": ".NET 10.0.0",
"platform": "osx-arm64"
}Il campo platform usa l’identificatore di runtime (RID) di .NET su .NET 5 e versioni successive, e una stringa sintetica <os>-<arch> sui target precedenti.
Pilotare lic da un agente
Un agente che non ha mai visto lic può usarlo partendo dalla sola guida in JSON: legge lo schema delle opzioni, costruisce la riga di comando in base alle indicazioni di args e container, la esegue con --format json --quiet --strict-exit e decide come proseguire in base a exitReason. Un ciclo tipico per emettere una licenza ha questo aspetto:
lic --help --format json > lic-options.json
lic MyApp.dll --keyfile keys.pem --sign --licensee name="Contoso" --expiredate 365 --output MyApp.licenses --format json --quiet --strict-exit > result.json
jq -r '.exitReason' result.jsonLo stesso contratto, gli stessi codici di uscita e gli stessi nomi delle opzioni valgono per la riga di comando dell’offuscatore, documentata in Modalità CLI compatibile con l’AI nel manuale dell’offuscatore, quindi una sola integrazione copre entrambi gli strumenti.
Compatibilità con le versioni precedenti
- Il valore predefinito di
--formatètext; l’output testuale tradizionale, i codici di uscita e il comportamento non cambiano se non specifichi nessuna delle nuove opzioni. - Senza
--strict-exit, il processo continua a restituire0in caso di successo e1per qualsiasi errore, quindi i controlli esistenti che decidono in base a$?continuano a funzionare. --quietè indipendente e può essere attivato senza abilitare l’output strutturato.