Skip to content

Conversation

@RomeoV
Copy link

@RomeoV RomeoV commented Nov 26, 2025

This PR may relate to or close Roger-luo/Configurations.jl#100.

Summary

This PR implements a simple CLI interface to launch Pluto using Julia 1.11 "apps".

Using this PR allows a user to run

pluto mynotebook.jl
pluto --port=1235 --dont-launch-browser
# etc

Currently only a small subset of Pluto.run(; ...) flags are supported - in particular those which are documented under ?Pluto.run (see PlutoApp.jl in this PR.)
For more complex use cases a user can just launch Pluto from a Julia REPL as before.

Motivation

A minor issue that we keep running into is that students are confused exactly how Pluto relies to a "package" they are developing (typically bundling some research code etc).
They end up installing Pluto into their package (adding it as a dependency) and are confused why their package is not available from inside Pluto.
I think this is because the mental model that Pluto launches new Julia workers is not obvious.

With the app workflow I hope that users have a new mental model that you launch Pluto from "anywhere" as an app and then activate their own project from inside Pluto.

Choice of CLI Parser library

I have chosen Comonicon.jl. Alternatives include

I have chosen because it is relatively widely used, let's us write a quite concise interface, Pluto already uses Configurations.jl from the same ecosystem (i.e., author), and I was the most familiar with it.

Happy to get feedback whether this feature is wanted and reasonable in this current form.

Run the app code

You can either do something like

julia --project -m Pluto.PlutoApp --help

or

]app dev .
;pluto --help

For the prior, you may want to consider commenting out the precompile when playing around with the CLI interface (to accelerate your CLI interface feedback loop) by commenting out include("./precompile.jl") in src/Pluto.jl.

Try this Pull Request!

Open Julia and type:

julia> import Pkg
julia> Pkg.activate(temp=true)
julia> Pkg.add(url="https://github.com/RomeoV/Pluto.jl", rev="add-app")
julia> using Pluto

that will be printed in the beginning of the help string.
Notice that the formatting (i.e., the line breaks) are sometimes a bit
scuffed, but that seems to be a limitation of Markdown.jl as discussed
in comonicon/Comonicon.jl#213 (comment).

Notice also that the `# Intro` header is required for Comonicon to
accept this docstring (otherwise it is skipped) as per https://comonicon.org/stable/conventions/#Description.
@fonsp
Copy link
Owner

fonsp commented Dec 1, 2025

Ahh very cool! I definitely want Pluto to feel more like an "app" and I agree that this will improve the mental.

We are currently working again on https://github.com/JuliaPluto/PlutoDesktop, and the hope is to release this within the next year :) So that should cover it for most beginner users, but we will continue to publish Pluto as a Julia package.

For this PR, I would really like to investigate if it would be possible to automatically generate the complete list of keyword arguments. Since Comunicon and Configurations.jl and from the same awesome developer, I was wondering if this was already achieved for another project. The talk at Juliacon that we mentioned in the issue you linked never happened :( but I'm still curious to hear Roger's opinion about this :)

Would you mind investigating this a bit? Maybe you can find more about the combination in documentation, or you can ask Roger about it.

Thank you!

Btw, we recently launched #3218 which allows students to test their local package inside a Pluto notebook without registering it. I still need to write good documentation for this on the Pluto website (help welcome!), but I am curious if you already knew about this feature and what your experience is.

@RomeoV
Copy link
Author

RomeoV commented Dec 2, 2025

Comonicon can directly work with @option annotated structs as per https://comonicon.org/stable/conventions/#Working-with-option-types-from-Configurations, for instance

using Test
using Comonicon
using Configurations

@option struct OptionA
    a::Int
    b::Int
end


"""
# Options

- `-c, --config <path/to/option/or/specific field>`: config.
"""
@main function run(;config::OptionA)
    @test config == OptionA(1, 1)
end

so this could lead to a very simple integration. I'm thinking something like

Comonicon.@main function pluto(
    notebooks::String...;
    server::Configuration.ServerOptions,
    security::Pluto.Configurations.SecurityOptions,
    compiler::Configuration.CompilerOptions,
    evaluation::Configuration.EvaluationOptions
)
    options = Options(; server, security, evaluation, compiler)
    session = ServerSession(; options)
    run(session)
end

One issue this currently has is that @option fields with type Union{Nothing, T} are not supported well at the moment. I think in the end there is a tryparse(Union{Nothing, T}, input) call that fails. We could pirate that, or make a PR to Comonicon to try to fix that. Or perhaps we wrap every Union in some wrapper type PlutoUnion{Union{...}} and then override tryparse for that...

@RomeoV
Copy link
Author

RomeoV commented Dec 2, 2025

The Union{Nothing, T} problem could probably be solved by using Configurations.Maybe instead, and then telling MsgPack about that type.

Nvm that just aliases Maybe{T} = Union{Nothing, T} as per https://github.com/Roger-luo/Configurations.jl/blob/f7da275772610d0a9b58eab0438fdcf6491024cd/src/types.jl#L2

@fonsp
Copy link
Owner

fonsp commented Dec 10, 2025

Okay! What do you think we should do next? Maybe we can write an issue for Roger to ask for help?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

What is the best way to support --module arguments in Julia 1.12?

2 participants