I've been thinking for awhile about how to revise the roc subcommands to be simpler and more obvious. Here's the design I'm currently thinking of:
dbg always does the same thing regardless of what command you use (that is, we no longer sometimes ignore it)expect always does the same thing regardless of what command you use, unless you explicitly added the --optimize flag (in which case it gets ignored)roc foo.roc (foo.roc is optional and defaults to main.roc) works the way roc run does today: it always runs foo.roc even if there are compile-time errors. In the future, we have a platform-specific concept of "this platform supports 'watch mode' with hot reloading" (e.g. basic-webserver would support this but basic-cli would not); with this command, "watch mode" is always enabled when the platform supports it.roc build always builds the executable even if there are compile-time errors.roc dev and roc run (although later we may want to repurposeroc run for running scripts or something)we used to have something closer to this, and we introduced roc dev based on the feedback that it was common to want to "only run once I've addressed all the compile-time errors" and prepending with roc check && to get that behavior was annoying
however, that was before we had a language server and editor extensions!
my thinking is that now, if you want to fix all your compile errors before running, you'll fix them in your editor anyway and won't be reliant on roc check to do that
which means we can simplify the CLI subcommand structure
Possibly related issue: https://github.com/roc-lang/roc/issues/6637
yeah, this design overlaps with some of that, except for the "flags" section
Do you have any reasons why roc build should be happy to build even if there are errors?
I really liked the idea of * Prioritise **safety** and **performance**, panic/crash at compile time for roc build.
Do we want dbg in a "release" build?
Same with inline expects, doesn't this slow down "release" builds?
I'm assuming "release" builds would have --optimize
I which would drop expects
setting aside dbg for a moment, it's an interesting idea to have roc build default to --optimize because it does seem to be pretty common that people build Roc programs and forget to use --optimize
e.g. when benchmarking things
however, I'm not sure if in those scenarios people are actually using the roc build command :sweat_smile:
My logic is that if you are building the app into an executable then it is because you plan to run it many times. -- so you care about performance and safety
I'm also not sure how often in general people will be directly running roc build for releases as opposed to using something like a GitHub Action to do automate building for multiple targets etc. - and I'm sure those will use the appropriate optimizations because someone will report it if they forget and then it will be fixed for everyone
As opposed to a script (or in a dev loop) where you want to build fast, and don't mind if the runtime is not as optimised.
at Vendr we exclusively did roc build but it was through roc-esbuild and whether optimizations were enabled depended on whether it was a prod build
Why wouldn't we default to --optimize? I may be missing something here... it's just that we ask the LLVM backend to run the full optimisations right?
Or another way, you would use roc instead of roc build if you are not building a release?
I'm interested to learn and explore this. I have very limited experience with this topic.
The main motivation for my proposal was to simplify the subcommands and avoid the confusion between roc, roc run and roc dev which has come up a couple of times.
if I'm using Roc to build a plugin for another system (e.g. an editor extension, or at Vendr a Node.js extension) then I'll only ever be doing roc build, including for development
yeah I think we should do that either way (as noted at the start of the topic) - the question is just whether roc build should have the same default optimization level as all the other commands, or if it should be special
In that case, you may want the dev backend and something else might be calling roc build and driving the linking etc... so that may be why we don't default to --optimise
I think roc build also makes sense if you are compiling some application for your own use (e.g. some package you pulled from a Linux distribution)
In which case you would also want to optimize
I guess a similar logic for the CI/CD release applies there though. If roc build is being called by something else which is driving the process then it could also use --opt none or --opt size.
I would also think it would be good to allow creating optimized builds still with inline expects kept. For example, if a customer is running your software, but runs into an issue, being able to hand them a build with expects in would be very useful as a way to help triangulate the problem.
Richard Feldman said:
my thinking is that now, if you want to fix all your compile errors before running, you'll fix them in your editor anyway and won't be reliant on
roc checkto do that
Do we need to keep roc check then? it sounds like errors and warnings are going to be picked up by the language server, and/or at build time.
CI will often want to run roc check I suspect
and also I do think it's important that people have access to that locally if they don't have an editor set up (even if we assume that an editor setup will be the norm)
importantly, I don't think roc check or roc build have ever been confusing
the confusing part has been roc vs. roc run vs. roc dev - those are the ones I think should be collapsed into one command
and I think roc with no subcommand is the best choice, in part because it's what many other languages do (e.g. it's python foo.py not python run foo.py) and also because that frees up roc run to be used for future script-running purposes
also, separately I do like the idea of changing --optimize to --opt=speed vs --opt=size vs --opt=none (default), in part because it didn't occur to me until this discussion that --optimize is the American spelling, so it invites unnecessary annoyance for people who are used to the non-American spelling :sweat_smile:
regarding whether dbg should be omitted from optimized builds, I have a concern that people maybe trying to debug something in a situation where optimization is a hard requirement (e.g. a part of a game that doesn't run fast enough to be playable without perf optimizations, or a binary that doesn't fit on an embedded device with limited memory unless size optimizations are always used) and then they just can't debug it
or at least can't debug it using printline debugging, which is something I think should always be available!
that said, I could see an argument for a --disallow-dbg flag which could be added to any command (roc build, roc test, etc.) for use in CI servers, so they could fail the build if any dbgs are left in
Would you consider, that calling roc (without a subcommand) starts the repl?
I don't have used python for a long time. But all the time, I want to do a small calculation or some filesystem manipulation in a loop, I call python, since it is the easiest way to start a repl.
When the roc repl gets the ability to run some basic Tasks, I think it will get very useful.
I think, the way python works, is intuitive. python starts the repl, python file.py runs the file. Maybe roc could do the same.
Last updated: Jun 16 2026 at 16:19 UTC