The nd command
Every nd subcommand with its flags and one example each.
nd is one binary (crates/nd-cli). Run it from an app's directory (the one holding Cargo.toml and nativedesktop.toml). nd <command> --help prints the same flags as below.
| Command | Does |
|---|---|
new | Creates an app. |
check | fmt, clippy, framework lints, appearance audit. |
test | Runs the test tiers through nextest. |
build | Native release build, or the web bundle. |
serve | Builds and serves the web bundle. |
diagnose | Summarises incident bundles. |
package | Builds installers. |
release | Packs, signs and publishes an update feed. |
diag | Measures framework budgets. |
docs | Checks, builds and captures this documentation. |
new
Creates a directory with a buildable app: Cargo.toml, nativedesktop.toml, a justfile, a nextest config, tests, and the agent docs (for agents). Refuses a non-empty directory and names that are not a lowercase package name.
<name>: directory to create; its last component is the package name.--id <id>: reverse-DNS app id, defaultcom.example.<name>.--nd-path <path>(envND_PATH): depend on a local checkout of thendcrate instead of crates.io.--standalone: add an empty[workspace]so the app builds on its own inside another workspace.
nd new notes --id es.canarycoders.notes && cd notes && nd check && nd test
check
Runs, in order: cargo fmt --check, the framework lints, cargo clippy --all-targets with the framework lint table denied (warnings, unwrap_used, expect_used, dbg_macro, todo, print_stdout), and the appearance audit of every package that has tests/appearance.rs (see testing). Exits non-zero if any step failed. A framework lint is silenced with // nd-allow(rule): reason on its line or the line above.
-p, --package <name>: only these packages, default the workspace's default members.--release: also fail on<!-- nd: ... -->placeholders left in markdown files.--no-clippy: skip clippy.--no-audit: skip the appearance audit.--manifest-path <path>: anotherCargo.toml.--target native|web:webadds the web lints, builds clippy forwasm32-unknown-unknownand skips the audit (web).
nd check --target web -p notes
test
Maps a tier to a nextest profile and runs cargo nextest run (testing). Needs cargo-nextest.
--tier fast|real|all:fast(default) is tiers 1 and 2,realis tier 3 and needs a window server,allruns fast then real.-p, --package <name>: only these packages.<filters>...: test name filters, as nextest takes them.
nd test --tier real -p hello real_add
build
Without a target flag this is the native release build. With --target web it compiles the app for wasm32-unknown-unknown, runs the matching wasm-bindgen, and writes a static bundle with an index.html (web).
--target native|web: defaultnative.-p, --package <name>: default the package in the current directory.--debug: build without optimisations.--out <dir>: where the web bundle goes, defaulttarget/nd/web/<package>/.
nd build --target web --out dist
serve
Builds the web bundle (unless told not to) and serves it on localhost.
--target web: the only target, and the default.-p, --package <name>,--debug,--out <dir>: as inbuild.--port <n>: default 8080.--no-build: serve the last bundle as it is.
nd serve --target web --port 3000
diagnose
Summarises the incident bundles an app left behind: panics, crashes, hangs and issue reports (diagnostics). With no argument it summarises the newest.
<id>: a bundle id or a unique part of it, as--listprints it.--last: the newest bundle (the default).--list: list bundles, newest first.--json: machine-readable output.--app <name>: the app's Cargo package name when the current directory does not say.--manifest-path <path>.
nd diagnose --list && nd diagnose --last --json
package
Builds the installer for one OS: a macOS .app, .pkg and .dmg, a Linux AppImage, a Windows Setup.exe, all through Velopack (packaging). The result lands in target/nd/releases.
<os>:mac,linuxorwindows; default is this OS.--dir <path>: app directory, default..--channel <name>: one ofupdates.channels, default the first.--notes <file>: markdown release notes for the app's "what's new".--binary <path>: package this prebuilt binary instead of runningcargo build --release(cross-packing).--runtime <id>: Velopack runtime id for cross-packing, such aslinux-arm64.
nd package mac --channel beta --notes CHANGES.md
release
Packs like package, then writes a delta against the newest full package, signs the feed with an ed25519 key, and uploads it to [updates.publish] (packaging). Without [updates] feed and public_key in nativedesktop.toml it stops with a message.
--dir,--channel,--notes,--binary: as inpackage.--os mac|linux|windows: default this OS.--key <file>: signing key (base64 seed). ElseND_UPDATE_SIGNING_KEY(the key itself), else the filekeygenwrote.--no-publish: write and sign the feed directory without uploading it.
nd release --channel stable --notes CHANGES.md
Two subcommands:
nd release keygen [--dir <path>] [--out <file>]: makes an ed25519 key, writes it to--out(default~/.config/nd/keys/<app id>.key) and prints the public key for[updates] public_key.nd release serve [--dir <path>] [--root <dir>] [--host <addr>] [--port <n>]: serves the feed directory over HTTP for update tests.--rootreplaces the defaulttarget/nd/releases; host defaults to127.0.0.1, port to 8790.
nd release keygen && nd release serve --port 8790
diag
Measures a framework budget. The one subcommand is scroll (performance).
nd diag scroll --rows <n>: rows in the list, default 100000.--seconds <s>: how long to scroll, default 10.--step <points>: points scrolled per display frame, default 40.--bin <path>(envND_SCROLL_BIN): thescroll-benchbinary, default the one next tond.
It prints the frame percentiles and exits non-zero when more than 2 frames are missed past warm-up or p95 is over 1.25 refresh periods.
nd diag scroll --rows 100000 --seconds 10
docs
Works on the documentation in docs/content (see docs/WRITING.md) from anywhere inside the repository.
nd docs check: every page loads (snippets, examples and directives resolve), links and anchors resolve, prose rules hold over the pages and thend newtemplates, and a capture report per OS.--require macosfails on a missing or stale macOS capture,--compilechecks every example natively and the web ones for wasm32,--webbuilds the site and each web example and loads them in headless Chrome.nd docs build: the docs app's web bundle with each page's markdown,llms.txtandllms-full.txtbeside it, intarget/nd/docs-site/.nd docs servebuilds and serves it.nd docs capture [example..]: runs each example through the test harness on this OS, light and dark, and records its source hash in the capture manifest.--staletakes only examples whose capture is missing or out of date. A changed example shows "not captured yet" until it is captured again.
nd docs check --require macos && nd docs capture --stale