Odin and Me ยท Chapter 1

Chapter 1: Odin and Me, Setup and a first console program

This chapter:

  • See what we're building for the terminal.
  • Install Odin and confirm it works.
  • Set up your editor.
  • Print your first line of output with odin run.

1.1 What we're building

In this book, I'll quickly walk you through the Odin basics in a few short chapters. We'll build small, complete programs targeting the terminal, using text, colour, and cursor control to make that text feel like a real application.

Along the way, you'll build some utilities: the classic temperature converter, a word counter, nested loops that draw triangles and diamonds out of asterisks, and of course a number-guessing game. Each is a complete, runnable program in its own right, teaching one idea cleanly before moving on.

From Chapter 7 onward, those ideas start pointing at one destination: Muninn, a small console application named after one of Odin's ravens, Memory. It opens with a banner, shows a box-drawn menu, and lets you add, list, search for, and delete short notes that persist between runs. It features a coloured, framed, keyboard-driven interface built entirely from characters printed to standard output, and a note store that persists to a plain text file.

Every visual effect in Muninn: colour, a cleared screen, a box drawn with clean corners, a banner centred just so, is a short sequence of bytes any terminal from the last four decades knows how to interpret.

1.2 What you need

  • A computer running Windows, macOS, or Linux.
  • A terminal.
  • A text editor.

That's the whole list. If you can open a terminal and type, you're fully equipped. Internet access is a bonus for extra research, but it's optional.

1.3 Installing Odin

Follow the official installation guide: https://odin-lang.org/docs/install/. There are prebuilt releases for each platform, and instructions for building from source if you prefer. Work through the guide there rather than trusting a summary here that might drift out of date.

Once it's installed and on your PATH, confirm it:

odin version

You should see something like dev-2026-07:... (I wrote and verified these chapters against a dev-2026-07 build).

1.4 Setting up your editor

Two things make Odin pleasant to write:

  • Syntax highlighting. Most editors have an Odin extension; the Odin site links the current ones.
  • The language server, ols. ols gives you go-to-definition, autocomplete, and inline errors. Install it and point your editor's LSP client at it. It isn't required (the compiler is the source of truth), but it makes exploring the standard library far more pleasant.

The command you'll lean on most doesn't need an editor at all:

odin check .

This type-checks a whole package directory without producing a binary: it's fast, and the quickest way to catch a mistake. For the single-file programs we start with, the equivalent is:

odin check hello.odin -file

The -file flag tells Odin to treat one .odin file as a self-contained package, rather than expecting a directory of them. You'll use -file throughout the early chapters, and drop it once Chapter 9 grows the project into a proper multi-file directory.

1.5 Hello, terminal

Make a directory for our exercises and create one file in it:

mkdir odin-and-me
cd odin-and-me
// hello.odin
package main

import "core:fmt"

main :: proc() {
	fmt.println("Hello, Odin!")
}

Run it:

odin run hello.odin -file

You should see:

Hello, Odin!

That's the goal: getting your toolchain to compile and run a program. Let's quickly see what this program does and how it works:

  • package main: a directory is a package (or, with -file, a single file stands in for one); the package containing a main procedure is a program's entry point. Every program we write here is package main.
  • import "core:fmt": pull in Odin's formatted-printing package from the standard library's core: collection. You'll meet several more core: packages over the coming chapters: Odin's standard library is generous, and it's all we'll need.
  • main :: proc() { ... }: a procedure declaration. :: binds a name to a value at compile time; here the value is a procedure. Every Odin program needs exactly one main.
  • fmt.println("Hello, Odin!"): print a string followed by a newline. You'll use fmt.println and its formatted cousin fmt.printf constantly from here on.

Odin note: odin run vs odin build. odin run compiles a temporary binary and immediately executes it: the everyday loop while you're working. odin build compiles and stops, leaving you a binary to run yourself (or ship): the tool for Chapter 12, when Muninn becomes something you hand to someone else.

Gotcha: the -file flag isn't optional for a lone file. odin run hello.odin on its own fails with an error telling you to add -file. Odin's run/build/check commands expect a package (a directory) by default. Once Chapter 9 gives Muninn several files in one directory, you'll drop -file and simply run odin run . instead.

1.6 The journey ahead

Here's the road from that one line of output to a working application:

  • Ch. 2: a fast tour of the parts of Odin we'll use throughout our programs: types, variables, control flow, procedures.
  • Ch. 3: reading a line from the keyboard and parsing it into a number: your first interactive program.
  • Ch. 4: strings, runes and UTF-8, building a word-counting tool.
  • Ch. 5: nested loops, drawing triangles, diamonds and pyramids out of text.
  • Ch. 6: structs, enums and a first taste of randomness, in a number-guessing game.
  • Ch. 7: clearing the screen, colour, box-drawing characters, and a menu loop: the DOS-style look, from first principles.
  • Ch. 8: reading and writing a file, so a program's data survives being closed and reopened.
  • Ch. 9: designing Muninn's note store: a struct, a dynamic array, and the operations over it.
  • Ch. 10: wiring the menu and the store together: Muninn, usable end to end.
  • Ch. 11: making it robust: validated input, and a save file that survives being corrupted.
  • Ch. 12: a release build, and shipping Muninn as a single binary.

Chapters 1 to 8 are one complete, standalone program apiece; each is shown to you in full, start to finish, so you can follow along. From Chapter 9 the project grows into one directory (all one package main):

odin-and-me/
โ”œโ”€โ”€ main.odin      # entry point: init, the menu loop, teardown
โ”œโ”€โ”€ screen.odin    # ANSI helpers: clear, cursor, colour, box-drawing, banner
โ”œโ”€โ”€ menu.odin      # the menu state machine + rendering
โ”œโ”€โ”€ note.odin      # the Note struct
โ”œโ”€โ”€ store.odin     # add/find/delete/list over the note store
โ”œโ”€โ”€ persist.odin   # save/load notes to a file
โ”œโ”€โ”€ input.odin     # line-reading + validated-input helpers
โ”œโ”€โ”€ build.sh       # makes it easier to build the project
โ””โ”€โ”€ run.sh         # handy for building then running the project

Checkpoint

odin run hello.odin -file prints Hello, Odin! and exits. Your compiler works and your editor is set up.

Exercises

  1. Change the greeting to print your own name, and add a second fmt.println call that prints a second line. Rebuild and confirm both lines appear in order.
  2. Run odin check hello.odin -file, then deliberately misspell fmt.println as fmt.Println. Read the error message Odin gives you, then fix it. (Solution sketch: Odin is case-sensitive, and the compiler names the exact identifier it couldn't find: get comfortable reading that error, you'll see its shape again.)
  3. Try fmt.print instead of fmt.println for your two lines. What's different about the output, and why? (Solution sketch: println appends a newline after its arguments; print doesn't: watch your two lines run together.)
  4. What happens if you delete the main :: proc() { ... } wrapper entirely and leave just the fmt.println call at the top level? Try it, read the error, and put main back. (Solution sketch: Odin has no implicit top-level statements: every executable line has to live inside a procedure, and every program needs exactly one main.)

Further reading