# Creating a CLI app in Julia

**URL:** https://discourse.julialang.org/t/creating-a-cli-app-in-julia/111160
**Category:** General Usage
**Tags:** cli
**Created:** [March 4, 2024, 9:07pm UTC](https://discourse.julialang.org/t/creating-a-cli-app-in-julia/111160 "2024-03-04T21:07:36Z")
**Posts on this page:** 8
**Page:** 1

<div class="post-metadata">

### Author: ![Eben60](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/eben60/32/13475_2.png) [@Eben60](https://discourse.julialang.org/u/Eben60)
#### Post date: [March 4, 2024, 9:07pm UTC](https://discourse.julialang.org/t/creating-a-cli-app-in-julia/111160/1 "2024-03-04T21:07:36Z")

</div>

I have to share my code in a way that my non-programming colleagues can use it on their own. Currently there is a Julia function which accepts a path to an Excel file, containing all data and metadata, does processing, creates a folder and puts result files therein. My personal usage is a script file in VSCode, where I just (re-)write the path as a parameter. Installing VSCode on their Win10 computers and teaching them how to run such a script is a feasible option.

Another option is a CLI application. Besides ArgParse.jl , a short search found Comonicon.jl , Fire.jl , and [maurice](https://github.com/diversable/maurice) . I am not sure I understand all usages, but it seems in each case the Julia script would be executed _once_ with the provided arguments, meaning Julia re-start for each input. Well, waiting 10…30s should be acceptable.

But I’d prefer a CLI app processing multiple inputs in a loop like this:

```julia
> mdeq.bat
provide the file please
mdeq>C:\somepath\experimentXX.xlsx
processed OK
provide the file please
mdeq>C:\somepath\experimentYY.xlsx
provide the file please
mdeq>exit
>

```

Sure, not that difficult to write from the scratch, but can it be that nobody has done that before?

---

<div class="post-metadata">

### Author: ![PeterSimon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/petersimon/32/25193_2.png) [@PeterSimon](https://discourse.julialang.org/u/PeterSimon)
#### Post date: [March 4, 2024, 10:26pm UTC](https://discourse.julialang.org/t/creating-a-cli-app-in-julia/111160/2 "2024-03-04T22:26:00Z")

</div>

```julia
while true
    print("Enter filename or empty line to finish: ")
    fname = readline(stdin)
    isempty(fname) && break
    do_computation(fname)
    println("Completed processing $fname")
end

```

---

<div class="post-metadata">

### Author: ![Eben60](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/eben60/32/13475_2.png) [@Eben60](https://discourse.julialang.org/u/Eben60)
#### Post date: [March 4, 2024, 10:52pm UTC](https://discourse.julialang.org/t/creating-a-cli-app-in-julia/111160/3 "2024-03-04T22:52:35Z")

</div>

Thank you, that indeed would be sufficient in my case (will only have to add activating the proper environment).

Still, just out of curiosity: E.g. Fire.jl offers a number of practical options. Maybe there exists something like that, but in a loop, ready to use?

---

<div class="post-metadata">

### Author: ![ffevotte](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ffevotte/32/6587_2.png) [@ffevotte](https://discourse.julialang.org/u/ffevotte)
#### Post date: [March 4, 2024, 10:55pm UTC](https://discourse.julialang.org/t/creating-a-cli-app-in-julia/111160/4 "2024-03-04T22:55:23Z")

</div>

> [@PeterSimon](#):
>
> ```julia
> print("Enter filename or empty line to finish: ")
> fname = readline(stdin)
> 
> ```

NativeFileDialog.jl is also nice for this:

```julia
using NativeFileDialog: pick_file

while true
    fname = pick_file(homedir(), filterlist = "xlsx")
    isempty(fname) && break # user cancelled

    do_computation(fname)
    println("Completed processing $fname")
end

```

---

<div class="post-metadata">

### Author: ![GHTaarn](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ghtaarn/32/216007_2.png) [@GHTaarn](https://discourse.julialang.org/u/GHTaarn)
#### Post date: [March 5, 2024, 1:34am UTC](https://discourse.julialang.org/t/creating-a-cli-app-in-julia/111160/5 "2024-03-05T01:34:40Z")

</div>

> [@Eben60](#):
>
> Another option is a CLI application. Besides ArgParse.jl , a short search found Comonicon.jl , Fire.jl , and [maurice](https://github.com/diversable/maurice) .

[GitHub - MasonProtter/ReplMaker.jl: Simple API for building repl modes in Julia](https://github.com/MasonProtter/ReplMaker.jl) is also a really nice tool for making CLIs with line editing and with options to have history and tab completion (mostly for the benefit of others reading this thread as it is probably not ideal for your situation).

---

<div class="post-metadata">

### Author: ![Eben60](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/eben60/32/13475_2.png) [@Eben60](https://discourse.julialang.org/u/Eben60)
#### Post date: [March 9, 2024, 9:47am UTC](https://discourse.julialang.org/t/creating-a-cli-app-in-julia/111160/6 "2024-03-09T09:47:57Z")

</div>

I’m leaving my job, and have to provide an access to my Julia software for my colleagues. Here I document how I do it - in case someone may use it, too, or maybe suggest improvements.

I’ve copied the package onto our file server. Colleagues installed `juiaup` onto their (Windows) computers and executed:

```julia
juliaup add 1.10
juliaup default 1.10

```

Julia version in the `Project.toml` is pinned to 1.10

```julia
[compat]
julia = "~1.10"

```

The package folder is copied onto a user computer, and before the first use, the file `instantiate.bat` , sitting at the root of the project folder, is executed in terminal:

```julia
julia %~dp0src\instantiate.jl 

```

`%~dp0` being the path to the `bat` file

The `instantiate.jl` file:

```julia
using Pkg
basedir = splitdir(@ __DIR__ )[1]
Pkg.activate(basedir)
Pkg.instantiate()

```

To start program, use the file `main.bat`

```julia
julia %~dp0src\main.jl 

```

`main.jl` :

```julia
using Pkg
basedir = splitdir(@ __DIR__ )[1]
Pkg.activate(basedir)

using Mdes # my package
# using NativeFileDialog: pick_file # moved now into Mdes.jl

repl()

```

`repl.jl` :

```julia
function repl()
    imgtype = nothing
    while true
        println("Select the plots output format")
        println("Enter s for SVG, p for PDF, or just press ENTER for PNG")
        t = readline(stdin)
        t = t |> strip |> uppercase
        if isempty(t)
            imgtype="png"
        elseif t == "S"
            imgtype="svg"
        elseif t == "P"
            imgtype = "pdf"
        else
            println("sorry, cannot understand your input")
        end
        !isnothing(imgtype) && break
    end

    while true
        fname = pick_file(homedir(), filterlist = "xlsx")
        isempty(fname) && break # user cancelled
        try
            fit_all_and_save(fname; imgtype)
        catch ex
            println("Something went wrong: $ex")
        end
        println("Completed processing $fname")
    end
    return nothing
end

```

---

<div class="post-metadata">

### Author: ![GHTaarn](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ghtaarn/32/216007_2.png) [@GHTaarn](https://discourse.julialang.org/u/GHTaarn)
#### Post date: [March 10, 2024, 4:01am UTC](https://discourse.julialang.org/t/creating-a-cli-app-in-julia/111160/7 "2024-03-10T04:01:01Z")

</div>

I think that you made a typo, your colleagues might not know what a PFD file is.

---

<div class="post-metadata">

### Author: ![Eben60](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/eben60/32/13475_2.png) [@Eben60](https://discourse.julialang.org/u/Eben60)
#### Post date: [March 10, 2024, 8:40am UTC](https://discourse.julialang.org/t/creating-a-cli-app-in-julia/111160/8 "2024-03-10T08:40:31Z")

</div>

> [@GHTaarn](#):
>
> might not know what a PFD file is

Edited - thank you 🙂
