/ documentation

Exit codes

The five maleta CLI exit codes, the exact conditions for each one, and the caveat for library usage.

The CLI uses five codes, defined as constants in cli/src/runtime.ts: EXIT_OK, EXIT_ERROR, EXIT_USAGE, EXIT_CONFLICT and EXIT_ENVIRONMENT. The seven device commands (login, logout, attach, detach, status, watch, and prune) use the same five values: any unknown command or invalid flag exits with 2; login with a credential that already exists, logout with a credential coming from MALETA_DEVICE_TOKEN, attach with a Maleta already bound, and prune with a maleta watch running all exit with 3 (EXIT_CONFLICT); no device command uses 4.

#Code table

maleta CLI exit codes
CodeConstantWhen it happens
0EXIT_OKinit completed; help printed; validate completed; install or sync finished with failures === 0 — skipped or unsupported items still exit with 0.
1EXIT_ERRORUnreadable or invalid document; any planning, GitHub resolution, limit, collision, staging, or write error; plugin failure.
2EXIT_USAGEUnknown command, unknown option, invalid flag value, or flag used with the wrong command.
3EXIT_CONFLICTinit targeting a file that already exists: it is opened with openSync(target, "wx"), which results in EEXIST.
4EXIT_ENVIRONMENTThe file's targetOs differs from the host during install or sync; the native tray binary is missing or lacks permission to execute; or the desktop tray is unavailable.

#Usage errors exit with 2

  • stderr receives the message [error] <mensagem> followed by Run 'maleta --help' for usage.
  • Usage errors are: unknown command '<x>', unknown option '<x>', --file requires a path, --tool must be all, claude, codex, or agents, --dry-run is only supported by install and sync and --tool is only supported by install and sync.
  • If --help or -h appears anywhere in the arguments, help takes precedence over usage errors and exits with 0.
An invalid flag exits with code 2
bash
maleta install --tool nope --file ./maleta.json
echo "exit=$?"

#The 4 versus 1 caveat

The same targetOs mismatch produces different codes depending on how it is used. On the command line, install and sync compare the value before building the plan: they print [error] targetOs '<x>' does not match the local host '<y>'; refusing install (or refusing sync) and the process exits with 4.

When createInstallPlan is called as a library, the corresponding check throws PlanError with the message targetOs '<x>' does not match the local host '<y>' — without the suffix ; refusing <mode>. If the error is not caught, the exception propagates; callers that catch it and map it to the host process's exit code must treat it as 1, not 4.

#What still exits with 0

  • Skills skipped because they do not exist in the local assets: the [skip] … line is printed, but the summary still reports success.
  • Plugins skipped because they are Claude-only under another --tool, or because they are not in the local plugin manifest.
  • maleta validate --tool claude: the flag is accepted and silently ignored, without affecting the result.