Tutorial: your first MoonBit program in Turbo MoonBit
By the end of this tutorial you will have written, formatted, run and broken a small MoonBit program without leaving the editor — and seen the editor tell you where the mistake was.
No prior knowledge of Turbo MoonBit is needed. You need Go 1.26 or later to build the editor, and the MoonBit toolchain to build the program.
Prerequisites
Check Go:
go version
You should see something like:
go version go1.26.5 linux/arm64
Check the MoonBit toolchain:
moon version --all
You should see three lines, each ending in a path:
moon 0.1.20260904 (94521db 2026-09-04) ~/.moon/bin/moon
moonc v0.10.12+1634b282e (2026-09-07) ~/.moon/bin/moonc
moonrun 0.1.20260904 (94521db 2026-09-04) ~/.moon/bin/moonrun
If that command is not found, install the toolchain first — one command does it.
Step 1 — Install the editor
git clone https://rickub.com/turbo-editors/turbo-moonbit.git
cd turbo-moonbit
make install
The installer builds, installs, and then checks what it installed. The last lines are:
==> Checking the language server
✓ moon-lsp at ~/.moon/bin/moon-lsp
==> Ready
We now have a turbo-moonbit command.
Step 2 — Make a project
cd /tmp
moon new hello
cd hello
Created username/hello at hello
moon new writes a moon.mod, a moon.pkg, a library file, some test files, and a cmd/main/main.mbt with a hello-world in it. moon.mod is what Turbo MoonBit looks for to find the root of a project, and it is the directory moon-lsp will be started in.
Step 3 — Open the file
turbo-moonbit cmd/main/main.mbt
The screen fills. Along the top:
File Edit Search Run Code Options Window Snippets MoonBit Help
Ten menus, and the ninth is named after the language. Along the bottom, at the right-hand end, you should see:
1:1 LSP: ready
LSP: ready means moon-lsp started in this directory. We will use it in Step 8.
Step 4 — Write the program
Select everything with Ctrl-A and press Delete, then type this in. Type it exactly; we will look at the colours next.
///|
struct Greeting {
name : String
times : Int
}
///|
fn greet(g : Greeting) -> Unit {
for i in 0..<g.times {
println("Hello, \{g.name}! (\{i + 1})")
}
}
///|
fn main {
greet({ name: "MoonBit", times: 3 })
}
Press F2 to save. The star beside main.mbt in the window's title goes away.
Step 5 — Read the colours
Look at what you have typed. In the default turbo-classic theme:
| What | Colour |
|---|---|
struct, fn, for, in |
bright white, bold — keywords |
Greeting, String, Int, Unit |
bright cyan — types |
greet, where it is declared and where it is called |
bright yellow, bold — functions |
println |
bright cyan, bold — a name the language provides |
name, times, g, i |
bright yellow — ordinary names |
"Hello, \{g.name}! (\{i + 1})" |
green, all of it — one string |
0, 1, 3 |
magenta — numbers |
///| |
grey — a comment |
Two of those rows are worth a second look.
Greeting is cyan and greet is yellow, and nothing in the editor was told which of them is a type. MoonBit's own rule decides it: a name beginning with a capital can only be a type, a trait or a constructor.
The string is green from the first quote to the last, interpolations included. The \{g.name} inside it is not coloured as code — and that is on purpose.
Step 6 — Give the project its tools
Press F10 to open the menu bar, then → eight times to reach MoonBit — past Edit, Search, Run, Code, Options, Window and Snippets. Faster: press Alt-M.
The menu holds two items, and only one of them is available:
┌───────────────────┐
│ Create tools file │
│ Open tools file │ ← greyed out; there is no file to open yet
└───────────────────┘
Choose Create tools file.
A second window opens on the file that was just written, .turbo-moonbit/tools.toml. Read it if you like — it explains every key it uses — then press Ctrl-W to close it.
Open the MoonBit menu again. It now holds nine commands, and the two items have swapped: Create tools file is greyed out, and Open tools file is the one you can choose.
Step 7 — Format it, and run it
Press Alt-M and choose Format.
A dialog opens, fills in, and says — exit 0. Press Escape.
Look at the last line of your main function. It has changed:
greet({ name: "MoonBit", times: 3, })
moon fmt added a trailing comma, and the editor reloaded the file it had just been told had changed underneath it.
Now Alt-M, then Run. A box asks for a value before the command runs:
┌──────────────── Run ────────────────┐
│ package, e.g. cmd/main │
│ [ ] │
└─────────────────────────────────────┘
Type cmd/main and press Enter. A terminal window opens and the program runs in it:
Hello, MoonBit! (1)
Hello, MoonBit! (2)
Hello, MoonBit! (3)
A terminal rather than a dialog, because a program that reads the keyboard has to be answerable. The program has finished, so the window has stopped behaving like a terminal and every key reaches the editor again: press Ctrl-W to close it.
Step 8 — Break it, and see where
Go to the println line and change g.name to g.nam. Press F2 to save.
Within a second or two, two things happen. A red × appears in the gutter, just left of that line's number. And the status bar reads:
⚠ The value identifier nam is unbound.
Nothing asked for that. moon-lsp publishes it by itself whenever it re-reads the file.
Put the e back and save again; both the mark and the message go away.
Step 9 — Change the theme
F10, then → five times to reach Options — past Edit, Search, Run and Code. Choose Theme….
A list opens on the theme you are in. Press ↓ to cobalt and Enter. The whole screen changes, keeping the same shape.
Press Alt-X to leave. The editor asks about unsaved files first, if there are any.
What now?
You have made a MoonBit project, written a program in the editor, formatted it, run it, broken it, and seen the editor say where. To go further:
- To do specific things → the how-to guides
- To see exactly what is coloured and how → languages coloured
- To understand why the editor is built this way → the explanation
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 |
|