LFE: a Lisp-2+ front-end to the Erlang compiler
Lisp Flavoured Erlang (LFE)
At a glance
- What is it?
- LFE (Lisp Flavoured Erlang) is a Lisp syntax layer over the Erlang compiler, shipped with its own REPL, shell and script runner. It suits Erlang developers who want macros and parentheses without leaving the BEAM.
- Who is it for?
- Adopt LFE if you already run Erlang/OTP and want Lisp macros and a REPL over the same compiler and runtime, and start by cloning the repository and running make compile to confirm your erl binary is on PATH. Skip it if you need a standalone language with its own VM, or if you want a documented library story for hex.pm, since the README only shows the maintainers' own publish target.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 7 days ago.
- What is it written in?
- Mainly Erlang, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 2, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What LFE is, and the Erlang developer it is written for
LFE describes itself as "a lisp syntax front-end to the Erlang compiler", and the README adds that code produced with it is compatible with normal Erlang code. That sentence carries the whole pitch. You are not getting a new runtime, a new scheduler or a new bytecode format. You are getting a reader and a compiler front-end that turn S-expressions into Erlang terms and modules, plus an evaluator and a shell.
The audience is narrow and specific. Someone who already writes Erlang and has an OTP release to maintain, and who wants macros, uniform syntax and a REPL that behaves like a Lisp. The README's own tagline calls LFE "A Lisp-2+ on the Erlang VM", which is a precise claim: separate namespaces for functions and variables, plus something extra the project does not spell out in the README. If you have never run an Erlang node, this project gives you no path around that. LFE requires Erlang to be installed and the erl binary to be in $PATH, and that is stated as a hard prerequisite rather than a suggestion.
What it is not: a self-contained language distribution. There is no bundled VM, no package manager of its own, and no installer that fetches Erlang for you.
How LFE sits on the Erlang compiler
The repository layout tells you where the work happens. src/ holds the Erlang sources, and the Makefile derives its source lists by wildcarding .erl, .xrl and .yrl files from that directory, so the compiler itself is built with Erlang's own toolchain. c_src/ holds C sources, and include/ holds headers, which means at least part of the system is native code rather than pure Erlang. The Emakefile at the top level is the older Erlang build description, and rebar.config plus rebar.config.script are present for rebar3 users.
The data flow is the conventional one for a language front-end: source text is read, parsed into an abstract form, and handed to the Erlang compiler, which emits .beam files indistinguishable in kind from those produced from .erl sources. That is why the README can claim compatibility in both directions. The REPL is a separate concern: an evaluator and shell are included, so you can type expressions and get results without writing a file. The examples directory shows the range the project expects you to cover, from examples/fizzbuzz.lfe and examples/guessing-game.lfe through examples/mnesia-demo.lfe and examples/ets-demo.lfe to examples/http-sync.lfe and examples/http-async.lfe. Two files, examples/object-via-closure.lfe and examples/object-via-process.lfe, show the same idea implemented two ways, which is a fair hint about the idioms the language encourages.
One structural detail worth noting: the default branch is develop, and the Dockerfile at the top level is not a build recipe at all. It is a single FROM line pulling lfex/lfe:latest. The actual image construction lives in a separate repository, lfex/dockerfiles, which the Dockerfile comments link to.
Building LFE from source and starting the REPL
The README gives the clone-and-build path directly. You need Erlang installed first, with erl on your PATH.
git clone https://github.com/lfe/lfe.git
cd lfe
make compileAfter that, the README says you can start the REPL from the working directory with the bin/lfe script:
./bin/lfeThe banner the README shows reports the Erlang/OTP version, the ERTS version, and the LFE version, then prints lfe> as the prompt. From there the README's quick taste is two expressions that both evaluate to 42:
lfe> (* 2 (+ 1 2 3 4 5 6))
lfe> (* 2 (lists:foldl #'+/2 0 (lists:seq 1 6)))The second line is the interesting one. It calls lists:foldl and lists:seq, which are Erlang standard library functions, and it passes #'+/2 as the function argument. That is the compatibility claim made concrete: LFE code calls Erlang modules directly, with no binding layer in between. If you want LFE available outside the clone, the install target places lfe, lfec, lfedoc and lfescript in /usr/local/bin by default, and both PREFIX and MANINSTDIR are overridable make variables:
make install PREFIX=/Users/rv/ MANINSTDIR=/Users/rv/manThat example, taken from the README, puts the programs in /Users/rv/bin and the man pages under /Users/rv/man/man*. For a container instead, the README documents pulling lfex/lfe, building the image from the clone with docker build, and running docker run -it lfex/lfe to reach the REPL.
Scripts get their own entry points. The README shows ./bin/lfe script-name script-arg-1 for a script run from the clone, lfe script-name script-arg-1 once installed, and a separate lfescript program for shell-style scripts. examples/sample-lfe-shellscript and examples/sample-lfescript are the files to read before writing your own.
Where LFE is the wrong tool
The first limitation is the prerequisite. LFE requires Erlang, and the README does not describe a bundled or vendored runtime. If your environment cannot install Erlang/OTP, LFE is not an option, and no amount of documentation reading changes that.
The second is the documentation surface. The README points outward: a docs site, a Quick Start gitbook, a user guide at doc/user_guide.txt, a version history, and a list of technical files including lfe_comp.txt, lfe_macro.txt and lfe_io.txt. It does not walk through the language. The quick taste is a single arithmetic expression and a fold. Anyone deciding whether to adopt LFE will have to read those files rather than the front page, and the front page gives no sense of how large the language surface is.
The third is a gap between what the README covers for users and what it covers for maintainers. There is a full section on cutting releases, including make tags for creating the number-only and v-prefixed tags, a manual GitHub release flow, and make publish for hex.pm, which requires rebar3 and a hex plugin entry in your system rebar.config. There is no equivalent section on consuming LFE from hex.pm, or on how a downstream project declares a dependency on it. The badge row does link the hex.pm package and its download counts, so the package exists, but the README's own treatment of hex.pm is one-directional.
Finally, the Dockerfile is a pointer, not a build. Building the image yourself from the clone runs docker build against a file whose only instruction is FROM lfex/lfe:latest. The README says you can build the image yourself, and technically you can, but you will get the published image's layers, not a build of your working tree. The comments in that file direct you to lfex/dockerfiles for the real recipes. If you expected a reproducible local build from source, that expectation is unmet.
LFE compared with writing plain Erlang, and with Clojure on the JVM
The nearest alternative is not another Lisp. It is Erlang itself. LFE and Erlang compile to the same target and can call each other's modules, so the real question is whether the syntax and macro system earn their place in your codebase. Plain Erlang gives you the official documentation, the full weight of OTP examples, and every Erlang developer you hire. LFE gives you a reader macro system and a uniform syntax over the same semantics. Note the repository files doc/lfe_clj.txt and examples/core-macros.lfe: the project treats macros as a first-class part of its identity, which is exactly the thing plain Erlang cannot offer.
A second comparison is Clojure on the JVM. Both are Lisps hosted on a mature VM, and both accept the host's libraries as native citizens, which is what the lists:foldl line demonstrates for LFE. The difference is the host. Clojure inherits the JVM's threading and memory model and its library ecosystem. LFE inherits Erlang's process model, its scheduler and its distribution, which is the reason to pick it. If your problem is concurrent, fault-tolerant and distributed by nature, the Erlang side of that trade is the whole point. If your problem is data processing on the JVM, LFE is simply the wrong host.
A third option worth naming: stay in Erlang and use parse transforms or a code generator when you need metaprogramming. That is more work per macro and it is not a Lisp, but it keeps the codebase inside the ecosystem's default tooling. The choice is about how much macro-driven abstraction you actually want.
Maintenance, releases and what the licence lets you do
The repository is not archived and the last push was on 2026-09-26, two days before this writing, so the project is being worked on now rather than merely preserved. Releases are frequent enough to matter: v2.2.2 and v2.2.1 both landed on 2026-08-05, and v2.2.0 before them on 2025-01-11. The gap between v2.2.0 and v2.2.1 is roughly seven months, then two releases on the same day, which reads like a fix followed immediately by a follow-up.
Upgrade cost is where the README is thin. The version history lives at doc/src/version_history.md, and that is the file to read before moving between releases, because the README itself says nothing about breaking changes, deprecations or migration. The release process described in the README is manual at the GitHub step: draft a release, choose the tag, generate release notes, publish. Automated release notes are only as good as the commits behind them.
On licensing: the project is Apache-2.0, and the Makefile carries the standard Apache header with the copyright line reading 2016-2025 Robert Virding. Apache-2.0 includes an explicit patent grant and requires that you preserve notices and state changes you make. If you modify LFE and redistribute it, or ship it inside a product, read the licence text and your own legal counsel's reading of it rather than treating this paragraph as advice.
One further cost to budget: LFE is built with Erlang and the Makefile produces native code from c_src/, so your build environment needs a working C toolchain alongside Erlang. The Makefile sets CFLAGS to -Wall -Wextra and, on Linux, LDFLAGS to -Wl,--as-needed, which tells you the project expects a normal GCC or Clang setup.
Editorial conclusion
Adopt LFE if you already run Erlang/OTP and want Lisp macros and a REPL over the same compiler and runtime, and start by cloning the repository and running make compile to confirm your erl binary is on PATH. Skip it if you need a standalone language with its own VM, or if you want a documented library story for hex.pm, since the README only shows the maintainers' own publish target. Verify before committing: that make install lands lfe, lfec, lfedoc and lfescript where you expect under PREFIX, and that the doc/ and examples/ files answer the questions the README leaves open.
Frequently asked questions
What is LFE, and what does the name stand for?
LFE stands for Lisp Flavoured Erlang. The README describes it as a lisp syntax front-end to the Erlang compiler, with code that is compatible with normal Erlang code, and it includes an evaluator and a shell.
How do I install LFE?
Clone the repository and run make compile, which requires Erlang to be installed with the erl binary in $PATH. To install system-wide, run make install, which by default creates lfe, lfec, lfedoc and lfescript in /usr/local/bin, and PREFIX plus MANINSTDIR can be overridden.
Can I run LFE without installing it system-wide?
Yes. After compiling inside the clone, the README shows starting the REPL with ./bin/lfe, and running a script with ./bin/lfe script-name script-arg-1. The README also documents pulling the lfex/lfe Docker image and running it with docker run -it lfex/lfe.
What is the difference between LFE and writing plain Erlang?
They target the same compiler and runtime, so LFE code and Erlang code are compatible. The difference is the syntax and the macro system: LFE is described as a Lisp-2+ on the Erlang VM, and the repository includes doc/lfe_macro.txt and examples/core-macros.lfe alongside documentation for the compiler, IO and code generation modules.
What licence does LFE use?
The project is Apache-2.0, and the Makefile carries the Apache header with a copyright line reading 2016-2025 Robert Virding.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/lfe-lfe)