User guide · Software preview
The command line
Everything day to day goes through one command, maisnie. This page documents every
subcommand, every flag, and what each exit code means. (The same install also provides the
command under its older name, majordomo, Maisnie’s internal codename, so anything already
scripted against it keeps working. Both run exactly the same program.)
maisnie [--data-dir DATA_DIR] {init,up,status,stop,start-at-login,doctor,unclaim,unlock,relocate,storage,vault,backup,restore,run,pause,resume,secrets,remote,card} ...
--data-dir is a global option that comes before the subcommand and overrides $MAISNIE_HOME
(and the older $MAJORDOMO_HOME, still honoured when $MAISNIE_HOME isn’t set) and the
per-OS default data directory for that one invocation. See install
for the default locations.
maisnie --version
maisnie --version
Prints the product name and the installed version (Maisnie 0.5.0, for example) and exits 0:
no subcommand, no data directory needed. Useful on its own, and worth including whenever you
report a problem, since it names exactly which build you’re running.
maisnie init
maisnie init [--port PORT] [--force]
Writes the configuration document to <data>/config/majordomo.json, with every path already
filled in for the chosen data directory. Refuses to overwrite an existing document unless you
pass --force (this only rewrites the configuration document itself: it never touches your
vault or any notes).
--port PORT: the front port (default8080). The two ports behind it follow automatically atPORT + 1andPORT + 2.--force: overwrite an existing configuration document.
maisnie up
maisnie up [--lan] [--no-browser]
Starts the box in the foreground: the gatekeeper, the setup surface, and the Home surface, each as
its own process, restarted with increasing backoff if one of them crashes. If any one of them
keeps crashing too many times too fast, up gives it up: logs it, stops every child (not
just the one that failed) and exits 1, rather than leaving the box half-running. Prints the URL
to open. Ctrl+C prints “Shutting down…” and stops every child process cleanly, releasing the
instance lock. On Windows, Ctrl+Break does the identical clean shutdown: Python has no built-in
handling for it the way it does for Ctrl+C, so without up’s own handler it would kill the
process outright and leave the gatekeeper and Desk running as orphans holding their ports; up
catches it and shuts down the same way Ctrl+C does. A second up against the same data
directory refuses, because the first one already holds that lock.
--lan: bind the front port on all network interfaces instead of loopback-only. Refused until the box has been claimed. See first boot.--no-browser: do not open the claim page in your browser by itself. Without it,upopens the page in your default browser when the box has not been claimed yet andupis running in a terminal you can type in (not when its output goes to a file or another program). If the browser cannot be opened,upcarries on and the printed address still works.
maisnie status
maisnie status [--json]
Reports whether an instance is running (by checking the same lock up holds, never by guessing
from a process id), whether the box has been claimed, each surface’s reachability, and every
configured connection’s status. Every line reads as one plain sentence, never a raw connection
error. The first line is the installed version. A stopped box reports, for example:
Version: 0.22.0
Running: no
Claimed: unknown
Front door: stopped
Setup: stopped
Home: stopped
The claim answer only works while the box is running: it comes from asking the live
gatekeeper, so a stopped box (exactly the state you’d run status in before unclaim) reports
Claimed: unknown, not a real yes or no: the line above it already says the box isn’t running,
so this isn’t a contradiction to chase. A connection’s own status, once the box is running, is the
Desk’s last saved test result, not a fresh check status runs itself; while the box is stopped,
each connection line says as much (“as of the last test, not checked just now”) rather than
implying a live answer it can’t back up. The last line says whether start at sign-in
is on (Starts when you sign in: yes or no; --json carries it as start_at_login). --json prints the same information as one JSON object,
for scripting.
maisnie stop
maisnie stop
Stops a running box cleanly, whether you started it with up in a window or it started by itself
at sign-in (and so has no window to press Ctrl+C in). It leaves a stop request that the running
up notices within a second, then waits (up to about a minute and a half) until the box has shut
down every service and let go of its lock, and says so. It signals no process id, so it can never
stop anything else. If nothing is running it says so and exits 0. Ctrl+C only works in the
window where up was started.
maisnie start-at-login
maisnie start-at-login [--off]
Makes Maisnie start by itself when you sign in to this computer, so it answers at its address
after a restart with no terminal open. It starts exactly what maisnie up starts, with the same
Python and the same data folder this command was run against. status has a line that says whether
it is on. Run it twice and nothing changes; --off removes what it set up, and only that. --off does not stop a box that is running right now: it says so, and maisnie stop stops it.
- Windows: a small
Maisnie.vbsin your Startup folder. It runs the console-lesspythonw, hidden, so no window ever appears. Output goes tostart-at-login.login the logs folder. - macOS: a Launch Agent (
com.maisnie.up.plistin~/Library/LaunchAgents), loaded withlaunchctl bootstrapand removed withlaunchctl bootout. Loading it starts Maisnie right now and at every sign-in. If Maisnie is already running, it is left alone and the agent only takes effect at the next sign-in. - Linux: a systemd user service (
maisnie.servicein~/.config/systemd/user), switched on withsystemctl --user enableand off withdisable. It starts when you sign in, not at power-on.
On Windows and Linux it starts at the next sign-in, not right now: if Maisnie is not running yet,
start it once with maisnie up. A data folder whose path contains a percent sign cannot be used on
Windows (Windows would rewrite it). If you move the data folder, run the command again from the new place.
maisnie doctor
maisnie doctor [--json]
Pre-flight checks: the Python version, whether the data directory is writable, whether the
configuration document loads through every component that reads it, whether the chosen ports are
free (or already held by this same instance), whether git is on PATH if version history is
enabled, whether the folder paths saved in the configuration document still point at this data directory (a copied or moved one fails here, and the line names maisnie relocate), whether your Python has a time zone database, whether your SQLite build supports
full-text search, and whether a configured subscription lane’s binary path is set and isn’t
pointed at Maisnie’s own model gateway by mistake. A missing time zone database or an
advisory-only file-permission note on Windows prints as informational, not a failure. --json
prints the same checks as one JSON object.
maisnie unclaim
maisnie unclaim [--yes]
Removes the claim, so the next visitor to reach the box claims it fresh with a new passphrase.
This is the recovery path for a forgotten passphrase: there is no “reset my passphrase” flow, on
purpose, because there’s no way to prove who’s asking that isn’t itself a security hole. The
instance must be stopped first (unclaim refuses while up’s lock is held). Without --yes it
does nothing but print what it would do and exit; pass --yes to actually remove the claim: this
is not an interactive confirmation prompt, just a required flag.
maisnie unlock
maisnie unlock
Clears the login lockout counter. Use this if you (or someone else) triggered the five-attempts lockout and you don’t want to wait out the cooldown. It does not touch the claim or the passphrase itself.
maisnie relocate
maisnie relocate
Run it after the data directory was copied or moved to a new place. init saves a few absolute
folder paths in the configuration document (runtime.data_dir, runtime.state_dir,
runtime.log_dir, gatekeeper.state_home and llm.telemetry.dir); a copy still carries the old
ones, which maisnie doctor reports. relocate works on the data directory the usual options
give it (--data-dir, $MAISNIE_HOME, or the default), prints each old and new path, keeps a
fresh copy of the document beside it (majordomo.json.relocate-<date>-<time>.bak), and rewrites
only those paths. Nothing else in the document changes, and sealed values are left as they are.
On macOS, where the key that opens them is a Keychain item named by the data directory’s path,
it first carries that key to the new path and proves every sealed value opens there, even when
no saved path reads as stale (a symlink to the same folder is a different Keychain path). If it
cannot (the old key is not on this Mac, a value does not open with it, or the new path already
holds a key that does not open them all), it changes nothing and says what to do: run
maisnie secrets open on the folder the copy came from, copy that folder again, then run
relocate and maisnie secrets seal on the new copy. On Windows, Linux and Docker the key is a file in the data
directory and moves with it; backup and restore has the table for another
computer or account. If every path already points at this data directory it says so and writes
nothing, so running it twice is harmless. It refuses, exiting 1, while the box is running
(stop maisnie up first).
maisnie storage
maisnie storage [--json]
Shows how much space each folder Maisnie uses takes, and how much is free on the disk it lives on.
It lists your vault, the data directory, and the folders the settings file names inside it (working
state, logs, the sign-in state and the spend records), plus the folder backups are saved in. Each
line gives the full path, the size on disk, the number of files, and the free space on that disk.
The data directory’s size includes the folders listed after it. A folder that does not exist says
so instead of failing. Links (shortcuts and junctions) are counted as one file and never followed,
so a link out of a folder does not add another disk’s size. --json prints the same facts as one
JSON object with a folders list. It only reads: it never writes, creates or removes anything.
The same facts are on the Storage section of the Settings page.
maisnie vault move
maisnie vault move [--dry-run] NEW_FOLDER
Moves your vault to another folder, for example to a bigger disk. Stop Maisnie first: it refuses,
exiting 2, while the box is running. It refuses before copying anything if the new folder is
inside the vault or the data directory (or holds either of them), is not empty, or sits on a disk
without room for the vault plus a margin. It also refuses if the vault contains shortcuts or
junctions (a copy would leave them behind) or if another saved setting or state file names the old
vault folder, because a move would leave that pointing at the old copy.
Then it copies every file, including the .git folder when the vault keeps version history, with
the same modification times, and checks the copy: every file must be present with the same size and
SHA-256. If anything differs it changes nothing else: the settings stay as they were, the old
folder is untouched, and it names what differed. Only when the copy is exact does it switch the
vault path in the settings, in one atomic write.
The old folder is never deleted. It is kept as a safety copy; run maisnie doctor and start
Maisnie to check things work with the new location, and delete the old folder by hand when you are
happy. --dry-run runs all the checks and prints the plan (what would be copied, how much room is
needed), then stops without copying or changing anything.
maisnie backup
maisnie backup FOLDER
Copies the data directory and the vault into a new folder named
maisnie-backup-<date>-<time> inside FOLDER, with a manifest.json listing every file’s size
and checksum. Every password and key in the data folder is left out (the place is emptied, so
Setup shows it as not entered), along with the key that opens sealed values, the plain-text
.bak copies, live sign-in material, logs and any media folder; the vault is copied as it is.
It prints file counts, the backup’s path and how many
passwords and keys were left out, never a value. If no vault is set up, or its folder is gone, it
says so and backs up the data directory only. It refuses, exiting 2, while the box is running
(stop maisnie up first), when FOLDER is inside the data directory or the vault, and when the
dated folder already exists; it writes nothing in each case. See backup and
restore.
maisnie restore
maisnie restore BACKUP [--vault-dir PATH] [--replace]
Puts a backup made by maisnie backup back, into the data directory the usual options give it
(--data-dir, $MAISNIE_HOME, or the default). It checks every file against the manifest, and
that nothing extra is in the backup, before it writes anything; then it copies the data directory
in, fixes the saved folder paths the way relocate does, copies the vault to
--vault-dir and points the settings at it. --vault-dir is required when the backup holds a
vault, and must be new or empty. It refuses, exiting 2 and writing nothing, while the box is
running, when the data directory already holds settings (add --replace to move it aside to a dated folder first), when --vault-dir is not empty, or when
the backup fails its check. It ends by telling you to run maisnie doctor and enter each password
and key again in Setup.
maisnie run
maisnie run TOOL
Runs every one of TOOL’s jobs once, right now, and exits with the result: 0 on a clean run,
and otherwise exactly the connector’s own exit code, passed straight through unchanged (1
for a runtime failure such as a network error, 2 for a configuration problem such as a missing
vault or a secret that was never set: the connector reuses the same code an operator error would
use here, so a failed run is not always exit 1). TOOL is one of the names in the shipped
manifest (ical, imap, feeds in this release; an unrecognized name is refused with the list of
what’s actually there, exit 2). Unlike the scheduler’s own tick, this ignores whether TOOL is
currently turned off on the Sources step (an explicit run is you asking for it right now, not the
scheduler deciding whether it was due) but it still refuses a tool that isn’t installed in this
build. See
connect your accounts for how
often each tool runs on its own.
maisnie pause / maisnie resume
maisnie pause
maisnie resume
pause stops the scheduler from starting any new connector run; a run already under way when
you pause finishes normally, never cut off mid-sync. resume lets it start scheduling runs again.
Both just write or remove a plain flag file under the data directory, so either works whether or
not maisnie up is currently running: pausing ahead of time means the box comes up already
paused, and the scheduler notices a pause or resume within moments either way (it re-checks the
flag on every tick, not just at startup). Both are idempotent: pausing an already-paused box, or
resuming one that was never paused, is the same request twice, not an error.
You do not need the command line for this: Settings > Updates from your sources has a Pause updates / Resume
updates button (it sets and clears the very same flag file), and while updates are paused Home
shows an “Updates are paused” line with a Resume button (a session from away that can only read
sees the line without the button). maisnie status prints a Source updates: line saying paused or
running.
maisnie card write / maisnie card check
maisnie card write PATH [--force]
maisnie card check PATH
write saves this computer’s own setup as a setup card at PATH: every choice, and a note in
place of every password and key it has saved, never a password or key itself, or anything that
looks like one; a plain value that looks like one is left out of the card and counted instead.
Refuses to overwrite an existing file unless you pass --force. check reads a card the way
importing it would and says whether it can be used, without changing anything, unlike importing
it in the Desk, it accepts a card written for a different computer, so it can check one before
sending it on. See import a setup card for the owner’s side of this, and
write a setup card for the format and what each check refuses.
Exit codes
| Code | Meaning |
|---|---|
0 |
Success. |
1 |
doctor found a real problem (including a configuration document that fails to load: doctor reports that as a failed check, not a crash), unclaim wasn’t confirmed with --yes, relocate found the box still running or could not carry the sealed key to the new path, up gave up on a service that kept crashing and stopped the whole box (see below), or run timed out, lost a lock race to a concurrently running copy of the same job, or a job it ran exited with a runtime failure (a network error, a bad response). |
2 |
An operator error for status, init, unclaim, unlock, relocate, backup, restore, up, pause or resume: a configuration document that fails to load, a command that can’t run given the current state (init without --force against a data directory that already has one, --lan before claiming, up against a data directory another instance already holds, backup or restore while the box is running, restore into a data directory that already holds settings or with a --vault-dir that is not new or empty, or a backup that is not whole; relocate uses 1, not 2, when the box is running), or run given a TOOL name the shipped manifest doesn’t have: printed as one plain sentence on stderr, never a traceback. run is different: it does not have its own operator-error code. It exits with exactly the connector’s own exit code, unchanged, and that connector reuses 2 for a configuration problem (a missing vault, a secret that was never set) the same way this launcher does, so a failed run can exit 2 for a config problem, not only for a bad TOOL name. |
up itself can end at either non-zero code: 2 if it’s refused outright before starting anything
(the two cases above), or 1 if it started fine but later gave up on a service that kept
crashing fast: every child stops in that case, not just the one that failed.
The component processes, for the curious
maisnie up starts several smaller processes under the hood, each installable and runnable on
its own if you’re scripting around Maisnie rather than just using it: the gatekeeper (the
one process bound to a network-reachable address), the Desk (python -m desk serve, the
setup wizard’s own HTTP surface), and the Surface (python -m surface, the Home/Search/
note-viewer pages): every service ships with the box, so up treats a missing Surface or a
missing connector manifest as a broken install and refuses to start, rather than running with a
piece silently absent. The Desk and the Surface both bind loopback-only and check no login of
their own: they’re reachable through the gatekeeper, or directly by anything else already running
on the same machine, which is why nothing but the gatekeeper is meant to be exposed beyond
loopback. A fourth package, the gateway, still isn’t a fifth long-running process under up,
but it is no longer only library code the Desk imports for the “Save and test” button and
connection validation: Ask spawns python -m gateway as its own short-lived subprocess
for every question you send it, one process per question, gone again once it answers. None of
these need to be run by hand for ordinary use; maisnie up wires all of them together with the
right configuration and environment variables already set. The
scheduler isn’t a fifth process: it’s a background thread inside up itself, ticking every
few seconds to start whichever connector job is due (see
connect your accounts); maisnie
run/pause/resume are how you reach it from outside without going through the wizard.
Next
Continue to backup.