Install & run

Amber compiles from source on first run. Nothing is installed system-wide, there is no package to add and no prefix to choose — the checkout is the installation.

Clone

git clone https://github.com/BonucciAndrea/amber.git
cd amber

Linux / WSL2

sudo apt-get update && sudo apt-get install -y build-essential   # one-time
chmod +x a build.sh install.sh    # restore exec bits if the copy dropped them
./a                               # builds, then opens the REPL

macOS (Intel or Apple Silicon)

xcode-select --install            # installs the Command Line Tools (clang); one-time
chmod +x a build.sh install.sh
./a

./a compiles the interpreter with portable -O3 and drops you at the prompt. It recompiles automatically whenever the C sources change, so you never run a stale build. If ./a prints Permission denied, the executable bit was lost in transfer — the chmod +x line fixes it, or just run bash a.

Machine-tuned builds

The default build is portable C99 and always includes -pthread (needed by the multithreaded vector engine) plus the scalar SIMD fallback. For a build that turns on AVX2 (x86_64) or NEON (aarch64), set AMBER_NATIVE=1:

AMBER_NATIVE=1 ./build.sh         # machine-tuned
amber>
`simd 0        / prints which backend was selected: scalar / avx2 / neon

NEON activates unconditionally on Apple Silicon regardless of the flag, since aarch64 implies it. The tuning flag itself is probed, not assumed: -march=native is x86 syntax that Apple clang rejects outright, so build.sh falls back to -mcpu=native and, failing both, to a portable build.

One command instead of all of the above

./install.sh                      # or: bash install.sh  (if the +x bit was lost)
AMBER_NATIVE=1 ./install.sh       # ... with a machine-tuned build

install.sh checks you have a C compiler (and prints the exact package command for your distro if you do not), repairs the executable bit on every script, builds, runs the self-test, and writes a managed shell block into the rc file your login shell actually reads~/.zshrc for zsh, ~/.bash_profile on macOS bash, ~/.bashrc on Linux bash, ~/.profile otherwise. Re-running it replaces that block rather than appending a second copy.

Shell configuration

~/.zshrc
# === Amber - native engine configuration ===================================
# AMBER_HOME is the Amber checkout ITSELF. Amber is one self-contained folder:
# there is no bin/ directory, nothing is copied anywhere, and deleting the
# folder uninstalls it completely.
export AMBER_HOME="$HOME/amber"

# amber  -> the full REPL: repl.k, the q/kdb+ vocabulary and the stdlib.
alias amber='AMBER_NATIVE=1 "$AMBER_HOME/a"'

# amberx -> the bare interpreter for scripts and pipes: no REPL, no stdlib.
alias amberx='"$AMBER_HOME/amber"'

# Pin the vector engine to your physical cores; omit to use every core.
# alias amber='AMBER_NATIVE=1 AMBER_THREADS=8 "$AMBER_HOME/a"'

# Aliases do not exist in non-interactive shells. For scripts, cron and CI,
# symlink the launcher instead of putting the repo root on PATH:
#     mkdir -p ~/.local/bin && ln -sf "$AMBER_HOME/a" ~/.local/bin/amber

Three variants that look right and are not

Looks likeWhy it does not work
PATH="$AMBER_HOME/bin:$PATH" Amber has no bin/, lib/ or share/ split and installs nothing outside its folder. That path does not exist. $AMBER_HOME is the checkout, not a prefix.
alias amber='$AMBER_HOME/amber' The bare amber binary is the interpreter with no stdlib: select, aj and sum are undefined there. Alias the launcher a, which loads repl.k, which loads everything else.
AMBER_NATIVE=1 ./amber AMBER_NATIVE is a build-time variable read by build.sh, not by the interpreter. It belongs on the a alias — which may rebuild — and does nothing on amberx.

Environment variables the engine reads at run time

VariableDefaultEffect
AMBER_THREADSonline CPU count (cap 64)Vector-engine lanes and peach worker count. =1 forces serial.
AMBER_DIAGoffRender the full Rust-style error[…] report alongside the terse caret line.
AMBER_NO_EDIToffDisable the native line editor; Amber reads whole lines instead.
AMBER_NO_RLWRAPoffSuppress the rlwrap fallback that AMBER_NO_EDIT=1 would otherwise use.
AMBER_HOMEWhere satellites (python-amber, amberd) load the .k standard library from.

There is no AMBER_MEM_MB: the heap is mmap'd with MAP_NORESERVE and sized lazily by the OS, so there is nothing to tune.

Do not use rlwrap

Line editing is built in since 1.9.5

rlwrap runs the wrapped program on a pty and speaks readline on its behalf, which only works for a program that reads whole lines in canonical mode. Amber puts the terminal into raw mode and reads single keypresses, so rlwrap is doing nothing useful — and says so, mid-session, while the two editors fight over one cursor and garble the redraw. ./a execs the interpreter directly.

The native editor (src/ln.c, ~700 lines of C99 + POSIX termios, no readline, no curses, no dependency) gives you:

KeyAction
, Ctrl-B / Ctrl-Fmove by character
Ctrl-A / Ctrl-E, Home / Endstart / end of line
, Ctrl-P / Ctrl-Nhistory, persisted in ~/.amber_history
Backspace, Del, Ctrl-W / Ctrl-U / Ctrl-Kdelete char / word / to start / to end
Tabcomplete globals, table columns, \ commands, the vocabulary, and whole lines you already ran
Ctrl-L · Ctrl-C · Ctrl-Dclear screen · abandon the line · exit on an empty line

The editor degrades to a plain line read whenever stdin/stdout are not a terminal, so echo '2+2' | ./a, here-docs and CI runs behave byte-for-byte as they always did. If you genuinely need the fallback (a dumb terminal, an editor subshell, a screen reader):

AMBER_NO_EDIT=1 ./a                      # Amber reads whole lines; ./a wraps it in: rlwrap -n -a
AMBER_NO_RLWRAP=1 AMBER_NO_EDIT=1 ./a    # ... or not even that

Verify the install

./amber --version            # amber 1.9.6
./amber --help               # options + the full \-command reference

./amber examples/tour.k      # a worked example of EVERY function
./amber examples/basics.k    # a 2-minute intro
./amber examples/tick.k      # trades & quotes: as-of/window joins, VWAP, OHLC
./amber examples/hft.k       # the finance module walkthrough

./amber test.k               # core suite (163)
tests/run_tests.sh           # build + all K suites + C unit tests + fuzz pass
tests/run_tests.sh --asan    # ... and again under AddressSanitizer + UBSan

The showcase demo

One command builds Amber with maximum optimization and runs the Mega Demo: a 5,000,000-row HFT tick session (VWAP, a tacit 50-period EMA, a native as-of join), a 10,000,000-element vector-op benchmark, and a couple of \ast/\disasm samples straight from the real parser and compiler.

./demo.sh                    # portable -O3 build
AMBER_NATIVE=1 ./demo.sh     # -march=native build (fastest on this machine)
benchmark summary
== benchmark summary =======================================
stage      ms
----------
gentq   2381.9
vwap     151.2
ema        0.1
asof     704.0
------------------------------------------------------------
total: ~3.2 s end-to-end for 500,000 trades

The shared library

Every satellite — python-amber, amber-arrow, amberd — links libamber.so rather than the executable. Build it explicitly:

./build.sh                 # ./amber           (unchanged; identical binary, zero new cost)
./build.sh --shared        # ./amber  +  libamber.so
./build.sh --shared-only   # libamber.so only
AMBER_SHARED=1 ./build.sh  # same as --shared, for callers that cannot pass a flag
Isolation

Amber is a single self-contained folder. The interpreter is named amber (never k or q), built only inside the folder, never placed on your PATH. It reads and writes no config, no QHOME, no dotfiles. Your kdb+, kona and other k/q installs are untouched.