Ref: Installing Erlang with man pages on Devuan Excalibur

tl;dr specifically for OTP 29

Follow normal Erlang/zx install procedure outlined below. After installation:

  1. Download the manpages from erlang.org

    Screenshot 2026-07-17
  2. Extract to ~/.erts/<whatever version>/

    The tarball extracts everything to ./man which you need to copy to ~/.erts/29.0.3/

    mkdir -p ~/build/eman
    cd ~/build/eman
    wget https://github.com/erlang/otp/releases/download/OTP-29.0.3/otp_doc_man_29.0.3.tar.gz
    tar xzvf otp_doc_man_29.0.3.tar.gz
    mv man ~/.erts/29.0.3/
  3. Edit your ~/.bashrc or ~/.zshrc and add

    # Erlang
    #
    # Need to set manpath this way otherwise the erts activate script
    # fucks up your life
    #
    # Trailing : is very very very important, do not neglect
    export MANPATH="$HOME/.local/share/man:$MANPATH:"
    . "$HOME"/.erts/29.0.3/activate

Start-to-finish cut sheet

Baseline context is Craig’s methodology for installing Erlang and zx. I have changed them slightly to reflect my own preferences.

sudo apt update
sudo apt upgrade -y
sudo apt install -y \
    gcc curl g++ dpkg-dev build-essential automake autoconf \
    libncurses-dev libssl-dev flex xsltproc libwxgtk3.2-dev \
    wget vim git

# Create directories we'll need
mkdir -p ~/build ~/bin
# make sure ~/bin is in $PATH

# clone kerl and add
cd ~/build
git clone https://github.com/kerl/kerl.git
cd
ln -s ~/build/kerl/kerl ~/bin/kerl

# this will print a bunch of versions, print whichever one you want
kerl update releases
export EVSN=29.0.3

# this will take a while as it's building Erlang from source
kerl build $EVSN $EVSN
kerl install $EVSN ~/.erts/$EVSN

# add man pages
mkdir -p ~/build/eman
cd ~/build/eman
wget https://github.com/erlang/otp/releases/download/OTP-29.0.3/otp_doc_man_29.0.3.tar.gz
tar xzvf otp_doc_man_29.0.3.tar.gz
mv man ~/.erts/29.0.3/

# add to ~/.zshrc:
export MANPATH="$HOME/.local/share/man:$MANPATH:"
. "$HOME"/.erts/29.0.3/activate

# You already have Erlang, this will get you ZX
wget -q https://zxq9.com/projects/zomp/get_zx && bash get_zx

Rant/explanation

I like having Erlang man pages on my system when I’m developing. Personally, when I can’t remember whether the function I want is lists:keyfind or lists:keysearch, I prefer running man 3 lists, having the docs appear instantly, then typing /key and hitting n a bunch of times until I visually see exactly the information I need, then moving on with my life.

This entire process takes 3 seconds or so start-to-finish.

The Recommended Approach nowadays is to use the documentation on erlang.org.

So let’s do some hallway testing. I don’t remember if I want to use lists:keyfind or lists:keysearch and I also don’t remember the argument order. So I’m going to do a Google search

Well we didn’t get the horrible gemini summary at least. But which of those seemingly identical pages should I click?

I’ll spoil it: the first two are for legacy versions of Erlang (R17 and R19 respectively), and the purple one is for R29.

The legacy versions of Erlang likely have different APIs. Up until recently, Erlang was a very stable language, so using documentation from multiple releases ago would probably not be an issue. But that’s no longer the case. I definitely need the most recent documentation.

So we’re already well over 30 seconds in just figuring out which thing to click on.

Supposing I already knew off-hand which module I need and the exact URL, simply loading https://www.erlang.org/doc/apps/stdlib/lists.html in my web browser takes around 5 seconds without caching. So unless it’s a page I have viewed recently on this machine, we would still be worse than the manpages approach even before we’ve ingested 1 bit of relevant information. My internet connection pretty effortlessly handles 4K video streaming so the issue is not on my end.

Once I load that page, I then have to click through 6 things to get to the information I want instead of it just being all there like it used to be.

Obviously I want a high-level executive summary of what the functions do and not the immediate type information I would erroneously get with the “man page”

No, I want to click on one of those functions, and then have to do a bunch of scrolling and keep a ton of context in my head, because in order to be Readable or whatever, the website only has enough vertical space to fit one function at a time on the screen (this is a 1080p laptop monitor)

Notice the man page does not have this issue

Funny how Erlang just recently (like in the 2020s) decided to jump on the “let’s make all our documentation JS web trash for no reason” bandwagon, just in time for TUIs to make a renaissance vis a vis Claude Code, Codex, Grok Build, whatever the fancy one du jour is.

I can only speak for myself, but I would guess programmers use the TUI harnesses because the web interfaces are all painfully slow vibecoded JS web trash, and a TUI simply has less friction.

Simultaneously, LLMs have de facto replaced search engines. Big Data can’t read vibecoded JS trash either. So now a good rule-of-thumb for what we used to call “SEO optimization” is “is your site readable via elinks”.

My read of the situation is that LLMs are applying market pressure in both directions simultaneously:

  • we can block Big Data from harvesting our site by making everything insane vibecoded JS web trash that he can’t read
  • we need Big Data to index our site so people can find it so we better have a super fast plain-text version somewhere

Just in time, kerl apparently removed support for building manpages in R27.

KERL_DOC_TARGETS

Default: chunks Available targets:

  • man (dropped in OTP 27): install manpage docs.
  • html: install HTML docs.
  • pdf (dropped in OTP 27): install PDF docs.
  • chunks: install the “chunks” format to get documentation from the erl REPL.

You can set multiple type of targets separated by space, example KERL_DOC_TARGETS="html chunks"

The kerl documentation is very confusing and contradicts itself multiple times. It seems like R27 was when Erlang changed its internal documentation markup format from whatever it was before to some weird markdown thing so that documentation would pop up when you do tab completion:

Pre-R27, setting KERL_BUILD_DOCS=yes before running kerl build 29.0.3 29.0.3 was the thing you needed to do in order to get the man pages installed. Then it was a matter of setting $MANPATH correctly in zshrc so that man knew where to find the erlang man pages.

That doesn’t work anymore because it wasn’t Best Practices. Best Practices dictate that a language whose selling point is nine-nines of uptime needs to be In Active Development and continually introducing new keywords (maybe) and breaking the build process.

What I’ve worked out (with the assistance of Big Data) is the following:

  • As of now (July 2026) there are multiple different breakages at different stages in the build/install process.
  • These breakages are are out-of-phase with each other and with the Kerl documentation.
  • This Is A Good Thing because it’s just the cost of Active Development. Moving Fast implies Breaking Things.

These breakages are:

  1. As of R27, KERL_BUILD_DOCS=yes no longer can build man pages, so they have to be downloaded/installed retroactively.

  2. In R29, pre-built manpages are available for download, but kerl doesn’t know how to build them. There was no ability to have man pages at all for R27 or R28.

The Kerl documentation is very confusing and contradicts itself multiple times. Can you model this state machine in your head and figure out which variables need to be set to what in order to get the man pages installed?1

KERL_BUILD_DOCS

If $KERL_BUILD_DOCS is set, kerl will create docs from the built Erlang/OTP version regardless of origin (tarball backend from <erlang.org> or via kerl build git, or via git backend).

If $KERL_BUILD_DOCS is unset, kerl will only install docs when not installing a build created via kerl build git..., and according to KERL_INSTALL_HTMLDOCS and KERL_INSTALL_MANPAGES.

KERL_DOC_TARGETS

Default: chunks Available targets:

  • man (dropped in OTP 27): install manpage docs.
  • html: install HTML docs.
  • pdf (dropped in OTP 27): install PDF docs.
  • chunks: install the “chunks” format to get documentation from the erl REPL.

You can set multiple type of targets separated by space, example KERL_DOC_TARGETS="html chunks"

KERL_INSTALL_MANPAGES

Install man pages when not building from Git source.

It’s noteworthy that when not using KERL_BUILD_DOCS=yes, the docset that may be downloaded can be up to 120 MB.

I can not. And even if you can, it doesn’t matter, because the documentation isn’t even correct.

I think what probably happened (I didn’t check, just an educated guess) is when Erlang changed the documentation format in R27 to the markdown chunks thing, kerl changed the documentation in the KERL_DOC_TARGETS section, but didn’t update the adjacent two sections so as to not be contradictory. I don’t think this is their fault necessarily. I think it’s more likely they are overstretched and don’t have the energy to keep up with the laser pointer.

I would consider submitting a patch to fix/clarify all of this, but I do not have the emotional bandwidth to deal with GitHub unless I absolutely have to, and I especially don’t have the patience for Code-of-Conduct projects. So fuck em.

Bottom line is to just download them and unpack the manpages tarball retroactively. And be prepared to work through this whole mess again next release.


  1. Kerl README source↩︎

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.