# Elm scripting, in the terminal

**URL:** <https://discourse.elm-lang.org/t/elm-scripting-in-the-terminal/10449>\
**Category:** Show and Tell\
**Created:** [September 25, 2025, 11:17pm UTC](https://discourse.elm-lang.org/t/elm-scripting-in-the-terminal/10449 "2025-09-25T23:17:50Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![setop](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/setop/32/4331_2.png) [@setop](https://discourse.elm-lang.org/u/setop)\
**Post date:** [September 25, 2025, 11:17pm UTC](https://discourse.elm-lang.org/t/elm-scripting-in-the-terminal/10449/1 "2025-09-25T23:17:50Z")

</div>

I wrote a [little hack](https://codeberg.org/setop/elm-scripting) to be able to produce static HTML code with Elm, in the terminal.

You give it :

```elm
import Html exposing (p, text)

main = p [] [text "Hello World!"]

```

It generates the corresponding HTML code:

```html
<p>
Hello World!
</p>

```

By extension, using only `text <content>`, it can produce any text output, like csv, any.

This is a cheap way to use Elm for scripting in the terminal.

---

<div class="post-metadata">

**Author:** ![setop](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/setop/32/4331_2.png) [@setop](https://discourse.elm-lang.org/u/setop)\
**Post date:** [September 26, 2025, 6:58pm UTC](https://discourse.elm-lang.org/t/elm-scripting-in-the-terminal/10449/2 "2025-09-26T18:58:39Z")

</div>

My first use case is to do some programmatic CAD.

 ![3D puzzle in OpenSCAD](https://canada1.discourse-cdn.com/flex035/uploads/elm_lang/original/2X/e/ed677f75904d9d7b5590611cf316174aa7128de7.jpeg)

I implement all the logic in Elm : model, translation, rotation, drawing ; use elm-scripting to generate the code for [OpenSCAD](https://openscad.org/) which does the rendering, and supports live reload. 🤓

---

<div class="post-metadata">

**Author:** ![dwayne](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/dwayne/32/5478_2.png) [@dwayne](https://discourse.elm-lang.org/u/dwayne)\
**Post date:** [September 27, 2025, 12:07pm UTC](https://discourse.elm-lang.org/t/elm-scripting-in-the-terminal/10449/3 "2025-09-27T12:07:25Z")

</div>

**Sidebar:** I looked into QuickJS and then went down this deep rabbit hole learning about [Fabrice Bellard](https://en.wikipedia.org/wiki/Fabrice_Bellard). His output and work ethic seems fascinating to me.

- [Portrait of a Super-Productive Programmer](https://web.archive.org/web/20210128085300/https://smartbear.com/blog/test-and-monitor/fabrice-bellard-portrait-of-a-super-productive-pro/)
- [ACM Journal Article](https://web.archive.org/web/20110726063943/http://www.freearchive.org/o/55dfc9935a719fc36ab1d16567972732c2db1fd7d7e3826fd73ee07e4c3c7d0b)

---

<div class="post-metadata">

**Author:** ![setop](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/setop/32/4331_2.png) [@setop](https://discourse.elm-lang.org/u/setop)\
**Post date:** [September 27, 2025, 4:48pm UTC](https://discourse.elm-lang.org/t/elm-scripting-in-the-terminal/10449/4 "2025-09-27T16:48:13Z")

</div>

Yes, it’s nice to be standing on the shoulders of giants.

---

<div class="post-metadata">

**Author:** ![dirkbj](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/dirkbj/32/3162_2.png) [@dirkbj](https://discourse.elm-lang.org/u/dirkbj)\
**Post date:** [September 30, 2025, 6:17pm UTC](https://discourse.elm-lang.org/t/elm-scripting-in-the-terminal/10449/5 "2025-09-30T18:17:46Z")

</div>

OK - this is super cool. Thanks for sharing! 🙂

---

<div class="post-metadata">

**Author:** ![setop](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/setop/32/4331_2.png) [@setop](https://discourse.elm-lang.org/u/setop)\
**Post date:** [October 7, 2025, 8:23pm UTC](https://discourse.elm-lang.org/t/elm-scripting-in-the-terminal/10449/6 "2025-10-07T20:23:08Z")

</div>

Yesterday I was playing with [elm-explorations/markdown](https://package.elm-lang.org/packages/elm-explorations/markdown/latest/Markdown) to do some markdown to html rendering.

I discovered that it is using `innerHTML` attribute to store the result of `toHtml` which my code was not handling properly. BTW it also requires `global` to exist.

This has been [fixed](https://codeberg.org/setop/elm-scripting/commit/0758e1e9b411550d29243bd87bd308fe383bc0ff). Now the [code](https://codeberg.org/setop/elm-scripting/src/branch/main/dom.js#L19) first looks for text content, if not, looks for inner HTML content, if not, recurse to children.

---

<div class="post-metadata">

**Author:** ![setop](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/setop/32/4331_2.png) [@setop](https://discourse.elm-lang.org/u/setop)\
**Post date:** [October 15, 2025, 11:52am UTC](https://discourse.elm-lang.org/t/elm-scripting-in-the-terminal/10449/7 "2025-10-15T11:52:31Z")

</div>

I made an improvement to the tool today. Input content can be passed to the script via standard input. On script side, this is captured as a parameter of the `init` function.

Now, with the following script :

```elm
module MdRender exposing (main)

import Browser
import Html.Attributes exposing (class)
import Markdown

main =
  Browser.element
    { init = \s -> (s, Cmd.none)
    , update = \m c -> (m, Cmd.none)
    , view = \m -> Markdown.toHtml [class "content"] m
    , subscriptions = always Sub.none
    }

```

We can render md content into html with `elmscript.sh src/MdRender.elm < README.md > README.html`.

I really enjoy how hackable the Elm runtime is 🙂

---

<div class="post-metadata">

**Author:** ![ad-si](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/ad-si/32/4713_2.png) [@ad-si](https://discourse.elm-lang.org/u/ad-si)\
**Post date:** [October 20, 2025, 8:58pm UTC](https://discourse.elm-lang.org/t/elm-scripting-in-the-terminal/10449/8 "2025-10-20T20:58:36Z")

</div>

Is the code for this available somewhere? I’d be very interested in checking it out 😁  
I’ve been playing around with using Lua as a frontend for OpenSCAD: [GitHub - ad-si/LuaCAD: Create CAD models with Lua and OpenSCAD](https://github.com/ad-si/LuaCAD)  
But using Elm would actually be cooler! 😎

---

<div class="post-metadata">

**Author:** ![arthur](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/arthur/32/5516_2.png) [@arthur](https://discourse.elm-lang.org/u/arthur)\
**Post date:** [October 22, 2025, 7:14pm UTC](https://discourse.elm-lang.org/t/elm-scripting-in-the-terminal/10449/9 "2025-10-22T19:14:34Z")

</div>

@setop, amazing project!

Could you please share some code on OpenSCAD? I had never heard of it until you mentioned your first use case. Programmatic CAD with Elm will be really cool!

---

<div class="post-metadata">

**Author:** ![setop](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/setop/32/4331_2.png) [@setop](https://discourse.elm-lang.org/u/setop)\
**Post date:** [October 22, 2025, 10:12pm UTC](https://discourse.elm-lang.org/t/elm-scripting-in-the-terminal/10449/10 "2025-10-22T22:12:42Z")

</div>

Woah, your project looks very interesting.

I’m very far from having anything similar to show.

Programmatic CAD in Elm is currently just an experimentation and elm-script is a side product born form the fact that I was tired of constantly copy-pasting code between the browser and the editor.

I may eventually publish something if it become usable.

---

<div class="post-metadata">

**Author:** ![setop](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/setop/32/4331_2.png) [@setop](https://discourse.elm-lang.org/u/setop)\
**Post date:** [October 22, 2025, 10:30pm UTC](https://discourse.elm-lang.org/t/elm-scripting-in-the-terminal/10449/11 "2025-10-22T22:30:01Z")

</div>

If you don’t know OpenSCAD yet, you should definitely start by reading the [tutorial](https://en.wikibooks.org/wiki/OpenSCAD_Tutorial), very nice reading.

Then, when using it, the [cheatsheet](https://openscad.org/cheatsheet/index.html) is really useful.

If you want to see what can be done with it in the 3D printing field, have a look at their [thigiverse group](https://www.thingiverse.com/groups/openscad#:~:text=Things).

---

<div class="post-metadata">

**Author:** ![arthur](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/arthur/32/5516_2.png) [@arthur](https://discourse.elm-lang.org/u/arthur)\
**Post date:** [October 23, 2025, 8:02pm UTC](https://discourse.elm-lang.org/t/elm-scripting-in-the-terminal/10449/12 "2025-10-23T20:02:38Z")

</div>

Thanks, @setop! Really nice!

Do you use _elm-scripting_ to produce OpenSCAD code with the `text` function, as in `text “cube(10);”`?

---

<div class="post-metadata">

**Author:** ![setop](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/setop/32/4331_2.png) [@setop](https://discourse.elm-lang.org/u/setop)\
**Post date:** [October 23, 2025, 8:11pm UTC](https://discourse.elm-lang.org/t/elm-scripting-in-the-terminal/10449/13 "2025-10-23T20:11:26Z")

</div>

> [@arthur](#):
>
> Do you use _elm-scripting_ to produce OpenSCAD code with the `text` function, as in `text “cube(10);”`?

Exactly

Create a file `src/Cube10.elm` with content :

```elm
module Cube10 exposing(main)

import Html exposing (text)

main = text "cube(10);"

```

Then invoking `./elmscript.sh src/Cube10.elm` will do the trick.

---

<div class="post-metadata">

**Author:** ![system](https://canada1.discourse-cdn.com/flex035/uploads/elm_lang/original/1X/50a05e53677a2c3b47776d7abd0f113eb50193a1.png) [@system](https://discourse.elm-lang.org/u/system)\
**Post date:** [November 2, 2025, 8:11pm UTC](https://discourse.elm-lang.org/t/elm-scripting-in-the-terminal/10449/14 "2025-11-02T20:11:58Z")

</div>

Closed on November 2, 2025, 8:11pm UTC

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.
