@monimesl/dot-cli
v0.1.0-alpha.19
Published
The dotctl command: build mini apps and run them in the simulator
Readme
@monimesl/dot-cli
The dotctl command. It creates dots, builds them and runs them in the simulator. Later it will
also package, sign and publish them.
dotctl create [dir] # create a dot (asks for its name, package name and template)
dotctl create page <path> # add a page to the dot you are in
dotctl build [root] # build the dot, minified, into dist/ui and dist/logic
dotctl dev [root] # run the dot in the browser simulator and reload it on each change
dotctl preview [root] # build as `build` does, then run that build in the browser simulator
dotctl keys show # print this computer's developer key: its public key and key ID
dotctl lsp # start the .dml language server (editors run this)| Option | Applies to | What it does |
| --------------------- | ------------------------- | -------------------------------------------------------------------------- |
| --out-dir <dir> | build, dev, preview | Output directory (default: <root>/dist) |
| --conditions <list> | build, dev, preview | Extra export conditions, such as @monimesl/dot-source |
| --port <port> | dev, preview | Simulator port (default: 3680, or the next free one) |
| --device | dev | Also serve the dot to the Dot example apps on phones, through a QR code |
| --name <name> | create | The dot's name, instead of asking |
| --package <name> | create | The dot's package name, such as com.mysalone.thing, instead of asking |
| --template <name> | create | starter (one page to build on, the default) or showcase (all features) |
| --pm <name> | create | The package manager to install with: npm, pnpm, yarn or bun |
dotctl create
Creates a self-contained project for a new dot. It asks for:
- The name. The default is
Dot. The project goes indir, or a folder named after the dot in kebab case. - The package name. A reverse domain name you own, such as
com.mysalone.thing. It can't change after the dot is published. The default iscom.example.<the folder's name>. - The template.
starteris one page to build on.showcasehas a page for each feature.
The dot depends on @monimesl/dot-runtime and @monimesl/dot-cli. Inside the Dot repository it
uses the workspace packages instead. Its dot.json starts with "id": "<monime-Internal-Id>".
Replace that with the ID Monime gives the dot when you register it, before you publish.
Then it offers to install the dependencies and start the simulator. If more than one package
manager is installed (npm, pnpm, yarn or bun), it asks which to use. The default is the one that
ran dotctl, or npm.
dotctl dev
Builds the dot, opens it in the browser simulator, and builds it again each time you save:
- A change under
pages/reloads in place. Each open page keeps its state and runs the new code. A page whose initial state changed starts over with the new state. - Any other change, such as to
dot.ts,dot.json,.envorstatics/, restarts the dot on the pages it had open. - If a build fails, the simulator shows the error and keeps running the last good build.
With --device, it also serves each build to the Dot example apps on your local network. It prints
a QR code. Scan it with an example app, and the app follows the dot in the same way. See
the example apps.
dotctl preview
Builds the dot as dotctl build does, then runs that build in the browser simulator. The build is
minified and has only the components its pages use, just as the host app gets it. Use it to check a
build before you publish it. It doesn't rebuild when files change, so run it again after editing.
It keeps the files the dot saved during dotctl dev.
Developer keys
Dash only opens a link if it was signed by one of the signed-in developer's keys.
dotctl dev --device signs with the Ed25519 key in ~/.dot/developer-key.pem, or in the file that
DOT_DEVELOPER_KEY names. dotctl reads this key but never creates it. Make one with OpenSSL 3.
macOS's built-in openssl can't, so run brew install openssl first:
mkdir -p ~/.dot && openssl genpkey -algorithm ed25519 -out ~/.dot/developer-key.pemdotctl keys show prints the public key in base64, and the key ID: the first 8 bytes of the public
key in lowercase hex. Add the public key to your Monime account, once for each computer you work on.
The link looks like dotdev://connect?server=…&secret=…. It only carries what a device can't
get any other way, so the QR code stays small.
- The secret is 16 random bytes and never goes over the network.
- A device proves it has the link by sending
HMAC-SHA256(secret, "dotdev-token")as its bearer token. The token reveals nothing about the secret. - Each build listing has the SHA-256 of every file.
dotctl dev --devicesends the listing with an HMAC-SHA256 of it, keyed with the secret, in adot-build-macheader. - A device only accepts a listing with the right MAC, and only accepts files that match their hashes. So no one else on the network can swap in a different build.
- A device proves it has the link by sending
- The signature is served at
GET <server>/dev/link, which needs no token. It returns{ "expires": …, "keyId": "…", "sig": "…" }.- It signs these values, one per line:
dotdev-connect, the server, the secret, the expiry time (12 hours after the link was made) and the key ID. - Before opening the link, Dash sends Monime the key ID, the signed text (in base64) and the signature. Monime checks that the key belongs to the signed-in account, that it made the signature, and that the link hasn't expired.
- A signature served by anyone else fails this check. Dash itself stores no keys.
- It signs these values, one per line:
Without a key there is no signature, and /dev/link answers 404. The Dot example apps don't need
one.
