Every task you run through Phel goes through one CLI. This page lists the built-in commands with a working example for each.
# Overview of all commands
vendor/bin/phel listInitialize a new project#
Scaffold a new Phel project:
vendor/bin/phel init
# Usage:
# init [options] [--] [<project-name>]
#
# Arguments:
# project-name The project/namespace name (default: "app")
#
# Options:
# --nested Use nested layout (src/phel/, tests/phel/)
# -m, --minimal Use root layout (single main.phel at project root)
# --force Overwrite existing files
# --dry-run Show what would be created without writing anything
# --no-gitignore Skip generating .gitignore
# --no-tests Skip generating a test file
# -t, --template[=NAME] Scaffold from a bundled example; omit the value to list
# --list-templates List available project templates and exit
Defaults to Flat layout (src/, tests/). --nested for src/phel/. --minimal for a single root file.
# Flat layout (default)
vendor/bin/phel init my-app
# Nested layout
vendor/bin/phel init my-app --nested
# Preview what would be created
vendor/bin/phel init my-app --dry-run
Scaffold from a bundled, runnable example instead of a bare skeleton. The template's namespaces, composer.json, and entry points are renamed to your project name. Composes with --dry-run and --force.
# List the bundled templates
vendor/bin/phel init --list-templates
# http-json-api, todo-app, cli-wordcount
# Scaffold a project from a template
vendor/bin/phel init my-api --template=http-json-apiBuild the project#
vendor/bin/phel build
# Usage:
# build [options]
#
# Options:
# --cache|--no-cache Enable cache
# --source-map|--no-source-map Enable source maps
# -O, --optimization-level=LEVEL Override configured level (0 = off, 2 = inline + tail-call rewrite)
# --report Print a build report (namespaces, sizes, time)
Compiles Phel to PHP, writing to the configured main path (entry point out/index.php). Run the resulting PHP directly. Skips recompilation, improving runtime.
# Build with optimizations on (inlining + self-recursive tail-call rewriting)
vendor/bin/phel build -O 2
# Print a build summary to spot bloat and verify CI builds
vendor/bin/phel build --report
-O overrides the level set via withOptimizationLevel(...) in phel-config.php. See Performance for what each level does. --report prints namespace count, per-namespace compiled size, total size, the fresh/cached breakdown, and build time.
Configuration in phel-config.php:
<?php
return (new \Phel\Config\PhelConfig())
->withMainPhelNamespace('your-ns.index')
->withMainPhpPath('out/index.php');Export definitions#
Exports definitions with {:export true} metadata as PHP classes. Generates one class per namespace, one method per exported definition. Lets you call Phel functions from PHP.
vendor/bin/phel export
Configure the export dirs, namespace prefix, and target directory in phel-config.php; see Configuration.
Format phel files#
Formats files. Accepts relative or absolute paths.
vendor/bin/phel format # formats src and tests by default
vendor/bin/phel format src/foo.phel
vendor/bin/phel format --dry-run # report files that would change, exit non-zero if any
Configuration in phel-config.php:
<?php
return (new PhelConfig())
->withFormatDirs(['src', 'tests']);
Indents definition and body forms (defstruct, defprotocol, defmethod, reify, doseq, letfn, ...) cljfmt-style, and collapses consecutive blank lines to one.
Read-eval-print loop#
Interactive prompt for quick tests and language exploration.
vendor/bin/phel repl
See REPL.
Run a script#
Run a file or namespace:
vendor/bin/phel run
# Usage:
# run [options] [--] <path> [<argv>...]
#
# Arguments:
# path The file path that you want to run.
# argv Optional arguments
#
# Options:
# -t, --with-time With time awareness
Configuration in phel-config.php:
<?php
return (new PhelConfig())
->withSrcDirs(['src']);
See Getting Started.
Test your Phel logic#
Runs tests. No paths runs everything in tests/.
vendor/bin/phel test
# Usage:
# test [options] [--] [<paths>...]
#
# Arguments:
# paths The file paths that you want to test.
#
# Options:
# -f, --filter[=REGEX] Filter by test name regex. Repeatable.
# --fail-fast Stop on first failure or error.
# --include=TAG Only run tests tagged TAG. Repeatable.
# --exclude=TAG Skip tests tagged TAG. Repeatable.
# --ns=GLOB Only run namespaces matching GLOB. Repeatable.
# --reporter=NAME Reporter: default|testdox|dot|tap|junit-xml. Repeatable.
# --output=PATH Output path (for junit-xml).
# --testdox Shortcut for --reporter=testdox.
# --repeat=N Run each test N times (default 1).
# --seed=INT Seed used for randomized order.
# --random-order Run tests in random order (uses --seed if given).
# --parallel=N Run namespaces in subprocess workers: int, "auto" (capped at 8), or "max".
# --watch Re-run selected tests on every .phel / phel-config.php change.
# --last-failed Re-run only tests that failed on the previous run.
# --slowest=N Print the N slowest tests after the summary (0 disables).
# --stack-trace Print the full PHP stack trace for each errored test.
# --coverage[=FORMAT] Collect line coverage (text|clover) via pcov or xdebug.
# --coverage-output=PATH Write the coverage report to a file (use with --coverage=clover for CI).
See Testing for what each flag does.
Configuration in phel-config.php:
<?php
return (new PhelConfig())
->withTestDirs(['tests']);Evaluate an expression#
Evaluate and print. Pass a literal expression, or - for stdin.
vendor/bin/phel eval '(+ 1 2 3)'
# => 6
echo '(map inc [1 2 3])' | vendor/bin/phel eval -
# => @[2 3 4]Compile to PHP#
Emit the PHP that Phel generates for a snippet, file, or stdin, without evaluating it. Handy for understanding the compiler or debugging interop.
vendor/bin/phel compile '(php/strlen "hello")'
# => strlen("hello");
vendor/bin/phel compile src/main.phel # compile a file
echo '(map inc [1 2 3])' | vendor/bin/phel compile -
# Usage:
# compile [options] [--] [<source>]
#
# Arguments:
# source Phel expression, path to a .phel file, or "-" for stdin
#
# Options:
# -t, --target Compilation target (currently only "php")Lint#
Static analysis. Rules: unresolved-symbol, arity-mismatch, unused-binding, unused-require, unused-import, shadowed-binding, redundant-do, duplicate-key, invalid-destructuring, discouraged-var.
vendor/bin/phel lint
# Usage:
# lint [options] [--] [<paths>...]
#
# Options:
# --format=FORMAT human (default), json, github
# --config=PATH Path to phel-lint.phel
# --no-cache Disable linter cache
Configure rules in phel-lint.phel at the project root.
Watch#
Reloads changed namespaces in dependency order. Backends: inotify, fswatch, polling.
vendor/bin/phel watch
# Usage:
# watch [options] [--] [<paths>...]
#
# Arguments:
# paths Files or directories to watch (default: configured src dirs)
#
# Options:
# -b, --backend=BACKEND Watcher backend: auto, inotify, fswatch, polling (default: auto)
# --poll=MS Polling interval in ms, polling backend only (default: 500)
# --debounce=MS Debounce window in ms (default: 100)
From Phel code, use phel.watch:
(ns my-app
(:require phel.watch :refer [watch!]))
(watch! ["src/"])nREPL#
Bencode-over-TCP nREPL server for editor inline eval.
vendor/bin/phel nrepl --port=7888 --host=127.0.0.1
See Editor support for supported ops and connecting your editor.
LSP#
LSP v3.17 over stdio.
vendor/bin/phel lsp
See Editor support for supported features and PHP-interop-aware completion.
Analyze and index#
phel analyze <file> emits JSON diagnostics; phel index <dir>... builds a symbol table for tooling.
vendor/bin/phel analyze src/main.phel
vendor/bin/phel index src --out=symbols.json
phel api-daemon serves the Api facade as JSON-RPC over stdio.
vendor/bin/phel api-daemonAgent install#
Writes skill/recipe files for AI coding assistants: Claude Code, Cursor, Codex, Gemini, Copilot, Aider. Copies a per-platform skill file plus the shared .agents/ docs tree. Re-install is idempotent; existing files are backed up to .pre-phel.bak unless --force.
vendor/bin/phel agent-install # pick platform interactively
vendor/bin/phel agent-install claude # single platform
vendor/bin/phel agent-install --all # every platform
vendor/bin/phel agent-install --auto # only platforms detected in project
vendor/bin/phel agent-install --uninstall # remove skill files, restore .pre-phel.bak
# --no-docs Skip the .agents/ docs tree (copied by default)
# --with-examples Also copy example projects into .agents/examples/
# --dry-run Show what would be written, change nothing
# --force Overwrite without .pre-phel.bak backupsProfile#
Per-function timings and compile-phase costs:
vendor/bin/phel profile path/to/file.phel
# Options:
# --format=FORMAT text (default), json
# --output=PATH Write report to PATHInspect configuration#
Print the effective configuration and where each part comes from. Useful when a phel-config.php, a phel-config-local.php override, or the PHEL_DIR env var is not taking effect as you expect.
vendor/bin/phel config
# Sources:
# - project root: /path/to/project
# - phel-config.php: not found, using auto-detected defaults
# - phel-config-local.php: not present
# - PHEL_DIR env: (unset)
#
# Effective config:
# { "src-dirs": ["src"], "test-dirs": ["tests"], ... }
# Machine-readable: just the effective config as JSON
vendor/bin/phel config --json
See Configuration for every setter.
Clear caches#
Clear namespace and compiled-code caches:
vendor/bin/phel cache:clear
Removes everything in the cache dir. Useful for stale caches or after upgrades.
Runtime state (cache, REPL history, error log) lives under .phel/ by default. Override via withPhelDir('...') in phel-config.php or the PHEL_DIR env var.
Next steps#
- REPL - the interactive loop behind
phel repl - Editor support - connect your editor to
phel nrepl - Configuration - tune paths, cache, and export in
phel-config.php