isaias-dias-machado

isaias-dias-machado

IEx’s h macro is great but it lacks a pager, so I built a small tool that caches documentation and lets you fuzzy search through it in your OS shell.

It follows the Unix philosophy - Internally pipes to fzf and your default $PAGER. The cache lives at ~/.cache/exh and builds up over time as you workon different projects (no duplicates).

It compiles your project, loads all the available modules, and encodes the documentation using ETF.

Performance-wise, it caches a vanilla Phoenix project in about 10 seconds on first run, 3 seconds on subsequent runs. Tested on my old T420.

The formatting of the docs matches IEx’s `h` macro since I borrowed some of that code.

Example usage:

$ exh fetch
$ exh

Originally tried making it IEx-native using Ports (check the less-in-iex branch), but, despite redirecting the group leader and waiting for the Port’s exit message, couldn’t find a way to make the BEAM fully yield terminal control - resulted in race conditions between the BEAM and the TUI. If anyone has insights on this, I’m all ears!

https://github.com/isaias-dias-machado/exhelp

Feedback welcome!

Showing Posts 1 to 10

nikfp

nikfp

This solves a pain point I’ve been experiencing a lot, and never got a chance to dig in. (Too busy scrolling up after calling help!)

Looking forward to trying it out.

isaias-dias-machado

isaias-dias-machado OP

I feel you! Let me know if everything works smoothly or not.

rhcarvalho

rhcarvalho

Interesting! How do you deal with versioning?

E.g., the help for a certain module/ function may change depending on the current branch/commit, in particular for “in development” state, not between tagged releases.

The cache invalidation problem :slight_smile:

isaias-dias-machado

isaias-dias-machado OP

Good question, I haven’t thought of that until now. The currently supported solution would be to exh clean and exh fetch.

To make it more efficient, my first thought is to create a key-value store with the module names and a checksum for each module. This way, the caching algorithm can check the validity of each existing cached module when re-caching and clean up stale cache.

Also, validating against .tool-versions and mix.lock could be great.

How useful do you think each approach would be to you? Is cleaning + fetching fine for your use-case?

nikfp

nikfp

Does the cache speed improve on subsequent runs because it’s only compiling user land code? Whereas first run also caches and prepares dependencies?

isaias-dias-machado

isaias-dias-machado OP

The improvement comes from not having to perform disk IO for modules that have already been cached previously.
It will always iterate over every available module to the project: erlang/elixir installation, dependencies, and source code.

rhcarvalho

rhcarvalho

I find myself consuming docs most of the time from hexdocs.pm or source code. When I do use h inside IEx, I’m typically inside tmux and can “scroll” back up with the keyboard.

So, speaking hypothetically, if exh clean nukes the whole cache, it would be too aggressive if I just want to refresh docs for a particular project. A refetch or fetch --force would be more targeted.

I still wonder how are you structuring the cache. Do you shard by package version? How do you treat Elixir and Erlang documentation?

This idea of centrally storing a deduplicated cache of packages reminds me of the Go Module Cache. In the Go ecosystem published modules have an immutable cryptographic checksum, and the multiple versions of a package are cached read-only in a single place. Separately, there’s also a build cache. How I’d translate that idea to Elixir is that published Hex packages could be cached by version, while “current project” needs special treatment as it can change anytime without a version change.

rhcarvalho

rhcarvalho

Have you seen the new mix help task in Elixir 1.19?

“[mix help] Add mix help Mod, mix help :mod, mix help Mod.fun, mix help Mod.fun/arity, and mix help app:package”

It’s not interactive, but trivial to combine with fzf and a pager.

isaias-dias-machado

isaias-dias-machado OP

A refetch or fetch --force would be more targeted.

This sound very reasonable, I am going to add it.

I still wonder how are you structuring the cache. Do you shard by package version? How do you treat Elixir and Erlang documentation?

The cache structure is just a flat dir. There is a “tags” file that works as the index for fzf, then each cached module has its own file. Maybe it is a bit naive, if the re-caching process proves cumbersome I will think about something more complex.

isaias-dias-machado

isaias-dias-machado OP

Have you seen the new mix help task in Elixir 1.19?

Interesting, I wasn’t aware.

I still see some value in exh, people working in older versions can still browse docs on the terminal. Maybe I’ll add an option to just cache an index to use fzf with mix help in the future

Where Next? Top

Trending in Announcing Top

restlessronin
The repo is at GitHub - cyberchitta/openai_ex: Community maintained Elixir library for OpenAI API · GitHub. Docs are at OpenaiEx User Gu...
152 12366 136
New
type1fool
WebAuthnLiveComponent WebAuthnComponents See this post about renaming the package. Passwordless authentication for Phoenix LiveView app...
New
GenericJam
Edit: 2026 May 15 - This post is archived. Mob is alive!! Main docs: mob v0.7.11 — Documentation A bit of explanation for the slightly c...
New
woylie
I released Doggo, a collection of unstyled Phoenix components. https://github.com/woylie/doggo Features Unstyled Phoenix components....
New
mudasobwa
I fully migrated to my own harness from Anthropic/Gemini and I think it’s time to share it. Welcome DSH, the DeepSeek Harness, fully writ...
New
ausimian
Castle is a package I put together to assist with building Elixir releases capable of being live-upgraded via the ‘official’ release hand...
New
mcass19
ExRatatui lets you cook up rich terminal UIs in Elixir, powered by Rust’s ratatui via Rustler NIFs. Build interactive terminal applicatio...
New

Other Trending Topics Top

budgie
A little off-topic, but I feel like people here have a good head on their shoulders. I used to be quite good at making software. Was luc...
New
KristerV
Hey. Is there anyone here who creates agents in their apps? Not talking about using agents, but creating them. I’m finding it pretty diff...
New
juhalehtonen
There has been a thread to discuss the Stack Overflow Developer Survey on this forum every year since 2018, so here’s yet another one for...
New
budgie
I love Elixir. It’s one of 2 programming languages I’ve ever fallen in love with. But I don’t use it anymore. Serverless was the promis...
New
Null-logic-0
What IDE or editor are you using for Elixir development? Personally, I use Zed, and I really like it, but sometimes I wish there were a ...
New
OndrejValenta
(I just needed to vent somewhere and LinkedIn is full of hope, or hype, I’m not sure which exactly) AI dream has many faces, but general...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews