Skip to content

CLI reference

Running mj without a subcommand starts the per-user daemon when necessary and opens the terminal dashboard. If no workspace exists, it creates one using the current directory name and leaves it ready for an explicit new session. Otherwise it opens the requested workspace or the most recently opened workspace. The terminal surface needs at least 60 columns, and 80 for the Sessions sidebar to sit beside the conversation.

mj [--instance <name>] [--workspace <name>] [command]

mj --workspace <name> with no command opens the dashboard in that workspace. Given before a command that works in a workspace, it applies to that command. It is not a global option: the commands that work in a workspace (mj new, mj acp, mj sessions, mj events, mj resume, and mj import) take --workspace <name> after the command name too, and the other commands refuse it there. mj new and mj acp require it. mj sessions and mj events show only that workspace when it is given, and every workspace when it is not. mj import, and mj resume --wiki when it imports another tool’s session, put the session in it and need it when the instance has more than one workspace.

--instance (-i, or MJ_INSTANCE) is global and runs a fully isolated copy — configuration, database, daemon, and logs under instances/<name> (for example mj -i dev daemon status). Hidden worker, broker, daemon-run, and desktop-bootstrap commands are internal implementation interfaces and are intentionally omitted here.

mj acp is listed in mj --help. It is the ACP agent a program starts instead of a coding harness, and is documented in ACP agent.

CommandPurpose
mjOpen or attach to the terminal dashboard.
mj --workspace <name>Open a particular workspace.
mj workspacesOpen the workspace manager in the dashboard.
mj workspaces list [--json]List workspaces without a terminal.
mj workspaces create <name> [--json]Create a workspace, or select the one that already has the name.
mj go [--setup] [--global-default] [<folder>]Open the dashboard on a folder (default: the current directory) with its remembered account and target. --setup changes that folder’s setup; --global-default also makes it the default for new projects.
mj simple [<folder>]Open the folder’s last running Simple session or start one immediately with the default enabled agent, the local localhost target, and an isolated checkout. Automatic turn review is off for the session. Commands are direct Ctrl-key chords with no prefix, so Ctrl+B remains available to tmux.
mj appOpen the authenticated web viewer in the separate mj-desktop application.

Use prefix+q to detach from the dashboard without stopping the daemon or any session. The terminal surface documents its keys; the web viewer covers mj app and browser access.

mj simple is intentionally narrower than mj go: it does not show the profile, target, project, or review wizard, does not choose a remote or container target, and does not write its fixed recipe into the folder’s normal mj go setup. In Simple mode, ctrl+q detaches, ctrl+n starts another session, ctrl+g opens the session list, and ctrl+f1 lists every command. Ctrl+B is not a Mjolnir prefix or command.

mj daemon status
mj daemon stop
mj daemon restart
  • status prints the daemon PID, version, start time, connected-client count, and viewer state. When the viewer is ready it also prints the URL and six-digit access code; otherwise it reports disabled, starting, stopped, or error state.
  • stop gracefully stops the controller daemon. Detached workers keep running.
  • restart gracefully replaces the daemon with the installed Mjolnir build and reconnects to existing workers. It refuses when the running daemon’s build is newer than its own; to go back to an older build, run mj daemon stop first.
mj setup
mj setup instructions --platform linux
mj setup instructions --platform macos

mj setup reruns the same automatic agent and repository discovery used on first interactive startup. It detects installed harnesses and home-directory overrides, adds profiles and a bundle for the current GitHub origin, and preserves existing entries and preferences. Matching entries are reused; identifier collisions get separate names. It also probes every SSH or EC2 machine that has no runtime yet and adds the runtimes it can run. It saves additions without questions and reports actionable doctor errors. Container downloads remain background daemon work. Configure container options, SSH hosts, and AWS targets in Settings; use mj doctor --smoke for explicit container smoke tests.

setup instructions prints coding-agent-friendly preparation steps for a Linux or macOS host.

mj doctor
mj doctor --json
mj doctor --smoke

Doctor checks configuration compatibility, harness authentication, worker binaries, container runtimes, SSH targets, AWS prerequisites, and Apple Container support. Results are classified as ready, warning, fixable, or unsupported.

--json emits a machine-readable array. --smoke adds real disposable pull/run probes where a target supports them; run it after resolving ordinary fixable checks because it can download an image and provision short-lived resources.

mj login
mj login --profile <profile-id>
mj login --profile <claude-profile> --setup-token

The profile may be omitted only when exactly one is configured. Mjolnir launches the appropriate authentication command for that profile. --setup-token is Claude-only: it mints and stores a long-lived subscription token so containers do not race the controller for a rotating OAuth refresh token.

See profiles and harnesses for home directories, credential handling, and runtime limitations.

mj github-token --owner <login>
mj github-token --repo <owner>/<repository> [--repo <owner>/<repository> ...]

Print a currently valid installation token for the configured GitHub App. The daemon owns the shared token cache; this command does not need the private key on the caller’s host. --owner returns an installation-wide token. One or more --repo options discover an installation and limit the token to those repositories; all selected repositories must belong to the same installation. The command fails clearly when no GitHub App is configured. Treat its output as a secret. See GitHub App credentials for setup and CI usage.

mj import <harness> (--session <uuid> | --latest) [options]

<harness> is one of claude, codex, kimi, grok, or muse. OpenCode and MiMo Code keep their sessions in SQLite stores and are not importable yet.

OptionMeaning
--session <uuid>Import one native session by its harness ID. Mutually exclusive with --latest.
--latestImport the most recently modified native session.
--profile <id>Profile whose home holds the session. Needed only when several enabled profiles run this harness.
--bundle <id>Associate an existing configured repository bundle.
--title <text>Set the title displayed in the dashboard.
--allow-dirtyAcknowledge that dirty Git roots will be archived in their complete current state.
--allow-dirty-localCompatibility alias for --allow-dirty.
--allow-omitted-non-gitAcknowledge that modified non-Git or scratch directories will be omitted.
--review-model <name>, --review-effort <name>, --review-tier quick|extendedReview every turn of the imported session with that model or effort. The deprecated tier flag still accepts either value and enables automatic review, but its value is ignored.
--no-reviewDo not review the imported session’s turns automatically.
--workspace <name>Workspace to put the imported session in. Needed when the instance has more than one workspace.

Import never edits the harness’s source transcript. It builds and verifies a Mjolnir recovery archive, creates a suspended session record, and makes that record available through prefix+g.

Examples:

Terminal window
mj import codex --latest --bundle product
mj import claude --session 018f2d00-0000-7000-8000-000000000000 \
--bundle product --title "Finish migration"
mj checkpoint --session <session-id>

Creates and verifies a recovery copy for an active session. It waits for a safe dispatch boundary, then lets normal work continue while the archive is packaged where supported. Mjolnir also checkpoints completed idle turns automatically, throttled to roughly one checkpoint per ten minutes.

mj move --session <id> [--target <target-id>] [--profile <profile-id>]
[--queue discard|start] [--clear-resources] [--yes] [--json]
[--prepare] [--allow-large-transfer] [--exclude <repository>:<path>]...
[--subagents native|mjolnir|none]
[--subagent-straightforward <model>] [--subagent-straightforward-effort <effort>]
[--subagent-subtle <model>] [--subagent-subtle-effort <effort>]
mj move-sources --session <id> [--cleanup <operation-id> --yes]

Move keeps the logical session, workspace, transcript, and recoverable repository state while rebuilding its execution environment. At least one of --target or --profile is required; an omitted selector keeps its current value. The destination must satisfy the same compatibility checks as resume. Moving between harnesses creates a bounded transcript handoff rather than copying harness-private process state.

Move inherits the source resource sizing and attached directories by default. --clear-resources explicitly removes inherited sizing so the destination uses its configured defaults; attached directories remain part of the fixed workspace selection.

--subagents native switches to harness delegation; --subagents mjolnir uses the global task choices in [subagents.straightforward] and, when configured, [subagents.subtle], or provide a session override for either type. --subagent-straightforward M and --subagent-subtle M independently override the matching task choice for this session; each unspecified type uses its global choice. Either override implies Mjolnir. The matching --subagent-*-effort flag requires its model flag. Omitted policy retains the session’s override. --subagents none removes delegation tools entirely; it needs a Claude or Codex session. A retry of a sealed Move retains its recorded policy; an explicit different policy is refused.

A session that works in a bare checkout on an SSH host cannot move to another machine. Its working tree is the checkout itself, so --target is refused with this session's working tree lives on <host>; resume it there. Such a session can change profile in place, or move to another bare target on the same host; that Move is the same in-place profile switch, keeping the checkout and transferring no files. To continue elsewhere, push its branch and start a new session from that branch. The same rule applies to mj resume --target.

When the move copies a workspace, it transfers the repository history and tracked edits, plus the untracked files you keep selected. Three flags control that selection:

  • --prepare inspects the transfer and prints the preparation as JSON without moving anything. Use it to see the eligible files, their sizes, and any blockers.
  • --exclude <repository>:<path> leaves an untracked file or directory at the source. Repeat it for each path.
  • --allow-large-transfer accepts a workspace transfer of at least 1 GB. Without it, a large selection is refused, and the error says which of these flags can resolve it.

Paths left behind stay in a retained source. mj move-sources --session <id> lists the retained sources for a session as JSON. To delete one together with its excluded files, pass its operation ID as --cleanup <operation-id> and confirm with --yes; --cleanup without --yes is refused.

An interactive invocation prepares the destination and asks for confirmation. --yes confirms the interruption for unattended use, but it does not choose what to do with queued work. If commands are pending, unattended use must pass --queue discard or --queue start; discard is the default only in an interactive confirmation. For start, commands are accepted in their original order after destination readiness. The interrupted active prompt is never replayed.

Human output reports the operation ID and phase progress. --json suppresses progress on stdout and emits one final object containing the operation ID, session ID, resolved profile and target, outcome, and any recovery guidance. Failures return a nonzero status. Ctrl-C requests cancellation from the daemon; disconnecting a client does not cancel a detached move.

mj upgrade-container --session <id>
mj upgrade-container --session <id> --acknowledge-writable-layer-loss
mj upgrade-container --session <id> --cancel

The first command previews the inspected current image, selected target and preservation warning. The acknowledgment queues a durable request; accepted work finishes before replacement starts. Workspace and build-cache mounts are retained. Writable-layer files, including manually installed packages, may be lost. A checkpoint does not preserve the whole environment. Pending requests survive daemon replacement and can be cancelled before replacement begins. Unsupported storage layouts fail before the worker is stopped. Normal Restart agent keeps the existing container and its filesystem.

mj recover scan [--json] [--all-instances]
mj recover adopt --session <id> --target <id> [--profile <id>] [--bundle <id>] [--all-instances]
mj recover destroy --session <id> --target <id> --confirm <id> [--all-instances]
  • scan lists Mjolnir-managed workers that exist on a target but are absent from controller state. By default it lists only workers this Mjolnir instance created (the --instance name, or a fingerprint of the data directory). --all-instances also lists workers created by other instances and workers from older builds that carry no instance stamp; the plain output shows which instance created each one.
  • adopt probes a worker and adds it back to state. --profile and --bundle are needed only for older current-v1 workers created before ownership markers were recorded. Adopting a worker from another or an unknown instance requires --all-instances.
  • destroy deletes an untracked managed resource. --confirm must repeat the exact session ID to make accidental deletion harder, and a worker from another or an unknown instance is refused without --all-instances.

Inspect scan output before adopting or destroying anything. See session recovery and durability for the surrounding guarantees.

mj workspaces list [--json]
mj workspaces create <name> [--json]
mj new (--workspace <name> | --workspace-id <id>) [--profile <id>] [--target <id>] [--bundle <id>]
[--project-directory <path>] [--at <sha>] [--branch <name>] [--base <revision>]
[--title <text>]
[--model <name>] [--effort <name>] [--subagents native|mjolnir|none]
[--subagent-straightforward <model>] [--subagent-straightforward-effort <effort>]
[--subagent-subtle <model>] [--subagent-subtle-effort <effort>]
[--review-model <name>] [--review-effort <name>] [--review-tier quick|extended]
[--no-review] [--no-project-memory] [--no-github-events] [--cpus <count>] [--memory-gib <GiB>]
[--prompt-file <path>] [<prompt>|-] [--json]
mj prompt --session <id> [<text>|-] [--prompt-file <path>] [--command-id <id>]
[--timeout <seconds>] [--return-on-input] [--json]
mj message --session <id> [<text>|-] [--prompt-file <path>] [--command-id <id>] [--json]
mj wait --session <id> [--turn <turn-id>] [--timeout <seconds>] [--return-on-input] [--json]
mj transcript --session <id> [--after-seq <seq>] [--limit <count>]
[--role <role>]... [--finished-only] [--json]
mj diff --session <id> [--base <revision>] [--json]
mj export --session <id> [--kind patch|branch|bundle] [--branch <name>]
[--out <path>] [--json]
mj fetch --session <id> --path <path> [--stdout | --ls] [--json]
mj sessions [--session <id>] [--all] [--workspace <name>] [--json]
mj suspend --session <id> [--acknowledge-unpublished-work] [--json]
mj destroy --session <id> [--delete-branch] [--json]
mj resume (--session <id> | --wiki <sessionwiki-id>)
[--profile <id>] [--target <id>] [--workspace-id <id>] [--workspace <name>]
[--queue start|discard] [--json]
mj interrupt-turn --session <id> [--json]
mj review start --session <id> [--json]
mj review status --session <id> [--json]
mj review (forward | dismiss | cancel) --session <id> [--json]
mj stop-task --session <id> (<task-id> | --all) [--json]
mj api-info [--json]
mj events [--session <id>] [--workspace-id <id>] [--workspace <name>] [--after-seq <seq>]
mj usage --session <id> [--after-seq <seq>] [--limit <count>] [--json]
mj put-file --session <id> --path <workspace-relative path> [--overwrite] [--json] <source>|-
mj elicitations --session <id> [--json]
mj respond --session <id> --elicitation <id> [<response JSON>|-] [--response-file <path>]
mj models --profile <id> [--model <name>] [--json]
mj set-config --session <id> [--key <key> --value <value>] [--json]

mj new --at <sha> starts the workspace checked out at that full commit ID in the bundle’s primary repository, before the first prompt. It requires --bundle. With --at, --branch <name> creates that new branch at the commit; without --branch, HEAD is detached. Without --at, --branch <name> selects an existing branch to check out in a new isolated clone; otherwise the clone starts on the remote default branch. --base <revision> records the diff base for mj diff when it should not be --at; it defaults to --at and does not move the checkout. A local clone resolves the base in the source repository, while a network clone resolves it from fetched Git history. A base cannot be combined with a session that runs directly in the selected directory.

  • mj new without --profile or --target uses the saved default for the missing one (the pair GET /api/v1/options reports as default).
  • mj new --model <name> chooses the highest-quota enabled, usable profile offering that exact model and starts the session on it. It conflicts with --profile; the saved default profile breaks quota ties. If --effort is supplied, the selected profile must offer that exact effort for the model or the request fails.
  • mj new --subagents native|mjolnir|none selects delegation. Omitted defaults to Native. none gives the session no delegation tools, native or Mjolnir; it needs a Claude or Codex profile and is not offered in the TUI or browser. Mjolnir requires a Claude or Codex parent and a straightforward choice in [subagents.straightforward] or a session override. The subtle choice in [subagents.subtle] is optional. Configure global defaults in config.toml or TUI Settings → Sub-agents. --subagent-straightforward M and --subagent-subtle M override only their named task type; an unspecified type uses its global choice. Either implies --subagents mjolnir and cannot be combined with native or none. Each effort flag requires its matching model flag; omitted effort uses the harness default and adaptive is invalid. The retired --subagent-model and --subagent-effort flags fail with guidance to use the four per-type flags. single-model and all-models remain rejected. When both types are configured, each spawn selects straightforward or subtle. With only straightforward, the spawn tool has no task type, every child uses the straightforward choice, and the parent is told to delegate straightforward work. Mjolnir chooses an eligible profile offering its model and effort by quota.
  • mj new --review-model <name>, --review-effort <name> and --review-tier quick|extended review every turn of the new session with that model or effort, even when [review] is off. The deprecated tier flag still accepts either value and enables automatic review, but its value is ignored. --no-review turns off automatic review for the session, even when [review] is on; /review still works. mj import <harness> takes the same flags for the session it adopts. See per-session settings.
  • mj new --no-project-memory starts the session with no project memory: nothing from the workspace’s project memory is put in the agent’s startup context, and the harness is offered no memory directory to write to. Its sub-agents get none either. Use it when a session must see only its checkout and its prompt, as an evaluation run does. Without the flag the session loads the workspace’s project memory as before. See project memory.
  • mj new --no-github-events prevents the GitHub watcher from registering the session as a delivery target. Its sub-agents inherit the flag. This is the flag’s only effect. [github.watch] enabled and [jev] enabled control GitHub event production.
  • On a container target, mj new gives the session the same CPU and memory limit that the dashboard and the web viewer select: the size last chosen for that host, else 8 CPUs and 32 GiB, capped at the host’s totals. --cpus <count> and --memory-gib <GiB> override either one. Other targets refuse both options.
  • --return-on-input makes mj prompt and mj wait return as soon as the agent asks for structured input, with the outcome input_required. Answer with mj elicitations and mj respond, then wait again.
  • By default, mj transcript omits tool and terminal entries. Repeat --role to select several kinds of entry from user, agent, thought, tool, terminal, plan, plan_proposal, and system. To include every kind, list all eight roles; there is no --all-roles option. --finished-only selects closed agent messages and can be combined only with --role agent; it implies the agent role when no role is given.
  • mj events prints durable session events as line-delimited JSON, following new events until you stop it. --after-seq replays from that sequence first.
  • mj usage reads recorded token usage for a session.
  • mj put-file uploads a file, or standard input with -, into an idle session’s workspace. It refuses to replace a file unless you pass --overwrite.
  • mj fetch copies a file, or a directory as a zip archive, from a session’s target to this machine and prints where it landed. See below.
  • mj models lists the models and efforts a profile offers.
  • mj set-config applies one session setting, such as the model or effort. Without --key and --value it lists the settings the session’s agent offers, with their choices.

mj diff compares against the recorded launch base by default. Use --base to compare against an explicit Git commit or revision, for example after checking out an older task base. This does not change the session’s recorded baseline. --json returns diff, base, head, and head_descends_from_base; base and head are resolved commit IDs. The patch includes committed, staged, unstaged, and untracked work. An unknown base is refused. mj diff asks the worker for the metadata either way, so both forms need a worker that supports it; an older worker reports that the session needs upgrading.

When head_descends_from_base is false, the session’s HEAD is no longer a descendant of the base — the agent rebased, amended, or reset — so the diff carries history changes as well as session work. Without --json, mj diff writes the patch to standard output and one warning: line to standard error saying so. An older worker leaves the field out, and no warning is printed.

Every session lives in a workspace that the dashboard and the web viewer list, so mj new needs --workspace <name> (or --workspace-id <id>). Without it, mj new fails, lists the instance’s workspaces with their session counts, and says how to create one. A fresh instance has no workspace. Run mj workspaces create <name> first. It selects the workspace when the name already exists, so a script can run it every time:

Terminal window
mj workspaces create agents
mj new --workspace agents --project-directory . "Fix the failing test"

The terminal dashboard still names its first workspace after the directory it was started in. A store from an earlier release that holds sessions made without a workspace lists them in a workspace named default.

mj sessions lists top-level sessions by default. Add --all to include Mjolnir sub-agents.

These commands run one Mjolnir session as a subagent: mj new starts it with a first prompt and prints its id, mj wait blocks until the turn ends and prints the outcome, the elapsed time, the number of tool calls, and the agent’s final message, and mj prompt does both for the next prompt. A prompt comes from the positional argument, from --prompt-file, or from standard input when the argument is -; mj message takes its text the same way.

Each command has one behavior: mj prompt always waits, and mj message never does.

mj prompt --session <id> <text> sends the text as your prompt and waits for that turn to end. Before it waits, it prints turn N on standard error, so if the wait is cut off you can go on with mj wait --session <id> --turn N. With --json, standard output holds only the wait’s result. --command-id <id> makes the send safe to retry: after an ambiguous reply, run the same command with the same ID and you get the same turn, not a second prompt. The retired --wait flag is still accepted and changes nothing. Because a prompt sent this way reads exactly as your own, mj prompt refuses to run inside a session (when MJ_SESSION_ID is set); an agent sends with mj message and follows with mj wait.

mj message --session <id> <text> sends and returns. From your own shell (MJ_SESSION_ID not set), it submits the text as your prompt, just as mj prompt does: the session starts a turn with it, takes it into the running turn, or queues it. It prints turn N; follow it with mj wait --session <id> --turn N when you want the result. --command-id <id> makes it safe to retry in the same way. Inside a session (MJ_SESSION_ID set), mj message sends a message to another top-level session, or to one of the caller’s own sub-agents. Messages from sessions show the sender’s title and full ID, with a reply instruction, and --command-id identifies the message across retries.

The first line of a wait says how the turn ended in the same words as mj sessions --session <id>, for example turn finished (completed, end of turn) in 5.3s · 4 tool calls or turn error (failed: harness inactive) in 30.3s. The tool-call count appears when the turn made any. The line carries no turn number: the number mj prompt and mj message print is the handle mj wait --turn takes, not a count. With --json, the stop_reason field keeps the harness’s own spelling, such as EndTurn, and turn_id and tool_calls are separate fields.

mj wait answers one of two questions:

  • mj wait --session <id> --turn <turn-id> waits until that turn has ended and says how. The turn ID is the number mj new and mj message print. A server retry of the turn is part of it, but nothing that starts new work is: not a turn the agent starts on its own, background work it left running, or Mjolnir’s automatic continuation. When the session is still busy as the wait answers, the first line ends with what it is doing, in the dashboard’s words, for example turn finished (completed, end of turn) in 5.3s; the session is not idle: [BG 2m10s]. --json carries it as next.
  • mj wait --session <id> without --turn waits until the session settles: the agent is idle, nothing is queued, and the session can take a prompt. That includes turns the agent starts on its own, so it can keep waiting long after your prompt’s turn ended. To learn when your prompt’s turn ended, pass --turn, or use mj prompt.

mj resume continues a session that mj suspend suspended. The session keeps its id, its transcript, and its work; Mjolnir provisions a fresh target and restores the verified checkpoint. Every selector is optional: the session’s own record supplies the profile, the target, and the workspace, so mj resume --session <id> is the whole command for continuing where you left off. --profile and --target resume somewhere else, and --queue decides whether prompts queued when the session was suspended are started or discarded (start by default).

mj resume --wiki <sessionwiki-id> continues a session found in the SessionWiki index, whoever ran it, so an agent that searched for earlier work does not have to decide what kind of row it found. Mjolnir takes one of three branches and says which one it took. A Mjolnir session it still has a record of is resumed exactly as --session resumes it. A Mjolnir session whose record the archive job destroyed is restored: a new session starts with a compacted hand-off from the indexed transcript, using --profile and --target when given and the profile and target recorded in the index otherwise. Another tool’s session (Claude Code, Codex, Kimi Code, Grok Build, Muse) is imported from that harness’s own home and then resumed, which needs the session to still be there; the error names the indexed path so you can import it by hand if it is not. --wiki and --session are mutually exclusive, and --json answers with action (resume, restore or import), session_id and wiki_id.

mj sessions --session <id> accepts a SessionWiki id too. An id that names no Mjolnir session is looked up in the index and reported as mine, archived or native, with the tool, the indexed path and the Mjolnir session id when there is one, so an agent can explain what it found before it continues it.

The command answers as soon as the daemon has taken the session, because restoring an archive takes minutes. Follow it with mj wait --session <id>, which blocks while the resume runs and reports the reason if it fails, and then mj set-config, mj prompt and mj message as for any live session. A session that is already running is refused: suspend it first. mj move is the command for a live session that should continue elsewhere.

mj sessions --json and mj sessions --session <id> --json include background_tasks, with each task’s opaque id, command, started_at_ms, and can_stop. Use mj stop-task --session <id> <task-id> to stop one task, or --all to request stops for every currently listed stoppable task. Unsupported tasks are skipped and reported. With --json, the result contains session_id, accepted_task_ids, skipped_task_ids, and a failures object mapping task IDs to errors. All selected stops are attempted; any failure makes the command exit nonzero. Acceptance does not establish that the task has exited: inspect the session again to confirm it disappeared.

mj suspend saves a verified recovery copy and releases the environment. It reports acceptance; follow it with mj wait --session <id> to observe completion or a reported failure. A session’s active Mjolnir sub-agents are stopped without a recovery copy of their own, and only the session is suspended. When some of them have not handed back their reports, mj suspend prints a warning on standard error, such as warning: 2 sub-agents have not handed back; suspending stops them. With --json the answer carries stopped_subagents, subagents_not_handed_back, and warning (omitted when there is none). When the session resumes, its agent is told which sub-agents were stopped. For an independent clone whose work may be unpublished, pass --acknowledge-unpublished-work after reviewing the warning; suspension still verifies the recovery copy before releasing the clone. mj interrupt-turn interrupts only the current turn and keeps the session available for another prompt.

mj review start reviews the turn a session just finished with the session’s reviewer, as /review does in Prompt. It answers once the review has opened, which can take a few minutes while a reviewer is chosen and started, and fails with the reason when the session is still working, has queued prompts, is a sub-agent, or has no usable reviewer. mj review status prints the open review’s status, reviewer role, and verdict, or no review is open. mj review dismiss and mj review cancel close the open review, for example a failed one, so another can start; mj review forward retries a forward the primary refused. See turn review.

mj destroy permanently removes the live session record, environment, and recovery archive. Its conversation is indexed in SessionWiki first: mj sessions --session <id> can find the archived conversation, and mj resume --wiki <id> starts a new session from it. That restores conversation context, not the deleted checkout or unexported files. New managed clones have no branch in the source repository. For older linked worktree sessions, the managed branch remains unless --delete-branch is specified. mj close was removed: use mj suspend to keep the session, or mj destroy to remove it (this replaces mj close --force). mj cancel-turn was removed too; use mj interrupt-turn. Both old names fail with a notice naming their replacement and perform no lifecycle action.

mj export writes a patch or a bundle to --out, or to standard output when no file is named; --kind branch pushes the session’s work and reports the branch and remote instead. With --json and --out, mj export prints one object with the path, the bytes written, and the format (patch or bundle); with --json and no --out the export itself is still the output.

mj fetch reads a path on a session’s target, which may be another host or a container, so one session can read evidence another session cites. A relative --path resolves in the directory the session’s agent runs in; an absolute one is read as the target spells it. After symlinks are resolved, the path must lie in the session’s workspace, its sub-agent report directories, or the target’s temporary directory. A file is copied as it is, up to 16 MiB. A directory arrives as a zip archive of at most 16 MiB, made from at most 128 MiB of files; symlinks inside it are stored as links, not followed. The copy lands in $TMPDIR/mjolnir/<session>/ followed by the path on the target, with .zip after a directory’s name, and mj fetch prints that local path. For example, mj fetch --session d8443f17… --path /tmp/rust-veto-cf prints /tmp/mjolnir/d8443f17…/tmp/rust-veto-cf.zip. With --json it prints the local path, the kind (file or directory), the source path on the target, and the bytes written. --stdout writes the file, or the zip archive, to standard output instead.

mj fetch --ls lists the path on standard output instead of copying it: a directory’s entries in name order, or the file itself. Each line gives the size in bytes (- for a directory), the modification time in UTC, and the name, with / after a directory and -> target after a symlink. Symlinks are listed, not followed. With --json it prints the resolved path and an entries array; each entry has name, kind (file, directory, symlink, or other), size, modified (RFC 3339, or null when the target records none), and target for a symlink. mj transcript pages by --after-seq; use the response’s next_after_seq for the next page. The selected roles are filtered before the page limit. The cursor advances across entries outside that selection, so a page with no matching items can still make progress. latest_seq is the newest sequence in the full transcript. --limit sets a target number of matching items per page; tied entries with the same sequence stay together, so a page can exceed the target.

With --finished-only, next_after_seq is an exclusive resume cursor for the finished agent prefix: it never passes the sequence of the earliest currently open agent message. If the page reaches that open message, the cursor stops at the preceding sequence; poll again with that exact cursor, and the message is returned after its body reports streaming: false. If the page limit is reached first, the cursor is the last returned sequence. With no open agent message remaining, it can advance across non-agent rows to latest_seq, even when the page has no items. Here, “finished” means the stored stream was closed at the time of the read. ACP can still append late chunks to the same stable_id; a consumer that deduplicates only by stable_id may ignore that later revision.

Each command in this section except mj events and mj respond takes --json to print its JSON result. For mj transcript, the server applies the default role selection or the repeated --role selection before paging, and returns next_after_seq and latest_seq with the response. --finished-only filters agent messages and uses the finished-prefix cursor described above. mj events always prints JSON lines. mj checkpoint, mj login, mj app, mj go, mj setup, and the mj daemon commands do not take --json. The commands in this section are clients for the HTTP API, which documents the routes, the wait outcomes, the export preconditions, and the bearer token these commands read. mj api-info prints the base URL and the token file.

Most behavior belongs in configuration. These environment variables select filesystem locations or companion binaries before configuration loads:

VariablePurpose
MJ_CONFIG_DIRDirectory containing config.toml; overrides the platform config directory.
MJ_DATA_DIRRoot for Mjolnir’s database, logs, archives, and other local state.
MJ_WORKER_BINARYExplicit target-compatible worker binary.
MJ_WORKER_DIRDirectory searched for bundled worker binaries.
MJ_WORKER_URLRemote worker URL fallback; it may contain {target} and requires MJ_WORKER_SHA256.
MJ_WORKER_SHA256Required 64-character hexadecimal digest when MJ_WORKER_URL is set.
MJ_DESKTOP_BINARYExplicit mj-desktop executable used by mj app.
MJ_CONTROLLER_BINARYExplicit controller executable used by companion launchers.
MJ_VOICE_WORKERExplicit local voice-worker executable.
CODEX_HOMECodex home used by setup discovery and native import.
CLAUDE_CONFIG_DIRClaude Code home used by setup discovery and native import.
KIMI_CODE_HOMEKimi Code home used by setup discovery and native import.
GROK_HOMEGrok Build home used by setup discovery and native import.
MIMOCODE_HOMEMiMo Code profile root used by setup discovery; contains config/ and data/. A profile at the conventional ~/.mimocode home uses the stock ~/.config/mimocode and ~/.local/share/mimocode trees instead.
XDG_CONFIG_HOME, XDG_DATA_HOMEMuse configuration and external native session storage roots, respectively.
GH_TOKEN / GITHUB_TOKENGitHub token available for syncing into every live target except a bare runtime on this machine.
GIT_SSH_COMMANDSSH command used by checkpoint/archive Git operations.
RUST_LOGController logging filter.

Setting MJ_WORKER_URL requires MJ_WORKER_SHA256; an unverified downloaded worker is not accepted. A digest set without a URL is ignored.

Run mj <command> --help for Clap’s installed-version spelling and option summary. Continue to troubleshooting for logs, target diagnosis, and common command failures.