Skip to content

Artisan commands

Generated from Command classes in api/app and api/packages

Run them inside the API container: docker compose -f api/docker-compose.yml exec api php artisan <command>. In a multi-tenant install add --domain=<tenant host> to run a command for one tenant (Tenancy). Laravel’s and third-party packages’ own commands (migrate, queue:work, passport:*, horizon, …) are not listed; php artisan list shows everything.

Package: ai

Command Description Signature
ai:usage AI calls, tokens and cost per day and task for this tenant ai:usage {--days=30 : How many days back}

Package: auth

Command Description Signature
ulams:admin Create a new admin account ulams:admin
ulams:auth:prune-agent-audit Delete agent audit log rows older than the retention period ulams:auth:prune-agent-audit {--days= : Keep this many days (default: ulams_auth.agent_audit_days)}
ulams:auth:prune-device-authorizations Revoke device-login tokens nobody collected and delete device requests expired for over a day ulams:auth:prune-device-authorizations
ulams:tokens:export-scopes Write the token scope vocabulary and route map as JSON for the CLI generator ulams:tokens:export-scopes {--check : Fail when the committed JSON is out of date}

Package: cart

Command Description Signature
cart:abandoned-event Find all abandoned cart in 24-48h and run event cart:abandoned-event

Package: categories

Command Description Signature
category-permissions:seed Seed the database with the permissions required to support the categories category-permissions:seed

Package: cmi5

Command Description Signature
cmi5:move-to-bucket Copy cmi5 packages from another disk to the configured cmi5 disk (idempotent) cmi5:move-to-bucket {--from=local : Disk the packages were uploaded to}

Package: consultations

Command Description Signature
meetings:purge-frames Delete stored consultation and webinar webcam frames (never the images folders) meetings:purge-frames {--dry-run : Only list what would be deleted}

Package: core

Command Description Signature
csp-reports:prune Delete aggregated CSP violation reports that were not seen for a while csp-reports:prune {--days= : Keep reports seen within this many days (default: ulams.core.csp.retention_days)}

Package: course-builder

Command Description Signature
course-builder:eval Evaluate the Course Builder on golden fixtures (fake driver by default, –live for the real model) course-builder:eval {--fixtures=coffee : all, or a comma list of coffee, injection, git, pdf, docx} {--live : call the real model} {--record : write cassettes (tests/cassettes) from this run} {--author= : user id that owns the eval sessions (default: the first admin)} {--patch=1 : also run one element-chat patch on a quiz question} {--total-minutes=30 : course length for the brief}
course-builder:prune-events Delete Course Builder AG-UI events older than the retention period course-builder:prune-events
course-builder:session:export Write a builder session (brief, current and applied versions, sources and fragments) to a tar archive course-builder:session:export {session : Session id} {path : Archive to write (.tar)}
course-builder:session:import Create a builder session from an archive for an author of this tenant. The last output line is JSON with the new session id. course-builder:session:import {path : Archive written by course-builder:session:export} {--author-email= : The author of the new session; created as an admin with an invitation when missing} {--author-name= : Display name for a new author}

Package: demo

Command Description Signature
ulams:demo:reset Wipe and reseed this demo tenant (database, demo users, demo courses, cache, tokens). Requires DEMO_MODE=true. ulams:demo:reset {--force : Do not ask for confirmation} {--wipe-files : Also delete every file on the tenant\'s default disk (bucket)} {--recapture : Take a new baseline (name, theme, accent, students) from the current database}
ulams:demo:seed Seed the demo courses of this tenant and give the demo student access to every published course ulams:demo:seed {--experience= : Demo experience to seed (coffee, oncall, nightsky, gravity, poland, ulam or all); defaults to ULAMS_DEMO_EXPERIENCE, then the tenant slug} {--skip-content : Only grant the demo student access to the published courses}

Package: images

Command Description Signature
images:cache-clear Clear images cache. images:cache-clear

Package: living-course

Command Description Signature
living-course:backfill Record revision 1 for sources built before Living Course existed (idempotent) living-course:backfill {--session= : Only this builder session id}
living-course:eval Evaluate Living Course update proposals on golden v1/v2 fixtures (fake driver by default, –live for the real model) living-course:eval {--fixtures=all : all, or a comma list of coffee, git, injection} {--live : call the real model for the update analysis} {--record : write cassettes (tests/cassettes) from this run} {--author= : user id that owns the eval sessions (default: the first admin)} {--max-usd=1 : total spend cap of a live run}
living-course:poll Check the connected sources that are due and prune old webhook deliveries living-course:poll

Package: lti

Command Description Signature
ulams:lti:rotate-keys Rotate the tenant LTI signing keys: next becomes active, a new next key is generated, old retired keys are removed ulams:lti:rotate-keys {--init : only create the key set when missing (tenant provisioning)}

Package: scorm

Command Description Signature
scorm:copy-serviceworker Copy serviceworker.js to s3 bucket scorm:copy-serviceworker
ulams:scorm:publish-player Write the content-origin SCORM player (player.html, player.js, scorm-again) to scorm/_player on the SCORM disk ulams:scorm:publish-player

Package: templates-pdf

Command Description Signature
templates-pdf:migrate-reportbro Convert stored ReportBro PDF templates and issued PDFs to pdfme (originals are backed up to storage/app/reportbro-legacy) templates-pdf:migrate-reportbro {--dry-run : List what would change without writing} {--reset : Replace ReportBro templates with the default pdfme template of their event instead of converting them}

Package: tenancy

Command Description Signature
ulams:db:recreate-views Recreate the searchable_events SQL view with the current model class names ulams:db:recreate-views
ulams:h5p:export-config Write the least-privilege env files and Passport public keys the H5P service mounts in production (H5P_SERVICE_CONFIG_DIR) ulams:h5p:export-config
ulams:tenant:create Provision a tenant (database, bucket, env file, migrations, keys, demo users). Safe to re-run: finished steps are skipped. ulams:tenant:create {slug : Lowercase letters and digits, used for hosts, database and bucket names} {--name= : Display name (APP_NAME and the global.companyName setting)} {--theme= : Front theme preset key, coffee, oncall, nightsky, gravity, poland or ulam} {--accent= : Accent colour, e.g. #C2552D} {--users=5 : Number of demo students} {--demo= : Demo mode (DEMO_MODE: login without password, hourly reset): on or off} {--db-password= : Password of a database you created yourself (TENANCY_DATABASE_PROVISIONER=manual), at least 16 characters} {--redo=* : Step to run again even if recorded as done: database, bucket, env, migrate, passport_keys, passport_client, permissions or demo}
ulams:tenant:delete Delete a tenant and all its data ulams:tenant:delete {slug} {--force : Required. Drops the database, role, bucket objects, env file and storage}
ulams:tenant:list List provisioned tenants ulams:tenant:list {--hosts : Print only the API hosts of active tenants, one per line}
ulams:tenant:schedule-loop Run the scheduler of this domain every minute in one long-lived process ulams:tenant:schedule-loop {--max-time=3600 : Exit after this many seconds (the supervisor starts it again with fresh code and config)} {--once : Run one scheduler tick now and exit} {--lock : With --once, claim the minute with the shared lock first (workers.sh lean mode: one process ticks every domain each minute)}
ulams:tenant:seed-demo Create demo users and public settings for the current tenant (internal step of ulams:tenant:create) ulams:tenant:seed-demo {--users=5 : Number of students} {--name= : Display name, stored as global.companyName} {--theme= : Front theme preset key, stored as theme.theme} {--accent= : Accent colour, stored as theme.accent} {--front-url= : Stored as global.frontURL} {--email-domain= : Domain of the demo e-mail addresses}
ulams:tenant:set-env Override or reset inheritable platform settings (AI key, driver, models) for one tenant ulams:tenant:set-env {slug} {--set=* : KEY=value override for this tenant (inheritable settings only, e.g. AI_DRIVER=fake)} {--unset=* : KEY to drop, so the tenant inherits the platform value again}
ulams:tenant:sync-env Rebuild .env. files, domain registrations and Passport keys of all tenants from the tenants table ulams:tenant:sync-env {--migrate : Also run pending migrations for every tenant}
ulams:tenant:work-once Run the scheduler tick and drain a queue once, then exit (for cron instead of long-lived workers) ulams:tenant:work-once {--queue=default,broadcast,video : Comma-separated queues to drain, highest priority first} {--connection= : Queue connection (default: the default connection; builder and long jobs use <driver>-builder and <driver>-long-job)} {--timeout=60 : Seconds a single job may run (builder jobs run up to 1800, long jobs up to 18000)} {--max-time=50 : Stop taking new jobs after this many seconds} {--memory=256 : Memory limit of the worker in MB} {--schedule : Run one scheduler tick before the queue (only on the line that runs every minute)}
ulams:upgrade Bring the platform and every tenant to the current release: migrations, permissions, keys and one-off data steps ulams:upgrade {--tenant=* : Only these tenant slugs (the platform is then left out)} {--platform-only : Only the platform} {--force-step=* : Run this one-off step again even if it already ran} {--dry-run : List what would run; change and record nothing}

Package: topic-type-gift

Command Description Signature
gift:snapshot-max-scores Freeze the maximum score of past quiz attempts (ADR 0033) gift:snapshot-max-scores

Package: topic-types

Command Description Signature
ulams:fill-topic-types-metadata Fill the metadata for the specific model ulams:fill-topic-types-metadata {model}
ulams:fix-topic-types-paths Fixes all topic types paths so they are always in courses/{id} folder ulams:fix-topic-types-paths
ulams:fix-type-column-name Fixes Topicable DBs column name from old Ulams\Courses\Models\TopicContent\XXX to Ulams\TopicTypes\Models\TopicContent\XXX ulams:fix-type-column-name

Package: translations

Command Description Signature
translations:merge-permissions Create files with translations of permissions from other packages translations:merge-permissions