CLI reference

The langoost binary is the entry point for everything. (During development you can substitute go run . for ./langoost.)

./langoost run [--debug] [--pprof :ADDR] [--watch] <file.goost>   Execute a script
./langoost build [dir]                       Build src/main.goost → build/ (binary + run.sh + .env)
./langoost compile [--os OS] [--arch ARCH] [--jit] <file.goost>   Compile one file to a binary
./langoost repl                              Interactive REPL (multiline + history)
./langoost server [--bind H] [--port N] [--auth-token T]   Persistent HTTP execution server
./langoost test [dir] [-v] [-run FILTER]     Run *_test.goost tests
./langoost bench [dir] [-run FILTER] [--tui]  Run *_bench.goost benchmarks
./langoost install [--frozen]                Install deps; write/verify langoost.lock
./langoost verify [--signed]                 Re-hash langoost_modules against langoost.lock
./langoost debug <file.goost>                Interactive TUI debugger
./langoost dap [--port N]                    DAP debug adapter (stdio; --port for TCP)
./langoost disasm <file.goost>               Disassemble bytecode
./langoost version                           Print version

run

Compile and execute a script:

$ ./langoost run hello.goost
Hello, world!
FlagDescription
--debugEnable debug logging (the logging.debug level)
--pprof :ADDRExpose Go’s net/http/pprof on ADDR — visit /debug/pprof/
--watchRe-run the script whenever a .goost file in its directory changes (hot reload)
$ ./langoost run --watch app.goost          # restart on save
$ ./langoost run --pprof :6060 app.goost     # profile while it runs

--watch runs a supervisor that restarts the child process on every change; --pprof is also accepted by server.

repl

Start an interactive session. The REPL supports multi-statement (multiline) blocks and command history (arrow keys), persisted to ~/.langoost_history:

$ ./langoost repl
> let x = 21
> print(x * 2)
42

build

Build a project into a self-contained build/ directory. A project is a folder with a src/ directory whose src/main.goost is the entry point:

myapp/
├── src/
│   └── main.goost      ← entry point (required)
└── build/              ← created by `langoost build`
    ├── myapp           ← compiled native binary (pure-Go, standalone)
    ├── run.sh          ← loads .env, then execs the binary
    └── .env            ← default env config (created once, never overwritten)
$ ./langoost build              # builds ./ (uses the directory name for the binary)
$ ./langoost build ./myapp      # builds a specific project
$ ./myapp/build/run.sh          # run it
FlagDescription
-oOutput binary name (default: the project directory name)
--os / --archCross-compile target (linux/arm64, …)
--no-aotSkip AOT translation; embed the bytecode + interpreter instead
--force-envOverwrite build/.env if it already exists

The binary is pure-Go and standalone. Deploy by copying the build/ directory to a server and running run.sh — no Go toolchain or Langoost install needed. Rebuilding never clobbers a build/.env you’ve edited (unless you pass --force-env).

compile

Compile a single file to a standalone native binary — handy for scripts that aren’t structured as a project. Cross-compile with --os/--arch:

$ ./langoost compile app.goost                       # host platform
$ ./langoost compile -o app --os linux --arch arm64 app.goost   # e.g. a Pi
FlagDescription
-oOutput binary name (default: the input filename without extension)
--osTarget OS for cross-compilation (linux, windows, darwin, …)
--archTarget architecture (amd64, arm64, …)
--jitAOT-compile the script to native Go (no interpreter at runtime); falls back gracefully on unsupported opcodes

Use build for an app you’ll deploy (it adds run.sh + .env); use compile for a one-off binary from a single file.

test

Discover *_test.goost files under [dir] (default .) and run every top-level function named test_*. See the testing guide for writing tests with the assert module.

$ ./langoost test
$ ./langoost test ./tests -v -run parse   # verbose, only tests matching "parse"
FlagDescription
-vVerbose — list every test, not just failures
-run FILTEROnly run tests whose name contains FILTER

The process exits non-zero if any test fails.

bench

Discover *_bench.goost files and run every top-level function named bench_*, timing each and reporting nanoseconds per iteration:

$ ./langoost bench
$ ./langoost bench -run parse --tui
FlagDescription
-run FILTEROnly run benchmarks whose name contains FILTER
--tuiLive-updating terminal UI instead of plain text
--jit-traceOpt into the experimental trace JIT (for measurement)

server

Run as a long-lived execution server. The process stays warm and serves requests with no cold start. It binds loopback (127.0.0.1) by default — exposing it publicly requires an auth token:

$ ./langoost server                                   # local only
$ ./langoost server --bind 0.0.0.0 --auth-token "$TOKEN"   # public, authenticated
FlagDefaultDescription
--bind127.0.0.1Interface to bind; 0.0.0.0 exposes it publicly (needs --auth-token)
--port8080HTTP port
--auth-token$LANGOOST_AUTH_TOKENBearer token required for /execute and /cache
--dir.Directory searched for .goost files
--pprof :ADDRoffExpose Go’s net/http/pprof
--max-source-bytes1 MiBCap on submitted source/file size
--allow-stdliballComma-separated stdlib allowlist (empty = allow all)
--unsafe-allow-no-authoffPermit a public bind with no token — never use in production

It exposes an HTTP API — POST /execute, GET /health, and DELETE /cache. See the execution server guide for request and response shapes and the auth model.

install

Fetch the dependencies declared in ./langoost.json into ./langoost_modules/:

$ ./langoost install
Installing 2 dependencies into langoost_modules/
FlagDefaultDescription
--manifestlangoost.jsonPath to the manifest
--dirlangoost_modulesWhere to install packages
--frozenoffInstall exactly what langoost.lock pins; fail on any mismatch

A regular install writes a langoost.lock lockfile recording the resolved version and content hash of each dependency. Commit it; then install --frozen reproduces the exact same dependency tree and fails if anything has changed — ideal for CI and reproducible builds.

See modules & imports for the manifest format and how installed packages are resolved.

verify

Re-hash everything in langoost_modules/ and check it against langoost.lock — detects tampering or drift without reinstalling:

$ ./langoost verify
$ ./langoost verify --signed     # also require a valid signature per entry
FlagDefaultDescription
--dir.Project directory containing langoost.lock
--moduleslangoost_modulesInstalled-modules directory
--signedoffRequire every lockfile entry to carry a valid ed25519 signature from a trusted signer
--trusted-keys$LANGOOST_TRUSTED_KEYSPath to the trusted-keys file

debug

Launch an interactive terminal debugger — a source viewer with breakpoints and stepping, no editor required (for editor debugging, use dap):

$ ./langoost debug app.goost

Pass --stop-on-entry=false to start running immediately instead of pausing on the first line. See the debugging guide.

dap

Start the Debug Adapter Protocol server so an editor can debug .goost files. Defaults to stdio (what editors expect); --port N listens on TCP instead:

$ langoost dap                 # stdio
$ langoost dap --port 4711     # TCP

See the debugging guide for VS Code and Neovim setup.

disasm

Print the compiled bytecode for a script — useful for understanding what the compiler produces:

$ ./langoost disasm examples/math.goost

=== examples/math.goost (16 instructions) ===
0000 [   3] CONST                #0 (<fn add/2>)
0001 [   3] DEF_GLOBAL           #1 (add)
...
=== add (6 instructions) ===
0000 [   4] LOAD_LOCAL           slot=0
0001 [   4] LOAD_LOCAL           slot=1
0002 [   4] ADD
0003 [   4] RETURN

Error messages

Runtime and compile errors include the file name and line (and column for lex/parse errors):

main.goost:12: undefined variable "x"
main.goost:7: function "add" expects 2 arguments, got 3
main.goost:3: array index 5 out of bounds (len=3)
script.goost:4:12: expected }, got EOF

Uncaught runtime errors print a source-mapped stack trace — each frame shows its function and file:line, from the throw site down to the top-level script:

runtime error: division by zero
  at level3 (math.goost:9)
  at level2 (math.goost:5)
  at level1 (math.goost:2)
  at <script> (main.goost:14)

For how the pipeline fits together, see architecture.