Skip to content

Loom73 Shuttle

Shuttle is the Loom73 command-line tool.

It installs, inspects and maintains a Loom73 instance through small, explicit commands.

Small tools.
Clear conventions.
No unnecessary machinery.

Running Shuttle

Run commands from the application root:

cd /var/www/example.com
php shuttle <command>

On a deployed instance, use the deployment user. Avoid using root or the web-server user for ordinary administration.

sudo -iu deploy
cd /var/www/example.com
php shuttle loom73.info

Shuttle loads:

Composer dependencies
config/system.php
config/labels.php
config/.env
config/modules/*.php
application/config/modules/*.php

before resolving the requested command.

Available commands

The current command set is:

loom73.info
loom73.install
loom73.update
user.admin
asset_type.new
ledger.cleanup
session.cleaner
gauge.info
gauge.enable
gauge.disable

loom73.info

Inspect the current instance:

php shuttle loom73.info

The command reports:

Loom73 version
SYSTEM_STATUS environment
PHP version

environment-file health
module configuration
database connection
storage directory availability and permissions

required PHP extensions
installed runtime dependency versions

Ledger configuration
Gauge configuration

The database check uses:

Connection::ping()

which prepares and executes:

SELECT 1

The final status is one of:

HEALTHY
HEALTHY WITH WARNINGS
UNHEALTHY

An unhealthy result exits with status code 1. A healthy result, including one with warnings, exits with status code 0.

Warnings include incomplete environment values. Errors include a missing .env, failed database connection, missing or unwritable runtime directories, missing required extensions, or missing runtime packages.

Gauge is reported as enabled or disabled according to its current instance and environment configuration.

Gauge commands

Inspect, enable or disable Gauge for the current instance:

php shuttle gauge.info
php shuttle gauge.enable
php shuttle gauge.disable

Gauge is disabled by default. gauge.enable creates storage/.loom73-gauge-enabled in development. In production (SYSTEM_STATUS=production), explicit activation requires:

php shuttle gauge.enable --production

gauge.info reports the environment, marker state and whether Gauge is active. gauge.disable removes the marker. Activation alone does not display the bar: the authenticated user needs the view_gauge ability and must opt in through the browser.

loom73.install

Install the database structure and runtime directories:

php shuttle loom73.install

This is a destructive clean-install command. It asks for confirmation and may drop and recreate Loom73 core tables.

Application-specific tables are left untouched.

It currently initializes:

authentication tables
roles and seed data
asset types
assets
Ledger events
core updates registry
storage/
storage/uploads/
storage/logs/
storage/cache/

Use it for a new instance or a deliberately disposable development database.

Do not use it as an update mechanism for an existing production database.

loom73.install
    create a new instance

loom73.update
    evolve an existing instance

After installation, run:

php shuttle user.admin

loom73.update

Inspect and apply Loom73 core database updates:

php shuttle loom73.update --plan
php shuttle loom73.update

--plan reports the registered baseline, applied scripts and pending scripts without changing the database. Run it before applying an update.

On an existing 6.2.0 database without core_updates, the command first checks the expected core schema. If it finds missing structures or additional columns in core tables, it stops for manual review. Otherwise, a normal run creates the registry, records the 6.2.0 baseline and applies pending core scripts in order.

A fresh loom73.install already records the version from package.json as its baseline. Version 6.3.0 ships without additional schema scripts.

Each script is recorded only after successful execution. If one fails, execution stops; inspect the database before retrying because a database schema change may have taken effect even though the script was not recorded. Back up the database and test the update on a non-production instance first.

loom73.update does not merge changes into application code, update application-specific tables or deploy files.

user.admin

Create an administrator interactively:

php shuttle user.admin

Shuttle asks for:

username
email
password

It creates the user with the administrator role and initializes a session record.

The command requires a working database and should normally be run after loom73.install.

asset_type.new

Create a Yarn asset type:

php shuttle asset_type.new

Shuttle asks for:

slug
label
description

Asset types provide semantic classifications such as:

image_avatar
project_report
informed_consent

They are distinct from owner slots. An owner slot describes where an asset belongs; an asset type describes what the file represents.

ledger.cleanup

Apply the configured Ledger retention policy:

php shuttle ledger.cleanup

The retention period is read from:

Config::get('ledger.retention');

Interactive execution displays the configured period and asks for confirmation.

For scheduled or otherwise non-interactive execution, pass:

php shuttle ledger.cleanup --force

To request permanent removal of all Ledger records:

php shuttle ledger.cleanup --purge

For non-interactive purging:

php shuttle ledger.cleanup --purge --force

A retention value of 0 means that automatic retention cleanup is disabled.

The application administrator must configure any cron schedule separately. Shuttle does not install cron entries.

session.cleaner

Run the current PHP-session diagnostic cleaner:

php shuttle session.cleaner

The current command opens the CLI session, invokes PHP session garbage collection, destroys that session and prints diagnostic session data.

It does not purge Loom73 authentication-session rows from the database and should not be documented or scheduled as a complete application-session cleanup mechanism.

Treat it as a development or diagnostic command until a production session-cleanup contract is defined.

Command resolution

Command files live in:

commands/

The filename is the command name:

commands/database.update.php
    → php shuttle database.update

Dots separate words when Shuttle resolves the class:

database.update
    → Loom73\Shuttle\DatabaseUpdate

The file must contain the resolved class:

<?php

namespace Loom73\Shuttle;

class DatabaseUpdate
{
    public function __construct(?array $args = null)
    {
        $this->run($args ?? []);
    }

    private function run(array $args): void
    {
        // Command logic.
    }
}

Shuttle passes command-line arguments after the command name as an array to the constructor.

Existing commands that do not need arguments may ignore it.

A command does not need to extend a common base class.

CLI helper

The reusable helper is:

Loom73\Shuttle\CLI

It currently provides:

cout_color()
confirm()
ask()

Colored output

$CLI = new CLI();

echo $CLI->cout_color(
    'Operation completed.',
    'green'
) . PHP_EOL;

Supported named colors include:

red
green
yellow
blue
magenta
cyan
light grey
dark grey
light red
light green
light yellow
light blue
light magenta
light cyan

Questions

Read a free-form answer:

$name = $CLI->ask('Enter the name: ');

Request confirmation:

if (!$CLI->confirm('Continue?')):
    echo 'Cancelled.' . PHP_EOL;
    return;
endif;

confirm() accepts y, yes, n and no, repeating the question for any other input.

Command design

A Shuttle command should:

perform one recognizable operation
make destructive behavior explicit
confirm destructive interactive operations
require explicit flags for destructive automation
return a non-zero exit code on failure
avoid browser or web-session assumptions
avoid exposing passwords and secrets

Small commands may keep their flow in the constructor. Larger commands should delegate to private methods.

Shuttle is intentionally small. Shared abstractions should be introduced only after more than one real command needs them.

Deployment relationship

Deployment and installation are separate operations:

GitHub Actions
    builds and sends application code

Shuttle
    initializes or maintains runtime state

VPS
    owns configuration, database data, uploads and logs

The core rule is:

Deploy code.
Install runtime state.
Preserve instance data.