Maisnie

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,doctor,unclaim,unlock,run,pause,resume} ...

--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 (default 8080). The two ports behind it follow automatically at PORT + 1 and PORT + 2.
  • --force — overwrite an existing configuration document.

maisnie up

maisnie up [--lan]

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.

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 — a stopped box reports, for example:

instance: not running
claimed: unknown
gatekeeper: not reachable -- is maisnie running?
desk: not reachable -- is maisnie running?
surface: not reachable -- is maisnie running?
lanes: none configured

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. --json prints the same information as one JSON object, for scripting.

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

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, 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, 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), 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.