import { Command } from "commander"; import { doctorCommand } from "./commands/doctor"; import { initCommand } from "./commands/init"; import { runCommand } from "./commands/run"; import { scriptsListCommand, scriptsShowCommand } from "./commands/scripts"; import { serviceInstallCommand, serviceStatusCommand, serviceUninstallCommand, } from "./commands/service"; import { startCommand } from "./commands/start"; import { usersAddCommand, usersAddTokenCommand } from "./commands/users"; import { validateCommand } from "./commands/validate"; import { getVersion } from "./version"; function collect(value: string, previous: string[]): string[] { return [...previous, value]; } const program = new Command("triggershell") .version(getVersion()) .description( "Launch the TriggerShell web app: run your configured shell scripts from a browser.", ); program .command("init [path]") .description("Scaffold a new triggershell.yml (and .env, if auth is enabled)") .option( "--port ", "Port the web app will listen on.", (v) => Number(v), 4173, ) .option("--no-auth", "Disable built-in login for the web app.") .option("--force", "Overwrite an existing config file.", false) .action(initCommand); program .command("validate") .description("Validate a config file against the full schema.") .option("-c, --config ", "Path to the config file.") .action(validateCommand); program .command("start") .description("Run the web app in production mode.") .option("-c, --config ", "Path to the config file.") .option("--port ", "Override the port from the config file.", (v) => Number(v), ) .option("--host ", "Override the host from the config file.") .option("--no-browser", "Don't open a browser automatically.") .action(startCommand); program .command("doctor") .description("Print diagnostic info about your environment and config.") .option("-c, --config ", "Path to the config file.") .action(doctorCommand); const scripts = program .command("scripts") .description("List and inspect configured scripts."); scripts .command("list") .description("List configured scripts.") .option("-c, --config ", "Path to the config file.") .action(scriptsListCommand); scripts .command("show ") .description("Show a script's command and variables.") .option("-c, --config ", "Path to the config file.") .action(scriptsShowCommand); program .command("run ") .description("Run a configured script.") .option("-c, --config ", "Path to the config file.") .option( "--var ", "Set a variable, e.g. --var environment=staging (repeatable; repeat the same name for a multiselect variable).", collect, [], ) .option("--host ", "Override the host from the config file.") .option("--port ", "Override the port from the config file.", (v) => Number(v), ) .option( "--token ", "API token for an already-running server (or set TRIGGERSHELL_API_TOKEN).", ) .option( "--local", "Always run in this process, even if the web server is reachable.", false, ) .option( "--remote", "Require a reachable web server; don't fall back to running locally.", false, ) .option( "--no-wait", "Print the run ID and exit immediately instead of streaming output.", ) .action(runCommand); const users = program .command("users") .description("Manage auth users and API tokens defined in your config file."); users .command("add ") .description("Hash a password with argon2id and wire it up for auth.users.") .option( "-c, --config ", "Path to the config file (used to locate .env).", ) .option( "--inline", "Print the raw hash to paste into the config instead of storing it in .env.", false, ) .action(usersAddCommand); users .command("add-token ") .description("Generate an API token and wire its hash up for auth.tokens.") .option( "-c, --config ", "Path to the config file (used to locate .env).", ) .option( "--inline", "Print the raw hash to paste into the config instead of storing it in .env.", false, ) .action(usersAddTokenCommand); const service = program .command("service") .description("Manage the systemd service (Linux only)."); service .command("install") .description("Install a systemd unit that runs `triggershell start`.") .option("-c, --config ", "Path to the config file.") .option("--port ", "Override the port from the config file.", (v) => Number(v), ) .option("--host ", "Override the host from the config file.") .option( "--system", "Install a system-wide unit instead of a per-user one.", false, ) .action(serviceInstallCommand); service .command("uninstall") .description("Stop, disable, and remove the systemd unit.") .option( "--system", "Target the system-wide unit instead of the per-user one.", false, ) .action(serviceUninstallCommand); service .command("status") .description("Show the systemd unit's status.") .option( "--system", "Target the system-wide unit instead of the per-user one.", false, ) .action(serviceStatusCommand); if (process.argv.length <= 2) { program.outputHelp(); process.exit(1); } await program.parseAsync(process.argv);