Todd Resudek
11 min readJan 31, 2018

What is Hex?

Hex is the package manager for the Erlang VM. It is analogous to RubyGems for the Ruby ecosystem or NPM for Javascript.

Hex was authored by Eric Meadows-Jönsson and first released December 23, 2013. (The first release of Elixir (0.5.0) was May 24, 2012.)

There are currently about 5,700 packages available on hexpm. Compare that to RubyGems (~9,000), Crates (~13,500), or NPM (~500,000).

Why become a power user?

Most users will suffice with just searching hex.pm for packages, and then adding them to their project deps. But learning more about hex can help you work faster, prevent potential issues, make debugging easier, and become a stronger developer.

Anatomy of a Hex Package

Any Hex package you look at will follow the same basic file structure:

A typical hex package

You may also find files like, LICENSE.md that are not always required, but are common. In this case, if a package is released under a license, it is required to have a markdown file containing the full text of that license.

The mix.exs file contains some required metadata for the package.

mix.exs

From top to bottom, the most important parts to notice are:

version — Hex requires packages to follow semantic versioning. Major versions make breaking changes, minor versions add features in a non-breaking way, and patches are bug fixes.

description — Writing a useful description is important. This is what users see when they are searching for packages, or what they read on hex.pm when they are browsing.

deps — This isn’t hex-specific, but it is worth pointing out that dependencies can be loaded from hex, directly from git, or even from a local path. This means you could create and use a hex package that you never actually publish.

package[:name] — The name your package is given on hex.pm and in search.

package[:organization] — Useful if you intend to publish a package to a private repository (not required.)

Package Naming

There is only one hard rule when naming a Hex package:

Avoid using offensive or harassing package names, nicknames, or other identifiers that might detract from a friendly, safe, and welcoming environment for all.

That said, there are conventions to follow.

If you are providing functionality on top of an existing package, consider using that package name as a prefix. For example, if you want to add authentication to Plug, consider calling your package plug_auth (or plug_somename) instead of auth (or somename).

Avoid namespace conflicts with existing packages. Plug owns the Plug namespace, if you have an authentication package for Plug use the namespace PlugAuth instead of Plug.Auth.

When porting a library from another ecosystem, the tradition is to use the existing name, and prepend it with “ex_”, or less commonly, append “_ex”.

Names are first come first serve. If you want to publish a package for the spotify API, you can name it “spotify” as long as no one has taken it first. There is no preference given to the trademark owner.

That said, squatting is not allowed. You cannot publish a package just to reserve a name. Your published package must be non-trivial or it could be removed.

mix hex.info

Calling Hex.Info with no arguments will return information about your local hex installation. You will see an output like this:

Knowing this information could help diagnose why you are having an issue that your coworker isn’t (or vice versa.)

Hex also checks if an update is available when you run this command. If so, you’ll see an this line at the end:

Hex will cache the result of the version check for 24 hours.

mix hex.info <package>

Adding a package name will give you information about all the releases of that package, and it’s most current description.

This output will show you the last 8 releases (plus an ellipsis if there are more than 8). And perhaps most importantly, it will show you which versions have been retired. (More on retired packages later)

The Config: {:alphabetify, "~> 1.0"} tells you what to add to your mix file. It will not recommend matches that point to release candidates or retired versions. For example, the highest version of postgrex is 1.0.0-rc.1 . But hex will recommend {:postgrex, "~> 0.13"} because that is the most recent stable version.

The underlying code looks like this:

Hex looks in the list of releases and tries to find the newest stable version. It also cross-checks that with the list of retired versions of that package.

If there are no stable or non-retired versions, hex will still just recommend the most recent version.

mix hex.info <package> <version>

Adding a version will give you information about that specific release.

Pay attention to the dependencies, they can help you diagnose potential conflicts or outdated code.

mix hex.search

This one is pretty self-explanatory — it searches hex.pm for packages matching a search string. The search is limited to 100 results (most searches should match less than 10 packages.)

You can try this out with: mix hex.search alpha , which gives a result like this:

The version listed is the latest stable version (it does not include release candidates.)

You can search for multiple words by separating your search words with a plus (eg. alpha+beta). However, those searches are joined with a logical “OR”, so it returns matches of either word, not both. There is a project going on now to move the search from a basic postgres ILIKE to a more advanced technology (elasticsearch perhaps) and adding more advanced search options is being considered for that implementation.

By default, this only searches the public repository. You can search a private repo by passing the --organization flag.

mix hex.docs

Now that you have found some potentially great packages, you will want to read their documentation.

  • * when you search for [“eex”, “elixir”, “ex_unit”, “iex”, “logger”, “mix”] it will get the version that matches your currently installed elixir version.
  • otherwise, it will get the latest version
  • unless you specify a version

documentation is downloaded, and unpacked into ~/.hex/docs/PACKAGE/VERSION/

mix hex.docs offline elixir 1.5.0will open your downloaded version of the documentation. Using the online task opens the documentation on the hex.pm website.

There is a flag for organization, however publishing documents is not yet supported for private repos, it does nothing.

mix hex.user

Before you can publish a Hex package, or join and organization, you will need to register for an account on Hex.pm. You can do start the process by typing: mix hex.user register .

The prompt will ask you for a username, email address, and password.

The requirements are pretty minimal; your username has to be at least 3 characters, can only contain letters, numbers, and/or limited set of symbols (underscores, hyphens, periods, or parens.)

To activate your account, you will need to confirm your email address by clicking a link in an email Hex sends after you register.

That’s it! Now you are an official Hex user.

At some point, you may want to change your password. Hex uses 2 passwords, one local, and one for Hex.pm.

To change your local password, use: mix hex.user reset_password local . You will just need your current password and then to choose a new password.

Your local password is stored in ~/.hex/hex.config as encrypted_key. The password is encrypted using the A256CBC algorithm (but will be updated to A256GCM once support for OTP 17 is dropped.)

To change your remote password, you can use: mix hex.user reset_password account .

You will be prompted for you username, then an email will be sent with a link to reset your password. After doing that, you might find your locally stored api keys will not work.

You can see your locally stored keys with: mix hex.user key — list . If they are not working you can easily regenerate them. First, remove all of your local keys: mix hex.user key --revoke-all . Next, authorize your user: mix hex.user auth . Now all of your keys will be regenerated.

mix hex.config

Reads, updates or deletes local Hex configuration.

Running that command with no keys (or values) will print your current configs.

username: "supersimple"
offline: "false"

These configurations are all stored in a config file on your computer. Most of the time that file is located at: ~/.hex/hex.config .

you can set review an individual setting with:

mix hex.config KEY

To set it’s value, use: mix hex.config KEY VALUE . Technically, you can use any key/value pair, however there are only 8 keys hex will consider;

api_url, offline, unsafe_https, unsafe_registry, http_proxy, https_proxy, http_concurrency, and http_timeout

Generally, you can ignore these settings unless you decide to set up your own hex server.

The one setting worth noting is http_concurrency. By default, hex will make up to 8 concurrent requests. You can play with this number if you have a lot of dependencies and want to increase speed, but it has been known to sometimes cause conflicts.

To remove a custom setting, you can use the --delete flag. For example, mix hex.config KEY --delete .

mix hex.outdated

Shows all Hex dependencies that have newer versions in the registry.

By default, it only shows top-level packages explicitly listed in the mix.exs file. All outdated packages can be displayed by using the — alloption.

You can also add the --pre flag which will include release candidates when looking for newer versions.

If a dependency name is given all requirements on that dependency, from the entire dependency tree, are listed. This is useful if you are trying to figure why a package isn’t updating when you run mix deps.update.

mix hex.audit

Shows all Hex dependencies that have been marked as retired. Retired packages are no longer recommended to be used by their maintainers. The task will display a message describing the reason for retirement and exit with a non-zero code if any retired dependencies are found.

If any of your dependencies have been retired, you will see an output like this:

mix hex.publish

Sharing a hex package with the community is very simple. Just make sure your mix.exs file contains the necessary metadata (as described above), and that you are a registered user. Then you can build and publish the package by using: mix hex.publish .

By default, this command will build (using mix docs) and publish the documentation as well. You can exclude publishing your documentation by using mix hex.publish package .

If you have included organization in your package configuration (in mix.exs), the package will be pushed to your organization’s private repository. You can also publish to an organization by using the --organization flag. For example, mix hex.publish --organization org-name .

Note that hexdocs currently does not support private repositories, so documents will not be included when you publish to a private repo.

Your publish will fail if you have included any pre-release dependencies. Pre-releases are identified by a version that contains a “-”. For instance, 1.2.0-rc1 or 1.2.0-pre .

There are some exceptions to this rule. First off, if the version of your hex package is also a pre-release, it can include pre-release dependencies.

This rule also does not apply to packages published to private organizations.

Typo Squatting

As a package is published the name is checked for levenshtein distance against all existing packages. The default distance is 2. When a package is submitted with a name that is within that threshold to another package, emails are sent to the hex admins. The admins will determine if it is a bona fide attempt to typo squat, or just a name that is close for a legitimate reason.

If the name is determined to be an attempt to typo squat, the package will be permanently removed from the hex repository.

This does not apply to private repos.

Revoking a Release

If you find an error in you release, you can withdraw it from the public repository by using: mix hex.publish --revert VERSION . This is only possible within 1 hour from when you originally published that release.

Releases are designed to be available in perpetuity. This is one of the great features of Hex. In recent times, we have seen problems in the node.js community as a result of packages that applications depend on being removed. (https://www.theregister.co.uk/2016/03/23/npm_left_pad_chaos/)

Hex is designed in a way that you can count on your dependencies always being available.

Updating documentation

While your release can only be amended within the first hour of it’s release, documentation can be updated any time.

mix hex.publish docs will republish documentation.

The documentation will be accessible at: hexdocs.pm/my_package/1.0.0

hexdocs.pm/my_package will always redirect to the latest published version.

Retiring Releases

While releases cannot be withdrawn from the hexpm repo, they can be retired.

This feature was added in version 0.15.0 (released 2016–12–24)

You should mark a release as retired when you no longer recommend it’s usage. A retired package is still resolvable and usable but it will be flagged as retired in the repository and a message will be displayed to users when they use the package.

There are 5 valid reasons for deprecation:

  • renamed — The package has been renamed, including the new package name in the message.
  • deprecated — The package has been deprecated, if there’s a replacing
    package include it in the message.
  • security — There are security issues with this package.
  • invalid — The package is invalid, for example it does not compile
    correctly.
  • other — Any other reason not included above, clarify the reason in the
    message

Use the task: mix hex.retire PACKAGE VERSION REASON to retire a release, where REASON is one of the above 5 reasons. Entering anything else will throw an error.

You can add more details by using the --message flag. Adding a message is not required, but you should consider adding it, especially if the reason is “other”.

Organizations

This feature was added in version 0.17.1 (released 2017–08–29)

Organizations are a way to share packages in a private repository. This feature is still in private beta, but it scheduled to be released in February 2018. There will be a per user price for being a member of an organization.

Technically speaking, all requests are including an organization now. They default to “hexpm”, which is the global public repo.

To publish or consume a package in a private repository, a user must belong to it. You can sign up for an organization on the hex.pm website. Once that is done, you can invite other users to join your organization.

The organizations interface on hex.pm

To authorize your user as a member of an organization, type: mix hex.organization auth ORGNAME . Later, you can use hex mix.organization deauth ORGNAME to remove yourself.

Then, you can verify which organizations you are authorized for by using: mix hex.organization list .

As the admin of an organization, you can also remove access to a user on the hex.pm website.

Submit and Issue or Open a Pull Request

Hex and Hexpm are open source software (released under the Apache 2 license.) The software is only as great as it is because of it’s contributors. Check out Hex or Hexpm on Github if you are interested in getting involved.

Code of Conduct

The Hex community adheres to a code of conduct to ensure everyone feels welcome and safe. Please read it

  • Be respectful.
  • We’re here to help: support@hex.pm
  • Abusive behavior is never tolerated.
  • Data published to Hex is hosted at the discretion of the Hex team, and may be removed.
  • Violations of this code may result in swift and permanent expulsion from the Hex community.