Ecko
The language where ai is a keyword, not an import.
Ecko is a programming language for the AI era - built in Rust, designed for human-AI collaboration. It pairs expression-oriented syntax with first-class LLM primitives, pattern matching, pipelines, contracts, and share-nothing concurrency, all in one static binary.
# Call an LLM directly - no imports, no setup
result = ai "What is the capital of France?"
print(result)
# Typed output maps straight to your types
count = ai[Int] "Count the words in this text"
print(count)
# Pipe data through LLM calls
text = "Meet me on 12 March and again on 4 April."
dates = text |> ai "Extract all dates" |> ai "Format as ISO 8601"
print(dates)
Every ai call above runs offline in deterministic mock mode with no API key - so the whole program is runnable and testable before you configure a single provider.
It just works - one step, zero config, offline. Installing drops in a single binary with nothing to configure. Running is just
ecko file.ecko- no project to set up, nopackage.json, noCargo.toml. A file is a program. Without an API key, everything still runs in mock mode: typed calls return schema-valid values (ai[Int]->42), so your pipelines, contracts, and tool calls all keep working. The standard library is already there -import std.httpgives you an HTTP server,import std.sqlgives you SQLite - with noapt install, nopip install, nocargo add.
Quick start
Install Ecko - one command, a single binary, nothing to configure:
curl -fsSL https://ecko.sh/install | sh
The installer picks the right build for your machine, checks its checksum, and puts ecko on your PATH. Prebuilt binaries ship for:
| platform | |
|---|---|
| Linux | x86-64, arm64 |
| macOS | Apple Silicon |
| Windows | x86-64 |
Intel Macs are not supported - an Apple Silicon binary cannot run on one.
Prefer a manual install? Download the archive for your platform and put the binary on your PATH:
https://ecko.sh/dl/latest/ecko-x86_64-linux.tar.gz
https://ecko.sh/dl/latest/ecko-aarch64-linux.tar.gz
https://ecko.sh/dl/latest/ecko-aarch64-macos.tar.gz
https://ecko.sh/dl/latest/ecko-x86_64-windows.zip
Each has a .sha256 beside it, so you can verify before unpacking:
curl -fsSLO https://ecko.sh/dl/latest/ecko-x86_64-linux.tar.gz
curl -fsSLO https://ecko.sh/dl/latest/ecko-x86_64-linux.tar.gz.sha256
shasum -a 256 -c ecko-x86_64-linux.tar.gz.sha256
To pin a version, swap latest for the tag - https://ecko.sh/dl/v0.9.5/...; https://ecko.sh/dl/latest.txt says which tag latest currently is.
Run a file, or start the REPL:
ecko examples/hello.ecko # run a file
ecko # start the REPL (or `ecko repl`)
Your first program is one line:
print("Hello, AI World!") # Hello, AI World!
And the ai keyword needs no setup - it runs in mock mode until you add a key:
# Typed output; runs offline in mock mode (a real key returns a real answer)
count = ai[Int] "Count the words in this sentence"
print(count) # 42
Set ECKO_API_KEY for real responses, and ECKO_AI_PROVIDER to switch between openai (default), anthropic, and ollama. Configuration is always through
Start here
- Installing? The one-liner is at the top of this page; the full set of
archives and checksums is on the download page.
- Kicking the tyres? Every
aicall runs offline in mock mode, so a
program is testable before you configure a provider.
- Looking for a package? The official packages below
are written in Ecko, capability-gated, and installed with ecko get.
Reference
Every page below is written. The documentation covers the language, the ai keyword, concurrency, the standard library, packages, the CLI and the runtime's architecture.
Getting started
- Install - the
curl | shone-liner, the platform archives, and verifying a checksum - A file is a program - no project scaffolding, ever
- Your first program - hello world to a typed
aicall - The REPL - interactive sessions, multi-line input
- Mock mode - how Ecko runs fully offline with no API key
- Editor support - the VS Code grammar and the language server
Language
- Statements & syntax - newline-terminated statements, comments, continuation rules
- Comments & documentation -
#comments,##doc comments, theexample:convention - Variables & mutability -
let/const/mut, bare assignment, shadowing, no silent nulls - Assignment through fields & indexes -
user.name = ...,user.tags[0] = ... - Destructuring bindings -
let (a, b) = pair,mut (x, y) = ..., the(x, y) = [y, x]swap - Values & types -
null,bool,int,float,decimal,string,bytes,list,map,struct - Numbers - checked-overflow
int, IEEE-754float, exactdecimal(19.99m) - Bytes -
b"..."literals, the text-to-bytes boundary, JSON base64 - Type definitions -
type Shape = Circle { r: Int } | Square { ... }, call-style constructors - Bitwise & word operators -
band,bor,bxor,shl,shr,bnot - Functions & lambdas -
fn,|x| ..., defaults, named arguments, closures,asynclambdas - Pipelines -
|>, the loosest-binding operator, feeding data through calls - Control flow -
if/unless,for ... in, ranges,while,loop,break/continue, for-destructuring - Pattern matching - literals, guards (
when), variant and map/struct patterns,_ - Error handling & the error dialect -
try/catch/finally,error(v), the four rules, errorkinds - Strings & interpolation -
"{expr}", triple-quoted, raw stringsr"..." - Templates -
template name(...) = """...""",{for}/{if}/{input}directives - Structured data access - strict
xs[i]/m.keyvs nullableget(m, k), slices, negative indices - Secrets -
secret(v),reveal(v),is_secret(v), structural redaction - Modules & imports -
import std.*,import "./util", theexportmodifier (private by default), re-export (export * from,export import), circular-import detection - Resource limits - recursion, parse depth, step budgets; adversarial input degrades to a catchable error
The ai keyword
aiand typed output -ai "...",ai[Int]/ai[Bool]/ai[Enum]/ai[Struct]/ai[json<...>], schema coercion- Mock mode - deterministic schema-valid values with no key; how tests stay offline
- Contracts -
@requires/@ensures, boolean and natural-language, self-correcting retries - Majority voting -
ai[T] n "..."runsnsamples and takes the mode - Tool calling -
@tool("...")functions,ai[T] "..." using [f, g], the runtime tool loop - Sessions -
session()andai "..." with chatfor multi-turn conversations - Multimodal / vision -
ai "..." on img, image handles, provider serialization - Embeddings & RAG -
embed,embed_all,cosine;std.dbandstd.rag - Streaming -
ai "..." -> stream, live SSE tokens, consuming a stream - Token budgeting -
tokens(text),cost(model, in, out), hard call caps - Retry -
retry(n, f)with exponential backoff for any failing operation - Providers & configuration - OpenAI / Anthropic / Ollama, swap with one env var
- Caching - content-addressed prompt cache, replayable, budget-free
- Tracing -
ECKO_TRACEJSONL: every call's provider, model, tokens, latency, retries
Concurrency and async
pmap- data-parallel map over a bounded worker poolcell- shared state -cell,cell_get,cell_set,cell_update(atomic read-modify-write)- Async tasks -
async fn/await, spawning tasks, error propagation,cancel - Channels -
channel(bounded/unbounded),send,recv,try_recv,close,select - Streaming responses & SSE - HTTP handlers that stream from a channel
- Background tasks -
std.bg:spawn,status,result,after,every,join_all
Standard library
std.string- the full UTF-8 string toolkit (upper,split,replace,pad_*,trim, ...)std.math- constants (pi,e,tau) and float functions (sin,sqrt,log,clamp, ...)std.io-printand basic I/Ostd.fmt-format(raw-string{}placeholders),pad_left,pad_right,truncatestd.uuid-v4(random) andv7(time-ordered) UUIDsstd.cli- declarative arg parsing:parse(spec, argv),help(spec)std.random- seedable RNG plus a CSPRNG (bytes,token)std.test-case,eq,ok,err,failfor the test runnerstd.time-now,now_iso,monotonic,format,parsestd.re- regex:test,find,find_all,captures,split,replacestd.hash-sha256,hmac_sha256,sha1, and Argon2idpassword/verifystd.encoding- base64, hex, and URL encode/decode (*_decode_textvariants)std.term- colors, styles, cursor control, TTY info, key input (honorsNO_COLOR)std.debug-inspect(secret-safe),type,timer,elapsedstd.humanize-duration,size,relative,ordinal,pluralstd.zlib-gzip,gunzip,deflate,inflateover bytesstd.fs- files and directories (read,write,list_dir,copy,rename, ...) -fs:read/fs:writestd.os- host environment and process:env,env_or,set_env,args,cwd,platform,exec,exit(env/execgated)std.json-encode,decode,read,writestd.csv-parse,stringify,read,write(rows as column-keyed maps)std.toml-parse,stringify,read,writestd.yaml-parse,stringify,read,writestd.log- leveled logging with text/JSON sinks and file rotation (fs:writefor file sinks)std.image- decode / resize / crop / encode PNG & JPEG; backsai ... on <image>std.config- layered config (env > file > default), withsecretfields -env+fs:readstd.defaults- the project'secko.json, loaded automatically:defaults.<key>plus anenvironmentblock applied to the process - ungatedstd.db- in-process vector store:add,search,save,load(netto embed,fsto persist)std.http- HTTP client and server, streaming/SSE, TLS, WebSocket upgradestd.web- a router overhttp.serve: routes,:params, middleware, static files (GET routes also answer HEAD)std.ws- WebSocket client (connect,send,recv,close)std.net- raw TCP/TLS sockets and DNS (connect,connect_tls,starttls,send,recv)std.dns- DNS resolver (resolve,reverse,lookup; A/AAAA/CNAME/MX/TXT)std.llm- low-levelchataccess to the provider layerstd.rag- retrieval-augmented generation:chunk,index,retrieve,answerstd.sql- embedded SQLite:open,exec,query,query_one,transaction;sql { ... }blocks (:memory:is pure, a file db needsfs:write)- Global builtins reference - the ~95 functions always in scope: collections (
map,filter,reduce,sort,group_by, ...), conversions (int,string,bytes, ...),json_encode/json_decode,embed/tokens/cost/retry,secret/reveal,error/assert,cell/channel, andpy(...)(Python FFI)
Packages
- Concepts - bare imports,
vendor/, and the three-layer model (kernel / std / packages) - The
ecko.jsonmanifest -name,version,entrypoint,capabilities,dependencies - Capabilities & gating -
net,fs:read,fs:write,env,exec; granted by the importer, attenuated down the tree - Lockfile & integrity -
ecko.locksha256 pins; commitvendor/for offline clones - Package commands -
init,add,install,remove,update,pack - Building an executable -
ecko buildbundles the interpreter + program into one file - Docker - a ~22 MB distroless image, no shell or package manager inside
CLI and tooling
ecko run/ a file - run a program (a bareecko file.eckoworks too)ecko repl- the interactive REPLecko dev- hot-reload for servers and scriptsecko fmt- the canonical formatter (one style, zero config;--check)ecko check- static analysis: undefined names, arity, use-before-def, exhaustiveness, unwrapped credentialsecko test- the test runner (mock mode forced);--generatescaffolds testsecko explain/lint/fix- explain a program, lint dead code, AI-assisted fixes (--migrate-bytes)ecko doc- markdown documentation from##commentsecko lsp- the stdio language server for editors- Package commands -
init/add/install/remove/update/pack/build - Global flags -
--model,--provider,--key,--cache,--trace
Configuration
- Environment variables - the complete reference. Grouped:
- AI / LLM -
ECKO_API_KEY,ECKO_AI_PROVIDER,ECKO_AI_MODEL,ECKO_AI_BASE_URL,ECKO_AI_EMBED_MODEL,ECKO_AI_MAX_RETRIES,ECKO_AI_MAX_CALLS,ECKO_AI_MAX_TOOL_ROUNDS,ECKO_AI_TOOL_TIMEOUT_MS,ECKO_AI_CACHE,ECKO_TRACE,ECKO_RETRY_BASE_MS - Concurrency -
ECKO_MAX_PARALLEL,ECKO_MAX_TASKS - HTTP / WebSocket server -
ECKO_HTTP_WORKERS,ECKO_HTTP_REQUEST_TIMEOUT_MS,ECKO_HTTP_MAX_BODY,ECKO_MAX_WS_CONNS - Runtime limits -
ECKO_MAX_DEPTH,ECKO_MAX_PARSE_DEPTH,ECKO_MAX_STEPS - Logging -
ECKO_LOG - Packages -
ECKO_PKG_MAX_BYTES,ECKO_PKG_MAX_UNPACKED - Terminal -
NO_COLOR,CLICOLOR_FORCE
Architecture
- The pipeline - source -> lexer -> parser -> bytecode -> stack VM
- Two execution tiers - the bytecode VM and the AST tier (AI, contracts,
async), and the bridge between them - The stack VM - chunks, frames, superinstructions, try/catch
- The value model - one
Valueenum, Arc-backed copy-on-write collections - Capability enforcement - the three layers and how gating is enforced
- Code map - how the runtime is organized
Official packages
Batteries that live outside the binary: each one is written in Ecko, versioned on its own, and deletable. ecko get vendors a package under vendor/ and pins a hash; what it is allowed to do is the grant you give it at the import, not what its manifest asks for.
Every reference below is generated from the ## comments in the package's own source, so it says what the code says.
cache- A general-purpose cache written in Ecko: in-memory LRU with TTL over an optional disk store. get/set/remember(key, ttl, fn).cli- Command-line argument parsing for Ecko: typed flags, options, positionals, defaults, and generated usage. Pure - no capabilities.cookies- Parse and serialize HTTP cookies for client sessions: read Set-Cookie headers into a jar, build the Cookie request header. Pure - no capabilities.datetime- Calendar dates, times, and durations for Ecko: components, arithmetic, and formatting over Unix-ms timestamps. Pure - no capabilities.deque- A double-ended queue for Ecko: push/pop/peek at both ends, amortized O(1). Immutable two-stack deque. Pure - no capabilities.heap- A priority queue (min-heap) for Ecko: push/pop/peek, heapify, and top-k. Immutable skew heap. Pure - no capabilities.html- A tolerant HTML parser for Ecko: parse to a node tree, extract text, and find elements. Great for feeding web content to ai. Pure - no capabilities.ip- IPv4/IPv6 address parsing, validation, CIDR membership, and private-range checks for Ecko. Pure - no capabilities.mysql- A MySQL/MariaDB client written in Ecko: classic protocol + mysql_native_password over std.net.perf- Measure the performance of your own Ecko code: time, measure, and bench (best-of-N stats)postgres- A PostgreSQL client written in Ecko: v3 wire protocol + SCRAM-SHA-256 over std.net.redact- Sensitive-key detection and masking for safe logging: is_sensitive_key, mask, and recursive map_of. Pure - no capabilities.redis- A Redis client (RESP2) written in Ecko, over std.net raw sockets + TLS.smtp- An SMTP client (RFC 5321) written in Ecko, over std.net raw sockets + STARTTLS.stats- Descriptive statistics for Ecko: mean, median, mode, variance, stdev, quantiles. Pure - no capabilities.struct- Pack and unpack binary data with a struct-style format string, over the bytes type. Pure - no capabilities.textwrap- Wrap, fill, indent, dedent, and shorten text for Ecko - prompt building and terminal output. Pure - no capabilities.tui- Terminal UI composition for Ecko: width-aware pad/center/truncate, bordered boxes, and aligned tables over std.term.url- URL parsing, query strings, and reference resolution for Ecko.validate- A data/input validation library written in Ecko: composable validator functions, whole-object schemas, collect-all errors. Pure - no capabilities.webkit- SaaS web-app batteries for Ecko: auto-escaping HTML templates, signed cookies, sessions, and CORS/security middleware.xml- An XML parser for Ecko: parse to a node tree, query by tag or path, extract text, and rebuild. Pure - no capabilities.
Ecko v0.9 - built in Rust, runs everywhere. Home at ecko.sh; licensing at ecko.sh/enterprise.