MixLab 0.0.20

Command reference

This handbook covers MixLab through the mix command line. If you would rather work in a graphical interface, you already have one: every installer places the MixLab window beside the command line. Both drive the same MixEngine underneath, so everything in this handbook still applies.

Every command mix accepts, in version 0.0.20. This page is generated from the binary's own definitions, so it cannot describe a flag that is not there. It is the one page of this handbook that exists in English only, because those definitions are. mix docs cli --lang vi says why, in Vietnamese.

The same text is mix <command> --help on the machine in front of you, and mix docs --reference prints this whole page.

Three flags are accepted by every command below and are not repeated in each table: --home <DIR> chooses which installation to talk to, --json asks for the answer as JSON, and --no-autostart refuses to start a daemon that is not running.

mix status

Show the daemon's health, version and what it is currently running

mix status

mix storage

Show where this home keeps the directories that grow, and whether that can still change.

Starts no daemon and needs none. runtimes/, packages/, data/ and logs/ can each be moved to another disk by [paths] in config.toml, or by starting mixengined with --runtimes, --packages, --data or --logs. That choice is free only until the first runtime, package or service is installed. From then on, where each of them lives is recorded against it.

The answer comes from mixengined itself, run once: whether anything is installed is a question about rows in this home's database, and mix does not open one.

mix storage

mix daemon

Control the daemon itself

mix daemon <COMMAND>

mix daemon stop

Stop the services this home is running, then stop the daemon

mix daemon stop

mix daemon credential-store

Choose where this home keeps its passwords from the next start: os, the system's credential store, or home, a file only your account can read

mix daemon credential-store <STORE>
FlagWhat it does
<STORE>os or home

mix docs

Read the MixLab handbook, offline, in English or Vietnamese.

With no topic it lists them. It talks to no daemon and needs no home, because the pages are compiled into this binary. That is why mix docs install answers on a machine where nothing starts. The same pages are published at https://mixnz.github.io/mixlab/, as HTML for a person and as plain Markdown for a program.

mix docs [TOPIC] [OPTIONS]
FlagWhat it does
<TOPIC>Which topic. Omit it to list them
--lang <CODE>Which language: en or vi. An unrecognised one is answered in English
--referencePrint the whole command reference as Markdown, instead of a topic. It is built from this binary's own command definitions, so it cannot describe a flag the binary does not have. It is English only, because those definitions are. It does not conflict with --lang: that flag carries MIXENGINE_LANG, and a variable somebody exported once should not be able to refuse a command.

mix runtime

Install, remove and choose between language runtimes

mix runtime <COMMAND>

mix runtime list

List the runtimes installed in this home

mix runtime list [OPTIONS]
FlagWhat it does
--kind <RUNTIME>Only this language. Every one of them when it is left out

mix runtime available

List the versions the package index offers for this machine

mix runtime available [OPTIONS]
FlagWhat it does
--kind <RUNTIME>Only this language. Every one of them when it is left out
--refreshAsk the package index again even if the cached copy is still fresh. The daemon otherwise answers from a cache for up to six hours, which is the wrong default for someone who just watched a version get published and does not want to wait for their own machine to notice.
--allPrint every release rather than one row per line
--line <LINE>Print every release of this line (8.4, 22)

mix runtime install

Download and install one version

mix runtime install <RUNTIME> <VERSION> [OPTIONS]
FlagWhat it does
<RUNTIME>Which language
<VERSION>Which version, exactly as mix runtime available lists it. Required, and never a range like 8.3: choosing a version from a range answers with what is installed, and an install would be choosing between versions none of which are here yet. mix runtime resolve is where a range belongs.
--no-waitReturn once the daemon has accepted the install, rather than once it has finished. mix waits by default, because mix runtime install php 8.3.33 && … is a sentence about PHP being there. What comes back instead is the job, which mix job wait can be pointed at later.
--yesInstall what this version needs of the machine first, without asking: the Microsoft Visual C++ Redistributable, on Windows. Windows still asks for approval
--ignore-requirementsInstall even though MixEngine judges this machine lacks something the version needs. The version is still run once before it is kept

mix runtime uninstall

Remove one installed version.

Refused while a registered project pins it, naming the projects, and while the php-fpm pool that runs out of it is running. --force crosses the first and never the second.

mix runtime uninstall <RUNTIME> <VERSION> [OPTIONS]
FlagWhat it does
<RUNTIME>Which language
<VERSION>Which version, exactly as mix runtime available lists it. Required, and never a range like 8.3: choosing a version from a range answers with what is installed, and an install would be choosing between versions none of which are here yet. mix runtime resolve is where a range belongs.
--forceRemove it even though a registered project pins it

mix runtime upgrade

Update one installed version to the newest release of its line, and move what uses it.

Sites, the default and pins move to the new version; the old one is removed afterwards unless --keep is given or something still needs it. The plan is printed first.

mix runtime upgrade <RUNTIME> <VERSION> [OPTIONS]
FlagWhat it does
<RUNTIME>Which language
<VERSION>Which version, exactly as mix runtime available lists it. Required, and never a range like 8.3: choosing a version from a range answers with what is installed, and an install would be choosing between versions none of which are here yet. mix runtime resolve is where a range belongs.
--to <VERSION>Update to this release of the same line instead of the newest
--keepKeep the old version installed
--dry-runPrint the plan and change nothing
--yesDo not ask: agree to the update and to what the new version needs of the machine
--ignore-requirementsUpdate even though MixEngine judges this machine lacks something the new version needs
--no-waitReturn once the daemon has accepted the update, rather than once it has finished

mix runtime default

Make one installed version the one its kind resolves to

mix runtime default <RUNTIME> <VERSION>
FlagWhat it does
<RUNTIME>Which language
<VERSION>Which version, exactly as mix runtime available lists it. Required, and never a range like 8.3: choosing a version from a range answers with what is installed, and an install would be choosing between versions none of which are here yet. mix runtime resolve is where a range belongs.

mix runtime adopt

Record a version that is on disk but not listed, such as one an earlier install left.

Nothing is downloaded. The folder is checked against the package index first.

mix runtime adopt <RUNTIME> <VERSION>
FlagWhat it does
<RUNTIME>Which language
<VERSION>Which version, exactly as mix runtime available lists it. Required, and never a range like 8.3: choosing a version from a range answers with what is installed, and an install would be choosing between versions none of which are here yet. mix runtime resolve is where a range belongs.

mix runtime found

List versions that are on disk but not listed, and why each is not

mix runtime found

mix runtime ext

Which extensions an installed PHP build loads

mix runtime ext <COMMAND>

mix runtime ext list

List what this build has, and why each is on or off

mix runtime ext list [OPTIONS]
FlagWhat it does
--php <VERSION>The version, exactly as it is installed. Defaults to the one php resolves to here

mix runtime ext enable

Load one on every PHP process of this version

mix runtime ext enable <EXTENSION> [OPTIONS]
FlagWhat it does
<EXTENSION>The extension, as the listing spells it
--php <VERSION>The version, exactly as it is installed. Defaults to the one php resolves to here

mix runtime ext disable

Stop loading one

mix runtime ext disable <EXTENSION> [OPTIONS]
FlagWhat it does
<EXTENSION>The extension, as the listing spells it
--php <VERSION>The version, exactly as it is installed. Defaults to the one php resolves to here

mix runtime resolve

Say which installed version a directory uses, and why that one.

It answers the question php -v answers, without running anything. The reason is the point: when a version surprises you, what you want to know is which of the four sources decided it.

mix runtime resolve <RUNTIME> [OPTIONS]
FlagWhat it does
<RUNTIME>Which language
--version <VERSION>Use this version or range instead of what the directory says. Exact (8.3.33), a series (8.3, 8) or a caret (^8.3), resolved against what is installed and never against what could be downloaded.
--cwd <DIR>Resolve as if this were the working directory

mix package

Install and remove the servers, databases and caches a service runs

mix package <COMMAND>

mix package list

List the packages installed in this home

mix package list [OPTIONS]
FlagWhat it does
--package <PACKAGE>Only this package. Every one of them when it is left out

mix package available

List the versions the package index offers for this machine.

Only packages this build knows how to configure and run: an entry MixEngine has no recipe for would unpack into a directory nothing could start.

mix package available [OPTIONS]
FlagWhat it does
--package <PACKAGE>Only this package. Every one of them when it is left out
--refreshAsk the package index again even if the cached copy is still fresh. The daemon otherwise answers from a cache for up to six hours, which is the wrong default for someone who just watched a version get published and does not want to wait for their own machine to notice.
--allPrint every release rather than one row per line
--line <LINE>Print every release of this line (8.4, 22)

mix package install

Download and install one version

mix package install <PACKAGE> <VERSION> [OPTIONS]
FlagWhat it does
<PACKAGE>Which package, as mix package available lists it
<VERSION>Which version, exactly as mix package available lists it
--no-waitReturn once the daemon has accepted the install, rather than once it has finished
--yesInstall what this version needs of the machine first, without asking: the Microsoft Visual C++ Redistributable, on Windows. Windows still asks for approval
--ignore-requirementsInstall even though MixEngine judges this machine lacks something the version needs. The version is still run once before it is kept

mix package uninstall

Remove one installed version.

Refused while a service is an instance of it, naming the services. mix service delete is what frees it, and deleting a service keeps its data directory.

mix package uninstall <PACKAGE> <VERSION>
FlagWhat it does
<PACKAGE>Which package, as mix package available lists it
<VERSION>Which version, exactly as mix package available lists it

mix package upgrade

Update one installed version to the newest release of its line, and move what uses it.

Its instances move to the new version one at a time; the old one is removed afterwards unless --keep is given or an instance could not move. The plan is printed first.

mix package upgrade <PACKAGE> <VERSION> [OPTIONS]
FlagWhat it does
<PACKAGE>Which package, as mix package available lists it
<VERSION>Which version, exactly as mix package available lists it
--to <VERSION>Update to this release of the same line instead of the newest
--keepKeep the old version installed
--dry-runPrint the plan and change nothing
--yesDo not ask: agree to the update and to what the new version needs of the machine
--ignore-requirementsUpdate even though MixEngine judges this machine lacks something the new version needs
--no-waitReturn once the daemon has accepted the update, rather than once it has finished

mix package adopt

Record a version that is on disk but not listed, such as one an earlier install left.

Nothing is downloaded. The folder is checked against the package index first.

mix package adopt <PACKAGE> <VERSION>
FlagWhat it does
<PACKAGE>Which package, as mix package available lists it
<VERSION>Which version, exactly as mix package available lists it

mix package found

List versions that are on disk but not listed, and why each is not

mix package found

mix project

Register the directories this home knows about, and what they pin

mix project <COMMAND>

mix project create

Register a directory as a project.

With no --name and no --pin, whatever the mixengine.toml in that directory says is used. That is how you adopt a colleague's checkout.

mix project create [DIR] [OPTIONS]
FlagWhat it does
<DIR>The project's root. Defaults to the current directory
--name <NAME>What to call it. Defaults to the manifest's name, then to the directory's own
--pin <RUNTIME=VERSION>Pin a language, as php=^8.3. May be given more than once

mix project list

List the projects this home has been told about

mix project list

mix project show

Show one, with its pins in the order they take effect

mix project show [PROJECT]
FlagWhat it does
<PROJECT>The project's name. Defaults to whichever project the current directory is in

mix project update

Change a project's name, root or pins.

--pin replaces every pin rather than adding to one: --clear-pins with no --pin removes them all, and leaving both out changes nothing.

mix project update [PROJECT] [OPTIONS]
FlagWhat it does
<PROJECT>The project's name. Defaults to whichever project the current directory is in
--name <NAME>A new name
--root <DIR>A new root, for a repository that moved
--pin <RUNTIME=VERSION>Pin a language, as php=^8.3. Replaces every pin the project had
--clear-pinsRemove every pin

mix project keep-warm

Hold this project's services out of idle shutdown while you are working on it.

A verb of its own rather than a flag on update, because it is a thing you do to a project for an afternoon and not part of what the project is.

It reaches the PHP pool this project's sites name. It does not yet reach the database they query, because nothing in MixEngine records which database a project uses.

mix project keep-warm [PROJECT] [OPTIONS]
FlagWhat it does
<PROJECT>The project's name. Defaults to whichever project the current directory is in
--offStop keeping it warm

mix project delete

Forget a project. The directory is left exactly as it is

mix project delete [PROJECT]
FlagWhat it does
<PROJECT>The project's name. Defaults to whichever project the current directory is in

mix project export

Write the project into <root>/mixengine.toml, keeping everything else in the file

mix project export [PROJECT]
FlagWhat it does
<PROJECT>The project's name. Defaults to whichever project the current directory is in

mix site

Declare what is served out of a project's directory, and at what name

mix site <COMMAND>

mix site create

Declare a site under a project.

With nothing but a project named, whatever the [site] and [[services]] in that project's mixengine.toml say is used. That is how you adopt a colleague's site. With several sites in the file, --from says which.

mix site create [OPTIONS]
FlagWhat it does
--project <PROJECT>The project. Defaults to whichever project the current directory is in
--from <DOMAIN>Which site in mixengine.toml to adopt, by any of its names. Needed when the file declares more than one
--domain <DOMAIN>A domain. The first is the primary; repeat for aliases. Defaults to <project>.test
--doc-root <DIR>What is served, relative to the project's root. Defaults to the root itself
--kind <KIND>What serves it
--upstream <URL>Where a reverse-proxy forwards to
--port <PORT>The port a node-app listens on
--pool <SERVICE>The php-fpm pool a php-fpm site uses. Defaults to whatever this directory resolves to
--proxy <PATH=URL>Forward a path prefix to an address: /api=http://127.0.0.1:3003/xyz. Repeatable. The upstream's path, when it has one, replaces the matched prefix.
--php <PATH[=POOL]>Answer a path prefix with a php-fpm pool: /admin=php-fpm@8.3.33, or /admin alone for whatever this project resolves to. Repeatable
--files <PATH=DIR>Serve a path prefix from a directory: /assets=dist. The prefix is stripped. Repeatable
--no-routesRemove every route this site has
--service <SERVICE>A service the site declares, as mariadb@main. May be given more than once
--https <HTTPS>Serve it over HTTPS too, with a certificate from this home's own authority
--https-redirect <HTTPS_REDIRECT>Redirect the plaintext address to the HTTPS one. Needs --https true
--i-knowAccept a .local domain, which belongs to mDNS

mix site list

List the sites this home has been told about

mix site list [OPTIONS]
FlagWhat it does
--project <PROJECT>Only this project's

mix site show

Show one, with its domains, its pool and its services

mix site show [DOMAIN]
FlagWhat it does
<DOMAIN>Any of the site's domains. Defaults to the site of whichever project you are in

mix site update

Change what a site is.

--domain and --service replace rather than add to what the site had: giving neither changes neither.

mix site update [DOMAIN] [OPTIONS]
FlagWhat it does
<DOMAIN>Any of the site's domains. Defaults to the site of whichever project you are in
--domain <DOMAIN>A domain. The first is the primary; repeat for aliases. Replaces the whole list
--doc-root <DIR>A new doc root
--kind <KIND>A new kind
--upstream <URL>Where a reverse-proxy forwards to
--port <PORT>The port a node-app listens on
--pool <SERVICE>The php-fpm pool
--proxy <PATH=URL>Forward a path prefix to an address: /api=http://127.0.0.1:3003/xyz. Replaces the whole list, together with --php and --files
--php <PATH[=POOL]>Answer a path prefix with a php-fpm pool: /admin=php-fpm@8.3.33, or /admin alone for whatever this project resolves to. Replaces the whole list
--files <PATH=DIR>Serve a path prefix from a directory: /assets=dist. The prefix is stripped. Replaces the whole list
--no-routesRemove every route this site has
--service <SERVICE>A service the site declares. Replaces the whole list
--https <HTTPS>Whether HTTPS is declared
--https-redirect <HTTPS_REDIRECT>Redirect the plaintext address to the HTTPS one. Needs HTTPS enabled, before or with this same update
--state <STATE>Serve it, or stop serving it
--i-knowAccept a .local domain

mix site share

Let the local network reach this site, and print a QR code for it.

This site only: every other site keeps answering on loopback alone. The certificate gains the LAN address, and one administrator prompt asks for the firewall rule.

mix site share [DOMAIN] [OPTIONS]
FlagWhat it does
<DOMAIN>Any of the site's domains. Defaults to the site of whichever project you are in
--interface <NAME>Which network to share on, by the name this machine gives it. Needed only where more than one is up. MixEngine refuses to choose rather than putting a site on a network you did not mean, and names the candidates when it does.
--for <LENGTH>How long to share for: 30s, 90m, 2h, 1d, or a bare number of seconds. Measured from when the share began, so asking for a length shorter than the site has already been shared for is refused rather than ending it on the spot. Off by default: a share with no --for lasts until you unshare it or this machine leaves the network.

mix site unshare

Take it back off the local network.

Removes the firewall rule, rebinds to loopback and reissues the certificate without the address. A site that is not shared is left as it is.

mix site unshare [DOMAIN]
FlagWhat it does
<DOMAIN>Any of the site's domains. Defaults to the site of whichever project you are in

mix site start

Serve this site.

This sets a flag and tells the front end to read its configuration again. Nothing is started: a site is not a process, and the services it uses have states of their own.

mix site start [DOMAIN]
FlagWhat it does
<DOMAIN>Any of the site's domains. Defaults to the site of whichever project you are in

mix site stop

Stop serving this site, keeping the declaration

mix site stop [DOMAIN]
FlagWhat it does
<DOMAIN>Any of the site's domains. Defaults to the site of whichever project you are in

mix site delete

Forget a site. The files are left exactly as they are

mix site delete [DOMAIN]
FlagWhat it does
<DOMAIN>Any of the site's domains. Defaults to the site of whichever project you are in

mix blueprint

Write down what a project is made of, and see what applying that somewhere else would do

mix blueprint <COMMAND>

mix blueprint capture

Write down what a project is made of

mix blueprint capture <NAME> [OPTIONS]
FlagWhat it does
<NAME>What to file it under: lower-case letters, digits and hyphens
--project <PROJECT>Which project. Defaults to whichever project the current directory is in
--description <TEXT>What it is for
--overwriteReplace the blueprint already filed under this name

mix blueprint import

Take in a blueprint somebody else wrote.

What arrives without a signature the gallery key vouches for is untrusted for good. Nothing raises that afterwards, and it decides how loudly its [scaffold] command has to be agreed to before it runs.

mix blueprint import <FILE> [OPTIONS]
FlagWhat it does
<FILE>The manifest to read
--name <NAME>What to file it under. Defaults to the file's own name, without .toml
--signature <FILE>The detached signature to check it against. Defaults to <FILE>.minisig if that exists
--overwriteReplace the blueprint already filed under that name

mix blueprint list

Every blueprint this home holds

mix blueprint list

mix blueprint apply

What applying one would do

mix blueprint apply <BLUEPRINT> [OPTIONS]
FlagWhat it does
<BLUEPRINT>Which blueprint
--project <NAME>What the new project is called, and what {project} becomes
--path <DIR>Where it goes. Defaults to a directory named for the project, in the current one
--dry-runStop after planning, and print the plan. Sent as it is typed rather than insisted on here: whether this build can carry an apply out is the daemon's to say, and a client that refused to ask would be holding a rule of its own.
--install-missingAnswer every version question by installing what the blueprint asks for
--with-front-endInstall a web server too, where this home has none. A home with no front end serves no site, and nothing installs one by itself. With this, a blueprint that declares a site plans the default web server as well. A home that already has one, Caddy or nginx, is left alone.
--autostartStart the services this apply creates whenever MixEngine starts. Only what it creates: a server this home already had is left as its owner set it. Read and changed afterwards with mix service autostart.
--startStart the services this project needs once the apply is done. These are the project's sites, the database and pool they use, and the front end they are reached through, not every service of this home. They start after the permission prompt, so every site's name already resolves when it comes up.
--use-installedAnswer every version question by using what this machine already has
--run-scaffoldRun the blueprint's own [scaffold] command without asking first. For a blueprint the gallery signed. An unsigned one takes the other flag, and neither covers the other: a script that runs somebody's unsigned command should say so on the line that does it.
--run-untrusted-scaffoldRun an untrusted blueprint's own [scaffold] command without asking first. Nothing vouches for what this runs. The command is still printed before it starts.
--write-dotenvWrite the database's URL, password included, to the project's .env without asking first, for every key the blueprint offers
--grantSpend the one elevation prompt at the end without asking first
--install-prerequisitesInstall what the blueprint's releases need of this machine first, without asking: the Microsoft Visual C++ Redistributable, on Windows. Windows still asks for approval. This is a flag of its own rather than part of --yes, because an apply asks several questions and one flag answering all of them would answer ones nobody read.
--ignore-requirementsApply even though MixEngine judges this machine lacks something the releases need

mix extension

Read an extension.toml without installing anything

mix extension <COMMAND>

mix extension inspect

Say what installing this extension here would produce

mix extension inspect <PATH>
FlagWhat it does
<PATH>The extension's directory, or its extension.toml

mix extension list

What this home has installed

mix extension list

mix extension available

What the signed registry publishes

mix extension available [OPTIONS]
FlagWhat it does
--refreshAsk the registry again even if the cached copy is still fresh. The daemon otherwise answers from a cache for up to six hours, which is the wrong default for someone who just watched an extension get published and does not want to wait for their own machine to notice.

mix extension plan

Say what installing one would do, and change nothing

mix extension plan [ID] [OPTIONS]
FlagWhat it does
<ID>The extension's id in the registry
--path <PATH>A directory to read instead of the registry. Nothing vouches for one of these.

mix extension install

Install one

mix extension install [ID] [OPTIONS]
FlagWhat it does
<ID>The extension's id in the registry
--path <PATH>A directory to install instead of a registry entry. Nothing vouches for one of these, and the row records it as unsigned for as long as it stays installed
--yesInstall without asking about what it declares
--no-waitAnswer with the job rather than waiting for it

mix extension uninstall

Remove one

mix extension uninstall <ID> [OPTIONS]
FlagWhat it does
<ID>Which extension
--delete-dataDelete its data directory as well. Kept when this is absent, which is the answer that can be undone.

mix extension start

Start the service an extension runs as

mix extension start <ID>
FlagWhat it does
<ID>Which extension

mix extension stop

Stop it

mix extension stop <ID>
FlagWhat it does
<ID>Which extension

mix database

Make a database on one of this home's database servers, and an account that reaches it

mix database <COMMAND>

mix database create

Make a database and the account that reaches it.

The instance is started if it is not running. Nothing prints the password: it is put in this machine's credential store, and what is printed is where.

mix database create <SERVICE> [OPTIONS]
FlagWhat it does
<SERVICE>Which instance: mariadb@main, postgres@shop
--name <NAME>The database's name
--user <ACCOUNT>The account's name. The database's own when nobody says
--password <VALUE>Choose the account's password instead of generating one. With a value, that is the password. Without one, mix prompts and reads one line from standard input, so this also works piped: `echo secret

mix database client

Where this instance could be opened, and with what.

MixLab, the window this MixEngine installed, when the install has one; nothing on a headless install.

Reads only: starts nothing, opens nothing. "No client" is an answer, not a failure.

mix database client <SERVICE>
FlagWhat it does
<SERVICE>Which instance: mariadb@main, redis@main

mix database credentials

The password MixEngine holds for one account.

Reads only: starts nothing. Prints the password itself, and the last line of the plain rendering is the value alone, so a script can read it with tail -1. This is the only mix database command whose whole purpose is to print a credential.

mix database credentials <SERVICE> [OPTIONS]
FlagWhat it does
<SERVICE>Which instance: mariadb@main, postgres@shop
--user <ACCOUNT>The account to read. The server's administrator when nobody says

mix database open

Open this instance in MixLab, the window this MixEngine installed.

MixLab need not be running: a copy already open takes the connection as a new tab and this command says so, and one that is not open is started.

The instance is started if it is not running. The account's password is read from this machine's credential store at that moment and handed to the client in its own environment. It is never printed and never put in an argument. Exits 1 on an install with no window (a headless install), and says so.

mix database open <SERVICE> [OPTIONS]
FlagWhat it does
<SERVICE>Which instance
--user <ACCOUNT>The account to sign in as. The server's administrator when nobody says
--database <NAME>A database to open at

mix metrics

Show what MixEngine is costing this machine: CPU and memory, per service and for the daemon.

One reading and out by default. --watch opens the live stream, which also puts the daemon on its one-second rate. When nobody is looking, it samples once a minute.

mix metrics [OPTIONS]
FlagWhat it does
--watchKeep printing, a block per reading, until interrupted
--since <SINCE>Read the recorded history instead, starting this far back: 30m, 2h, 1d
--service <SERVICE>One subject only. Omit for every service and the daemon

mix doctor

Examine this machine and say what is wrong with it.

Reports and repairs nothing unless --repair is passed. Exits non-zero when it found a problem, so a script can ask.

mix doctor [OPTIONS]
FlagWhat it does
--repairRepair everything that can be repaired, and ask for the rest. Repairs inside this home are made at once. Anything needing an administrator is queued, shown, and then granted with one prompt for the whole batch.
--yesDo not ask before raising the prompt. Only with --repair
--no-waitReturn as soon as the grant has started, rather than waiting for it. Only with --repair
--bundleWrite one diagnostics archive and print where it went. Everything a bug report needs in one file: the findings above, this daemon's status, what this machine is, any crash reports this home has recorded, and the tail of the log. Whatever was deliberately left out is named beside them.
--out <FILE>Copy the archive here as well. Only with --bundle

mix self-update

Update MixEngine itself.

Checks for a newer release and shows its version, its size and what changed before asking. On yes, the daemon downloads it, checks the signature, runs the new mixengined once to be sure this machine will start it, stops what it is supervising, replaces the binaries and exits. This command then starts the new daemon, which starts your services again.

mixengine-elevate is never replaced here. It runs as root, and updating it needs an elevation prompt of its own.

A copy of MixEngine that a package manager installed is not updated by this: it says so, and names the directory.

On a Mac that installed MixLab from the .pkg, the next .pkg is downloaded, checked and opened in Installer.app instead, and nothing is stopped. When the installation is done, mix self-update --finish restarts MixEngine on the new version.

mix self-update [OPTIONS]
FlagWhat it does
--checkCheck and print what is available. Installs nothing
--yesAnswer the prompt in advance, for a script with nobody at the keyboard
--finishFinish an update Installer.app has installed: stop the services, start the new daemon, and start them again

mix disk

Where this home's disk has gone, and what would take each part back.

Five categories (runtimes, data, logs, certs and cache) plus everything else. Each row says what would reclaim it: your databases never, a runtime only through mix runtime uninstall, the certificates only by losing HTTPS until they are issued again, and the logs and the cache by mix cleanup.

mix disk

mix home

Bring back an earlier install's projects, sites and services from the folders it kept

mix home <COMMAND>

mix home previous

Say what the copy an earlier install left in its kept folders holds, if there is one

mix home previous

mix home restore

Restore that copy into this home: projects, sites, domains and services.

Every database gets a new admin password and is left stopped; the databases in it are kept.

mix home restore [OPTIONS]
FlagWhat it does
-y, --yesDo not ask first

mix cleanup

Take back what is safe to lose: rotated log files and the download cache.

Nothing else, whatever mix disk says the total is. Your databases, your installed runtimes, your certificates, the log files being written right now and this home's crash reports are all out of reach: this command matches file names, it does not sweep the home.

Refuses while another job is running, because a cleanup empties the directory a download resumes from.

mix cleanup [OPTIONS]
FlagWhat it does
--keep-logsLeave the rotated log files where they are
--keep-cacheLeave the download cache where it is
--yesAnswer the confirmation in advance, for a script with nobody at the keyboard
--no-waitStart the work and print the job, rather than waiting for it to finish

mix uninstall

Take MixEngine off this machine.

Undoes everything MixEngine has written outside its own directory (the hosts block, the DNS routing, the port grant, the certificate authority, the firewall rules, the login entry, your PATH entry, the privileged helper and its audit log), and then removes the directory itself.

--dry-run names every one of them and changes nothing. Exits non-zero when anything it acted on is still there, so a script can ask.

mix uninstall [OPTIONS]
FlagWhat it does
--dry-runList what would be removed, and remove nothing
--keep-homeLeave this home's directory where it is, and undo only what is outside it. Keeps the databases in data/, the certificates and everything else this home holds. The daemon stops all the same; the next mix command starts it again.
--keep-relocatedLeave the directories [paths] moved out of the home where they are. Its own choice, apart from --keep-home: a home can go while data/ on another disk stays, or the reverse. A directory that was never moved is inside the home.
--packageAlso remove the program itself, where the macOS package placed it: the commands in /usr/local/bin, MixLab.app and the package receipt. Without it the program stays, and the plan's package row says so. On Linux the package manager removes the program, and the row names the command.
--relocatedWith --dry-run: print only the relocated directories, one path per line. For a program to read. The Windows uninstaller shows them before it asks anything.
--blockedWith --dry-run: print only the programs in the way, one per line, with the pid and the folder each one uses. Prints nothing when nothing is in the way. For a program to read: the Windows uninstaller shows the list before it removes anything.
--yesAnswer the confirmation in advance, for a script with nobody at the keyboard
--no-waitStart the work and print the job, rather than waiting for it to finish

mix domain

Add, remove and diagnose the names this home answers for

mix domain <COMMAND>

mix domain add

Give a site one more name.

The new name is an alias: the site's primary domain is unchanged, because that is what its canonical URL and its certificate are named after.

mix domain add <DOMAIN> [OPTIONS]
FlagWhat it does
<DOMAIN>The name to add
--site <DOMAIN>Any of the site's existing domains
--i-knowAccept .local, which belongs to mDNS and works until somebody plugs in a printer

mix domain remove

Take one name away.

Refused for a site's last domain and for its primary; mix site update reorders, and the first --domain it is given becomes the primary.

mix domain remove <DOMAIN>
FlagWhat it does
<DOMAIN>The name to take away. It names its own site

mix domain status

What actually happens to a name, as four facts that can fail one at a time

mix domain status [DOMAIN]
FlagWhat it does
<DOMAIN>One name, or every name this home declares

mix service

Inspect and control the services this home declares

mix service <COMMAND>

mix service list

List every declared service and what it is doing

mix service list

mix service status

Describe one service.

The id is required, where start and the rest take an optional one: a status with no subject is a list that was typed wrongly, and answering it as a list would hide that.

mix service status <SERVICE>
FlagWhat it does
<SERVICE>The service to describe

mix service logs

Print what a service has been printing.

The one mix service subcommand that is not a service.* method: output is a stream, and a JSON-RPC call cannot be one, so the lines arrive on a connection of their own.

mix service logs <SERVICE> [OPTIONS]
FlagWhat it does
<SERVICE>The service to read
-n, --lines <LINES>How many of the lines already printed to begin with
-f, --followKeep printing as the service prints, rather than stopping at what it already said. Survives the service crashing and being restarted: what is being followed is the service, not one run of its process.

mix service limits

What this service may take, and what this machine will actually enforce of it.

With no subcommand: read it. set replaces it, clear removes it.

mix service limits <SERVICE> <COMMAND>
FlagWhat it does
<SERVICE>The service to read or cap

mix service limits set

Replace every limit on this service.

Every field, not only the ones named. A flag left out is that field's default (uncapped, or ordinary priority), so set --cpu 50 clears a memory ceiling that was there. All three fields of the result are printed, so a cleared limit is on the screen.

mix service limits set [OPTIONS]
FlagWhat it does
--cpu <PERCENT>A ceiling on CPU, as a percentage of one core. Left out: uncapped
--memory <MB>A ceiling on memory, in megabytes. Left out: uncapped
--priority <PRIORITY>How this service competes for CPU

mix service limits clear

Remove every limit from this service.

A named operation rather than a set with three absent flags, so that "uncap this" is something a person can type rather than something they have to infer.

mix service limits clear

mix service idle

When this service is stopped for being unused, and what is holding it open.

With no flag: read it. One of the three flags replaces it.

Nothing idles by default in this build: a stopped service stays stopped until you start it, so switching this on is a choice you make per service.

mix service idle <SERVICE> [OPTIONS]
FlagWhat it does
<SERVICE>The service to read or set
--after <DURATION>Stop it once nothing has used it for this long, such as 30m, 2h or 90m
--neverNever stop it for being unused, whatever a later release makes the default
--defaultGo back to whatever its recipe wants, which in this build is never

mix service save-resources

Whether this home stops services nobody is using ("Save battery" in MixLab).

With no flag: read it. Off unless you turn it on. While it is off, a service is never stopped for being idle unless you gave it a time with mix service idle. While it is on, a PHP pool nobody used for half an hour, or a database or cache for an hour, is stopped and started again by the next request that needs it.

Setting this starts and stops nothing. The next idle check reads it.

mix service save-resources [OPTIONS]
FlagWhat it does
--onStop services nobody is using
--offDo not

mix service autostart

Whether this service starts when MixEngine does.

With no flag: read it. mix autostart is a different question: whether this machine starts a daemon for this home when you log in.

A service that something set here depends on is started too, whether or not it is set itself: a pool whose database is missing is a pool that fails its health check.

Setting this starts and stops nothing. What it changes is what the next daemon start walks.

mix service autostart <SERVICE> [OPTIONS]
FlagWhat it does
<SERVICE>The service to read or set
--onStart it when MixEngine starts
--offDo not

mix service create

Create a service from an installed package.

The part of the id before @ is the package it is an instance of, which is why there is no separate argument for it: mariadb@main is an instance of mariadb. A package that runs only once, such as Caddy, is named without an @ at all.

mix service create <SERVICE> <VERSION> [OPTIONS]
FlagWhat it does
<SERVICE>The service to create
<VERSION>Which installed version of its package to run
--port <PORT>The port it listens on. The recipe's own default when it is left out
--bind <ADDR>The address it binds. 127.0.0.1 when it is left out
--data-dir <DIR>Where its data lives. The home's own layout when it is left out, and never a directory another service already keeps its data in
--autostartStart it whenever the daemon starts

mix service delete

Delete a service, keeping its data directory.

Takes the row and the configuration generated from it. Never the data, because that is somebody's databases. The answer names the directory that was left, so nobody has to go looking.

mix service delete <SERVICE> [OPTIONS]
FlagWhat it does
<SERVICE>The service to delete
--forceDelete it even though a site declares it

mix service front-end

Which program every site in this home is reached through.

Answered from the service listing: what a service is for travels on its summary, so there is no second question to ask and no client anywhere decides that nginx means "front end".

mix service front-end

mix service set-front-end

Change it.

Stops the front end this home is on, swaps the row, renders every site for the new one and starts it. Every site is unreachable while that happens.

On Linux the new server needs this machine's permission to answer on 80 and 443, because that permission is written into the binary and the new binary does not have it. A machine where nobody grants it stays on the front end it had, and says so.

mix service set-front-end <SERVER> [OPTIONS]
FlagWhat it does
<SERVER>The program to move to
--version <VERSION>Which installed version of it. The newest installed when it is left out
-y, --yesAnswer the question in advance
--no-waitReturn once the daemon has accepted the switch rather than once it has made it

mix service set

Move a service to another port.

The port is checked the way one is when a service is created: no other service or extension may hold it, and nothing else on this machine may be listening there. The configuration is rendered again for the new port. A running service is restarted, which drops every open connection, so it asks first; a stopped one stays stopped.

A project's .env, a saved connection in MixLab and shell history still name the old port, and are listed afterwards.

mix service set <SERVICE> [OPTIONS]
FlagWhat it does
<SERVICE>The service to move: mysql@8, redis@cache
--port <PORT>The port it should listen on
-y, --yesDo not ask before restarting a running service

mix service start

Start a service, and everything it depends on

mix service start [SERVICE] [OPTIONS]
FlagWhat it does
<SERVICE>The service to act on. Every declared service when it is left out. Naming one does not mean acting on only that one: a plan is the transitive set, and what the daemon walked comes back in the answer.
--no-waitReturn once the daemon has accepted the plan, rather than once it has walked it. mix waits by default, because mix service start db && … is a sentence about the database being up: an answer sent before the walk would exit 0 for a service that never came up.
--project <PROJECT>Every service one project needs, instead of one or all. Its sites' databases and caches, the php-fpm pool they name, and the front end they are reached through, as the daemon works them out.

mix service stop

Stop a service, and everything that depends on it

mix service stop [SERVICE] [OPTIONS]
FlagWhat it does
<SERVICE>The service to act on. Every declared service when it is left out. Naming one does not mean acting on only that one: a plan is the transitive set, and what the daemon walked comes back in the answer.
--no-waitReturn once the daemon has accepted the plan, rather than once it has walked it. mix waits by default, because mix service start db && … is a sentence about the database being up: an answer sent before the walk would exit 0 for a service that never came up.

mix service restart

Stop a service and what depends on it, then start that same set again

mix service restart [SERVICE] [OPTIONS]
FlagWhat it does
<SERVICE>The service to act on. Every declared service when it is left out. Naming one does not mean acting on only that one: a plan is the transitive set, and what the daemon walked comes back in the answer.
--no-waitReturn once the daemon has accepted the plan, rather than once it has walked it. mix waits by default, because mix service start db && … is a sentence about the database being up: an answer sent before the walk would exit 0 for a service that never came up.

mix service reset-credential

Re-set this database's superuser password inside its own data directory.

For a server that refuses the password MixEngine holds for it, with ERROR 1045 or password authentication failed. A database keeps its own copy of that password inside its data directory, and this machine's credential store holds the other. They are written together when the service first starts and can only come apart afterwards. Once they have, nothing can log in to put them back, because every way of changing the copy inside the directory needs the password that was lost.

This stops the service and everything that depends on it, writes the password this home holds into the data directory through the server's own offline bootstrap, and starts back what went down. Every database in it is kept. mix job list holds the account of what ran.

Only the database servers keep a password of their own; anything else is refused before anything stops.

mix service reset-credential <SERVICE> [OPTIONS]
FlagWhat it does
<SERVICE>The database to repair: mariadb@main, postgres@shop
-y, --yesDo not ask before stopping the service
--no-waitAnswer as soon as the repair has been accepted, rather than when it has finished

mix service found

List service data an earlier install left, and whether each can be adopted

mix service found

mix service adopt

Turn service data an earlier install left back into a service, with a new admin password.

The databases and accounts in it are kept. The service is left stopped.

mix service adopt <SERVICE>
FlagWhat it does
<SERVICE>A service mix service found lists: mariadb@main

mix job

Watch the long operations this daemon is running

mix job <COMMAND>

mix job list

List what this home has run, newest first

mix job list [OPTIONS]
FlagWhat it does
--state <STATE>Only jobs in this state
-n, --limit <COUNT>At most this many

mix job status

Describe one job

mix job status <JOB>
FlagWhat it does
<JOB>The job, as mix job list numbers them

mix job wait

Wait for a job to finish.

Answers when the job ends or when the wait runs out, and the second is not an error: what comes back is the job as it stands. The exit status is what a script branches on. It is non-zero for a job that failed, and for one that has not finished yet.

mix job wait <JOB> [OPTIONS]
FlagWhat it does
<JOB>The job to wait for
--timeout <SECONDS>How long to wait. The daemon caps what it grants

mix job cancel

Ask a running job to stop.

Cancellation is cooperative, so what comes back may still say running: the work ends when it next looks. Cancelling a job that has already ended is not an error.

mix job cancel <JOB>
FlagWhat it does
<JOB>The job to cancel

mix job logs

What a job printed.

Only a job that runs another program prints anything. Today that is an apply running a blueprint's [scaffold] command; other jobs report progress and a result, and show nothing here. The lines stay in memory while the daemon keeps the job, so read them while it runs.

mix job logs <JOB> [OPTIONS]
FlagWhat it does
<JOB>The job, as mix job list numbers them
-f, --followKeep printing as the job prints
-n, --lines <COUNT>How many of the lines already printed to begin with

mix path

Put this home's commands on your PATH, or take them off again

mix path <COMMAND>

mix path status

Say whether a new terminal would find this home's commands

mix path status

mix path install

Fill <root>/bin and put it on this user's PATH.

Idempotent, and it says which of the two it did: a profile that already carries the line is left exactly as it is.

mix path install

mix path uninstall

Take <root>/bin back off this user's PATH.

The commands stay in the directory. They are inside the home, and removing the home is what removes them.

mix path uninstall

mix path rescan

Look for a tool you installed into a runtime, now.

The daemon notices on its own when a runtime's folder changes, so npm install -g yarn makes yarn a command without anybody asking. This is for a folder the system would not let it watch.

mix path rescan

mix autostart

Start this home's daemon when you log in, or stop doing that

mix autostart <COMMAND>

mix autostart status

Say whether this home's daemon starts when you log in

mix autostart status

mix autostart enable

Register it.

Does not start the daemon: there is one running, and it is the one answering this. What it changes is what happens at your next login. Idempotent, and it says which of the two it did.

mix autostart enable [OPTIONS]
FlagWhat it does
--at-bootAlso start at boot, before anyone logs in. On Linux this turns on your account's systemd linger, which needs no administrator where the system allows it

mix autostart disable

Remove it.

Does not stop the daemon that is running. Turning off "start at login" is not a request to lose the daemon you are using.

mix autostart disable [OPTIONS]
FlagWhat it does
--at-bootOnly stop starting at boot, and keep starting when you log in

mix elevation

See what needs an administrator's permission, ask for it once, or forget it

mix elevation <COMMAND>

mix elevation status

Say what is waiting for permission, and what each of them will change

mix elevation status

mix elevation grant

Ask once, for everything that is waiting.

One prompt covers the whole list. Saying no is a normal answer: the list stays, and this command can be run again later.

mix elevation grant [OPTIONS]
FlagWhat it does
--yesSay yes in advance, instead of being asked. What it skips is the question, never the screen: every operation and what it will change is printed either way. It exists for a caller that cannot be asked, such as a script or a CI step, and for --json, which has no way to answer.
--no-waitAnswer as soon as the prompt has been raised, without waiting for it

mix elevation drop

Forget an operation that is waiting, so it is never asked about again

mix elevation drop [OP] [OPTIONS]
FlagWhat it does
<OP>Which one, as mix elevation status numbers them
--allForget all of them. Its own flag rather than "drop with nothing named": emptying the queue by typing less is exactly the mistake worth making impossible.

mix cert

Look at the certificate authority this home signs its sites with

mix cert <COMMAND>

mix cert issue

Give a site the certificate its names need, or every HTTPS site one.

Idempotent: a certificate that still covers the right names, has more than thirty days left and was signed by the authority this home has now is left exactly as it is.

mix cert issue [OPTIONS]
FlagWhat it does
--site <DOMAIN>One site, by any of its domains. Every HTTPS site when this is left out

mix cert status

Say whether each site's padlock is green, by asking the server rather than the disk.

Opens a real TLS connection to this home's front end for every site and reports the certificate it presents. That is the only thing a browser ever sees, and the only way to notice a server still holding a certificate that was replaced underneath it.

Reads only. Nothing is issued, nothing is installed and nothing is reloaded.

mix cert status [OPTIONS]
FlagWhat it does
--site <DOMAIN>One site, by any of its domains. Every site when this is left out

mix cert ca-status

Say what this home's certificate authority is, and where this machine trusts it.

Its name, its fingerprint and how long it has, then whether the system's certificate store trusts it and which browser databases hold it.

mix cert ca-status

mix cert ca-rotate

Replace this home's certificate authority with a new one.

Destructive: every browser holding a cached chain under the old authority stops accepting it, and every site's certificate is reissued. Nothing is replaced unless this machine can be made to trust the new one. Declining the prompt leaves this home exactly as it was.

mix cert ca-rotate [OPTIONS]
FlagWhat it does
--yesAnswer the confirmation in advance, for a script with nobody at the keyboard
--no-waitStart the work and print the job, rather than waiting for it to finish

mix cert ca-uninstall

Take this home's certificate authority out of every store that trusts it.

Leaves the certificate and its key on disk, and leaves every site's certificate alone. mix doctor --repair puts the trust back. Removing it from the system store needs an administrator; the browser databases do not.

mix cert ca-uninstall [OPTIONS]
FlagWhat it does
--yesAnswer the confirmation in advance, for a script with nobody at the keyboard
--no-waitStart the work and print the job, rather than waiting for it to finish

This page as Markdown: https://mixnz.github.io/mixlab/en/cli.md