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/3812-keyword-nul-namespace
- dev-fix/3809-re-matches-full-match
- dev-fix/3808-json-big-numbers
- dev-fix/3816-profiler-fiber-stacks
- dev-fix/3815-profile-report-write-failure
- dev-fix/3814-global-options-before-run
- dev-fix/3821-lsp-definition-utf16
- dev-fix/3822-http-client-query-fragment
- dev-fix/3820-polling-same-size-edits
- dev-fix/3799-quasiquoted-sets
This package is auto-updated.
Last update: 2026-11-13 22:42:03 UTC
README
Phel is a Lisp that compiles to PHP. It has macros, persistent data structures and a REPL, and it calls any PHP class or function directly.
Requirements
PHP 8.5 or newer, on Linux or macOS. CI runs the full test suite on both. Windows gets a smaller suite and best-effort support. The stability policy says what a version number promises.
Get started
composer require phel-lang/phel-lang
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!"
Create a project. phel init writes phel-config.php, src/main.phel and tests/main_test.phel; --minimal puts the two sources in the project root instead.
./vendor/bin/phel init ./vendor/bin/phel run src/main.phel # run a script ./vendor/bin/phel test # run the tests ./vendor/bin/phel build # compile to PHP
Evaluate code from the command line or from stdin:
./vendor/bin/phel eval '(+ 1 2)' echo '(println "hi")' | ./vendor/bin/phel eval -
To start from a template, use web-skeleton or cli-skeleton.
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")) ;; prints: not zero
PHP interop
(def now (new DateTime)) (.format now "Y-m-d") ;; => "2026-11-13"
Shell completion
phel completion prints a tab-completion script for bash, zsh or fish. It completes commands, options, function names for doc and project namespaces for run and test.
./vendor/bin/phel completion bash | sudo tee /etc/bash_completion.d/phel # then restart the shell ./vendor/bin/phel completion zsh > "${fpath[1]}/_phel" ./vendor/bin/phel completion fish > ~/.config/fish/completions/phel.fish
The zsh script starts with #compdef phel, so it only completes a binary named phel on your $PATH. If you call ./vendor/bin/phel, link a global phel first. On macOS with Homebrew:
phel completion zsh > "$(brew --prefix)/share/zsh/site-functions/_phel" ln -sf "$PWD/vendor/bin/phel" "$(brew --prefix)/bin/phel" rm -f ~/.zcompdump* # rebuild the completion cache, then open a new shell
Standalone PHAR
Each release attaches phel.phar, a single file that runs without Composer. Check it against the sha256 digest GitHub shows for the asset before you run it:
tag=v1.0.0 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 - # or: sha256sum -c -
phel.phar: OK means the file matches. On any other output, delete the file. Without gh, copy the digest from the release page and compare it with shasum -a 256 phel.phar.
Release tags are GPG-signed. In a clone, git tag -v "$tag" checks the signature once you import the maintainer's public key.
Documentation
- Getting started: install, REPL and a first script
- CLI reference: every command and the development loop
- phel-lang.org: language guide, tutorials and exercises
- Contributor docs: architecture and project layout
- Architecture decisions
- Contributing
AI coding agents
phel agent-install copies Phel skill files for Claude Code, Cursor, Codex, Gemini, Copilot or Aider into your project. See resources/agents/.
./vendor/bin/phel agent-install claude # one agent ./vendor/bin/phel agent-install --auto # agents detected in this project ./vendor/bin/phel agent-install --all # every supported agent