Skip to Content
Nuova versione 12 disponibile 🎉
LicensingRiga di comandoModalità compatibile con l'AI

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|ndjson seleziona 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-exit attiva 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:

ValoreDescrizione
textPredefinito. L’output di console tradizionale, leggibile dalle persone.
jsonUn 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.
ndjsonJSON 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 uscitaCostanteSignificato
0successIl comando è terminato senza errori.
10invalidArgumentsNon è stato possibile interpretare la riga di comando, oppure conteneva un valore non valido (per esempio un’opzione sconosciuta).
20inputNotFoundL’assembly, il file di licenza o un altro file di input obbligatorio non è stato trovato.
30processingFailureL’elaborazione della licenza non è riuscita: generazione, aggiornamento, oppure una firma che non ha superato la verifica.
40licensingFailureLa licenza di Babel Licensing dello strumento stesso è mancante, non valida o scaduta.
50keyOrSigningFailureNon è 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:

event
{ "schema": "lic.cli.v1", "kind": "event", "ts": "2026-09-03T06:31:54.1686900Z", "level": "info", "message": "License saved to 'MyApp.licenses'" }
CampoTipoNote
tsstring (ISO 8601, UTC)Data e ora in cui l’evento è stato prodotto.
leveldebug | info | warning | errorGravità.
codestringCodice di diagnostica, presente solo quando il messaggio ne ha uno.
messagestringMessaggio leggibile dalle persone.
dataobjectPayload 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:

result (json)
{ "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:

result (json, failure)
{ "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:

result (ndjson)
{"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}
CampoTipoNote
exitCodeintegerCodice di uscita numerico effettivamente restituito dal processo (tradizionale o semantico, a seconda di --strict-exit).
exitReasonstringToken di classificazione stabile. Riflette sempre la classe semantica, anche senza --strict-exit.
elapsedMsintegerDurata totale in tempo reale, in millisecondi.
warningsintegerNumero di eventi di livello warning.
errorsintegerNumero di eventi di livello error.
eventsarrayPresente 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.

--help --format=json (excerpt)
{ "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..." } ] }
CampoSignificato
name, aliasesIl nome dell’opzione e le sue grafie alternative, comprese le forme negate e gli alias di una sola lettera.
argsIl segnaposto dell’argomento come compare nella sintassi d’uso, oppure vuoto per un’opzione senza argomento.
argRequired, argOptionalIndica se l’opzione accetta un argomento obbligatorio o facoltativo.
negatableIndica se l’opzione accetta il prefisso no.
containerscalar per un valore singolo, array per un’opzione ripetibile, hash per le coppie key=value.
typestring o integer.
groupLa sezione dell’output della guida a cui appartiene l’opzione.
detailsLa 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:

--version --format=json
{ "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.json

Lo 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 restituire 0 in caso di successo e 1 per 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.
Last updated on