/ 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 or another prune running, or with an environment credential for another device, all exit with 3 (EXIT_CONFLICT), as does tray when a live tray instance already holds tray.pid; 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; a corrupt state record during prune; or an interrupted command ([error] interrupted).
2EXIT_USAGEUnknown command, unknown option, invalid flag value, or flag used with the wrong command.
3EXIT_CONFLICTA refusal that needs a decision: init on a file that already exists (opened with openSync(target, "wx"), resulting in EEXIST); login with a credential already stored or with MALETA_DEVICE_TOKEN set; attach with a Maleta already bound; watch or prune --yes when another command holds watch.lock; prune --yes when the environment credential belongs to another device; or tray when a live tray already holds tray.pid.
4EXIT_ENVIRONMENTThe file's targetOs differs from the host during install or sync; the native tray binary is missing, lacks permission to execute, or cannot run here; or the tray fails to start — it exits before READY, does not become ready within 10 seconds, or its pid file cannot be created or resolved. A tray that becomes ready and then dies within the 400 ms grace window is instead an exit 1 failure.

#Usage errors exit with 2

  • stderr receives the message [error] <mensagem> followed by Run 'maleta --help' for usage.
  • Usage errors are: unknown command '<x>' (a near-typo adds . Did you mean '<y>'?), unknown option '<x>', unexpected argument '<x>', duplicate --file, duplicate --tool, --file requires a path, --tool requires a value, --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 — except for a command name that is a near-typo of a real command (edit distance ≤ 2), which exits 2 instead. maleta help is an accepted spelling of maleta --help and prints the same bytes.
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.

Privacy preferences

Choose what this origin may measure. You can change it here at any time.

Essential storage

This browser always keeps your theme, the Maletas you save here and this choice so the site works. They stay on this origin.

Optional analytics

Maleta.dev measures aggregate traffic and real-user performance only after you allow it.

Current choice: not made yet, so measurement stays off.

Privacy policy