MDK Logo
ReferenceTooling

CLI reference

Every `mdk` command, its arguments, flags and defaults, grouped as `mdk --help` groups them

Overview

mdk is the command-line tool that scaffolds, runs and checks an MDK stack from the mdk.yaml spec in a project directory. This page lists every command with its arguments, flags and defaults, in the groups mdk --help uses. It states what each command takes and does, not how to sequence them: the install guide puts mdk on your PATH, the Worker guide runs a stack end to end, and the first operator page creates the user who signs in. Every command reads mdk <verb> [noun], and mdk <command> --help prints the same options from the binary.

Every command that reads an existing project takes --dir <path>, the directory holding mdk.yaml, and defaults to the current directory. mdk onboard is the exception: it creates the project and asks for the directory as its first prompt, so it has no --dir. Commands that print data honor the global --output flag.

Global flags

FlagStatusTypeDefaultDescription
-o, --output <fmt>OptionalstringtableOutput format for data: table, json, or yaml
-v, --verboseOptionalbooleanfalseIncrease log detail
--debugOptionalbooleanfalsePrint stack traces for unexpected failures
--versionOptionalbooleanfalsePrint the CLI version and exit
-h, --helpOptionalbooleanfalsePrint usage help and exit

Set up

mdk onboard

Sets up a new project interactively: checks the environment, asks which Workers, apps and dashboard to include, writes mdk.yaml, package.json, .gitignore and a project README.md, and prints the commands to run it. The policy it writes binds the CLI's own account and each app, so the stack boots; the first operator is created afterwards. It takes no flags and needs an interactive terminal.

Build

mdk create worker <name>

Scaffolds a Worker Plugin (mdk-contract.json, handlers and a mock device) into workers/<name>, links it into package.json and adds it to mdk.yaml under spec.workers with a mock device. <name> is lowercase letters, digits, ., _ or -.

FlagStatusTypeDefaultDescription
--org <scope>Optionalstringnonenpm scope for the package name: your-org gives @your-org/<name>
--dir <path>Optionalstring.Project directory
--forceOptionalbooleanfalseOverwrite the target if it already exists
--no-installOptionalbooleanfalseSkip npm install
--no-stack-entryOptionalbooleanfalseDo not add the Worker to mdk.yaml; the entry is printed instead

mdk create app <name>

Scaffolds an app (mdk-app.yaml, a plugin/ route table with controllers, and a starter UI built into ui/) into apps/<name>, links it into package.json, adds it to mdk.yaml under spec.apps and grants it the Kernel access its manifest requests in spec.rbac. <name> follows the Worker rule.

FlagStatusTypeDefaultDescription
--org <scope>Optionalstringnonenpm scope for the package name
--dir <path>Optionalstring.Project directory
--flatOptionalbooleanfalseScaffold into <dir> itself as the root of a standalone app repo, for mdk add app github:…; nothing is linked or added to mdk.yaml
--forceOptionalbooleanfalseOverwrite the target if it already exists
--no-installOptionalbooleanfalseSkip npm install and the starter UI build
--no-stack-entryOptionalbooleanfalseDo not add the app to mdk.yaml; the entry is printed instead

mdk create dashboard [name]

Scaffolds the MDK UI shell into apps/dashboard, named <stack>-dashboard from mdk.yaml. With a name it lands in apps/<name> instead. Inside the monorepo the template is copied locally; elsewhere it is fetched from GitHub at --ref.

FlagStatusTypeDefaultDescription
--dir <path>Optionalstring.Project directory
--ref <git-ref>Optionalstringv<cli version>Branch, tag or SHA to fetch the UI shell from; ignored inside the monorepo
--forceOptionalbooleanfalseOverwrite the target if it already exists
--no-installOptionalbooleanfalseSkip npm install

mdk add app <source> and mdk add worker <source>

Installs a package from npm or GitHub with npm install --ignore-scripts --save-exact, checks it with the same rules as mdk validate, then adds it to mdk.yaml under spec.apps or spec.workers. A refused package leaves mdk.yaml and package.json unchanged. A path on disk is refused: reference a local package by path in mdk.yaml instead.

<source> is one of:

FormExample
npm package, optionally with a range@your-org/mdk-worker-rig@^1
npm package with a subpath inside it@your-org/apps/ops
GitHub shorthand, optionally with a refgithub:owner/repo#v0.2.0, owner/repo
GitHub URLhttps://github.com/owner/repo
FlagStatusTypeDefaultApplies toDescription
--dir <path>Optionalstring.bothProject directory
--name <name>OptionalstringderivedbothName in mdk.yaml; the default strips the mdk-app- or mdk-worker- prefix from the package name
--no-installOptionalbooleanfalsebothSkip npm install; the npm package must already be installed. Not for GitHub sources
--accept-permissionsOptionalbooleanfalseappWhen the app's requested Kernel access changed, replace its role in spec.rbac with the new request
--keep-permissionsOptionalbooleanfalseappWhen the app's requested Kernel access changed, keep its role as it is and record the new request as seen

An app installs as service account app:<name>, with a credential under .mdk/credentials/apps/ and a role in spec.rbac granting exactly what its mdk-app.yaml requests. A Worker without a bundled mock is added without mock: true.

mdk validate app [name] and mdk validate worker [name]

Checks a package and lists every problem; exits 1 when it is not valid. Name a component mdk.yaml declares, or check any package directory with --path. For an app the check covers mdk-app.yaml, its version against package.json, the permission rules, the route table, every handler file and the UI build; a named app's grant in spec.rbac is checked too. For a Worker it covers package.json and mdk-contract.json against the schema and its semantic rules, with every handler resolved on disk and compiled but not run.

FlagStatusTypeDefaultDescription
--dir <path>Optionalstring.Project directory
--path <dir>OptionalstringnoneCheck this package directory instead of a name declared in mdk.yaml
--strictOptionalbooleanfalseApp: fail on warnings too. Worker: hold a legacy contract to the full v1 requirements
--smokeOptionalbooleanfalseApp: call every route against a mock Kernel that grants only the declared permissions. Worker: run the behavioural checks against the mock smoke.config.js sets up
--smoke-config <json|path>OptionalstringnoneMock fleet or device spec for --smoke: inline JSON, a .json file, or a module with setup()
--timeout <ms>Optionalstring10000Deadline per smoke call
--jsonOptionalbooleanfalsePrint { ok, kind, name, path, errors, warnings }

The Worker testing guide lists every smoke.config.js field for a Worker, and the apps guide covers the app smoke checks.

Run

mdk run [target] [name]

Starts the Kernel, Workers, app runtimes and Gateway from mdk.yaml, or one component. Runs in the foreground; Ctrl+C stops everything in reverse boot order. Each Kernel, Worker and app runs once per project, held by a lock under .mdk/run/. A spec.rbac that binds nobody is refused before boot, with mdk rbac init as the fix.

TargetStartsTakes [name]
allKernel, every Worker with its mocks, every app, the Gateway. The defaultno
kernelThe Kernel aloneno
gatewayThe Gateway alone, signing in as mdk-gatewayno
workerOne Worker and its mock devicesyes
appOne app runtime in the foregroundyes
dashboardThe scaffolded UI shell's dev server, as its own processno
mcpA standalone MCP server over the apps spec.apps declares; never part of all and needs the Kernel reachableno
FlagStatusTypeDefaultDescription
-d, --dir <path>Optionalstring.Project directory
--allow-writeOptionalbooleanfalsemcp only: expose tools whose routes are not declared read-only

--detach is reserved and refused until background runs land. mdk run stays in the foreground, and mdk --help does not list the flag.

mdk run mcp reads these optional keys from spec.mcp in mdk.yaml:

KeyTypeDefaultDescription
portnumberspec.gateway.port + 100Port the MCP server listens on
allowWritebooleanfalseSame as --allow-write
allowToolsstring[]noneExpose only these tool ids, write tools included

spec.mcp.token and spec.mcp.identity are refused: each agent signs in with its own service account, and spec.rbac decides what it may call.

mdk status

A one-shot report on the environment (Node version, package manager, mdk.yaml validity, whether every declared package resolves) and the stack (Kernel, Gateway, each Worker with its state, health and device count, each app). It starts, stops and repairs nothing; its one write is the CLI's caller key under .mdk/trusted-keys/.

FlagStatusTypeDefaultDescription
-d, --dir <path>Optionalstring.Project directory
Exit codeFires whenFix
0Environment checks pass and every component reports healthyNone
1Gathering the report threw an unexpected errorRead the printed error and check --dir
2--output names a format other than table, json or yamlPass one of the three
4An environment precondition fails: old Node, a missing or invalid mdk.yaml, a declared package that does not resolveFix the precondition the report names
5The stack is not fully up: Kernel or Gateway unreachable, a Worker not READY, an app not runningCheck the component the report marks unhealthy

Auth

spec.rbac in mdk.yaml is the only place policy is written, and no matching rule means denied. The security blueprint covers the policy itself; the first operator page walks the sign-in sequence. Every command in this group takes -d, --dir <path> (default .).

mdk rbac

CommandEffect
mdk rbac initBinds the CLI's account mdk-cli to an admin role (written if missing), mdk-gateway and mdk-mcp to a policy-reading role, and grants each app its requested Kernel access, then applies the policy to a running Kernel. A role you edited is left alone
mdk rbac applyValidates spec.rbac, listing every problem, and hands it to the running Kernel, which switches at once. A refused policy leaves the one in force untouched
mdk rbac showCompares spec.rbac with the policy the Kernel enforces

apply and show exit 1 when the Kernel is down or refuses the policy. init still writes mdk.yaml with the Kernel down and exits 0, since the Kernel applies the file when it next starts; it exits 1 when an app's grant cannot be written. All three exit 1 on an invalid spec.rbac.

mdk user

Users live in the Kernel's token issuer, so every subcommand needs the Kernel running.

CommandEffect
mdk user add <name>Creates or updates a user and sets their password; <name> is the sub of their tokens and an email works
mdk user passwd <name>Sets the password and ends the user's sessions
mdk user disable <name>Stops the user signing in and ends their sessions
mdk user enable <name>Lets a disabled user sign in again
mdk user remove <name>Deletes the user; their spec.rbac bindings stay until you remove them
mdk user listLists users, honoring -o json and -o yaml

Flags of mdk user add:

FlagStatusTypeDefaultDescription
--email <email>OptionalstringnoneEmail, also matched by User bindings
--group <group>OptionalstringnoneGroup matched by Group bindings; repeatable, and replaces the current groups
--adminOptionalbooleanfalseBind the user to the admin role in spec.rbac, writing the role if missing, and apply the policy
--no-passwordOptionalbooleanfalseCreate the user without a password; they cannot sign in until mdk user passwd
--password-stdinOptionalbooleanfalseRead the password from stdin instead of prompting twice

mdk user passwd takes --password-stdin too. A password is never accepted as a flag value, and the Kernel refuses one shorter than twelve characters.

mdk serviceaccount

mdk sa is the alias. A service account signs in with its own key: app:<name> for each app, created by mdk add app, and a named account per AI agent. The private key stays in .mdk/credentials/ and never ships in a package.

CommandEffect
mdk sa add <agent>Creates an agent credential and registers it with a running Kernel; bind it to a role in spec.rbac next
mdk sa rotate <name>Replaces the key of app:<app> or an agent; the old key's sessions end
mdk sa remove <agent>Deletes an agent's credential and registration
mdk sa token <name>Signs in as the account and prints a short-lived access token for an HTTP client; -o json adds the refresh token
mdk sa listLists the credentials here against what the running Kernel registered

mdk login <username>, mdk logout, mdk whoami

mdk login signs in to the Kernel's token issuer and keeps the session in .mdk/session.json, readable by you alone. While it lasts, mdk status, mdk user, mdk sa and mdk rbac act as you, with what spec.rbac binds you to; an expired session is an error, never a quiet return to the service account. mdk logout ends the session, and mdk whoami prints who the CLI acts as, honoring -o json and -o yaml.

FlagStatusTypeDefaultApplies toDescription
--password-stdinOptionalbooleanfalseloginRead the password from stdin

Agent enablement

mdk skill add

Installs the MDK Developer Skill suite into the project, so a coding agent knows MDK conventions.

FlagStatusTypeDefaultDescription
--client <client>OptionalstringallTarget client: cursor, claude or all
--dir <path>Optionalstring.Project directory

Meta

mdk version

Prints the package name and version to stdout. mdk --version prints the version alone.

Next steps

On this page