You can make ELPA compatible archives locally and then add them to your package-archives so you can install locally developed packages.

Your package-archives might look like this:

{{{
(("local-dir" "/home/nic/my-emacs-packages/")
 ("gnu" . "http://elpa.gnu.org/packages/")
 ("marmalade" . "http://marmalade-repo.org/packages/"))
}}}

== Why do this? ==

It's really useful if you are developing packages, it makes your code more portable. You can spin up another emacs instance very quickly to test it.

== Building local archives ==

Mirroring is difficult, so consider using already-developed tools for this purpose. For example (there may be others):

=== ElpaKit ===

NicFerrier wrote the [[ElpaKit]] tool for this process, but it also

* [MakingPackages makes Emacs packages] from source files
* isolates, runs, and manages tests

Unfortunately (as of 3 Aug 2021) ElpaKit

* has [https://github.com/nicferrier/elpakit/commits/master had no commits since 2014]
* has [https://github.com/nicferrier/elpakit/issues open issues from 2013-2016]

=== elpa-mirror ===

[http://blog.binchen.org/ Redguardtoo] wrote [https://github.com/redguardtoo/elpa-mirror elpa-mirror], which

* is more focused on the mirroring task
* has (as of 3 Aug 2021) [https://github.com/redguardtoo/elpa-mirror/commits/master commits less than 6 weeks old]
* seems better tested: has [https://github.com/redguardtoo/elpa-mirror/blob/master/.github/workflows/test.yml CI], tests over [https://github.com/redguardtoo/elpa-mirror#why Emacs versions=25-27 on OS ∈ {macOS, Cygwin, Windows 10, Linux}]

== Temporarily declaring the local archive ==

You might want only some code to affect the local archive. Here is ##package-let## which let's you do that:

{{{
(defun package-let (package archive)
  "Install a package using the specified archive."
  (let ((package-archives
         (cons (cons "archive" archive)
               package-archives)))
    (package-refresh-contents)
    (package-install
     (if (stringp package)
         (intern package)
       package)))
  (package-refresh-contents))
}}}

An example of its use:

{{{
(package-let 'kv "~/teamchat.net/shoesoff-elpa")
}}}

this will install the package ##kv## from the archive to be found at ##~/teamchat.net/shoesoff-elpa##. Any inter package dependancies pulling from the same archive will work... but as soon as the //transaction// is finished the archives revert to the user specified ones.
