This is the guided start: you create a folder, paste four small files, and end up stepping through your first Mica program in a real debugger — variables in the panel, breakpoints on source lines. It takes about fifteen minutes, works the same on macOS, Linux, and Windows, and installs nothing on your machine beyond Docker and VS Code.
The short way. Everything on this page also exists ready-made:
git clone https://gitlab.com/mica-lang/mica-container.git, open the folder in VS Code, choose Reopen in Container, and you have the container, all the example suite, the benchmarks and F5 debugging over every one of them. That repository is the starter for Mica and the home of this tutorial series.This page is the long way, and it is worth the fifteen minutes once: you build the setup by hand, so you know what each piece does rather than inheriting it.
What you need — once
- Docker Desktop (macOS, Windows) or Docker Engine (Linux), running.
- VS Code.
- In VS Code, the Dev Containers extension — open the Extensions view,
search
Dev Containers, install the one by Microsoft (ms-vscode-remote.remote-containers).
That is the only extension you install yourself. The Mica language extension and the debugger extension arrive automatically in a moment — the container configuration you are about to paste names them, and VS Code installs them inside the container for you.
Step 1 — an empty folder
In a terminal:
mkdir hello-mica && cd hello-mica
mkdir .devcontainer .vscode
code .The two dot-folders are where VS Code looks for its configuration — the
container description goes into .devcontainer, the build-and-debug wiring
into .vscode.
(If code is not on your PATH: open VS Code, press F1, run Shell Command:
Install ‘code’ command in PATH — or simply open the folder via File → Open
Folder.)
Step 2 — describe the container
In VS Code’s Explorer, create a file devcontainer.json inside the
.devcontainer folder, with exactly this content:
{
"name": "Mica",
"image": "micalang/mica:latest",
"customizations": {
"vscode": {
"extensions": [
"mica-development-ug.mica-language",
"ms-vscode.cpptools"
]
}
},
"runArgs": ["--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined"],
"containerEnv": { "DEBUGINFOD_URLS": "" },
"remoteUser": "mica"
}Four facts in one file: which image to run (the official Mica image — compiler, linker tools, and gdb, about 77 MB, for Intel and ARM machines alike), which two extensions to install inside it, and debugger-friendly container settings — including switching off gdb’s online symbol lookup, which would otherwise freeze containerized debug sessions for minutes.
Step 3 — wire the debugger
Two more small files teach VS Code how to build and debug the file you are
editing. Create .vscode/tasks.json:
{
"version": "2.0.0",
"tasks": [
{
"label": "Mica: build current file (debug)",
"type": "shell",
"command": "mica-build-debug",
"args": ["${file}"],
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": []
}
]
}and .vscode/launch.json:
{
"version": "0.2.0",
"configurations": [
{
"name": "Debug current Mica binary",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build/${fileBasenameNoExtension}/${fileBasenameNoExtension}",
"args": [],
"stopAtEntry": true,
"preLaunchTask": "Mica: build current file (debug)",
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"miDebuggerPath": "/usr/bin/gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
},
{
"description": "Set disassembly flavor to Intel",
"text": "-gdb-set disassembly-flavor intel",
"ignoreFailures": true
}
],
"internalConsoleOptions": "openOnSessionStart"
}
]
}The task compiles whatever .mica file you have open, at the debug tier —
every variable observable, every line breakable. The launch configuration runs
the result under gdb. (Both files, and everything else on this page, also live
ready-made in the tutorial repository.)
Step 4 — your first program
Create Hello.mica:
program Hello;
imp
WriteLn : std;
begin
WriteLn("Hello, Mica!");
end.Two things worth noticing already. program Hello; names the program — the
compiled binary will be named Hello after this declaration, and by
convention the file carries the same name. And WriteLn is imported: in
Mica everything a program uses arrives
through an imp declaration, so a source file tells you its dependencies
honestly — nothing is ambient.
Step 5 — reopen in the container
VS Code has noticed the .devcontainer folder and offers Reopen in
Container in the corner — click it (or press F1 and run Dev Containers:
Reopen in Container).
The first time, this pulls the image and installs the two extensions into it —
a minute or two. Every later open is seconds. When the window reloads you are
inside the container: the Mica extension is active, and hovering WriteLn
shows its signature — that answer comes from the compiler itself, running as a
language server.
Step 6 — compile it
Open a terminal (Terminal → New Terminal — it is a shell inside the container) and:
mica-build-debug Hello.micaEverything the build produces lands in a folder named after the source file:
build/Hello/. There is a sibling, mica-build-fullopt, that produces the
fully optimized build with the same usage — but for the debugger, the debug
tier is the one you want.
Step 7 — run it
./build/Hello/HelloHello, Mica!Two namings meet here: the folder is named after the file, the binary after
the program declaration in the source — and by Mica convention the two
agree, which is why the file is called Hello.mica. Rename the program, and
the binary renames with it: the source is in charge.
Step 8 — something worth debugging
Replace the content of Hello.mica with:
program Hello;
imp
WriteLn : std;
var
greeting: string;
answer: int64;
begin
greeting := "Hello, Mica!";
answer := 6 * 7;
WriteLn("%ls says the answer is %lld", greeting, answer);
end.var declares variables with explicit types; := assigns. The format string
is checked at compile time: %ls is a string, %lld an int64. Try
changing %lld to %d and saving — the editor underlines it immediately with
the compiler’s own error (format specifier ‘%d’ incompatible with type:
int64), because the language server runs the same analysis the build does.
Change it back.
Step 9 — breakpoint, inspect, step
- Make sure
Hello.micais the active editor tab — the debugger builds and runs whatever source file you have focused, so debugging always starts from the program you are looking at. Then click in the gutter left of theWriteLnline — a red breakpoint dot appears. - Press F5. The build task compiles the focused file —
Hello.mica— and gdb launches its binary, pausing at the program’s entry — that first stop is deliberate, so you always get control before anything runs. (The Debug Console fills with startup chatter — gdb’s version banner, aFailed to set controlling terminalwarning, on ARM machines anassuming x86_64guess from the VS Code extension. All of it is harmless and none of it is Mica: the pause at entry and the Variables panel are the debugger working.) - Press F5 again to continue to your breakpoint. Look at the
Variables panel:
greetingis there with its text and its length of12runes,answeris42, andexit— the program’s result variable — is0. - Press F10 to step over the
WriteLnline. The Debug Console showsHello, Mica! says the answer is 42. - Press F5 to let the program finish.
You have compiled, run, and stepped through native ARM64 or x86-64 machine code — whichever your machine speaks — with full source-level debugging, and nothing was installed on your computer beyond Docker and VS Code.
Where to go next
Mica as a scripting language is the five-minute stop
worth making before the series proper: one command compiles and runs a file,
a shebang line turns it into a tool on your PATH, and every compile-time
check runs before the program does. It changes how you use everything that
follows.
Part 2: The shape of a Mica program reads that program
properly — the four parts every Mica program has, why every name must be
imported, and the format string the compiler checks before it builds anything.
It works from the cloned repository, so
git clone https://gitlab.com/mica-lang/mica-container.git is the one command
that carries you into the rest of the series.
Meanwhile:
- The project file — how a compilation’s facts get a home beside the sources, and why the editor is never wrong about your build.
- The command-line reference — every flag of the
micabinary the build scripts wrap. - Install Mica natively — the Debian package, when you want the compiler on the machine itself.
- What the compiler guarantees — the part of Mica that grows on you.
Stuck, or delighted? info@mica-dev.com reads everything.