Library / SDK
melpa/melpa avatar
melpa/melpa

MELPA: how the Emacs package archive builds packages from upstream source

Recipes and build machinery for the biggest Emacs package repo

2,974 stars2,820 forksEmacs LispGPL-3.0

At a glance

What is it?
MELPA is a package.el-compatible Emacs archive whose contents are generated from upstream repositories by build recipes rather than uploaded tarballs. This covers how a recipe becomes an installable package, how to add the archive to Emacs, and where the model breaks down.
Who is it for?
Adopt MELPA if you want Emacs packages built from upstream source and are willing to run development snapshots; the README's own setup block is the whole installation. Do not adopt it if you need versioned releases: the maintainers state they do not use MELPA Stable and do not particularly recommend it, and switching later requires removing and reinstalling packages.
Can I use it commercially?
Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
Is it still maintained?
Yes. The repository last received commits 4 days ago.
What is it written in?
Mainly Emacs Lisp, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The problem MELPA solves for Emacs users and package authors

Emacs has had package.el since Emacs 24.1, but package.el only knows how to read an archive. Someone has to produce that archive, and the classic model is that each package author builds a tarball, writes a package descriptor and uploads both to a server. That works, and it is what ELPA does, but it makes the author responsible for a release process that has nothing to do with writing Emacs Lisp. A package that is actively developed between tagged releases is invisible to users until the author cuts a release.

MELPA inverts that. The README describes it as a collection of package.el-compatible packages "built automatically on our server from the upstream source code using simple recipes", and compares the idea to a server-side el-get or to Homebrew. The unit of contribution is not a tarball but a recipe file: a small Lisp form naming the package and pointing at the repository it lives in. The build server does the rest, and the README states that packages are updated at intervals throughout the day.

The audience is therefore two groups. Emacs users who want current code from upstream rather than whatever the last release tag contained. And package authors who maintain their code in a Git or Mercurial repository and do not want to run a release pipeline just to be installable. The cost of that convenience lands on the user's side, because what gets installed is the tip of the upstream branch, not a version anyone chose.

How a recipe becomes a package in the MELPA archive

The repository layout makes the pipeline visible. The recipes/ directory holds one file per package. package-build/ is the build machinery. packages/, packages-stable/ and packages-releases/ are output directories for the three published channels, with html/, html-stable/ and html-snapshots/ holding the generated index pages. Nothing in those output directories is hand-edited; they are regenerated by the build.

The recipe form is the contract. The README gives the shape, with :fetcher selecting the source type: git or hg for generic repositories, plus dedicated fetchers for GitHub, GitLab, Codeberg and Sourcehut. The generic fetchers require :url, the forge-specific ones require :repo in user-name/repo-name form and reject :url. A :commit or :branch pins the checkout; :version-regexp controls how a version string is pulled out of repository tags; :files selects which Emacs Lisp and info files end up in the built package.

The default :files value is worth reading closely, because it is where most accidental packaging problems come from. It picks up *.el and lisp/*.el plus info files in several conventional locations, and excludes dotfiles, test.el, tests.el and the *-test.el and *-tests.el patterns. The README is explicit about the consequence: Emacs Lisp libraries belong in the repository root or in lisp/, test files belong in test/ and should not provide a feature, and no NAME-pkg.el should be checked into version control. If your layout does not match those conventions, you override :files, and the README asks you not to unless the default is genuinely inadequate.

The build itself is driven by the Makefile. Its help output lists targets for building a single recipe, a channel, or all channels, with BUILD_PACKAGES to limit the set, ASYNC for parallel builds, V to echo the commands, and NOFETCH to build without fetching. Fetching can be run separately. Signing, archive-contents generation and HTML index generation are separate targets, which tells you the archive is assembled in stages rather than in one pass.

Installing MELPA in Emacs and installing your first package

The README's usage section is the whole installation procedure. You need an Emacs with package.el, meaning Emacs 24.1 or greater. The archive entry must be added to package-archives after (require 'package) and before the call to package-initialize in your init.el or .emacs:

elisp
(require 'package)
(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)
;; Comment/uncomment this line to enable MELPA Stable if desired.
;; See `package-archive-priorities` and `package-pinned-packages`.
;; Most users will not need or want to do this.
;; (add-to-list 'package-archives
;;              '("melpa-stable" . "https://stable.melpa.org/packages/") t)
(package-initialize)

After restarting Emacs, the README says to run M-x package-refresh-contents or M-x package-list-packages so Emacs fetches the MELPA package list. Skipping that step is the usual reason a package appears to be missing when you try to install it. Once the list is present, M-x package-list-packages browses and installs from MELPA and any other archive you have configured.

If you want to test that TLS works before blaming the archive configuration, the README suggests visiting an HTTPS URL, for example M-x eww RET https://wikipedia.org RET. That is a useful check because a broken TLS setup produces failures that look like archive problems.

For a package author, the contribution path is a pull request adding a file under recipes/. The CONTRIBUTING.org document is where the README points for the details, and it is not reproduced in the README itself. If you are building the archive locally rather than consuming it, the Makefile exposes the single-recipe target:

bash
make recipes/<package>

The help text also documents running a package through a sandbox, which installs a named package in an isolated environment:

bash
make INSTALL=<package> sandbox

That target is the closest thing to a local verification step before opening a pull request, and it is worth using because it exercises the recipe rather than your working copy.

MELPA vs ELPA, and what MELPA Stable actually changes

The most common question about MELPA is how it differs from ELPA, and the README answers it indirectly. ELPA is the archive that ships with Emacs and holds released packages; MELPA builds from upstream source. That is the difference in approach: release artifacts versus build output. It is why a MELPA package can be newer than any tag its upstream repository has, and why the version string is derived from tags using :version-regexp rather than being declared by the author.

MELPA Stable is the middle path, and the README is unusually blunt about it. The project builds and publishes packages corresponding to the latest tagged code where version tags exist, into a separate archive. But the README states that most users should prefer MELPA over MELPA Stable, and that the MELPA maintainers do not use MELPA Stable themselves and do not particularly recommend its use. That is a rare thing to find in a project's own documentation, and it should be read as a signal about where maintenance attention goes.

The practical trap is mixing the two. If both archives are in package-archives, the README notes you get development versions by default because development versions are higher. And you cannot simply flip a switch later: packages already installed from MELPA will never be updated to the stable version, because of how version numbering is handled. The README's suggestion is to remove all packages and reinstall them. For anyone with a large configuration, that is a real migration cost, and it argues for deciding which channel you want before you install anything.

package-pinned-packages and package-archive-priorities are the two variables the README names for controlling this. package-pinned-packages is available in Emacs 24.4 and later.

Where MELPA is the wrong tool

MELPA is the wrong choice when you need reproducibility. A MELPA package is built from the latest upstream source, and the README says packages are updated at intervals throughout the day. Two machines configured identically but refreshed at different times can end up with different code for the same package name. If your workflow depends on knowing exactly which revision of a dependency is running, MELPA does not give you that by default, and MELPA Stable only helps for upstreams that actually tag releases.

It is also the wrong choice when you want to install a package that is not in the archive and not a candidate for it. MELPA only serves what a recipe in recipes/ points at. A package whose upstream layout does not match the expected conventions needs a :files override, and the README asks contributors not to override unless necessary, so a repository that keeps its Lisp somewhere unusual is a harder sell than one that follows the convention.

The third case is version pinning. A recipe can carry :commit, :branch or :version-regexp, but those are properties of the recipe as maintained in the MELPA repository, not knobs you turn from your init file. If you need to hold a package at a specific revision, the archive is not the mechanism; you would be looking at vendoring the code or pinning through your own build.

Finally, the maintenance status is worth stating plainly. The repository is not archived, and the last push was on 2026-09-20. The README describes no deprecation and no wind-down.

Licence and the cost of keeping a recipe working

MELPA is GPL-3.0. That covers the recipes and build machinery in this repository. It does not relicense the packages MELPA builds: each upstream package keeps its own licence, and the archive is distributing build output from those upstreams. If you are contributing a recipe, the licence question you need to answer is about the upstream package, not about MELPA itself. Nothing here is legal advice, and the LICENSE file in the repository root is the authoritative text for the project's own code.

Upgrade cost has two sides. For users, the cost is the refresh cycle: M-x package-refresh-contents or M-x package-list-packages to pick up a new package list, and the acceptance that an update may bring upstream changes you did not ask for. For recipe maintainers, the cost is that a recipe is a standing commitment. If upstream renames the repository, changes its default branch, moves its Lisp out of the root and lisp/ directories, or starts tagging versions in a format the default :version-regexp cannot parse, the recipe stops producing a correct package. The :branch property exists precisely because a non-default branch has to be named explicitly.

There is also a structural cost visible in the repository layout: three output channels (packages/, packages-stable/, packages-releases/) plus three HTML index sets, all generated. That is build infrastructure the project carries, and it is the reason the Makefile separates fetching, building, signing and index generation into distinct targets. Anyone running a private MELPA-like archive inherits that structure, not just the recipe format.

Editorial conclusion

Adopt MELPA if you want Emacs packages built from upstream source and are willing to run development snapshots; the README's own setup block is the whole installation. Do not adopt it if you need versioned releases: the maintainers state they do not use MELPA Stable and do not particularly recommend it, and switching later requires removing and reinstalling packages. Before relying on a package, check its recipe file under recipes/ for the fetcher, branch and files list, since that is what decides what gets built.

Frequently asked questions

What is the difference between ELPA and MELPA?

MELPA builds packages automatically from upstream source code using recipes, while ELPA serves released packages. The practical effect is that MELPA packages track the latest upstream code rather than the last tagged release.

How do I install MELPA in Emacs?

Add an entry for "melpa" pointing at https://melpa.org/packages/ to package-archives after (require 'package) and before package-initialize in your init file. Then run M-x package-refresh-contents or M-x package-list-packages so Emacs fetches the package list.

How do I add MELPA to Emacs?

The README shows adding the archive with add-to-list on package-archives, using the cons cell ("melpa" . "https://melpa.org/packages/") and a non-nil APPEND argument. The entry has to come after (require 'package) and before the call to package-initialize.

What is MELPA Stable and should I use it?

MELPA Stable is a separate archive holding packages built from the latest tagged code in upstream repositories, where version tags exist. The README states that most users should prefer MELPA, and that the MELPA maintainers do not use MELPA Stable themselves and do not particularly recommend it.

How do I install a package from MELPA in Emacs?

Run M-x package-list-packages to browse and install, or M-x package-install for a package by name. Either way the MELPA package list has to have been fetched first with M-x package-refresh-contents or M-x package-list-packages.

Official sources

  1. Issues
  2. License: GPL-3.0
  3. melpa/melpa on GitHub
  4. Project website
  5. README
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.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/melpa-melpa.svg)](https://hysenlabs.com/projects/melpa-melpa)