MixEngine 0.0.1

Command reference

This handbook covers MixEngine through the mix command line. If you would rather work in a graphical interface, download the MixDB app at https://lab.mixnz.com/#mixdb. MixDB drives the same MixEngine, so everything in this handbook still applies.

Every command mix accepts, in version 0.0.1. This page is generated from the binary's own definitions, so it cannot describe a flag that is not there — and 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 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 docs

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

With no topic it lists them. It talks to no daemon and needs no home — the pages are compiled into this binary, which is what makes mix docs install answer on a machine where nothing starts. The same pages are published at https://mixnz.github.io/mixengine/, 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. This is what docs/guide/en/cli.md is generated from, by packaging/docs.sh --reference — so the reference cannot describe a flag this binary does not have. It is English only, because the definitions it is generated from 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.

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 deliberately not a constraint like 8.3, even now that the daemon can read one: choosing a version from a range is resolution, it answers with what is installed, and none of these three commands is asking that question — an install picking 8.3's newest would be picking 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.

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 deliberately not a constraint like 8.3, even now that the daemon can read one: choosing a version from a range is resolution, it answers with what is installed, and none of these three commands is asking that question — an install picking 8.3's newest would be picking 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 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 deliberately not a constraint like 8.3, even now that the daemon can read one: choosing a version from a range is resolution, it answers with what is installed, and none of these three commands is asking that question — an install picking 8.3's newest would be picking between versions none of which are here yet. mix runtime resolve is where a range belongs.

mix runtime ext

Which extensions an installed build loads.

Under runtime rather than as mix php ext …, which is what .claude/features/runtime-versions.md wrote: a per-language command family for one language is a noun this CLI would then owe every other runtime.

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.

The question php -v answers by running, asked without running anything — and the reason is the point of it: what a person wants when the version surprises them 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.

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

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 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 — which is what adopting a colleague's checkout is.

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. id spelled out because the flattened project argument is also called name, and clap refuses two arguments under one id — it did so at parse time, so mix project update blog --name blogging panicked instead of running. Found by T77's every_command_is_one_clap_can_build, which is now what stops the next one.
--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 — 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 — which is what adopting a colleague's site is.

mix site create [OPTIONS]
FlagWhat it does
--project <PROJECT>The project. Defaults to whichever project the current directory is in
--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
--service <SERVICE>A service the site declares, as mariadb@main. May be given more than once
--https <HTTPS>Declare HTTPS for it. Phase 5 is what acts on this
--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
--service <SERVICE>A service the site declares. Replaces the whole list
--https <HTTPS>Whether HTTPS is declared
--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.

A flag and a re-render: the front end is told 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. Positional rather than --name, because the flattened project argument is already called name and clap refuses two arguments under one id — found by running the command rather than by a test, which is why it is worth a sentence here.
--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 is what 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 <current directory>/<project>
--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
--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.
--grantSpend the one elevation prompt at the end without asking first

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.

Reads only: starts nothing, opens nothing. "Not installed" 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 — 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 the installed desktop database client.

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 — never printed, never put in an argument. Exits 1 when no client is installed, and says what to install.

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 is also what puts the daemon on its one-second rate — it samples once a minute when nobody is looking.

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 once — 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 — with whatever was deliberately left out 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 — and this command 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.

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

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 keeps running, because there is still a home for it to serve.
--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 — from the HTTPS work — 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. That is deliberate: composing a partial change would mean reading the current value and merging it, which is business logic a client may not hold. What this does instead is print all three fields of the result, 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 — 30m, 2h, 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 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, and a package that runs only once — 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 — that is somebody's databases, and 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 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 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 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 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 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 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 — 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 — roadmap task T78a.

Only a job that runs somebody else's program prints anything, which today is an apply running a blueprint's own [scaffold] command. Everything else a job does is reported as progress and as its result, and this answers nothing for those rather than pretending output was lost.

The lines live in memory for as long as the daemon keeps the job's log, so this is what to read while one runs rather than a record to come back to a week later.

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 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

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

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 for the whole queue: .claude/decisions/0005-on-demand-elevation.md calls asking inside a loop a defect. 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 the caller that cannot be asked — a script, a CI step, anything with no terminal behind it — 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 upgrade

Fetch the privileged helper this release publishes, and queue its installation.

mixengine-elevate runs as root and is deliberately never replaced by mix self-update, so this is the one part of an upgrade that has to be asked for separately.

Nothing is installed by this command. It downloads the helper, checks MixEngine's signature on it, runs it once to be sure this machine will start it, and puts the replacement in the queue — mix elevation grant is what raises the prompt, and the helper already installed checks that signature again itself before it replaces anything.

mix elevation upgrade

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

Say what this home's certificate authority is: its name, its fingerprint, how long it has.

Not whether this machine trusts it. That is a question about the operating system's own certificate stores rather than about the authority, this build does not yet ask it, and nothing printed here implies an answer to it. 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 — which 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

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/mixengine/en/cli.md