The dune command-line tool
The dune binary has a small set of commands.
Run a program
dune path/to/program.dn [args...]
Runs a program on the bytecode VM. Any trailing arguments are exposed to the
program through the process module's args().
Type-check without running
dune check path/to/program.dn
Type-checks the program and reports diagnostics without executing it. Exits non-zero if there are errors.
Interactive REPL
dune repl
Starts an interactive session on the bytecode VM. Successful input remains in scope for later entries, including bindings, imports, functions, records, choices, and type aliases. Bare expressions print their result automatically:
> value = 40 + 2;
> value
42
> import math;
> math.square(9)
81
Blocks and declarations may span multiple lines; the prompt changes to ...
until the entry is complete. Parser, type-checker, and runtime errors are
reported without ending the session.
The built-in commands are:
:help— show the command list.:reset— clear all accumulated source and values.:quit— exit successfully.
The first implementation recompiles and re-executes accumulated successful source for every entry. Stable repeated console output is hidden, but external side effects such as file writes can run again. Program reads from stdin are not available because stdin belongs to the REPL command loop. True incremental compiler and VM state can replace this model later without changing the command surface.
Notebooks
dune notebook new tutorial.dnb --title "Tutorial"
dune notebook serve tutorial.dnb
Notebooks are versioned .dnb JSON documents with Markdown cells, Dune code
cells, execution counts, and structured outputs. The local server opens a
token-protected browser workspace for editing and executing cells. The same
files can be run, checked, and exported without starting the server:
dune notebook run tutorial.dnb
dune notebook run tutorial.dnb --update
dune notebook check tutorial.dnb
dune notebook export tutorial.dnb --html -o tutorial.html
See the notebook guide for the file format, server options, kernel behavior, and CI workflow.
Run tests
dune test path/to/program.dn
Runs every @test function and test "..." { ... } block in the
file and prints a per-test ok/FAILED/ignored line plus a summary. Each test
runs in isolation — the file's top-level code is skipped, so only the tests
execute — while top-level functions, constants, and imports remain in scope. A
failed assertion aborts just that test; @should_panic and @should_fail can
make a matching failure the expected result, and @ignore skips a test. The
command exits non-zero if any non-ignored test fails.
Language server
dune lsp
Starts the Language Server over stdio. Editors launch this for diagnostics, completions, hover, and go-to-definition — see Editor integration.
Generate API documentation
dune doc path/to/module.dn # print Markdown to stdout
dune doc path/to/module.dn -o out.md # write one page
dune doc path/to/modules -o out/ # a page per module, plus index.md
dune doc path/to/modules -o out/ --check # fail if out/ is out of date
Renders a module's public API — functions, constants, type aliases, records
(with their fields and methods), choices, and contracts — to Markdown, using the
real parser so signatures and doc-comments match the
source exactly. Only exported declarations appear (a module with no export is
treated as fully public). --check regenerates in memory and exits non-zero on
any drift, which keeps generated docs current in CI.
Diagnostics
When a command fails to lex, parse, or type-check the main file, dune prints a
source snippet that points at the exact span the error refers to:
error: expected type 'int' but got 'text'
--> program.dn:1:10
|
1 | x: int = "hello";
| ^^^^^^^
Runtime failures use a category plus an innermost-first Dune stack trace:
panic: invalid state
stack trace:
0: validate
at program.dn:4:5
1: <top-level>
at program.dn:7:1
Imported pure-Dune modules keep their own file locations. The test runner, REPL, and notebook kernel use the same format; notebook locations include the cell ID. See Runtime errors and stack traces.
The --> line gives file:line:column, and the caret underline marks the
offending token or expression. Lexer, parser, and type-check errors all use this
format; dune check shows it beneath its per-stage progress trace. Errors from imported modules and runtime failures fall
back to a single-line message (source snippets for other files are a follow-up).
The same locations are sent to editors over the language server, so
squiggles land on the right span.
Version
dune --version