While the erl application is really useful to tinker with Erlang modules, the lack of a persistent history has always been annoying. I recently discovered via Adopting Erlang that the history can be made persistent since Erlang 20 with specific flags, which can be added to the ERL_AFLAGS environment variable to have them enabled by default.

Shell history is handled by the group_history module; since this module is part of the kernel application, the configuration flags are provided with the -kernel command line argument (see the erl documentation, specifically the -Application Par Val syntax. An interesting property of this mechanism is that parameters are passed as Erlang terms. Therefore a string should be passed in shell as '"foo bar"'.

The module will simply use application:get_env(kernel, Name) to read these parameters.

The kernel_app documentation presents the following parameters:

  • shell_history: whether to enable or disable permanent history.
  • shell_history_drop: a list of commands to be omitted from the history.
  • shell_history_file_bytes: the maximum size of the history.
  • shell_history_path: the path of the directory to write history to.

It is really simple to add these flags to ERL_AFLAGS, for example in $HOME/.zshenv for the zsh shell:

ERL_AFLAGS="+pc unicode"
ERL_AFLAGS="$ERL_AFLAGS -kernel shell_history enabled"
ERL_AFLAGS="$ERL_AFLAGS -kernel shell_history_path '\"$HOME/.erl_history\"'"

export ERL_AFLAGS

I only found two small issues with this feature:

  • There is a small delay between the time an entry is saved and the moment is is actually written to disk. Therefore quitting quickly after entering a command may result in the entry missing from the history.
  • History searching with C-r seems to work, but is far less powerful than the readline feature. Good enough I guess.