Skip to content

feat(cli): Add support to NVRAM - #519

Draft
brunomenezes wants to merge 21 commits into
prerelease/v2-alphafrom
feat/cli-add-nvram-support
Draft

brunomenezes wants to merge 21 commits into
prerelease/v2-alphafrom
feat/cli-add-nvram-support

Conversation

@brunomenezes

@brunomenezes brunomenezes commented Aug 18, 2026 •

Copy link
Copy Markdown
Member

Summary

Adds NVRAM support to the CLI. Stacked on refactor/sdk-update-anvil-state-source, which supplies emulator 0.21.0 and rollups-node 2.0.0-alpha.13.

An NVRAM is a raw range of bytes exposed to the guest as a /dev/uio* device. Unlike a flash drive it has no filesystem, no mount point and no page cache between the guest and the memory range, so writes are visible to the emulator immediately, with no flush before snapshotting.

New cartesi.toml section

[nvrams] is optional — a config without it behaves exactly as before, emits no new flags and runs no new build steps.

[nvrams.input]
size = "4Ki"              # pristine, zero-filled by cartesi-machine

[nvrams.output]
size = "4Ki"
shared = true             # guest writes persist to .cartesi/output.raw
user = "dapp"             # required for the app to write to it

[nvrams.seed]
filename = "./seed.raw"   # existing raw image; size defaults to the file size

Each table needs size or filename (both is allowed, and they must agree exactly). Sizes must be a multiple of 4Ki, at most 8 nvrams, and labels cannot collide with drive labels — all validated at parse time.

config flag
size = "4Ki" --nvram=label:input,length:4096
size, shared, user --nvram=label:output,length:4096,data_filename:output.raw,user:dapp,shared
filename = "./seed.raw" --nvram=label:seed,data_filename:seed.raw

Only nvrams needing a backing image get a build step: shared is allocated zero-filled in .cartesi/, filename is copied there (the source is never written). A pristine nvram produces no artifact.

Documented in apps/cli/tests/unit/config/fixtures/full.toml.

Behaviour change: cartesi-machine 0.21.0 required

--nvram does not exist before 0.21.0, so requiredVersion moves from ^0.20.0 to ^0.21.0.

That constant was previously declarative only — nothing read it at runtime. It is now enforced: build and shell check before booting, and doctor reports it alongside the Docker checks. Without this, a user on 0.20.0 got a raw unrecognized option --nvram=... lua traceback instead of:

✖ Unsupported Cartesi Machine version. Required version is ^0.21.0. Installed version is 0.20.0.

The check does not block when the version cannot be determined at all, since that also happens with Docker down or the binary missing.

Note user = "dapp" is a Unix permission on the device node, not a read-only range — --user=root writes a root-owned nvram fine. The emulator's real read_only memory-range flag is not exposed here.

Also included

  • fix(cli) — the version check ignored its forceDocker option, reading the host binary instead of the SDK image.
  • test(cli) — CARTESI_TEST_SDK overrides the image the integration suite runs against.
  • test(cli) — cartesi-machine-stored-hash no longer prefixes the output with 0x, which 0.21.0 already includes.
  • refactor(cli) — argument assembly split out of bootMachine into a pure buildMachineArgs, so the flags can be unit tested without spawning a machine.

Testing

level file covers
unit tests/unit/config.test.ts [nvrams] parsing, IEC sizes, validation errors
unit tests/unit/machine.test.ts the exact --nvram= strings and their order
unit tests/unit/exec/cartesi-machine.test.ts the version range
integration tests/integration/builder/nvram.test.ts the backing images on disk
integration tests/integration/machine/nvram.test.ts a real machine booting with nvrams

The boot test builds a throwaway app declaring a pristine input and a shared output, then asserts: only the nvrams needing an image get one; one /dev/uio* per nvram; labels resolve in cartesi.toml order; and writemmap/readmmap round-trips and reaches the host's output.raw — the assertion that proves shared works.

It is gated on the emulator supporting --nvram, not on CARTESI_TEST_SDK, so it skips cleanly on an older image and starts running by itself once DEFAULT_SDK_VERSION is bumped.

Against an SDK image with emulator 0.21.0: 202 pass, 1 skip, 0 fail.

bun run build --filter @cartesi/cli
CARTESI_TEST_SDK=cartesi/sdk:devel bun test apps/cli/

Merge blocker

DEFAULT_SDK_VERSION is still 0.12.0-alpha.41, whose published image ships emulator 0.20.0. Until an SDK release carrying 0.21.0 exists and the default is bumped to it, anyone on the default image hits the new version error. Do not merge before that bump.

⚠️ Temporary commit — remove before merging

The tip commit, wip(cli): Point CI integration tests at the PR's SDK image., touches one file and must be dropped before merge.

It adds three things to .github/workflows/cli.yaml: packages/sdk/** in the paths filter, CARTESI_TEST_SDK: ghcr.io/cartesi/sdk:pr-${{ github.event.number }}, and a ghcr.io login step so that image can be pulled. This makes CI run the integration suite against an emulator that supports --nvram, which the released cartesi/sdk does not yet.

Known fragility: that image is built by sdk.yaml, a separate workflow with no ordering against cli.yaml. A first run can fail on a missing image and pass on re-run.

  • Drop wip(cli): Point CI integration tests at the PR's SDK image.
  • Bump DEFAULT_SDK_VERSION to the SDK release shipping emulator 0.21.0

@changeset-bot

changeset-bot Bot commented Aug 18, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 2d4fe71

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@cartesi/cli Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@brunomenezes brunomenezes moved this to 🧑‍💻 In Progress in Rollups Tooling Aug 18, 2026
@brunomenezes brunomenezes self-assigned this Aug 18, 2026
@github-actions

github-actions Bot commented Aug 18, 2026 •

Copy link
Copy Markdown
Contributor

Coverage Report

Status Category Percentage Covered / Total
🟢 Lines 98.24% (🎯 0%) 5137 / 5229
🔵 Statements 98.24% 5137 / 5229
🔵 Functions 94.44% 153 / 162
🔵 Branches 0% 0 / 0
📁 File Coverage (20 files)
File Lines Statements Functions Branches Uncovered Lines
apps/cli/src/builder/directory.ts 🟢 100% 🟢 100% 🟢 100% 🔴 0% -
apps/cli/src/builder/docker.ts 🟢 86.72% 🟢 86.72% 🟡 66.67% 🔴 0% 75-77, 79, 109-111, 169-178
apps/cli/src/builder/empty.ts 🟢 100% 🟢 100% 🟢 100% 🔴 0% -
apps/cli/src/builder/none.ts 🟢 100% 🟢 100% 🟢 100% 🔴 0% -
apps/cli/src/builder/nvram.ts 🟢 96.88% 🟢 96.88% 🟢 100% 🔴 0% 27
apps/cli/src/builder/tar.ts 🟢 100% 🟢 100% 🟢 100% 🔴 0% -
apps/cli/src/compose/builder.ts 🟢 99.79% 🟢 99.79% 🟢 100% 🔴 0% 228
apps/cli/src/compose/common.ts 🟢 100% 🟢 100% 🟢 100% 🔴 0% -
apps/cli/src/compose/node.ts 🟢 99.24% 🟢 99.24% 🟢 100% 🔴 0% 106
apps/cli/src/config.ts 🟢 95.12% 🟢 95.12% 🟢 96.15% 🔴 0% 78-79, 298, 307, 316, 410, ...
apps/cli/src/contracts.ts 🟢 100% 🟢 100% 🟢 100% 🔴 0% -
...rc/errors/ForkChainValidationError.ts 🟢 100% 🟢 100% 🟢 100% 🔴 0% -
...c/errors/UnsupportedForkChainError.ts 🟢 100% 🟢 100% 🟢 100% 🔴 0% -
...c/exec/cartesi-machine-stored-hash.ts 🟢 92.86% 🟢 92.86% 🟢 100% 🔴 0% 36-37
apps/cli/src/exec/cartesi-machine.ts 🟢 89.19% 🟢 89.19% 🟢 100% 🔴 0% 27-29, 53
apps/cli/src/exec/genext2fs.ts 🟢 96.92% 🟢 96.92% 🟢 100% 🔴 0% 87-88
apps/cli/src/exec/index.ts 🟢 100% 🟢 100% 🟢 100% 🔴 0% -
apps/cli/src/exec/mksquashfs.ts 🟢 91.53% 🟢 91.53% 🟢 100% 🔴 0% 70-74
apps/cli/src/exec/util.ts 🟢 85.11% 🟢 85.11% 🟡 66.67% 🔴 0% 24-28, 68-69
apps/cli/src/machine.ts 🟢 82.48% 🟢 82.48% 🟡 70% 🔴 0% 19, 22, 25, 81-82, 88, 101,...

@brunomenezes brunomenezes changed the title feat(cli): Support nvrams in cartesi.toml feat(cli): Add support to NVRAM Aug 18, 2026
@brunomenezes
brunomenezes force-pushed the feat/cli-add-nvram-support branch from 391697a to 9a7432d Compare August 18, 2026 18:29
@tuler
tuler force-pushed the refactor/sdk-update-anvil-state-source branch from edd91c9 to 0a66b6f Compare September 2, 2026 20:57
@brunomenezes
brunomenezes force-pushed the feat/cli-add-nvram-support branch from 9a7432d to 2d4fe71 Compare October 3, 2026 09:18
Base automatically changed from refactor/sdk-update-anvil-state-source to prerelease/v2-alpha October 3, 2026 12:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

Status: Todo
Status: 🧑‍💻 In Progress

Development

Successfully merging this pull request may close these issues.

1 participant