Skip to content
Moku
@moku-labs/native pages

doctor

Per-target toolchain diagnosis, run in parallel. One broken check never sinks the report.

On this page

What it does

doctor tells you what is missing for a target, before a build fails on it. Each problem comes with a fix-it. It checks that secret env vars exist without reading their values.

How it works

Applicable checks run in parallel, and the report keeps registry order. A check that throws becomes a fail. A check that outruns probeTimeoutMs becomes a warn. A warn does not flip report.ok, a fail does.

CheckScopeWorst statusLooks at
node-binaryhostfailA real node on PATH.
tauri-clihostfailThe CLI answers.
tauri-version-skewhostwarn@tauri-apps/* in package.json against the crate majors.
web-scripthostfailweb.build and web.devCommand name real scripts.
cross-repo-corshostwarnA reminder: the packaged origins belong in your server's CORS allowlist.
cross-repo-deep-link-well-knownhost, with deep-linkwarnA reminder about .well-known files if you later leave scheme mode.
rustup-targetseach targetfailThe Rust triple is installed.
signingsigning targetswarnCredentials are present. Unsigned builds stay legal.
xcode-toolchainiOSfailxcodebuild and simctl.
ios-toolsiOS on a MacfailRust iOS triples, xcodegen, pod.
ios-platformiOS on a MacwarnAn installed iOS platform and simulator.
android-toolchainAndroidfailANDROID_HOME, ANDROID_NDK_HOME, java.
android-platformAndroidfailThe SDK platform of compileSdk.
android-debug-signingAndroidwarnThe debug keystore exists.
gen-completenessiOS, AndroidfailThe gen/ tree is not half-written. A tree not yet created passes: the first build creates it.

Config

pluginConfigs.doctor.

OptionTypeDefaultDescription
probeImpl(cmd, args) => Promise<{ code, stdout }>real subprocessesTest seam.
probeTimeoutMsnumber10000Budget per check.

API

Mounted at app.doctor.

MethodSignatureDescription
run(opts?: { target? }) => Promise<DoctorReport>One target, or every configured target plus the host checks.

DoctorReport is { ok, checks }. Each CheckResult is { id, target, status, message, fixIt? }.

Events

Emits

EventPayloadWhen
doctor:checkCheckResultAs each check settles. Hook it with depends: [doctorPlugin].

Listens to

None.

Depends on

Example

scripts/native-check.ts
import { native } from "../src/native";

await native.start();

const report = await native.doctor.run({ target: "android" });
for (const check of report.checks) {
  if (check.status !== "pass") console.log(check.id, check.message, check.fixIt);
}

await native.stop();
if (!report.ok) process.exitCode = 1;
  • signing never fails. A green report does not mean a build can be shipped to a store.
  • A target scope skips host checks. run({ target }) diagnoses that target only. Call run() for the whole picture.
  • cli: the same report, rendered.