Global builtins reference
Around 95 functions are always in scope, with no import.
Collections
Transform: map, filter, reduce, flatten, zip, enumerate, chunk, window, unique, reverse, sort, sort_by, group_by, partition, frequencies, select.
Access: first, last, take, get, len, contains, index_of, find, count, any, all, sum, min, max, empty_map, keys, values.
Build: push, pop, insert, remove, range, list.
Parallel: pmap.
get is the nullable lookup - get(m, k) and get(xs, i) return null on a miss, where m.k and xs[i] raise. See Structured data access.
Strings
upper, lower, trim, split, join, replace, contains, starts_with, ends_with, chars, lines, reverse, index_of, len, escape_html.
is_blank is not a global - it lives in std.string.
The full toolkit is std.string.
Numbers and conversion
int, float, decimal, bool, string, bytes, abs, floor, ceil, round, pow, sqrt, min, max, sum, approx, type_of, is_null.
approx(a, b, eps?) is tolerance comparison for floats - == on floats is exact IEEE. See Numbers.
JSON
json_encode, json_decode. File forms are in std.json.
AI
embed, embed_all, cosine, tokens, cost, retry, session, uuid.
See Embeddings, Budgeting, Retry, Sessions.
Concurrency
cell, cell_get, cell_set, cell_update, channel, send, recv, try_recv, close, select, cancel, sleep, pmap.
Secrets
secret, reveal, is_secret. See Secrets.
Errors and assertions
error, assert. See Error handling.
Output
print, print_no_newline, read_file, write_file.
Python escape hatch
result = py("[x*2 for x in range(5)]")
py(...) evaluates Python in a persistent worker process, for the case where a library exists there and nowhere else. It is the deliberate escape hatch: reaching for it stays inside your Ecko program rather than becoming a separate service.
It needs Python on the machine, which is the one place Ecko's "one binary, nothing to install" promise does not reach - so treat it as a bridge, not a foundation.
Shadowing
Assigning to a builtin name shadows it in the current scope rather than erroring, so sum = 0 is always safe. ecko check warns, because it is usually accidental. Reach the original through core.*:
export fn get(c, key) { ... }
fn internal(m, k) = core.get(m, k)
Arity
Every builtin's arity is checked at the call site by ecko check, before the program runs - so a wrong argument count is caught rather than raising mid-run.