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

Windows: Cygwin

WSL2 above is one way on Windows. Plain Cygwin works too, since 2.3. Get setup-x86_64.exe from cygwin.com and install a compiler, make and git (python3 only if you'll run the test suite), by ticking them in the installer or in one go:

setup-x86_64.exe -q -s https://mirrors.kernel.org/sourceware/cygwin/ -P gcc-core,make,git,python3   # one-time

Then, in a Cygwin terminal, clone as above and:

./a                               # builds (a few minutes, LTO), then opens the REPL

Clone with Cygwin's own git (or run git config --global core.autocrlf false before cloning from Windows) so the scripts keep their LF line endings. The interpreter, the REPL and the test suite all run there. The one thing that doesn't is the shared library, which is Linux and macOS only.

./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 run bash a instead.

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 really 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 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)Threads for big vectors and peach. =1 forces serial.
AMBER_DIAGonThe full Rust-style error[…] report. =0 gives the terse k form, the message and a ^ caret.
AMBER_FSYNConSync on-disk writes before they're renamed in, so a crash leaves each table whole. =0 skips it.
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_HOME(none)Where 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 put rlwrap on the REPL

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. It says so, mid-session, while the two editors fight over one cursor and garble the redraw. ./a execs the interpreter directly. Two places rlwrap does fit: with AMBER_NO_EDIT=1 Amber reads whole lines and ./a wraps it in rlwrap for you, and a script that serves a port reads its console a line at a time, so rlwrap works on that too (2.9.0).

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
Ctrl-Lclear screen, byte-identical to \clear
Ctrl-C · Ctrl-Dabandon the line (or a continuation) · exit on an empty line
PgUp / PgDn, wheelscroll the transcript while the status bar stays locked
\sbtoggle the status bar

Tab is a no-op. Tab completion existed in 1.9.5 and was removed at 2.0.0: with k's terse syntax it was near-useless and uncomfortable to use.

Multi-line input

A line that leaves a bracket open ({, (, [) is an incomplete statement, so the editor keeps reading on a ...> prompt until the brackets balance, then evaluates the joined statement as one. History stores it as one entry:

amber> f:{
  ...> x+1
  ...> }
amber> f 41
42

There is no key binding for this. Shift-Enter is indistinguishable from Enter in a terminal, since both send CR, unless you opt into an extended keyboard protocol (xterm modifyOtherKeys, kitty, a hand-made iTerm2 binding), so continuing on incomplete syntax, which is what python, node, ghci and q all do, is the only portable mechanism. Ctrl-C abandons a continuation. A bracketed paste of a multi-line function is rejoined by the same string- and comment-aware rule, so a function typed by hand and one pasted produce identical text; a bracket inside a string ("a{b") or after a comment never triggers it.

UTF-8

The buffer holds bytes but a terminal lays out cells, and the editor converts between the two: accented Latin, CJK and emoji all measure as the cells drawn, Backspace removes a whole character rather than one byte, and horizontal scrolling never cuts a sequence in half. The width table is built in rather than taken from wcwidth(), which answers according to LC_CTYPE and would otherwise lay the same line out differently on macOS and on a WSL box with a different locale.

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 really 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 2.9.1
./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 (202)
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 (Linux and macOS; not on Cygwin):

./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 kona and other k/q installs are untouched.