The correct solution is to use [`straight.el`](https://github.com/raxod502/straight.el), a package manager that I wrote to solve this problem. You can find more details about this in [another answer to this question](https://emacs.stackexchange.com/a/34241/12534). This answer, which was written months before I started work on `straight.el`, previously described a strictly inferior way of achieving a partial solution. This approach is described briefly below; I no longer recommend it. Even if you don't want to use `straight.el`, you should at least adopt [`use-package`](https://github.com/jwiegley/use-package). (Not that the two are mutually exclusive—I believe the cleanest setup comes from using both.) --- Start by defining a list of packages in your init-file: (defvar my-packages '( aggressive-indent avy . . . projectile undo-tree ) "List of packages to be installed at Emacs startup.") Then install them automatically: (require 'cl-lib) (package-initialize) (unless (cl-every #'package-installed-p my-packages) (dolist (package my-packages) (unless (package-installed-p package) (package-install package)))) If you keep your `init.el` file under version control, then syncing it to another machine will result in your packages being installed automatically. Of course, the versions that are installed will be completely different, and your configuration can't be expected to work out of the box as a result. This is a fundamental flaw of `package.el`, and is one of the reasons why this approach is bad. See again [`straight.el`](https://github.com/raxod502/straight.el). Note also that the code outlined above separates your package list from your configuration for those packages, making it harder to keep track of things in your init-file. This is another major disadvantage. See again [`use-package`](https://github.com/jwiegley/use-package).