Introduction
Amber is a small, fast, self-contained array language. The interpreter is portable
C99 that builds clean on gcc and clang; the vocabulary on top of it is
q/kdb+'s. It is one folder, it installs nothing system-wide, and deleting the folder uninstalls it
completely.
What it is
Amber's interpreter core is built on ngn/k, ngn's compact AGPLv3 implementation of the K array language. Amber keeps that engine's speed and small footprint and layers on:
- the q/kdb+ working vocabulary — dictionaries, tables and keyed tables with
([]…)literal syntax, qSQLselect/exec/update/delete, and the full join family: left, inner, union, plus, equi, as-of and window; - column attributes implemented in C —
`ssorted,`uunique,`pparted,`ggrouped — which turn?(find) from a linear scan into a binary search; - native temporal types — date, time and timestamp with literal syntax, type-aware arithmetic and a nanosecond epoch anchored at 2000-01-01;
- a tick / HFT toolkit — a native C as-of-join kernel, a zero-allocation arena, market-data generators, OHLCV bars, VWAP, Lee-Ready trade signing and effective spread;
- a modern REPL with a native line editor, Tab completion over your live globals and table columns, Rust-style diagnostics, a workspace inspector, an AST viewer, a bytecode disassembler and a phase profiler.
What it deliberately is not
Not a kdb+ distribution
Amber is an independent language. The interpreter is named amber,
never k or q; it reads no QHOME, no config and no dotfiles,
and your kdb+, kona or ngn/k installs are untouched.
Not a networked runtime
There is no AI code, no TLS and no listener anywhere in the engine
repository. A listener is a policy decision — which port, which framing, which auth — and it lives
outside, in amberd.
How the pieces fit
./a ──► build.sh ──► cc -std=c99 src/*.c ext/*.c ──► ./amber ──► repl.k
│ │
│ └─ amber.k · fin.k · std.k
│ qsql.k · temporal.k
│ sys.k · hdb.k · ipc.k
│ lib/ext.k (optional)
┌────────────────────────────────┴─────────────────────────────────┐
│ the interpreter │
│ a.c b.c f.c h.c i.c m.c v.c … ngn/k evaluator core, heap, verbs │
│ p.c ast.c vm.c parser · `\ast` tree · `\disasm` │
│ 3.c simd.c parallel.c peachpool.c vector kernels · threads │
│ arena.c ser.c csv.c ar.c HFT arena · -8!/-9! · CSV · Arrow │
│ e.c diagnostic.c the Rust-style error reporter │
│ inspect.c trace.c `\v` · `\trace` │
│ ln.c lnk.c the line editor and its `rdl` verb│
│ ext.c the extension seam (src/ext.h) │
└───────────────────────────────────────────────────────────────────┘Three properties of that layout are worth stating explicitly, because they are what it is for:
- No optional feature is switched off. Everything in
src/is compiled, always. There is no build matrix and no feature flag to get wrong. src/ln.chas no interpreter dependency. It includes<termios.h>andsrc/ext.hand nothing else of Amber's. The editor can be lifted into another project as-is.- Extensions never patch
src/. An out-of-tree package drops.cfiles intoext/and re-runs./build.sh; they are compiled with the same flags and plug themselves in from a constructor.
A two-minute taste
/ tables are first-class and render without `show` at the interactive prompt
([]sym:`a`b`c; px:100 200 300)
/ sym px
/ -------
/ a 100
/ b 200
/ c 300
meta ([]sym:`a`b; px:1.5 2.5) / column types + attributes (c | t a)
/ the join every tick shop needs — as-of (native C kernel since 1.9)
trade:([]sym:`a`b`a; time:3 4 9; px:100 200 300)
quote:([]sym:`a`a`b`a; time:1 5 2 8; bid:10 11 20 12)
aj[`sym`time; trade; quote] / last quote at or before each trade
/ qSQL — type select/exec/update/delete straight, no sel"…" wrapper
select last px by sym from trade / grouped aggregate
select from trade where px>150 / filter rows
/ binary serialization: -8! encodes any value to bytes, -9! decodes it back
b:-8!+`a`b!(1 2 3;4 5 6)
(-9!b)~+`a`b!(1 2 3;4 5 6) / 1b — exact, attributes and nulls included
/ multi-core: peach runs f over items in parallel worker processes (no GIL)
peach[{avg x?1.0}; 8#1000000]At the interactive prompt, select … by … from … where … works directly on the input
line, and a bare table auto-renders as a grid. Inside a .k script run through
./amber file.k, wrap a bare table in show and use the sel"…"
string form (or qselect/qby/qwhere directly).
Where to go next
Install & run →
Build from source on Linux, WSL and macOS; the shell block that actually works; the three environment variables the engine reads.
Language & qSQL →
K expressions, the built-in vocabulary, wavg, xbar,
aj, wj, tables and dictionaries, and the dialect notes that matter.
Temporal mechanics →
Why d, t and p count from 2000-01-01,
and exactly how to convert to and from Unix time without silently shifting your data.
Wire protocol →
amberd, IPC framing, the four reply encodings including
jsonc, and streaming sockets.