CLI client for interacting with LumenRadio serial generation backend service.
Project description
lr-serial
CLI + Python client for interacting with the LumenRadio Serial Number Generation Service.
Install
pip install lr-serial
AI assistant integration
lr-serial ships a bundled skill/instruction file that teaches AI coding assistants
about the CLI commands, Python API, data models, and common workflows.
Run this once from the root of your project:
serial --install-skill
This does three things:
- Claude Code — copies the skill to
~/.claude/skills/lr-serial/(global, available in all projects) - GitHub Copilot — writes
.github/instructions/lr-serial.instructions.mdin the current directory - VSCode — sets
github.copilot.chat.codeGeneration.useInstructionFiles: truein.vscode/settings.json(creates the file if it doesn't exist; merges if it does)
To inspect the skill content without installing:
serial --show-skill
Python API
lr-serial exposes a SerialClient class for programmatic use — no CLI parsing, no sys.exit().
All errors are raised as typed exceptions from serial.exceptions.
Quick start
from serial import SerialClient
# From stored credentials (after `serial login`)
client = SerialClient.from_config()
# Or from M2M credentials directly
client = SerialClient.from_m2m(
client_id="<CLIENT_ID>",
client_secret="<CLIENT_SECRET>",
token_url="https://login.microsoftonline.com/<TENANT_ID>/oauth2/v2.0/token",
)
# List articles
articles = client.list_articles() # -> list[ArticleListItem]
# Generate serial numbers
serials = client.generate("PROD-01", quantity=5, fields={"site": "Stockholm"}) # -> list[str]
# Look up a serial
info = client.lookup("PROD-STH-000001") # -> SerialInfo
# Full article details
article = client.article_get("PROD-01") # -> Article
Exception handling
from serial.exceptions import AuthenticationError, NotFoundError, SerialError
try:
info = client.lookup("UNKNOWN-000")
except NotFoundError:
print("Serial not found")
except AuthenticationError:
print("Token expired — run `serial login` again")
except SerialError as exc:
print(f"API error: {exc}")
Reference
| Method | Returns | Description |
|---|---|---|
SerialClient.from_config(path?) |
SerialClient |
Load from ~/.config/serial/login.json |
SerialClient.from_m2m(client_id, client_secret, token_url, scope?) |
SerialClient |
OAuth2 client credentials |
client.list_articles() |
list[ArticleListItem] |
All articles |
client.article_get(article_no) |
Article |
Full article details |
client.article_create(article_no, description, prefix, schema, disabled?) |
dict |
Create article |
client.article_update(article_no, *, description?, prefix?, disabled?, schema?) |
dict |
Partial update |
client.article_delete(article_no) |
None |
Delete article |
client.article_set_sequence(article_no, sequence_no) |
dict |
Set serial counter |
client.generate(article_no, quantity?, fields?) |
list[str] |
Generate serials |
client.lookup(serial_no) |
SerialInfo |
Serial metadata |
client.site_list() |
list[Site] |
All sites |
client.site_create(site_no, name) |
dict |
Create site |
client.site_update(site_no, name, *, client_id?, contact_email?, disabled?) |
dict |
Update site |
client.site_delete(site_no) |
None |
Delete site |
client.audit_list(limit?) |
list[AuditEntry] |
Audit log (admin scope) |
client.audit_restore(audit_id) |
dict |
Undo audited change (admin scope) |
Models
| Model | Key fields |
|---|---|
ArticleListItem |
article, description |
Article |
article, description, prefix, disabled, schema_ |
ArticleSchema |
version, format, regexp, fields |
SerialInfo |
serial_no, article, created_by, created_at |
Site |
site_no, name, client_id, contact_email, disabled |
AuditEntry |
id, touched_table, touched_key, change_type, changed_by, changed_at |
CLI Usage
Login Command
The login command supports two authentication modes:
User login (default)
Opens the system browser for interactive sign-in via OAuth 2.0 Authorization Code + PKCE. No client secret required — suitable for human operators.
LumenRadio employees can log in with no arguments (client ID and tenant ID are baked in):
serial login
If the browser does not open automatically the auth URL is printed to the terminal so you can paste it manually.
Machine-to-machine (M2M) login
Uses the OAuth 2.0 client credentials grant — suitable for automated pipelines.
serial login --mode m2m \
--client-id <CLIENT_ID> \
--client-secret <CLIENT_SECRET> \
--tenant-id <TENANT_ID>
Common options
--mode [user|m2m]— authentication mode (default:user) [env: SERIAL_AUTH_MODE]--client-id— Azure AD application client ID [env: SERIAL_CLIENT_ID]--client-secret— client secret, required form2m[env: SERIAL_CLIENT_SECRET]--tenant-id— Azure AD tenant ID [env: SERIAL_TENANT_ID]--token-url— token endpoint URL override (m2m only) [env: SERIAL_TOKEN_URL]--scope— OAuth2 scope override [env: SERIAL_SCOPE]--config-path— override the login.json location
Stores the bearer token (and refresh token for user logins) in your config directory for subsequent CLI commands.
Status Command
Check backend reachability and token validity:
serial status
Reports:
- Backend reachable ✓ / unreachable ✗
- Token valid ✓ / invalid ✗
Global Options
Most commands support:
--output [rich|json]— output format (rich table default, json for scripting)--config-path PATH— override the login.json location
Article Commands
List Articles
serial list-articles
serial list-articles --output json
Get Article
serial article get ARTICLE_NO
serial article get 710-4130 --output json
Returns full article details: article number, description, prefix, schema (version, fields, format, regexp), disabled flag.
Create Article
serial article create \
--article PROD-01 \
--description "Production line 1" \
--prefix PROD \
--schema-file schema.json
The --schema-file must be a JSON file with the ArticleSchema object:
{
"version": 1,
"fields": { "site": "string" },
"format": "{prefix}-{site}-{counter:06d}",
"regexp": "^[A-Z0-9]+-[A-Z0-9]+-[0-9]{6}$"
}
Options:
--article TEXT— article number (1-32 chars, [A-Za-z0-9-]) [required]--description TEXT— human-readable description (1-100 chars) [required]--prefix TEXT— serial prefix (1-10 chars, [A-Za-z0-9]) [required]--schema-file PATH— path to JSON file containing the ArticleSchema [required]--disabled / --no-disabled— create as disabled (default: enabled)
Update Article
serial article update ARTICLE_NO --description "New description"
serial article update ARTICLE_NO --prefix NEWP --disabled
At least one option must be provided. Options: --description, --prefix, --disabled/--no-disabled, --schema-file.
Delete Article
serial article delete ARTICLE_NO
Idempotent — succeeds even if the article does not exist.
Set Sequence Counter
serial article set-sequence ARTICLE_NO SEQUENCE_NO
serial article set-sequence 710-4130 1000
Sets the current counter value (integer ≥ 0) for the article.
Serial Number Commands
Generate Serial Numbers
serial generate ARTICLE_NO
serial generate ARTICLE_NO --quantity 5
serial generate ARTICLE_NO --field site=Stockholm --field year=2024
serial generate ARTICLE_NO --quantity 3 --output json
Options:
--quantity INT— number of serials to generate (1-1000, default 1)--field KEY=VALUE— extra field value consumed by the article schema (repeatable)
Lookup a Serial Number
serial lookup SERIAL_NO
serial lookup QWDNA010000001 --output json
Returns: serial value, article, created_by, created_at.
Site Commands
List Sites
serial site list
serial site list --output json
Create Site
serial site create --site-no 5 --name "Helsinki"
Options:
--site-no INT— site number (1-99) [required]--name TEXT— site name [required]
Update Site
serial site update 5 --name "Helsinki" --contact-email ops@example.com
serial site update 5 --name "Helsinki" --disabled
Note: --name is required by the API even when only updating other fields.
Options:
--name TEXT— new site name [required]--client-id TEXT— associated client ID (or empty to clear)--contact-email TEXT— contact email address (or empty to clear)--disabled / --no-disabled— enable or disable the site
Delete Site
serial site delete 5
Idempotent — succeeds even if the site does not exist.
Audit Commands
These commands require the app.admin.api scope.
List Audit Entries
serial audit list
serial audit list --limit 50 --output json
Returns audit entries newest-first: id, touched_table, touched_key, change_type (create/update/delete), changed_by, changed_at.
Options:
--limit INT— max entries to return (1-500, default 100)
Restore an Audit Entry
serial audit restore AUDIT_ID
Undoes the audited change:
create→ deletes the created rowupdate→ restores previous valuesdelete→ re-inserts the deleted row
If the token lacks the admin scope, the API returns 403 and the CLI will display:
Access denied. Ensure your credentials include the admin scope (app.admin.api).
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file lr_serial-0.6.0.tar.gz.
File metadata
- Download URL: lr_serial-0.6.0.tar.gz
- Upload date:
- Size: 40.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f967afd5db6add56cd2dcbe98cd64ae2ff24e797aa98a8b36a5bab95289bcb9c
|
|
| MD5 |
f4f835e91f49dd12a00b431f1b2f2ed5
|
|
| BLAKE2b-256 |
fd63ca69e74483840e31f1103b0e440bca69bbd5753e7e0db888e4b49a7ec3ee
|
File details
Details for the file lr_serial-0.6.0-py3-none-any.whl.
File metadata
- Download URL: lr_serial-0.6.0-py3-none-any.whl
- Upload date:
- Size: 32.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
73ce0ab5dcf640dbe06776693e2e34694d47fe6972fa1eee31ba182b46a1c5e3
|
|
| MD5 |
9ea39614a7a1015d917e0798e9ac3a50
|
|
| BLAKE2b-256 |
a56f8b66a256d0fcea0860f90f99c28f0d3f89a0a1ef789b0c1d242730777885
|