NativeDesktop

The nd command

Every nd subcommand, its flags, and one example of each.

nd is one binary (crates/nd-cli). Run it from an app's directory, the one that holds Cargo.toml and nativedesktop.toml. nd <command> --help prints the same flags that this page lists.

CommandWhat it does
newCreates an app.
upgradeMoves the app to a newer nd release.
checkRuns fmt, clippy, the framework lints, and the appearance audit.
testRuns the test tiers through nextest.
buildBuilds the native release, or the web bundle.
serveBuilds and serves the web bundle.
diagnoseSummarizes incident bundles.
packageBuilds installers.
releasePacks, signs, and publishes an update feed.
diagMeasures framework budgets.
docsChecks, builds, and captures this documentation.

new

Creates a directory with an app that builds: Cargo.toml, nativedesktop.toml, a justfile, a nextest config, tests, and the agent docs (for agents). It refuses a directory that isn't empty and a name that isn't a lowercase package name.

nd new notes --id es.canarycoders.notes && cd notes && nd check && nd test

upgrade

Moves every nd dependency and the GPUI [patch.crates-io] entries from their current tag to a newer one. It then re-resolves Cargo.lock (other locked versions stay) and prints the CHANGELOG.md entries between the two versions. If cargo can't resolve the new tag, nd upgrade restores Cargo.toml.

nd upgrade --to v0.7.0

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). It exits non-zero if any step fails. To silence a framework lint, put // nd-allow(rule): reason on its line or the line above.

nd check --target web -p notes

test

Maps a tier to a nextest profile and runs cargo nextest run (testing). It needs cargo-nextest.

nd test --tier real -p hello real_add

build

Without a target flag, nd build makes 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).

nd build --target web --out dist

serve

Builds the web bundle and serves it on localhost. Pass --no-build to skip the build.

nd serve --target web --port 3000

diagnose

Summarizes the incident bundles that an app left behind: panics, crashes, hangs, and issue reports (diagnostics). With no argument, it summarizes the newest one.

nd diagnose --list && nd diagnose --last --json

package

Builds the installer for one OS through Velopack: a macOS .app, .pkg, and .dmg, a Linux AppImage, or a Windows Setup.exe (packaging). The result goes to target/nd/releases.

nd package mac --channel beta --notes CHANGES.md

release

Packs the way package does, then writes a delta against the newest full package, signs the feed with an ed25519 key, and uploads it to [updates.publish] (packaging). If nativedesktop.toml has no [updates] feed and public_key, it stops with a message.

nd release --channel stable --notes CHANGES.md

nd release has two subcommands:

nd release keygen && nd release serve --port 8790

diag

Measures a framework budget. Its only subcommand is scroll (performance).

It prints the frame percentiles. It exits non-zero when more than 2 frames are missed after warm-up, or when 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). Run it from anywhere inside the repository.

nd docs check --require macos && nd docs capture --stale

The README's screenshots come from scripts/shots macos|linux|windows|all, run from the macbook. Each leg writes the gallery's dark capture to docs/shots/<os>.png. The Linux leg runs nd docs capture gallery on g815 through scripts/linux-gate. The macOS leg launches the gallery through scripts/mac/shoot, which captures with ndshot ($ND_NDSHOT), since an agent's terminal can't hold the Screen Recording grant that screencapture needs. The Windows leg builds in the Windows guest on g815 and captures through scripts/windows/vm shoot, which launches the app in the guest's desktop session through ndshell agent, dark and with a fresh data dir. Set ND_WINDOWS_HOST=<ssh host> to use a Windows machine instead of the guest. Messages and FormalMusic ship their own scripts/shots and call scripts/mac/shoot and scripts/windows/vm by path; Lynk's drives its landing page captures instead.