i use currently melpa for managing my emacs packages, but I'm not satisfied with that. Melpa seems to manage the packages by dumping them into my emacs.d - which i don't want to store inside my dotfiles git repo. But still, i want to be able to easily reinstall my emacs without much interaction (ideally just executing an update command)

Most Plugin Managers of vim provided a very neat way of solving that issue. They dump also the packages inside my .vim, but mainly manage them by a list inside the main vim config file:

call plug#begin('~/.dotfiles/nvim/autoload/plugged')

" Languages
Plug '0robustus1/vim-tmux-conf'
Plug 'hrother/offlineimaprc.vim'
Plug 'LaTeX-Box-Team/LaTeX-Box'
Plug 'Matt-Deacalion/vim-systemd-syntax'

" Editing
Plug 'tpope/vim-surround'
Plug 'scrooloose/nerdcommenter'

" git helpers
Plug 'jreybert/vimagit'
Plug 'airblade/vim-gitgutter'
Plug 'tpope/vim-fugitive'
Plug 'vim-scripts/gitdiff.vim'

" other useful stuff
Plug 'tyru/open-browser.vim'
Plug 'godlygeek/tabular'

call plug#end()

The packages there are basically listed as 'github-user/repo', therefore e.g. the url for 'godlygeek/tabular' is https://github.com/godlygeek/tabular. This way, i can completely ignore the content of my plugin directory. After reinstalling my vim, i can just execute ':PlugInstall'

To be clear what i search for: I don't care where my emacs installs its packages from (e.g. github, from the melpa servers, etc.). I just want to know a method how i can list all packages i want to install inside my emacs config file (like the vim solution).

is there sth similar for emacs?

  • 1
    Not what you asked, but add your ~/.emacs.d/elpa directory to your dotfiles .gitignore file if you don't want to track that. Also, not committing your packages makes you dependent on all of those upstream sources remaining available, stable, and compatible.
    – phils
    Mar 28, 2016 at 2:21
  • Just for reference: I found truongtx.me/2013/01/07/emacs-package-manager helpful.
    – uuu
    Apr 4, 2016 at 15:00

2 Answers 2


package.el is not designed for managing your package configuration entirely within your init-file. The state of package.el is partly stored in your init-file, but partly in the state of the elpa directory. In particular, if you remove all references to a package from your init-file, package.el will keep on loading it, forever!

Also, package.el has no support whatsoever for installing particular versions of packages. So if you want a reproducible Emacs configuration, you have to put the millions of lines of code from your packages into version control. Ugly!

Because of these problems, I wrote a new package manager, straight.el, which determines your package management configuration solely from your init-file and (optionally) a revision lockfile that specifies exact Git hashes for all of your packages. It is a declarative package manager, meaning that you do not need to interact with it manually. You just change your init-file, and straight.el figures out what needs to get done. In particular, there's no manual setup on a new machine. You just drop your init-file in place and start Emacs: all of your packages will be installed and loaded automatically. If you keep your revision lockfile in version control, then all of your packages will also be checked out at exactly the same revisions as they were on your previous machine.

Check out the extremely verbose documentation for details and comparisons to other package managers.


First, to get the packages out of .emacs.d, set the variable package-user-dir. You might need to reinstall your existing packages or move them by hand, but once that's set, new packages will go there.

As to the problem of declaring packages for auto-install, I think you're looking for the :ensure option for use-package. From the documentation:

You can use use-package to load packages from ELPA with package.el. This is particularly useful if you share your .emacs among several machines; the relevant packages are downloaded automatically once declared in your .emacs. The :ensure keyword causes the package(s) to be installed automatically if not already present on your system (set (setq use-package-always-ensure t) if you wish this behavior to be global for all packages)

Note that the one package use-package can't install for you is itself. I use this code to handle that:

(unless (package-installed-p 'use-package)
  (package-install 'use-package))
(require 'use-package)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.