polar

Command Line

Everything Polar does goes through one command, polar. This page lists every subcommand and flag.

Usage: polar [OPTIONS] <COMMAND>

Commands:
  build
  check
  run
  fmt
  start
  init

Inside a project, path arguments are optional: commands use the project you're in.

polar run

polar run [OPTIONS] [FILE] [-- <ARGS>...]

Compiles a file or project and calls its exported main. Arguments after -- reach the program as Process.args().

Flag Does
--host <HOST> Picks which host to run for, when there are several

If the project sets a launcher in [run], polar run without --host builds every host and hands the build to the launcher instead.

polar check

polar check [OPTIONS] [PATHS]...

Type-checks and reports errors without writing anything. It's the fastest way to see whether code compiles.

Flag Does
--watch Checks again on every change
--out <OUT> A folder to skip when looking for source files and watching for changes, like a build folder

polar build

polar build [OPTIONS] [PATHS]...

Writes .js, .js.map and .d.ts files, plus the runtime and a start.mjs entry point. With several hosts, it writes one folder per host: dist/Browser/, dist/Node/.

Flag Does
--out <OUT> Where to write. Defaults to the project's out, or dist
--watch Rebuilds on every change
--host <HOST> Builds only one host, into dist/
--emit <STAGE> Prints one compiler stage for a single file instead of building

--emit takes one of these stages:

Stage Prints
tokens The tokens the lexer produced
ast The parsed syntax tree
core The simplified core language
types The inferred type of every declaration
hosts Where each function can run. See Hosts
dictionaries How trait implementations are passed around
js The generated JavaScript

Tip: --emit=types is a quick way to see what Polar inferred for a function you didn't annotate.

polar fmt

polar fmt [OPTIONS] [PATHS]...

Formats files in place in the standard layout.

Flag Does
--check Only reports files that would change, and fails if there are any

polar test

polar test [PATH] [-- <NODE_ARGS>...]

Builds the project to a temporary folder and runs its tests on Node with node:test. A test file is any *_test.px under the project's src, such as money_test.px next to money.px. A test is an exported function whose name starts with test_ and that takes no parameters. It passes if it returns and fails if it throws. Other exports are ignored.

Arguments after -- go to Node, so polar test -- --test-name-pattern=format runs only matching tests. The exit code is Node's: 0 if everything passed, 1 if anything failed. A project with no test files prints no tests found and exits 0. Failed Std.Assert checks are reported as assertion errors, with the stack pointing into the .px file.

polar repl

polar repl [OPTIONS] [PATH]

Loads a project and evaluates one expression or binding at a time on Node. Every project module is in scope, along with the modules your files import and a few pure standard ones (List, Option, Result, Map, Json, Ref, Table, Math).

$ polar repl
polar> let post = Greet.post()
post: { id: Int, title: String } as Post = { id: 1, title: "Hi" }
polar> post.title
String = "Hi"
polar> :type Greet.hello
function(String) -> String

An expression prints its type and its value, using Show, or the derived Json when there is no Show, or <no Show for T>. A let prints the name, type and value, stays in scope for later lines, and a later let of the same name shadows it. A line with a parse or type error prints the diagnostic and keeps the session going. Bindings are replayed ahead of each new line, so an effectful let runs again every time.

Effects run under the binds the project declares. An effect with no bind is reported as a diagnostic on the line.

Flag or command Does
--setup <MODULE.FUNCTION> Runs a () -> {} function once before the first prompt, such as one that connects a database. If it fails, the exit code is 1 and the prompt never starts
-e, --eval <EXPRESSION> Evaluates the expression, prints, and exits
:type <expr> Prints the type without evaluating
:reload Recompiles the project and keeps the bindings that still type check
:help, :quit Show the commands, or leave. Ctrl-D leaves too

Piped input works the same as typing: echo '1+1' | polar repl prints Int = 2. When input is piped or given with -e, the exit code is 1 if any line errored. There is no line editing or multi-line input; wrap the command in rlwrap for history.

polar start

polar start [OPTIONS] [PATH] [-- <ARGS>...]

Runs an existing build without compiling. It's the same as node dist/start.mjs.

Flag Does
--host <HOST> Picks which host's build to run

polar init

polar init [OPTIONS] [DIR]

Starts a project: writes polar.toml, src/main.px and a .gitignore. With no DIR it uses the current folder; otherwise it creates DIR (and any parents). It never overwrites: if polar.toml exists it stops, and existing src/main.px or .gitignore files are kept.

Flag Does
--name <NAME> Project name. Defaults to the folder's name, lowercased, with - and spaces turned into _
--zone <KEYWORD> Adds a zone plugin stub and the .polar/ folder. Repeat it for several zones

Global flags

Flag Does
--color, --no-color Forces colored error output on or off
-V, --version Prints the version
-h, --help Prints help, for polar or any subcommand

polar.toml

The project file, for reference. Every key is described in Your First Project and Modules and Packages.

[project]                       # or [package] for a library
name = "app"
src = "src"
out = "dist"
main = "src/main.px"
hosts = ["Browser", "Node"]

[dependencies]
shapes = { path = "../shapes" }

[run]
launcher = "simple_framework"
options = { port = 3000 }

# packages only
[package]
name = "simple_framework"
module = "Framework"

[launcher]
script = "launcher/serve.mjs"

[plugin]
zones = ["schema"]
dependencies = { regex = "1" }