phel-lang / phel-lang
Phel is a functional programming language that compiles to PHP
Fund package maintenance!
Requires
- php: >=8.5
- amphp/amp: ^3.1
- gacela-project/gacela: ^2.6
- symfony/console: ^7.3|^8.0
- symfony/polyfill-mbstring: ^1.30
- symfony/routing: ^7.3|^8.0
Requires (Dev)
- ext-readline: *
- brianium/paratest: ^7
- ergebnis/composer-normalize: ^2.53
- friendsofphp/php-cs-fixer: ^3.95
- infection/infection: ^0.35.4
- phpbench/phpbench: ^1.7
- phpstan/phpstan: ^2.2
- phpstan/phpstan-deprecation-rules: ^2.0
- phpstan/phpstan-phpunit: ^2.0
- phpunit/phpunit: ^11.0|^12.0|^13.0
- psalm/plugin-phpunit: ^0.19.7
- rector/rector: ^2.6.7
- vimeo/psalm: ^6.18
Suggests
None
Provides
None
Conflicts
None
Replaces
None
- dev-main
- v1.0.0-rc2
- v1.0.0-rc1
- v0.54.0
- v0.53.0
- v0.52.0
- v0.51.0
- v0.50.0
- v0.49.0
- v0.48.0
- v0.47.0
- v0.46.0
- v0.45.1
- v0.45.0
- v0.44.0
- v0.43.0
- v0.42.0
- v0.41.0
- v0.40.0
- v0.39.0
- v0.38.0
- v0.37.0
- v0.36.0
- v0.35.0
- v0.34.1
- v0.34.0
- v0.33.0
- v0.32.0
- v0.31.0
- v0.30.0
- v0.29.0
- v0.28.0
- v0.27.0
- v0.26.0
- v0.25.0
- v0.24.0
- v0.23.1
- v0.23.0
- v0.22.2
- v0.22.1
- v0.22.0
- v0.21.0
- v0.20.0
- v0.19.1
- v0.19.0
- v0.18.1
- v0.18.0
- v0.17.0
- v0.16.1
- v0.16.0
- v0.15.3
- v0.15.2
- v0.15.1
- v0.15.0
- v0.14.1
- v0.14.0
- v0.13.0
- v0.12.0
- v0.11.0
- v0.10.1
- v0.10.0
- v0.9.0
- v0.8.0
- v0.7.0
- v0.6.0
- v0.5.0
- v0.4.0
- v0.3.3
- v0.3.2
- v0.3.1
- v0.3.0
- v0.2.0
- v0.1.0
- dev-fix/api-dashed-namespace-names
This package is auto-updated.
Last update: 2026-10-15 06:30:02 UTC
README
Lisp for PHP, macros, persistent data structures, REPL.
Requirements
PHP 8.5 or newer. Linux and macOS are supported: the full compiler, core and PHAR suites run on both in CI, and a failure on either blocks a release. Windows is best effort, running a reduced suite. What a version number promises, and for how long, is in the stability policy.
Get Started
composer require phel-lang/phel-lang
1. Open a REPL
./vendor/bin/phel repl
user:1> (->> [1 2 3 4 5] (filter odd?) (map #(* % %)) (reduce +)) 35 user:2> (defn greet [who] (str "Hello, " who "!")) #'user/greet user:3> (greet "Phel") "Hello, Phel!"
2. Scaffold a project
./vendor/bin/phel init # add `--minimal` for a single-file layout
Creates phel-config.php, src/main.phel, tests/main_test.phel. With
--minimal the two sources sit at the project root instead. Then:
./vendor/bin/phel run src/main.phel # run ./vendor/bin/phel test # tests ./vendor/bin/phel build # compile to PHP ./vendor/bin/phel config # inspect the merged config
3. Eval inline or via stdin
./vendor/bin/phel eval '(+ 1 2)' # prints 3 echo '(println "hi")' | ./vendor/bin/phel eval - ./vendor/bin/phel eval - < script.phel
4. Enable shell completion (optional)
./vendor/bin/phel completion dumps a tab-completion script for bash, zsh, or fish. It completes commands, their options, and dynamic values (function names for doc, project namespaces for run/test).
# bash — restart your shell afterwards ./vendor/bin/phel completion bash | sudo tee /etc/bash_completion.d/phel # zsh — write into a directory on your $fpath ./vendor/bin/phel completion zsh > "${fpath[1]}/_phel" # fish ./vendor/bin/phel completion fish > ~/.config/fish/completions/phel.fish
The zsh script starts with #compdef phel, so completion only triggers for a binary named phel on your $PATH. If you call ./vendor/bin/phel (or ./bin/phel in a dev checkout), symlink a global phel first, e.g. on macOS + Homebrew:
phel completion zsh > "$(brew --prefix)/share/zsh/site-functions/_phel" ln -sf "$PWD/bin/phel" "$(brew --prefix)/bin/phel" # global `phel` so #compdef matches rm -f ~/.zcompdump* # force compinit to rebuild # then open a new shell
Prefer a project template?
web-skeletonorcli-skeleton: click Use this template for a one-click start.
More examples →
|
Data pipeline (def users [{:name "Ada" :age 36} {:name "Bob" :age 17} {:name "Cam" :age 41}]) (->> users (filter #(>= (:age %) 18)) (map :name) sort) ;; => ["Ada" "Cam"] |
HTTP response (ns app (:require phel.http :as h)) (def req (h/request-from-globals)) (h/emit-response (h/response-from-map {:status 200 :headers {"Content-Type" "text/plain"} :body (str "Hello " (:uri req))})) |
|
Macros (defmacro unless [pred & body] `(if (not ~pred) (do ~@body))) (unless (zero? 1) (println "not zero")) ;; => not zero (unless false (println "ok")) ;; => ok |
PHP interop (ns app) (def now (new DateTime)) (.format now "Y-m-d") ;; => "2026-04-20" (def epoch (new DateTime "1970-01-01")) (.-days (.diff now epoch)) ;; => 20564 |
Standalone PHAR
Each release attaches phel.phar, a single file you can run without Composer. Check it against the sha256 digest GitHub shows for the asset before you run it. The PHAR carries its own hash, but anyone who rebuilds it can recompute that.
tag=v1.0.0 # the release you want gh release download "$tag" --repo phel-lang/phel-lang --pattern phel.phar expected=$(gh release view "$tag" --repo phel-lang/phel-lang --json assets \ --jq '.assets[] | select(.name == "phel.phar") | .digest | ltrimstr("sha256:")') echo "$expected phel.phar" | shasum -a 256 -c - # macOS and Linux echo "$expected phel.phar" | sha256sum -c - # Linux, if shasum is missing
phel.phar: OK means the file matches. Anything else, delete the file and do not run it. Without gh, copy the digest from the asset list on the release page and use shasum -a 256 phel.phar or sha256sum phel.phar.
Release tags are GPG-signed. In a clone, run git tag -v "$tag" with the maintainer's public key imported.
Documentation
- Getting Started: install, REPL, first script (5 min)
- CLI Reference & DX Guide: every command, the dev loop, compile vs eval vs run vs build
- phel-lang.org: full documentation, tutorials, exercises, blog
- Contributor docs: repository internals, architecture, project layout
- Architecture decisions: why the repository is shaped the way it is
- Packagist
- CONTRIBUTING.md: setup and workflow
AI Coding Agents
Skill files for Claude Code, Cursor, Codex, Gemini, Copilot, Aider: resources/agents/
./vendor/bin/phel agent-install [platform] # install skill file for one agent (claude, cursor, ...) ./vendor/bin/phel agent-install --auto # only agents detected in this project ./vendor/bin/phel agent-install --all # every supported platform