Wanting to raise this issue #3139 for further discussion.
We talked about this briefly at SYCL, and I think this helps discovery of platforms, and also getting up and running quickly with a new application. I also think this would be a fun project for a new contributor to dive into, so writing this up with the intention to make a new "good first issue".
The proposal below can be upgraded when the future roc package index design is completed and provides a good starting point to validate some ideas before then.
Platform index. We create a new repository, e.g. roc-lang/temporary-platform-index that contains an index of platforms that are currently available. It could be as simple as a single flat file with the URLs.
Adding a new package. a PR against the repo. We can have a checklist to help guide platform authors. For example; we expect some documentation is available, prebuilt-binaries for supported targets, a init.roc plugin script for scaffolding a new app.
Fetching index. the cli subcommand roc init will fetch the latest version of the index file from GH servers (or maybe a cached version from roc-lang.org) and list the available platforms with a TUI interface. We can use a cached version if not available, though I think it's acceptable for now to check each time for a newer file, as the index should change infrequently and be easily cached.
Updating the index we could have a bot that runs once a week and creates a PR to update the index to the latest version/release of all the platforms, and/or remove platforms that are no longer available. I think it is acceptable to leave support for older versions so we can keep this simple for now.
Fuzzy search. Typing in the name of a platform, like roc init cli will fuzzy search and filter the list of platforms. For example, roc init cli would display https://github.com/roc-lang/basic-cli/releases/download/0.10.0/vNe6s9hWzoTZtFmNkvEICPErI9ptji_ySjicO6CkucY.tar.br
Selecting a platform. the user can use up-down arrow keys to change their selection and when they press enter, the roc cli will scaffold out a new app that uses a release of the platform.
Metadata. use the a Raven package to provide metadata. For example we might want to store the following in the flat file instead of just a line separated list of URLs. For example, if we are currently on a arm64 mac machine and that target is not supported we can provide a helpful error message.
{
name: "roc-lang/basic-cli",
url: "https://github.com/roc-lang/basic-cli/releases/download/0.10.0/vNe6s9hWzoTZtFmNkvEICPErI9ptji_ySjicO6CkucY.tar.br",
desc: "Write basic CLI apps",
targets: [MacosArm64,MacosX64,LinuxArm64,LinuxX64,WindowsArm64,WindowsX64],
}
Scaffolding app structure. platform authors include a plugin script platform/init.roc which scaffolds out a new app. This should be located in the same folder as platform/main.roc alongside the prebuilt binaries. The roc cli provides a simple API main : { url : Str } -> List { name : Str, content : Str } where the url is provided so the script can use this to reference latest release. The script can import a URL package if there is a need use templated files. Future extension of this proposal could provide more information such as environment variables.
Minor note about the fuzzy search: The user should be able to change/refine the search term in the init TUI.
I'll update that Issue to track these changes. Let me know if your interested in implementing this. :smiley:
One question I have about this proposal: would the init.roc script maintained by the platform be required to accept an argument containing its own release URL? Since the script (I assume) would be included in the repo itself, the script could not possibly know its own Blake-3 hashed url.
That was the idea behind this API main : { url : Str } -> List { name : Str, content : Str }, though I'm not 100% if this is the best approach.
Also for future reference see the roc-start cli tool. This is a similar tool written using basic-cli.
I think we should come up with motivating examples if we want to go the script route, because copying a static folder might be enough and is simpler overall
Oh, I guess we do need it for the URL bit
Unless we have some kind of placeholder for that
In the case of templates, we can have local path to the platform and substitute the url at roc-init time. This way the templates might be just examples in the platform repo.
I mean look at this - it’s already a template, you just need to copy it and replace the platform path. And you can also run it in the context of the platform repo.
What level of the flexibility for scaffolding we want? It would be easier to maintain/audit valid straightforward roc examples/templates that can be parsed and checked immediately rather than having a script that outputs text or ast.
However, simple copying might be not enough as different platforms might need very specific tools depending on their domain.
Another thing to consider. Is that to support surgical linking, the platform needs to provide at a minimum a stubbed app to compile to a dynamic library. Maybe there is some way we could unify these with a convention? I have been using app.roc in the root of the templates repositories for this, or for rust I made a libapp.roc just because cargo would name the library what I needed.
We could possibly have the init.roc plugin/script is what is used by the platform author to generate the stubbed app dynamic library thing for surgical linking, instead of having a standalone example. And this would ensure the init script is always correct.
Also, probably over complicating this
Hi everyone, as mentioned in the new contributors channel I am interested in contributing to this topic ( https://roc.zulipchat.com/#narrow/channel/316715-contributing/topic/new.20contributors/near/479342332 ). @Sam Mohr mentioned that it would be good before jumping to implementation have some sort of plan which seems like a great idea.
Reading the different messages and comments in the issue and this conversation, I am tried to scaffold the requirements of an MVP: (This requirements are influenced by roc-start designed @Ian McLerran and previously mentioned by @Luke Boswell).
https://github.com/imclerran/roc-start/blob/main/repository/roc-repo.rvn)roc init --tui [LOCATION] would launch a TUI to pick the desired platform (great for discoverability of platforms as previously mentioned)roc init --platform [PLATFORM] [LOCATION] (great for automatic scripting)[LOCATION].tar.br file in the form of a template/ folder?roc-start depends on gh is it the idea that all platform should be hosted on github?I would appreciate some feedback as I am surely overlooking/misunderstanding many things and to be sure to start in the right direction.
Thanks for starting this discussion up! I'm going to bed now, but I can comment on this tomorrow
Great good night!
where should the template files go?
The idea is that roc init loads a roc app (plugin) script that is provided by the platform author. That file might be called init.roc is in the platform and would be included in the platform package .tar.gz etc along with the other files.
The roc cli will then load that plugin and call it passing in the latest version string/url for that platform that is being scaffolded. The cli knows what the latest version is from the central index/list of packages.
The plugin uses this url, and possibly other imported packages, to provide back a list of files (file name, and file contents) which the roc cli then copies into the new directory.
idea that all platform should be hosted on github?
No, this shouldn't be necessary. A roc package (e.g. including a platform package) can be hosted at any URL.
- Is it better to have this discussion in zulip or in the GitHub issue?
I think zulip is better for discussion when scoping ideas/proposals. GH is better during the implementation.
Thanks for clarifying, I understand much better now. Then I believe that good first steps would be to make a mock-up platform with an init.roc file and a mock-up index repository that references to that platform. Once I have this running I could implement roc init --platform [PLATFORM] [LOCATION] and after that the TUI part. It might take me sometimes though as I have never implemented platforms before, but that's fun!
Based on your previous messages I take as a working hypothesis that the init.roc would have a main function with the following signature main : { url : Str } -> List { name : Str, content : Str }.
I believe that I have what I need to get started. I will keep you posted on this channel of my questions and advances. In the mean time I am open to remarks and guidance :smile:
awesome, thanks for getting this moving!
I think making an index is blocked on #ideas > package naming and search
we don't know how the names should work yet, and there are a lot of tradeoffs there
which also influence how the index would work
that said, I think this part is totally unblocked:
roc init --platform https://...
(as long as it's taking a direct URL to the platform, since we already support that today!)
Great I will start with roc init --platform https://... and probably also support roc init --platform file://... . I understand that indexing packages might need more engineering :smile:
For now I focuss on how to implement a platform following the Go example of the website https://github.com/roc-lang/examples/tree/main/examples/GoPlatform
awesome, thank you so much!
The best example for a plugin here is the roc glue subcommand which does something similar but that generates souce code for interfacing with roc.
The platform files are here https://github.com/roc-lang/roc/tree/main/crates/glue/src
And entry from the cli is here https://github.com/roc-lang/roc/blob/69dd8d77f3127cb21eaa34f8c7533930e30b923a/crates/cli/src/main.rs#L116
Thanks that helps a lot. Something I wondered about yesterday is retro-compatibility. Should we support a platform without an init.roc file?
I'm not sure how we would do that. I can't imagine what we would put in... maybe just a blank app module header with the version? So something like this...
app [] { pf: platform "<PLATFORM URL>" }
I can only work on the ROC project on Wednesdays (my part time day) and I thought that it would be good to update you every week about my progress on the feature. I believe that this will help getting feedback, however if you consider this spamming (or in the wrong channel) let me know and I will adapt my communication.
nix wizard(s) that made this happen)init.roc (https://github.com/RobinCamarasa/simple-roc-go-platform/blob/feat/add-init.roc/platform/init.roc)roc build --bundle .tar.br platform/main.roc, with the new init.roc I have already the following stack trace to help me figure it outthread 'main' panicked at crates/packaging/src/tarball.rs:279:9:
not yet implemented
stack backtrace:
0: rust_begin_unwind
1: core::panicking::panic_fmt
2: core::panicking::panic
3: roc_packaging::tarball::read_header
4: roc_packaging::tarball::add_source_files
5: roc_packaging::tarball::build
6: roc_cli::build
7: roc::main
roc init subcommand based on roc glue~/.cache/roc already contains the already installed platform and we could use this for the user to generate the code from a platform that he already downloaded.Love the idea of giving an update. :grinning:
nix wizard(s) that made this happen)init.roc (https://github.com/RobinCamarasa/simple-roc-go-platform/blob/feat/add-init.roc/platform/init.roc)~/.cache/roc already contains the already installed platform and we could use this for the user to generate the code from a platform that he already downloaded.roc build --bundle .tar.br platform/main.roc, with the new init.rocroc init subcommandinit.roc and generate files from the output of the function. I am currently digging how this type of execution without platform could work, my intuition was that the code of the repl could help but not sure about this. I would really love some pointers here :smile:.@Robin Camarasa just curious, is your goal to write a Roc version of the roc init subcommand?
Maybe I'm missing something, but I'd say a compiler feature like this should be integrated into the Rust code that's already present
Hi @Sam Mohr, I probably did not make myself clear enough . I am working on a fork of the repo of the roc compiler and writing everything in Rust. Once it's ready I will make a pull request. Does that clear things out?
@Robin Camarasa pretty much everything you need is in the roc glue subcommand, and you cant find the entrypoint here;
So you could copy paste that, remove all the glue/Types related stuff and "call" the init.roc main to see what files the platform needs generated.
Roc cli will load the init.roc and build that roc app into a dynamic library, then load that and call it to see what files the plugin from the platform wants generated.
Oh yes indeed you already mentioned it before but I kind of forgot about it. I will explore glue! Thanks!
roc_init crate (in crates/init)roc_glue code to crates/initinit.rocmain : Str -> List { name : Str, content : Str }
main = \platform ->
[{ name : "app.roc", content: "app [main] { pf: platform \"$(platform)\" }\n\n# Can segfault on some Ubuntu 20.04 CI machines, see #164.\nmain = \"Roc <3 Go!\"\n" }]
LoadingProblem(FormattedReport("\u{1b}[1;36m── MISSING HEADER in scratch/test_platform/init.roc ────────────────────────────\u{1b}[0m\n\nI am expecting a header, but got stuck here:\n\n\u{1b}[1;36m1\u{1b}[0m\u{1b}[1;36m│\u{1b}[0m \u{1b}[37mmain = \\args ->\u{1b}[0m\n \u{1b}[1;31m^\u{1b}[0m\n\nI am expecting a module keyword next, one of \u{1b}[1;32minterface\u{1b}[0m, \u{1b}[1;32mapp\u{1b}[0m, \u{1b}[1;32mpackage\u{1b}[0m\nor \u{1b}[1;32mplatform\u{1b}[0m."))
init.roc file needs an header to be compiled. Is it the idea then that the init.roc should be an application?nix wizard(s) that made this happen)init.roc (https://github.com/RobinCamarasa/simple-roc-go-platform/blob/feat/add-init.roc/platform/init.roc)roc build --bundle .tar.br platform/main.roc, with the new init.rocroc init subcommand~/.cache/roc already contains the already installed platform and we could use this for the user to generate the code from a platform that he already downloaded.Is it the idea then that the
init.rocshould be an application?
Maybe, I'm not sure what @Luke Boswell had in mind for the plugin like behavior
Is it the idea then that the
init.rocshould be an application?
Yes this is the idea.
Similar to how RustGlue.roc is an app.
Last updated: Jun 16 2026 at 16:19 UTC