From source

Build it, test it, and how a release is cut.

Rust throughout. No Bun, no npm.

cargo run -p app                 # launch the app (dev binary: hopperdev)
cargo build --workspace          # build everything
cargo test                       # the whole suite
cargo clippy --all-targets       # lint
cargo run -p mcp                 # the stdio MCP server
cargo run -p site                # rebuild this documentation site

A source build behaves exactly like the shipped one. Hopper runs no VM of its own, so it needs no entitlement and no code-signing dance to reach its engine — Apple's container does the virtualizing under its own privileged helpers.

That was not always true: the VM needed a Developer ID to boot, which meant a cargo run build could never exercise the engine. Removing it removed the problem.

Conventions

This site

Markdown in site/content/, a small Rust generator in crates/site, output committed to docs/, which is what the Pages workflow publishes. The generated HTML is committed rather than built in CI so the site stays reviewable in the diff and a broken generator cannot take it down.

cargo run -p site

The landing page is hand-authored and left alone.

Cutting a release

Bump the workspace version in the root Cargo.toml and push to main. That is the whole trigger. CI runs the gate (tests, clippy -D warnings, a release build), produces a signed and notarized Hopper.dmg, publishes the GitHub release, and updates the Homebrew cask.

The release job also asserts the app carries no virtualization entitlement. Nothing virtualizes any more, and carrying it would quietly widen the sandbox.