The REPL

ecko            # or: ecko repl

An interactive session. Bindings persist across lines, so you can build up state:

ecko v0.24.0 // REPL on Linux // ecko.sh
> xs = [3, 1, 2]
> sort(xs)
[1, 2, 3]
> fn double(n) = n * 2
> map(xs, double)
[6, 2, 4]

The value of each expression is printed. Statements that produce nothing print nothing.

Multi-line input

A line that cannot yet be a complete program continues:

> fn classify(n) {
    if n > 0 { "positive" } else { "not positive" }
  }
> classify(5)
"positive"

Imports and ai

Everything the language has is available, including the standard library and the ai keyword:

> import std.time
> time.now_iso()
"2026-07-30T09:12:44Z"
> ai[Int] "How many continents?"
42

42 is the mock mode answer for ai[Int] - schema-valid and deterministic, because no provider is configured. Set ECKO_API_KEY before starting the REPL for real responses.

Completion and history

TAB completes the word under the cursor: keywords, std modules, anything in scope, and a module's members after a dot. One TAB fills in as far as the candidates agree, a second lists them.

> import std.io
> io.read_<TAB><TAB>
io.read_all  io.read_exact  io.read_line  io.read_text  io.read_until

Grey text ahead of the cursor is a line you typed before, not a completion. Right arrow or End accepts it. It comes from ~/.ecko_history, which lasts between sessions, so a line you once mistyped keeps being offered until you remove it from that file.

Session state

REPL globals live for the session. Redefining a name shadows the old value, and mut is not needed for a rebind at the top level.

State does not survive restarting. When you want something durable, put it in a file and run it - or use ecko dev, which re-runs a file every time you save it.

Leaving

exit leaves, and so do quit, :exit, :q and Ctrl-D. A trailing semicolon is ignored on those, so exit; works too. Ctrl-C cancels the line you are typing without exiting.