Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up

🍀 Next-generation, purely functional package manager for the Emacs hacker.

License

NotificationsYou must be signed in to change notification settings

radian-software/straight.el

Repository files navigation

straight.el: next-generation, purely functional package managerfor theEmacs hacker.

Please check out theFAQ andnews :)

Gitter chat

Features

  • Install Emacs packages listed onMELPA,GNU ELPA, orEmacsmirror, or provide your own recipes.
  • Packages are cloned as Git (or other) repositories, not as opaquetarballs.
  • Make changes to a package simply by editing its source code, noadditional steps required. Contribute upstream just by pushing yourchanges.
  • Powerful interactive workflows (with popups à la Magit) forperforming bulk maintenance on the Git repositories for yourpackages.
  • Save and load version lockfiles that ensure 100% reproducibility foryour Emacs configuration. Package state is defined entirely by yourinit-file and (optional) lockfile, with no extra persistent datafloating around.
  • Specify package descriptions using a powerful format based onMELPArecipes (with a familiar but improved syntax).
  • use-package integration.
  • Modular: you can install your packages manually and straight.el willload them for you. Or you can also have straight.el install yourpackages, while you provide the recipes explicitly. Or straight.elcan also fetch recipes, if you want. Bulk repository management andpackage updates are also optional.
  • Extensible APIs to add new recipe sources and version-controlbackends.
  • The cleanest source code you've ever seen.45%ofstraight.el is comments and docstrings.

Note:straight.el is a replacement forpackage.el,notuse-package.use-package can be used with eitherpackage.el orstraight.el.

Guiding principles

  • Init-file and version lockfiles as the sole source of truth. Nopersistent state kept elsewhere.
  • 100% reproducible package management, accounting for changes inpackages, recipe repositories, configuration, and the packagemanager itself.
  • No support whatsoever forpackage.el.
  • Edit packages by editing their code, no extra steps required. Allowfor manual version control operations.
  • Compatibility with MELPA, GNU ELPA, and Emacsmirror.
  • Trivial to quickly try out a package without permanently installingit.
  • Good for reproducing an issue withemacs -Q.

Getting started

Note:straight.el supports a minimum version of Emacs 25.1, andworks on macOS, Windows, and most flavors of Linux. You must installGit in order to usestraight.el.

First, place the following bootstrap code in your init-file:

(defvarbootstrap-version)(let ((bootstrap-file       (expand-file-name"straight/repos/straight.el/bootstrap.el"        (or (bound-and-true-p straight-base-dir)            user-emacs-directory)))      (bootstrap-version7))  (unless (file-exists-p bootstrap-file)    (with-current-buffer        (url-retrieve-synchronously"https://raw.githubusercontent.com/radian-software/straight.el/develop/install.el"'silent'inhibit-cookies)      (goto-char (point-max))      (eval-print-last-sexp)))  (load bootstrap-filenil'nomessage))

(Ifraw.githubusercontent.com is blocked by your ISP, try replacingthe URL withhttps://radian-software.github.io/straight.el/install.el. Or you canclonestraight.el manually to~/.emacs.d/straight/repos/straight.el.)

Here are some variables you may be interested in (some of them must besetbefore the bootstrap code runs, if they might affect howstraight.el itself is loaded):

  • straight-repository-branch -- toget the latest version ofstraight.el from thedevelop branch,rather than the defaultmaster which is updated less frequentlybut which is ostensibly more stable.
  • straight-check-for-modifications --to configure an alternate way forstraight.el to check formodifications made to package source code, rather than the default(which is 100% reliable, but has a minor cost to startup time).
  • straight-use-package-by-default-- if you useuse-package, then this makes eachuse-package form also invokestraight.el to install the package,unless otherwise specified.
  • straight-vc-git-default-protocol -- bydefault,straight.el clones over HTTPS. If you need packages fromprivate Git repositories in your configuration, then you might wantto use SSH instead.
  • straight-base-dir --by default, straight's main directory, containing its build files andpackage repos, is located inuser-emacs-directory. You can changethe location of straight's base directory via this variable.
  • straight-build-dir --by default, the directory in which packages are built is located atstraight-base-dir/build. Changing this variable will change the nameof that directory and the name of the build cache file (unlessstraight-build-cache-fixed-name is non-nil).
  • straight-use-version-specific-build-dir -- if non-nil, use anEmacs-version-specificstraight-build-dir directory to supportrunning multiple versions of Emacs against the sameuser-emacs-directory. There is a minor performance penalty onstartup becausestraight.el will not be byte-compiled.

You should remove any code that relates topackage.el; for example,references topackage-initialize,package-archives, and (if you'reusinguse-package):ensure oruse-package-always-ensure.

Users of Emacs versions >= 27 will want to add:

(setq package-enable-at-startupnil)

to theirearly init-file to prevent package.elloading packages prior to their init-file loading.

While it is technically possible to usebothpackage.el andstraight.el at the same time, there is no realreason to, and it might result in oddities like packages gettingloaded more than once.

Debugging

  • Sometimes, in a corporate environment,url-retrieve-synchronouslymay not work andstraight.el will be unable to download theinstallation script mentioned in the bootstrap snippet. In thiscase, you may simply clone this repository into~/.emacs.d/straight/repos/straight.el and check out your desiredrevision/branch. The installation script is just a more convenientway of doing that automatically when necessary (and looking up thecorrect revision ofstraight.el in your lockfile, if any).

  • On macOS, you may receive an error:

    Could not create connection to raw.githubusercontent.com:443

    This is likely because you are using an ancient version of Emacswhich has a broken TLS configuration. Upgrade withbrew upgrade emacs.

Install packages

Out of the box, you can install any package listed onMELPA,GNUELPA, orEmacsmirror, which is to say any package inexistence. (Although MELPA is used as a package listing, packages areinstalled by cloning their Git repositories rather than by downloadingtarballs likepackage.el does.) To install a package temporarily(until you restart Emacs), runM-x straight-use-package and selectthe package you want. To install a package permanently, place a calltostraight-use-package in your init-file, like:

(straight-use-package'el-patch)

Note that installing a package will activate all of its autoloads, butit will not actuallyrequire the features provided by the package.This means that you might need to userequire orautoload for someantiquated packages that do not properly declare their autoloads.

To learn more, see the documentation onthe packagelifecycle.

But what about my fork of (obscure .el package)?

Instead of passing just a package name tostraight-use-package, youcan pass a list ("recipe"). You can see the default recipe for anygiven package by runningM-x straight-get-recipe. For example, therecipe forel-patch is:

(el-patch:type git:host github:repo"radian-software/el-patch")

So, if you have forkedel-patch and you want to use your forkinstead of the upstream, do:

(straight-use-package '(el-patch:type git:host github:repo"your-name/el-patch"))

In fact,straight.el has explicit support for using a forkedpackage, since this is so common:

(straight-use-package '(el-patch:type git:host github:repo"radian-software/el-patch":fork (:host github:repo"your-name/el-patch")))

In the above,:type git may be omitted if you leavestraight-default-vc at its default value ofgit. Parts of the:fork keyword may be omitted as well. One common case is whenyour fork is on the same host and has the same name as the upstreamrepository. In this case, assumingstraight-host-usernames is set,specifying a fork is as simple as:

(straight-use-package '(el-patch:type git:host github:repo"radian-software/el-patch":forkt))

Note thatstraight.el doesn't do any Git operations during startupunless it needs to clone a package from scratch. This is forperformance. You can explicitly request forstraight.el to fix upthe Git configuration after you change a package recipe, e.g. to add afork. SeeAutomatic repository management below.

To learn more, see the documentation onthe recipeformat andthe Git backend.

Integration withuse-package

use-package is a macro that provides convenientsyntactic sugar for many common tasks related to installing andconfiguring Emacs packages. Of course, it does not actually installthe packages, but instead defers to a package manager, likestraight.el (which comes withuse-package integration by default).

To useuse-package, first install it withstraight.el:

(straight-use-package'use-package)

Nowuse-package will usestraight.el to automatically installmissing packages if you provide:straight t:

(use-package el-patch:straightt)

You can still provide a custom recipe for the package:

(use-package el-patch:straight (el-patch:type git:host github:repo"radian-software/el-patch":fork (:host github:repo"your-name/el-patch")))

The:straight keyword accepts backquoted forms.This makes it possible to dynamically compute part of the recipe:

(use-package el-patch:straight `(el-patch:type git:repo ,(alist-get'el-patch my-package-urls)))

Specifying:straight t is unnecessary if you setstraight-use-package-by-default to a non-nil value. (Note that thevariableuse-package-always-ensure is associated withpackage.el,and you should not use it withstraight.el.)

To learn more, see the documentation onstraight.el'suse-packageintegration.

Edit packages locally

One of the biggest strengths ofstraight.el is that editing packageslocally is trivial. You literally just edit the files (find-functionand friends all work as you would expect). Packages will beautomatically rebuilt if necessary when Emacs next starts up.

You can even commit your changes and push or pull to various remotesusing Git. You have complete control over your packages' Gitrepositories.

To learn more, see the documentation onthe packagelifecycle.

Automatic repository management

While being able to make arbitrary changes to your packages is verypowerful, it can also get tiring to keep track of the all thosechanges. For this reason,straight.el provides a suite of powerfulinteractive workflows to perform bulk operations on your packages.

  • To restore each package to its canonical state (a clean workingdirectory with the main branch checked out, and the remotes setcorrectly), runM-x straight-normalize-package orM-x straight-normalize-all.

  • To fetch from each package's configured remote, runM-x straight-fetch-package-and-deps orM-x straight-fetch-all; toalso fetch from the upstream for forked packages, supply a prefixargument.

  • To merge changes from each package's configured remote, runM-x straight-merge-package-and-deps orM-x straight-merge-all; toalso merge from the upstream for forked packages, supply a prefixargument.

  • To push all local changes to each package's configured remote, runM-x straight-push-package orM-x straight-push-all.

All of these commands are highly interactive and ask you before makingany changes. At any point, you can stop and perform manual operationswith Magit or other tools in a recursive edit.

To learn more, see the documentation onbulk repositorymanagement.

Configuration reproducibility

To save the currently checked out revisions of all of your packages,runM-x straight-freeze-versions. The resulting file(~/.emacs.d/straight/versions/default.el), together with yourinit-file, perfectly define your package configuration. Keep yourversion lockfile checked into version control; when you install yourEmacs configuration on another machine, the versions of packagesspecified in your lockfile will automatically be checked out after thepackages are installed. You can manually revert all packages to therevisions specified in the lockfile by runningM-x straight-thaw-versions.

To learn more, see the documentation onversionlockfiles.

Conceptual overview

This section describes, at a high level, how the different mechanismsinstraight.el play together. This illustrates howstraight.elmanages to accomplish all of itsguiding principles.

TL;DR

straight.el operates by cloning Git repositories and then symlinkingfiles into Emacs' load path. The collection of symlinked filesconstitutes the package, which is defined by its recipe. The recipealso describes which local repository to link the files from, and howto clone that repository, if it is absent.

When you callstraight-use-package, the recipe you provide isregistered withstraight.el for future reference. Then the package'srepository is cloned if it is absent, the package is rebuilt if itsfiles have changed since the last build (as determined byfind(1)),and its autoloads are evaluated.

You can also provide only a package name, in which case the recipewill be looked up in one of several configurable recipe repositories,which are just packages themselves (albeit with the build stepdisabled).

straight.el determines which packages are installed solely by howand whenstraight-use-package is invoked in your init-file.

What is a package?

Apackage is a collection of Emacs Lisp (and possibly other) files.The most common case is just a single.el file, but some packageshave many.el files, and some even have a directory structure.

Note that a package is defined only as a collection of files. Itdoesn't necessarily correspond to a Git repository, or an entry onMELPA, or anything like that. Frequently there is a relationshipbetween all of these concepts, but that relationship does not alwayshave to be direct or one-to-one.

A package also has a name, which must be unique. This is the name thatis used for the folder holding the package's files. It is frequentlythe same as the name of a Git repository, or an entry on MELPA, butagain this does not have to be the case.

Where do packages come from?

If you really wanted all of your packages to be unambiguously defined,you could just copy and paste all of their files into version control.But that would defeat the purpose of using a package manager likestraight.el. Instraight.el, packages are defined by two sourcesof information:

  • alocal repository
  • abuild recipe

The local repository is just a directory containing some files. Ofcourse, it also has a name, which may or may not be the same as thepackage's name. Frequently, the local repository is also a Gitrepository, but this is not necessary.

The build recipe is not a literal data structure. It is a concept thatrepresents a certain subset of the package's recipe. Specifically, the:files,:local-repo, and:build keywords.

To transform thisinformation into an actual package that Emacs canload,straight.elbuilds the package. This means that somesymbolic links are created in the package's directory that point backinto the local repository's directory. Exactly how these symlinks arecreated is determined by the:files directive, and which localrepository the symlinks point to is determined by the:local-repodirective.

After the symlinks are created, the resulting files are byte-compiled,and their autoloads are generated and written into a file in thepackage's directory.

If:build nil is specified, however, this entire process is skipped.This mechanism is used for recipe repositories.

What does this look like on disk?

The local repositories are kept in~/.emacs.d/straight/repos, andthe built packages are kept in~/.emacs.d/straight/build. If youhave initializedstraight.el and loaded packageel-patch, thenyour~/.emacs.d/straight directory will look roughly like this (someirrelevant details have been omitted for pedagogical purposes):

straight├── build│   ├── el-patch│   │   ├── el-patch-autoloads.el│   │   ├── el-patch.el -> ~/.emacs.d/straight/repos/el-patch/el-patch.el│   │   └── el-patch.elc│   └── straight│       ├── straight-autoloads.el│       ├── straight.el -> ~/.emacs.d/straight/repos/straight.el/straight.el│       └── straight.elc└── repos    ├── el-patch    │   ├── CHANGELOG.md    │   ├── LICENSE.md    │   ├── README.md    │   └── el-patch.el    └── straight.el        ├── LICENSE.md        ├── Makefile        ├── README.md        ├── bootstrap.el        ├── install.el        └── straight.el

As you can see, the package names areel-patch andstraight. Whileel-patch is built from a local repository of the same name,straight is built from a local repository by the namestraight.el.Also note that only.el files are symlinked, since only they arerelevant to Emacs.

Where do repositories come from?

Local repositories provide a way to define packages without specifyingthe contents of all of their files explicitly. But that's not helpfulwithout a higher-level way to define local repositories withoutspecifying the contents of all oftheir files. Instraight.el,local repositories are defined by two sources of information:

  • afetch recipe
  • theversion lockfiles

The fetch recipe is, like the build recipe, a concept representing acertain subset of the package's overall recipe. The situation is moreinteresting here becausestraight.el supports multipleversion-control backends. The version-control backend specified by thefetch recipe is determined by the:type directive (which defaults tostraight-default-vc). Each version-control backend then accepts someset of additional directives. For example, thegit backend accepts:

  • :repo
  • :host
  • :branch
  • :nonrecursive
  • :fork
  • :protocol

If a local repository is not present, then its fetch recipe describeshow to obtain it. This is done using thestraight-vc-clone function,which delegates to one of the backend implementations of thecloneoperation, according to:type. (The option:type built-in is aspecial case that results in all version-control operations for thepackage being ignored. You can also use:type nil to accomplish thesame, but with the difference that the package is still loaded fromits specified:local-repo.)

However, even with a particular repository source specified, there isstill the question of which version of the repository to use. This iswhere the version lockfiles come in. When a local repository iscloned, the version lockfiles are searched to see if there is aparticular commit specified for that local repository's name. If so,that commit is checked out. (For thegit backend, commits are40-character strings representing SHA-1 hashes, but the representationof a commit identifier could be different across different backends.)

Thestraight-freeze-versions andstraight-thaw-versions methodsalso use backend-delegating methods; in this case, they arestraight-vc-get-commit andstraight-vc-check-out-commit.

The fetch recipe and version lockfiles, together with theconfiguration options forstraight.el, precisely define the state ofa local repository. Of course, you may make any changes you want tothe local repository. But this information defines a "canonical" statethat you may revert to at any time.

When this information is combined with the build recipe,straight.elis able to construct canonical, universal versions of your Emacspackages that will be the same everywhere and forever.

Note that you do not have to provide fetch recipes or versionlockfiles. You may manage your local repositories manually, if youwish, although this has obvious disadvantages in terms ofrepeatability and maintainability.

What does it mean to load a package?

A prerequisite to loading a package is making sure the package hasbeen built. After that is done, loading the package means adding itsdirectory to the load path and evaluating its autoloads file.

Adding the directory to the load path means that you can userequireto load the package's files. Note thatstraight.el does not do thisfor you, since loading packages immediately is usually not necessaryand it immensely slows down Emacs startup.

Evaluating the autoloads file means that calling the functions thatare defined in the autoloads file will automaticallyrequire thefiles that define those functions. All modern packages define theirfunctions in autoloads and are designed to be loaded on-demand whenthose functions are called. Antiquated packages may need you toexplicitly define autoloads, or to justrequire the package rightaway.

Where do recipes come from?

straight-use-package does not require an actual recipe. You can justgive it a package name, and it will look up the recipe. This is doneusingrecipe repositories. Recipe repositories are set up as aswappable backend system, much like the version-control backendsystem.

A recipe repository consists of four parts:

  • a fetch recipe for the local repository (this will typically include:build nil, since recipe repositories usually do not need to bebuilt)
  • a function that, provided the local repository is already available,returns a list of all packages that have recipes in the reciperepository
  • a function that, given a package name, returns the recipe for thatpackage, or nil if the recipe repository does not provide a recipefor the package
  • an entry instraight-recipe-repositories indicating that therecipe provided actually corresponds to a recipe repository(otherwise it would just be a regular package)

Note that recipe repositories are implemented as regular packages!This means that all the usual package management operations work onthem as well. It also means that you usestraight-use-package toregister them (although typically you will provide arguments tostraight-use-package so that the recipe repository is onlyregistered, and not cloned until it is needed; seethe section onstraight-use-package).

If you givestraight-use-package just a package name, then eachrecipe repository instraight-recipe-repositories is checked for arecipe for that package. Once one is found, it is used. Otherwise, anerror is signaled (unless the package is built-in to Emacs, accordingtopackage.el).

Note thatstraight.el uses its own recipe format which is similar,but not identical, to the one used by MELPA (seethe section on therecipe format for information on the differences). Therecipe repository backends abstract over the formatting differences indifferent recipe sources to translate recipes into the uniform formatused bystraight.el. When you runM-x straight-get-recipe, thetranslated recipe is what is returned.

What happens when I callstraight-use-package?

There are three actions thatstraight-use-package can take:

  • Register a package's recipe withstraight.el.
  • Clone a package's local repository, if it is missing.
  • Build a package, if it has been changed since the last time it wasbuilt, and load it.

These actions must be performed in order. Depending on the argumentsyou pass tostraight-use-package, one, two, or all three may beperformed.

The normal case is to do all three. The fetch recipe is only requiredif the local repository is actually missing, but the build recipe isalways required.

Deferred installation can be accomplished by tellingstraight-use-package to stop if the local repository is not alreadyavailable. The deferred installation can be triggered by invokingstraight-use-package again, but telling it to go ahead and clone therepository (this is the default behavior). Becausestraight-use-package already registered the package's recipe thefirst time, you don't have to provide it again.

In some extraordinary circumstances (such as whenstraight.el isbootstrapping its own installation), it may be desirable to clone apackage's local repository if it is missing, but to stop beforebuilding and loading the package. This can also be done bystraight-use-package.

What does it mean to register a package?

Package registration is the first action taken bystraight-use-package, before building and cloning. First, if only apackage name was provided tostraight-use-package, a recipe isobtained from the configured recipe repositories. Next, the resultingrecipe is recorded in various caches.

This is important, since it allows for several things to happen:

  • if you later want to perform another operation on the package usingstraight.el, you do not need to provide the recipe again
  • if you use a custom recipe for Package A, and Package B requiresPackage A as a dependency, your custom recipe is remembered andre-used when Package A is used as a dependency, to avoid conflicts.
  • when multiple packages are built from the same local repository, andyou have specified a custom fetch recipe for one of those packages,straight.el can intelligently merge that fetch recipe into theautomatically retrieved recipes of dependencies, in order to avoidconflicts.
  • straight.el knows which packages you have installed, if you wantto perform interactive operations on them.
  • if you accidentally provide two different recipes for the samepackage,straight.el can issue a helpful warning, since this maylead to surprising behavior.

How doesstraight.el know when to rebuild packages?

When you request forstraight.el to load a package (usingstraight-use-package), it first checks if the package needs to berebuilt. This means that some of the files in its local repositoryhave been modified since the last time the package was built.straight.el uses an optimizedfind(1) command to check for packagemodifications, and it uses some caching mechanisms to perform bulkfind(1) operations on multiple packages, to speed up these checks(although it never performs optimizations that may result in erroneousbehavior).

This check occurs during Emacs init, when your init-file makes callstostraight-use-package. You may notice a significant delay on thefirststraight-use-package call, because this is whenstraight.elperforms a bulkfind(1) call and caches the results for later usage(this speeds up init considerably). The total delay is likely to be onthe order of 100ms for a double-digit number of packages.

The rebuild detection system is what allows for you to make changes topackages whenever you would like, without performing any additionaloperations.

(Packages are also rebuilt when their recipes change, of course.)

How doesstraight.el know what packages are installed?

straight.el does not require you to declare a central list ofpackages anywhere, like Cask does. Instead, it determines whatpackages are to be loaded implicitly, by your invocations ofstraight-use-package during Emacs initialization. Furthermore,straight.el allows you to install packages after initializationusingM-x straight-use-package (or even by evaluatingstraight-use-package forms). However,straight.el still providesadvanced features such as bulk package management and version locking.This creates some interesting challenges which other package managersdo not have to deal with.

straight.el solves these problems using a concept calledtransactions. The operation of the transaction system is mostlytransparent to the user, at least in recent versions ofstraight.el.Basically, it provides a way forstraight.el to keep track of whathappens within a single user operation (e.g. evaluate a buffer ofstraight-use-package calls, or load the init-file).

straight.el uses the transaction system to keep track of whatpackages you request in your init-file. If you invokestraight-use-package interactively, then this invalidates thatinformation, since you have now requested a package that is not inyour init-file. For this reason, if you have invokedstraight-use-package interactively, runningM-x straight-freeze-versions will prompt you to first reload yourinit-file.

Note: reloading your init-file must have the effect of running allof the samestraight.el-related functions again. For example, if youbootstrapstraight.el in a sub-file that you onlyrequire insteadofload, then the reloading functionality will not work correctlyand you may receive the messageCaches are still outdated; something is seriously wrong. See#437 for discussion.

Comparison to other package managers

(Disclaimer: while I try to be as objective and comprehensive aspossible here, I'm obviously biased. Please submit corrections if Ihave unfairly disparaged your favorite package manager!)

There are many package managers for Emacs, ranging from simple scriptsto download files from EmacsWiki to full-featured package managementsolutions likestraight.el. Here are the most feature-richalternatives tostraight.el:

  • package.el: de facto standard, bundled with Emacs.
  • Quelpa: allows you to use external sources like GitHub withpackage.el. Essentially a localMELPA.
  • Cask: anotherpackage.el wrapper. Specify your dependencies in aCask file; can be used for project management or an Emacsconfiguration.
  • el-get: ridiculously OP in terms of how many different sources youcan pull packages from (package.el, every known VCS, distropackage managers,go get(!!)).
  • Borg: assimilates packages as Git submodules into.emacs.d,relying onEmacsmirror.
  • "Screw package managers! I'll just handle it all myself!"

TL;DR

Here is a summary of the main differences in philosophy between thepackage managers:

  • Usepackage.el if you want package management to be as easy aspossible, and do not much care for installing packages from specificsources, keeping track of their versions, or doing local developmenton them.
  • Use Quelpa if you likepackage.el but really wish you couldspecify the sources of your packages.
  • Use Cask if you likepackage.el but wish it came with some projectmanagement tools, as well.
  • Use el-get if you want to easily install packages from as manydifferent sources as possible.
  • Use Borg if you like a more lightweight approach to packagemanagement that leverages existing solutions, if contributingchanges to packages upstream is important to you, and if using Gitsubmodules isn't a deal-breaker.
  • Use the manual approach if you need to contribute changes to apackage that is versioned in something other than Git.
  • Usestraight.el if you like reproducibility in your Emacsconfiguration, you regularly contribute changes to packagesupstream, or you are writing an Emacs configuration to be used byothers.

And here is a brief list of the main reasons you might not want to usestraight.el:

  • straight.el is largely unusable if you do not have Git installed,although it is still possible to use the package-building featuresif you manage your repositories manually (you also cannot use themagic bootstrap snippet, in that case). If you don't want to installGit, you'll have to usepackage.el or take the manual approach.
  • straight.el is not built in to Emacs. If you want something thatwill work right out of the box, you're stuck withpackage.el orthe manual approach.
  • straight.el takes a minute or two to update all your packages,since it does not rely on a centralized server. If you want quickupdate checking, you'll have to usepackage.el.
  • straight.el does not provide any user interface for packagemanagement. For that, you'll have to usepackage.el, el-get, Cask,or Borg (which expects you to useepkg for browsingpackages).
  • straight.el does not currently support using only stable versionsof packages (i.e. tagged revisions), although this is aplannedfeature. If this is important to you, you probably want to gowithpackage.el (with GNU ELPA and MELPA Stable), Cask, or Quelpa.
  • If you don't like having to modify your init-file to do packagemanagement, thenstraight.el is absolutely not for you. You wantpackage.el, Quelpa, el-get, or Borg.
  • If you really want to contribute changes to packages that are notversioned in Git, thenstraight.el will not help you. You'll haveto manage the package's repository manually. Unfortunately, there isno existing package manager that supports both non-Gitversion-control systems and contributing changes upstream. You'llhave to go with the manual approach.
  • straight.el does not provide project management tools. It is apackage manager. If you want project management tools, check outCask.
  • straight.el is quite new and moving fast. Things might break. Theother package managers can generally be ranked as follows, from mostactive to least active: el-get, Quelpa, Borg, Cask,package.el(glacial).

Comparison topackage.el

  • package.el downloads pre-built packages from central servers usinga special (undocumented?) HTTP protocol, whilestraight.el clonesGit (or other) repositories and builds packages locally.

Advantages ofstraight.el

  • straight.el allows you to install a package from any branch of anyGit repository.package.el only allows you to install a packagefrom apackage.el-compliant central server.
  • straight.el allows you to check out any Git revision of anypackage.package.el only allows you to install the latest version,and there is no way to downgrade.
  • straight.el supports Emacsmirror, whilepackage.el does not.
  • straight.el uses your init-file as the sole source of truth forpackage operations.package.el loads every package you everinstalled at startup, even if some of those packages are no longerreferenced by your init-file.
  • straight.el supports 100% reproducibility for your Emacs packageswith version lockfiles.package.el cannot provide reproducibilityfor the set of packages installed, the central servers they wereinstalled from, or the versions in use.
  • straight.el allows you to make arbitrary changes to your packageslocally. While it is possible to make local changes topackage.elpackages, these changes cannot be version-controlled and they willbe silently overwritten wheneverpackage.el performs an update.
  • straight.el allows you to perform arbitrary version-controloperations on your package's Git repositories, includingcontributing changes upstream.straight.el has explicit supportfor specifying both an upstream and a fork for a package.Contributing changes upstream withpackage.el is impossible.
  • straight.el is designed withemacs -Q bug reports in mind.package.el is unsuitable for minimal bug reproductions, since itautomatically loads all of your packages on any package operation,even inemacs -Q.
  • straight.el operates quietly when all is going well.package.eldisplays all messages, errors, and warnings that come frombyte-compilation and autoload generation.
  • straight.el considers modifying the user's init-file extremelyuncouth.package.el aggressively inserts (via Customize)auto-generated code settingpackage-selected-packages into theinit-file whenever a package is installed. Furthermore,package.elhas a history of impolite treatment of user configuration, which Ithink says some things about the design: until Emacs 27.1 (whenmypatch to fix this issue was adopted afteraround 300 emails' worth of squabbling on emacs-devel), it alsoinserted a call to thepackage-initialize function into theinit-file if it was not already present, with the officiallyrecommended workaround "comment it out if you don't want it, butdon't get rid of it".
  • straight.el has a profile system that allows users of someoneelse's Emacs configuration to manage an additional subset ofpackages, or to override upstream package configuration, withoutforking the upstream.package.el has no such concept.
  • straight.el is developed openly on GitHub, using a modernissuetracker and continuous integration from GitHub Actions. Itwelcomes contributions of any type.straight.el is licensed underthe permissive MIT license and does not require a copyrightassignment.straight.el is developed actively and has explicitsupport for installing development versions of itself, as well asfor contributing upstream changes.package.el is maintained as apart of Emacs core, meaning that the contribution process is poorlydocumented and discouraging. Releases ofpackage.el coincide withreleases of Emacs, which are infrequent and inflexible. There is noissue tracker specifically forpackage.el, only the Emacs bugtracker and the emacs-devel mailing list. Contributing topackage.el requires a poorly-documented, cumbersome copyrightassignment process and is done by submitting patches to anantiquated mailing list, unsupported by modern code review toolingor continuous integration.

Advantages ofpackage.el

  • package.el does not require that you have Git installed, since thecentral server deals with where the packages originally came from.straight.el cannot be used at all without Git.
  • package.el is built in to Emacs and does not require additionalconfiguration to get started with.straight.el requires the use ofa 10-line bootstrap snippet in your init-file.
  • package.el can perform bulk package updates more quickly since itrelies on central servers.
  • package.el has a user interface for package management that alsodisplays package metadata.straight.el has no user interface forpackage management; any UI is provided by the user'scompleting-read framework.
  • package.el does not require you to touch your init-file to installpackages, whilestraight.el absolutely refuses to permanentlyinstall a package without an explicit reference to it in yourinit-file (although this may be considered an advantage, dependingon your perspective).
  • Using MELPA Stable,package.el can install only stable versions ofpackages. By default,package.el also installs only stableversions of packages from GNU ELPA. These modes of operation areunsupported bystraight.el at this time, although this is aplanned feature.

Additional notes

  • package.el andstraight.el usually take approximately the sametime to install packages, despite the fact thatstraight.el iscloning entire Git repositories. This is because network latency andbyte-compilation are the dominant factors.
  • Somepackage.el servers build packages from non-Git upstreams.package.el can install these packages, whilestraight.el cannot.However, sincepackage.el has no version-control support, this ismore or less equivalent to installing those packages from theEmacsmirror, whichstraight.el can do by default.

Comparison to Quelpa

  • Quelpa allows for fetching packages from arbitrary sources andbuilding them into a format that can be installed bypackage.el.straight.el has a philosophy which is fundamentally incompatiblewithpackage.el, and non-compatibility withpackage.el is one ofits design goals.

Advantages ofstraight.el

  • straight.el has out-of-the-box compatibility with MELPA, GNU ELPA,and Emacsmirror, while Quelpa only has support for MELPA. To use GNUELPA, you must drop down topackage.el.Emacsmirror is notsupported by default, although it is easy to specify an Emacsmirrorrepository in a recipe. While Quelpa allows you to specify customrecipe folders, it does not have support for cloning these foldersautomatically from version control, nor for generating the recipesin any way other than copying them literally from files.straight.el allows you full flexibility in this regard.
  • straight.el has integrated support for selecting particular Gitrevisions of packages. This process is more manual in Quelpa, as itrequires placing the commit hash into the recipe, which disablesupdates.
  • straight.el uses your init-file as the sole source of truth forpackage operations. Since Quelpa is based onpackage.el, it alsoloads every package you ever installed at startup, even if thosepackages are no longer referenced by your init-file. Furthermore,there is an additional caching layer, so that deleting a packagefrom thepackage.el interface and removing it from your init-filestill does not actually delete it.
  • straight.el supports 100% reproducibility for your Emacs packageswith version lockfiles. Quelpa can theoretically provide somemeasure of reproducibility, but this requires significant manualeffort since all packages are not associated with specific revisionsby default, nor is the revision of MELPA saved anywhere.
  • straight.el allows you to make arbitrary changes to your packageslocally. While it is possible to make local changes to Quelpapackages, there are two places to do so: the built package, which isthe default destination offind-function, and the originalrepository. Changes to the former are not version-controlled andwill be silently overwritten bypackage.el operations, whilechanges to the latter will be silently overwritten by Quelpaoperations.
  • straight.el has explicit support for configuring both an upstreamrepository and a fork for the same package. Quelpa does not havesuch a concept.
  • straight.el allows you complete control over how your repositoriesare managed, and the default behavior is to draw all packagesversioned in a single repository from a single copy of thatrepository. Quelpa is hardcoded to require a separate repository foreach package, so that installing Magit requires three copies of theMagit repository.
  • straight.el builds packages using symlinks, meaning thatfind-function works as expected. Quelpa builds packages bycopying, a feature inherited from MELPA. This means thatfind-function brings you to the built package, instead of theactual repository, which is not version-controlled and will beoverwritten wheneverpackage.el performs an update.
  • straight.el allows you to perform arbitrary version-controloperations on your package's Git repositories. Quelpa allows this,but all local changes will be silently overridden whenever Quelpaperforms an update.
  • straight.el is designed withemacs -Q bug reports in mind. SinceQuelpa is based onpackage.el, it is also unsuitable for minimalbug reproductions, since it automatically loads all of your packageson any package operation, even inemacs -Q.
  • straight.el operates quietly when all is going well. Since Quelpais based onpackage.el, it displays all messages, errors, andwarnings that come from byte-compilation and autoload generation. Italso displays additional messages while cloning Git repositories,downloading files, and building packages from their repositoriesintopackage.el format.
  • straight.el does not modify your init-file. Since Quelpa is basedonpackage.el, it inherits the behavior of aggressively insertinga call topackage-initialize into your init-file on any packagemanagement operation.
  • straight.el has a profile system that allows users of someoneelse's Emacs configuration to manage an additional subset ofpackages, or to override upstream package configuration, withoutforking the upstream. Quelpa has no such concept.

Advantages of Quelpa

  • Quelpa supports all the version-control systems supported by MELPA,which is to say almost every commonly and uncommonly used VCS.straight.el only supports Git, although it is designed to supportother version-control backends.
  • Quelpa allows for installing only stable versions of packages, fromany source. This mode of operation is unsupported bystraight.el,although it is aplanned feature.
  • Since Quelpa is based onpackage.el, it inherits a user interfacefor package management that also displays package metadata.straight.el has no such interface.

Additional notes

  • straight.el and Quelpa both allow you to manage your package'slocal repositories manually, if you wish.
  • In principle,straight.el and Quelpa have identical packageinstallation times, since they are performing the same operations.In practice, Quelpa is slightly slower since it builds packages bycopying rather than symlinking, and it clones multiple copies of thesame Git repository when multiple packages are built from it.
  • straight.el encourages you to keep a tight handle on your packageversions by default. Quelpa encourages you to stick to the latestversions of your packages, and to upgrade them automatically.

Comparison to Cask

I have not used Cask extensively, so please feel especially free tooffer corrections for this section.

  • Cask installs packages using thepackage.el protocol, based on aCask file written in the Cask DSL.straight.el eschewspackage.el entirely, and clones packages from source based on howyou invokestraight-use-package in your init-file.
  • Cask focuses more on being a build manager, like Maven or Leiningen,whilestraight.el focusesexclusively on being a packagemanager.

Advantages ofstraight.el

  • straight.el has out-of-the-box compatibility with Emacsmirror,while Cask only supportspackage.el-compliant repositories.However, it is easy to specify an Emacsmirror repository in arecipe. Cask does not support custom package sources.straight.elsupports MELPA, GNU ELPA, and Emacsmirror, and allows you to add anyother sources you would like.
  • straight.el has integrated support for selecting particular Gitrevisions of packages. This process is more manual in Cask, as itrequires placing the commit hash into the recipe, which disablesupdates.
  • straight.el uses your init-file as the sole source of truth forpackage operations. Since Cask is based onpackage.el, it loadsevery package you ever installed at startup, even if some of thosepackages are no longer referenced by yourCask file.
  • straight.el determines your package management configurationimplicitly by detecting how you callstraight-use-package in yourinit-file and making the appropriate changes immediately. Caskrequires manual intervention (for example, issuing acask installcommand when you have updated yourCask file). However, bothstraight.el and Cask can be considered declarative packagemanagers.
  • straight.el supports 100% reproducibility for your Emacs packageswith version lockfiles. Cask can theoretically provide some measureof reproducibility, but this requires significant manual effortsince all packages are not associated with specific revisions bydefault, nor is the revision of Cask saved anywhere.
  • straight.el allows you to make arbitrary changes to your packageslocally. While it is possible to make local changes to Caskpackages, these will not be version-controlled and they will besilently overwritten or shadowed when Cask performs an update.
  • straight.el allows you to perform arbitrary version-controloperations on your package's Git repositories, includingcontributing changes upstream.straight.el has explicit supportfor specifying both an upstream and a fork for a package.Contributing changes upstream with Cask is impossible.
  • straight.el is designed withemacs -Q bug reports in mind. Caskappears to be unsuitable for minimal bug reproductions, since theredoes not appear to be a straightforward way to load a singlepackage, without loading all other packages configured in yourCask file.
  • straight.el operates quietly when all is going well. Since Cask isbased onpackage.el, it displays all messages, errors, andwarnings that come from byte-compilation and autoload generation.
  • straight.el has a profile system that allows users of someoneelse's Emacs configuration to manage an additional subset ofpackages, or to override upstream package configuration, withoutforking the upstream. Cask has no such concept.

Advantages of Cask

  • Cask provides a useful toolbox of operations for project management,which are completely absent fromstraight.el.
  • Since Cask is based onpackage.el, it does not require that youhave Git installed. (It does require Python, however.)straight.elis mostly unusable without Git.
  • Since Cask is based onpackage.el, it can perform bulk packageupdates more quickly thanstraight.el.
  • Since Cask is based onpackage.el, it inherits a user interfacefor package management that also displays package metadata.
  • Since Cask is based onpackage.el, you can install packageswithout editing a file manually, although this rather defeats theentire purpose of using Cask instead ofpackage.el.straight.elabsolutely refuses to permanently install a package without anexplicit reference to it in your init-file (although this may beconsidered an advantage, depending on your perspective).
  • Using MELPA Stable, Cask can install only stable versions ofpackages. By default, Cask also installs only stable versions ofpackages from GNU ELPA. These modes of operation are unsupported bystraight.el at this time, although this is aplannedfeature.
  • Cask supports more version-control systems thanstraight.el (whichonly supports Git).

Comparison to el-get

I have not used el-get extensively, so please feel especially free tooffer corrections for this section.

  • Both el-get andstraight.el implement their own package managementabstractions instead of delegating topackage.el. However:
    • el-get goes the route of adding as many package sources aspossible (e.g.package.el, many different version-controlsystems, various specific websites, and even system packagemanagers) so that packages can be used very easily.
    • straight.el only supports Git and in doing so is able toprovide more advanced package management features.

Advantages ofstraight.el

  • straight.el uses your init-file as the sole source of truth forpackage operations. el-get has additional metadata stored outsidethe init-file, although specifying all packages in your init-file isa supported mode of operation.
  • straight.el supports 100% reproducibility for your Emacs packageswith version lockfiles. el-get can theoretically provide somemeasure of reproducibility, but this requires significant manualeffort since all packages are not associated with specific revisionsby default, nor is the revision of el-get saved anywhere.
  • straight.el allows you to make arbitrary changes to your packageslocally, and conflicts during updates are presented to the user andresolved interactively. While it is possible to make local changesto el-get packages, the el-get manual warns that such changes maybreak the update mechanism.
  • straight.el has explicit support for configuring both an upstreamrepository and a fork for the same package. el-get does not havesuch a concept.
  • straight.el allows you to perform arbitrary version-controloperartions on your package's Git repositories. el-get allows this,but local changes will be overwritten when el-get performs anupdate.
  • straight.el provides a suite of powerful interactive workflows forperforming bulk operations on your package's Git repositories.el-get only allows you to install, uninstall, and update packages.
  • straight.el operates quietly when all is going well. el-getreports its progress verbosely.
  • straight.el has a profile system that allows users of someoneelse's Emacs configuration to manage an additional subset ofpackages, or to override upstream package configuration, withoutforking the upstream. el-get has no such concept.

Advantages of el-get

  • el-get supports virtually all known version-control systems, as wellas system package managers, EmacsWiki, arbitrary HTTP, and evengo get.straight.el supports only Git, although it does allow you tomanage your local repositories manually if you would like.
  • el-get has been around since 2010 and is on its fifth major version,whereasstraight.el was created in January 2017 and is only nowapproaching a 1.0 release. Clearly, el-get is more stable, althoughdespite its recencystraight.el is already almost 50% of the sizeof el-get, by the line count. Both package managers are activelymaintained.
  • el-get has a recipe format which is several orders of magnitude morepowerful than that ofstraight.el, since it supports many morepackage sources that can be configured and since it allows for amore complex build process.
  • el-get provides a number of features for running per-packageinitialization and setup code, including pulling that code fromarbitrary sources.straight.el does not support this and expectsyou to use a dedicated tool likeuse-package (withwhich integration is built in) for that purpose.
  • el-get has a user interface for package management that alsodisplays package metadata, similarly topackage.el.straight.elhas no user interface for package management; any UI is provided bythe user'scompleting-read framework.

Comparison to Borg

  • Borg andstraight.el are perhaps the two most similar packagemanagers on this list. The difference is that Borg is very minimaland expects you to complement it with other tools such asMagit,epkg,use-package, andauto-compile. On theother hand,straight.el aspires to be a one-stop packagemanagement solution, although it does not try to replace dedicatedversion-control packages (Magit) or dedicated packageconfiguration packages (use-package).
  • Borg uses Git submodules, whilestraight.el uses independentlymanaged Git repositories.

Advantages ofstraight.el

  • straight.el supports MELPA, GNU ELPA, Emacsmirror, and customrecipe sources. Borg only supports Emacsmirror and custom recipesources. However, as the Emacsmirror is a near-complete superset ofboth GNU ELPA and MELPA, this does not necessarily mean you haveaccess to more packages: it just means you benefit from the recipemaintenance efforts of the MELPA team and the Emacsmirror team,rather than only the latter.
  • Borg, even when combined with related tools, do not allow for thekind of massive interactive repository management provided bystraight.el.
  • straight.el provides an API designed for other version-controlbackends to be added in future. Borg is inextricably tied to Git.
  • The interface for Git submodules has a number of sharp edges.
  • straight.el provides dependency management. This is a manualprocess in Borg.
  • straight.el provides mechanisms for updating your packages. Thisis a manual process in Borg.
  • straight.el is configured solely by how you use in your init-file.Configuring Borg requires customizing~/.emacs.d/.gitmodules,which means (for example) that you cannot generate recipesdynamically. (However, the handling of configuration isplanned to be improved in a future release.)
  • straight.el has a profile system that allows users of someoneelse's Emacs configuration to manage an additional subset ofpackages, or to override upstream package configuration, withoutforking the upstream. Borg has no such concept.

Advantages of Borg

  • Borg does a heck of a lot less magic, so if you want a solution withsimple implementation details,straight.el may not be for you.(But see the developer manual and docstrings, first.)

Comparison to the manual approach

  • The manual approach is to download packages yourself and put them onyourload-path.straight.el is more or less what you get whenyou take the manual approach, think very hard about the best way todo everything, and then automate all of it.

Advantages ofstraight.el

  • straight.el figures out where to clone your packages from for you.
  • straight.el byte-compiles your packages for you and generatestheir autoloads automatically.
  • straight.el frees you from needing to manually recompile andregenerate autoloads.
  • straight.el keeps track of dependencies for you.
  • straight.el provides tools to manage all your packages in bulk,which would otherwise be a long, tedious process.
  • straight.el allows you to get reproducibility for yourconfiguration without needing to keep all of your packages underversion control.
  • straight.el links packages into a separate build directories.Running packages directly from their repositories has a number ofproblems, including:
    • making it impossible to run only one package, if others areprovided in the same repository.
    • making your working directory dirty when the package authorforgot to add their build artifacts like*.elc and autoloadfiles to the.gitignore.
    • instantly losing compatibility with MELPA recipes.
  • straight.el offers you a single entry point to install only asingle package in isolation, for a minimal bug reproduction. Withthe manual approach this would be more complicated, especially ifthe package has dependencies.
  • straight.el frees you from needing to think about packagemanagement, since I already did all the thinking to figure how bestto design everything.

Advantages of the manual approach

  • No dependencies.
  • You learn a lot, if you don't give up first.
  • You might end up writing a package manager (case in point).
  • This is the only way to deal with packages that have non-Gitupstreams which you need to contribute changes to. (However, you canalways use the manual approach for one package andstraight.el forthe rest. Or you can just eschewstraight.el's version-controlsupport for that package, and use it only for building the package.)

User manual

This section tells you everything you need to know about theuser-facing features ofstraight.el. For implementation details, seethedeveloper manual. It may also be helpful to get someperspective on the overarching concepts ofstraight.el from theconceptual overview.

Bootstrappingstraight.el

In order to usestraight.el, you will need to somehow get it loadedinto Emacs. (This is easy forpackage.el, sincepackage.el isbuilt in to Emacs.straight.el must work a little harder.)

straight.el comes with a file to do just this,bootstrap.el. Allyou need to do is load that file. You can do this withM-x load-fileor by a call toload in your init-file. However, there is an obviousshortcoming:bootstrap.el will only be available oncestraight.elis already installed.

You could just invokegit clone from your init-file, ifstraight.el is not installed, but then you would have to manuallytake care of selecting the correct branch, parsing your versionlockfile to check out the right revision, and so on. Instead, you canjust use this snippet, which uses a copious amount of magic to takecare of all these details for you:

(defvarbootstrap-version)(let ((bootstrap-file       (expand-file-name"straight/repos/straight.el/bootstrap.el"        (or (bound-and-true-p straight-base-dir)            user-emacs-directory)))      (bootstrap-version7))  (unless (file-exists-p bootstrap-file)    (with-current-buffer        (url-retrieve-synchronously"https://raw.githubusercontent.com/radian-software/straight.el/develop/install.el"'silent'inhibit-cookies)      (goto-char (point-max))      (eval-print-last-sexp)))  (load bootstrap-filenil'nomessage))

Despite the reference todevelop, this snippet actually installsfrom themaster branch by default, just like every other package.Furthermore, the correct revision ofstraight.el is checked out, ifyou have one specified in your lockfile. Even better, you canoverride the recipe forstraight.el,just like for any other package.

Installing packages programmatically

The primary entry point tostraight.el is thestraight-use-packagefunction. It can be invoked interactively (for installing a packagetemporarily) or programmatically (for installing a packagepermanently). This section covers the programmatic usage; seelater for interactive usage.

Here is the basic usage ofstraight-use-package:

(straight-use-package'el-patch)

This will ensure that the packageel-patch is installed and loaded.(Note thatstraight-use-package takes a symbol, not a string, forthe name of the package.) Precisely, this is what happens:

  • If the local Git repository forel-patch is not available, it iscloned, and the appropriate revision is checked out (if one isspecified in your version lockfiles).
  • If the local Git repository has been modified since the last timethe package was built, it is rebuilt. This means:
    • The.el files are symlinked into a separate directory toisolate them from other, irrelevant files.
    • The main package file is checked for dependencies, which areinstalled recursively if necessary usingstraight-use-package.
    • The.el files are byte-compiled.
    • Autoloads are extracted from the.el files and saved into aseparate file.
  • The package's directory is added to Emacs'load-path.
  • The package's autoloads are evaluated.

Package authors should note thatstraight.el checks for dependenciesthat are specified in thepackage.el format. Tospare you reading that documentation, this is either aPackage-Requires header inPACKAGENAME.el, or an argument to adefine-package invocation inPACKAGENAME-pkg.el. Despite themanyshortcomings ofpackage.el, ithas done a good job of creating a standardized format for dependencydeclarations.

There is one exception to the above statement: not all entriesspecified in thePackage-Requires header necessarily correspond topackages. For example, specifying a minimum Emacs version for apackage is done by depending on theemacs pseudo-package. Suchpackages are simply ignored bystraight.el, using the variablestraight-built-in-pseudo-packages.

Note that loading a package does not entail invokingrequire on anyof its features. If you wish to actually load the files of thepackage, you need to do this separately. This is because most packagesdo not need to be loaded immediately, and are better served by theautoload system.

Installing with a custom recipe

straight-use-package can also take a list instead of a symbol. Inthat case, the first member of the list is a symbol giving the packagename, and the remainder of the list is apropertylist providing information about how to install andbuild the package. Here is an example:

(straight-use-package '(el-patch:type git:host github:repo"radian-software/el-patch":fork (:host github:repo"your-name/el-patch")))

If you givestraight-use-package just a package name, then a recipewill be looked up by default (see the section onrecipelookup). You can see the default recipe for a packageby invokingM-x straight-get-recipe.

Ifstraight-allow-recipe-inheritance is non-nil, then you only needto specify the components of the recipe that you want to override. Allother components will still be looked up in the default recipe. In theexample above, we are only interested in changing the:forkcomponent. Therefore ifstraight-allow-recipe-inheritance is set,the recipe could be simplified as follows:

(straight-use-package '(el-patch:fork (:repo"your-name/el-patch")))

or even simpler:

(straight-use-package '(el-patch:fork"your-name/el-patch"))

The:files keyword and all version control keywords supportinheritance.

To learn more, see the section onthe recipe format.

Additional arguments tostraight-use-package

The full user-facing signature ofstraight-use-package is:

(straight-use-package PACKAGE-OR-RECIPE&optional NO-CLONE NO-BUILD)

As discussedpreviously, by defaultstraight-use-package will do three things:

  • Register the recipe provided withstraight.el.
  • Clone the package's local repository, if it is absent.
  • Rebuild the package if necessary, and load it.

By providing the optional arguments, you may cause processing to haltbefore all three of these tasks are completed. Specifically, providingNO-CLONE causes processing to halt after registration but beforecloning, and providingNO-BUILD causes processing to halt aftercloning (if necessary) but before building and loading.

straight.el supports lazy-loading by means of a special value forNO-CLONE, the symbollazy. If this symbol is passed, thenprocessing will halt at the clone step, unless the package is alreadycloned. This means that the package is built and loaded if it isalready installed, but otherwise installation is deferred until later.When you want to trigger the lazy installation, simply callstraight-use-package again, but withoutNO-CLONE. (There is noneed to pass the recipe again; seerecipe lookup.)

You can also pass functions forNO-CLONE orNO-BUILD, which willbe called with the package name as a string; their return values willthen be used instead.

Note that if it makes no sense to build a package, then you should put:build nil in itsrecipe, rather than specifyingNO-BUILD every time you register it withstraight.el. (This isespecially relevant when writing recipes forreciperepositories.)

Variants ofstraight-use-package

For convenience,straight.el provides some functions that wrapstraight-use-package with particular arguments, to cover all of thecommon cases. Each of these functions takes only a package name orrecipe, and no additional arguments.

  • straight-register-package: always stop after the registrationstep. This may be useful for specifying the recipe for an optionaldependency (seerecipe lookup, but see alsorecipeoverrides).
  • straight-use-package-no-build: always stop before the build step.This is used bystraight-freeze-versions tomake sure packages are cloned, since building them is unnecessaryfor writing the lockfiles.
  • straight-use-package-lazy: stop at the clone step if the package'slocal repository is not already cloned. This is used forlazy-loading.

Customizing when packages are built

By default, whenstraight.el is bootstrapped during Emacs init, ituses a bulkfind(1) command to identify files that were changedsince the last time a package depending on them was built. Thesepackages are then rebuilt when they are requested viastraight-use-package. Normally,straight.el will try to detectwhat sort offind(1) program is installed, and issue the appropriatecommand. If it makes a mistake, then you can manually customizestraight-find-flavor. Alternately, you can install GNU find andcustomize the variablestraight-find-executable to point to it.

For about 100 packages on an SSD, callingfind(1) to detectmodifications takes about 500ms. You can save this time by customizingstraight-check-for-modifications. This is a list of symbols whichdetermines howstraight.el detects package modifications. Thedefault value is(find-at-startup find-when-checking), which meansthatfind(1) is used to detect modifications at startup, and alsowhen you invokeM-x straight-check-package orM-x straight-check-all. If you prefer to avoid this performance hit, ordo not havefind(1) installed, then you can remove these symbolsfrom the list. In that case, you will probably want to add eithercheck-on-save orwatch-files to the list.

check-on-save causesstraight.el to usebefore-save-hook todetect package modifications as you make them (modifications made bythestraight.el repository management commands are also detected).This reduces init time, but modifications made outside of Emacs (ormodifications that bypassbefore-save-hook) are not detected. Pullrequests extending the number of cases in whichstraight.el is ableto detect live modifications are welcome. Also, for the sake ofefficiency, this form of modification checking is restricted tosubdirectories of~/.emacs.d/straight/repos, so you must put yourlocal repositories into that directory for it to work. (Pull requeststo change this would be welcome.)

watch-files causesstraight.el to automatically invoke afilesystem watcher to detect modifications as they are made, inside oroutside of Emacs. For this setting to work, you must havepython3 andwatchexec installed on yourPATH. By default, the watcher persists after Emacs is closed. Youcan stop it manually by runningM-x straight-watcher-stop, and startit again by runningM-x straight-watcher-start. The watcher scriptis designed so that when one instance is started, all the othersgracefully shut down, so you don't have to worry about accidentallyending up with more than one. There is nothing exciting in the processbuffer for the watcher, but if you are interested in it then its nameis given bystraight-watcher-process-buffer. (By default, the namehas a leading space so that the buffer does not appear in the bufferlist.)

There is probably no good reason to use bothcheck-on-save andwatch-files at the same time. Your configuration can dynamicallyswitch between which one is used depending on(executable-find "watchexec") or similar.

If you prefer to eschew automatic package rebuilding entirely, you canjust setstraight-check-for-modifications tonil. In that case,packages will only be rebuilt when metadata (e.g. the recipe or theEmacs version) changes, or when you manually invokeM-x straight-rebuild-package orM-x straight-rebuild-all.

Regardless of your preferred setting forstraight-check-for-modifications, you should set it before thestraight.el bootstrap snippet is run, since hooks relating to thisvariable are set during bootstrap.

On Microsoft Windows,find(1) is generally not available, so thedefault value ofstraight-check-for-modifications is instead(check-on-save).

Custom or manual modification detection

You can also use the low-level functions for modification detectiondirectly.

The functionstraight-register-repo-modification takes a string(e.g."straight.el") corresponding to the name of a localrepository, and marks all packages from that local repository to berebuilt at next Emacs startup. This function silently ignores localrepositories which contain slashes, a limitation which might beremoved in future.

The functionstraight-register-file-modification takes no argumentsand checks if the file visited by the current buffer (if any) iscontained by any local repository. If so, it delegates tostraight-register-repo-modification. Thecheck-on-save value forstraight-check-for-modifications just addsstraight-register-file-modification tobefore-save-hook.

Summary of options for package modification detection
find-at-startup

Save build timestamps and runfind(1) at startup to detect changes

  • Most reliable, never misses changes
  • Requiresfind(1)
  • Slows down startup
check-on-save

Usebefore-save-hook to detect changes

  • No external dependencies
  • No startup delay
  • No additional CPU or memory impact
  • Doesn't catch changes made except viasave-file inside Emacs
watch-files

Run filesystem watcher to detect changes

  • Requires Python 3 and Watchexec
  • No startup delay
  • Takes a few seconds to build virtualenv the first time
  • Memory and CPU impact of running filesystem watcher
  • Only misses changes if you make them after booting the system butbefore starting Emacs

Customizing how packages are built

By specifying:build nil in a package'srecipe, youmay prevent the package from being built at all. This is usuallyuseful for recipe repositories which do not bundle executable Lispcode. (Make sure to usestraight-use-recipesfor registering recipe repositories.)

Autoload generation

By specifying:build (:not autoloads) in a package's recipe, you mayprevent any autoloads provided by the package from being generated andloaded into Emacs. This is mostly useful if the package provides alarge number of autoloads, you know you need only a few of them, andyou wish to optimize your startup time (although this is almostcertainly premature optimization unless youreally know what you'redoing). You can also customize the variablestraight-disable-autoloads to effect this change on all recipeswhich do not explicitly disable autoloads via the:build keyword.

Byte compilation

By specifying:build (:not compile) in a package's recipe, you mayinhibit byte-compilation. Seethis issue for discussion of whythis might be useful. You can also customize the variablestraight-disable-compile to effect this change on allrecipes which do not explicitly disable byte-compilation via the:build keyword.

Native compilation

Experimental support for native compilation of Emacs Lisp code can beenabled in the latestmaster branch of the official Emacs repository(seegccemacs). When running on this version of Emacs,straight.el will perform native compilation of packages.

By specifying a:build (:not native-compile) in a package's recipe,you may inhibit native compilation. You can also customize thevariablestraight-disable-native-compile to effect this change onall recipes which do not explicitly disable native-compilation via the:build keyword.

Native compilation requires byte-compilation, so:build (:not compile)andstraight-disable-compile will also disable nativecompilation.

Symbolic links

Usually,straight.el uses symbolic links ("symlinks") to makepackage files available from the build directory. This happens whenstraight-use-symlinks is non-nil, the default. On Microsoft Windows,however, support for symlinks is not always available, so the defaultvalue ofstraight-use-symlinks is nil on that platform. That causescopying to be used instead, and an advice is placed onfind-file tocause the copied files to act as symlinks if you try to edit them.

If you want to activate symlink-support on MS Windows 7, 8, or 10, youshould ensure the following requirements:

  • straight-use-symlinks has to be set to non-nil manually.

  • Your user-account needs to be assigned the right to create symboliclinks. To do so, run "secpol.msc" and in "Local Policies → UserRights Assignment" assign the right to "Create symbolic links" toyour user-account.

  • If you have User Account Control (UAC) enabled and your user-accountbelongs to the theAdministrators group you'll need to run Emacsin elevated mode to be able to create symlinks (seehere andhere and,for an official reference, section Access Token Changesin thisdocument.

  • Windows Creators Update supportssymlink-creation without any special permission setup.

Customizing how packages are made available

By setting the variablestraight-cache-autoloads to a non-nil value,you can causestraight.el to cache the autoloads of all usedpackages in a single file on disk, and load them from there instead offrom the individual package files if they are still up to date. Thisreduces the number of disk IO operations during startup from O(numberof packages) to O(1), so it should improve performance. No otherconfiguration should be necessary to make this work; however, you maywish to callstraight-prune-build occasionally,since otherwise this cache file may grow quite large over time.

Hooks run bystraight-use-package

Currently,straight-use-package supports four hooks:

  • straight-vc-git-post-clone-hook: The functions in this hook arerun just after cloning a git repository. This allows users toautomate custom configuration of Elisp Git repositories after theyhave been cloned. For example, theuser.emailgit-configvariable could be set on clone, to make upstream contributions moreconvenient for developers who use different email addresses fordifferent repositories.

    Each hook function is passed the followingkeyword arguments:

    • :repo-dir - the local directory to which the repository wascloned
    • :remote - the name of the remote from which the repository wascloned
    • :url - the URL from which the repository was cloned
    • :branch - the branch as specified by the recipe, if any,otherwisenil
    • :depth - the clone depth as specified by the recipe orstraight-vc-git-default-clone-depth
    • :commit - the specific commit which was requested via thelockfile, if any, otherwisenil

    Since keyword arguments are used, each function should be definedviacl-defun, and&key used at the front of the argument list.

  • straight-use-package-prepare-functions: The functions in this hookare run just before a package would be built, even if the packagedoes not actually need to be rebuilt. They are passed the name ofthe package being (maybe) built as a string, and should take andignore any additional arguments.

  • straight-use-package-pre-build-functions: The functions in thishook are run just before building a package (and only if the packageneeds to be built). They are passed the name of the package beingbuilt as a string, and should take and ignore any additionalarguments.

  • straight-use-package-post-build-functions: The functions in thishook are run just after building a package (and only if the packageneeds to be built). They are passed the name of the package beingbuilt as a string, and should take and ignore any additionalarguments.

The recipe format

The general format for astraight.el recipe is:

(package-name:keyword value:keyword value ...)

Note that if you wish to pass a recipe tostraight-use-package, youwill need to quote it. If you need to compute part of the recipedynamically, use backquoting:

(straight-use-package  `(el-patch:type git:repo ,(alist-get'el-patch my-package-urls)))

The supported keywords aresimilar, but not identical to those usedin MELPA recipes. There is a complete list below which you can comparewith theMELPA documentation, but the maindifferences from the user's point of view are:

  • We use:host instead of:fetcher.

  • We only support Git recipes by default, although the system isextensible to other VCs to be added in the future or in userconfigurations. Thus the supported:host values are:

    • nil (any Git repository)
    • github,gitlab,sourcehut,codeberg, orbitbucket.
  • We support:branch, but not:commit or:version-regexp. Tolock a package to a specific commit, use alockfile. See also#246 for discussion ofextensions to the recipe to support package pinning, which is aplanned feature.

  • We support several additional keywords that affect how a package isbuilt; see below.

  • There are consistency and feature improvements to edge cases of the:files keyword as documented instraight-expand-files-directive.

  • :includes indicates a package is a superset of another package.

Here is a comprehensive list of all keywords which have specialmeaning in a recipe (unknown keywords are ignored but preserved):

  • :local-repo

    This is the name of the local repository that is used for thepackage. If a local repository by that name does not exist when youinvokestraight-use-package, one will be cloned according to thepackage'sversion-control settings.

    Multiple packages can use the same local repository. If so, then achange to the local repository will cause both packages to berebuilt. Typically, if multiple packages are drawn from the samerepository, both should specify a:files directive.

    If you do not provide:local-repo, then it defaults to a valuederived from theversion-controlsettings, or as a last resort thepackage name.

  • :files

    This is a list specifying which files in a package's localrepository need to be symlinked into its build directory, and how toarrange the symlinks. For most packages, the default value(straight-default-files-directive) will suffice, and you do notneed to specify anything.

    If you do need to override the:files directive (this happens mostcommonly when you are taking a single package from a repository thatholds multiple packages), it is almost always sufficient to justspecify a list of globs or filenames. All matching files will belinked into the top level of the package's build directory.

    In spite of this, the:files directive supports an almostcomically powerful DSL (with nested excludes and everything!) thatallows you full flexibility on how the links are made; see thedocstring ofstraight-expand-files-directive for the full details.

  • :flavor

    If this is non-nil, then it changes the interpretation of the:files directive for compatibility with an existing upstreamrecipe source. See the docstring ofstraight-expand-files-directive for details.

  • :buildThis specifies the steps taken on the files symlinked within apackage's straight/build/PACKAGE directory. It may be any of thefollowing values:

    • nil, in which case nothing is done.This also prevents :pre/:post-build commands from running.
(example:buildnil)
  • t, runs the steps listed instraight--build-default-steps.Note this ignores allstraight-disable-SYMBOL keywords.
(example:buildt)
  • A list of steps.Each step is a symbol which represents a function named:straight--build-SYMBOL.The function is passed the recipe as its sole argument.Steps are exectuted in the order they are listed. e.g.
(example:build (autoloads compile native-compile info))
  • A list which has:not as its car and step symbols as its cdr.This eliminates the listed steps from the default steps. e.g.The following recipe will not be compiled or have its texinfo generated:
(example:build (:not compile info))

Steps may be disabled globally for recipes which do not expliciltydeclare their:build via the defcustom variables namedstraight--build-SYMBOL. e.g. The last example but for all recipeswithout a:build:

(setq straight-disable-compilet      straight-disable-infot)

In the absence of a:build keyword,straight--build-default-steps are run.

  • :pre-build

    This specifies system commands and/or elisp to be evaluated beforesymlinking, and running a recipe's:build steps.

    Each command is either an elisp form to be evaluated or a list ofstrings to be executed in a shell context of the form:

("executable""arg"...)

Commands are executed in the package's repository directory.

The:pre-build keyword's value may be:

  • A single command

  • A list of commands

  • nil, in which case no commands are executed.

    For example:

(straight-use-package '( example:type git:host github:repo"user/example.el":pre-build ("make""all")))(straight-use-package `( example:type git:host github:repo"user/example.el":pre-build ,(pcase system-type                  (`windows-nt '(message"This might take a while"))                  (_ '(("./configure") ("make") ("make""install"))))))
  • :post-build

    This specifies system commands and/or elisp to be evaluated afterthe:build steps are run.

    Otherwise, it is identical to the:pre-build keyword in terms of the valuesit accepts and how it is executed.

    For example:

(straight-use-package '( example:type git:host github:repo"user/example.el":pre-build  (("./pre-build.sh") (message"hi")):post-build (("./post-build.sh") (message"bye"))))
  • :type

    This specifies the version-control backend to use for cloning andmanaging the package's local repository. It defaults to the value ofstraight-default-vc, which defaults togit.

    The only traditional version-control backend currently supported isgit, although more backends may be added.

    As a special case, however, you may specify the valuebuilt-in,which results in all version-control operations on the package beingignored. This allows you to tellstraight.el that a package hasalready been provided (for example, because a version of it isshipped by Emacs) and does not have a local repository which needsto be cloned, updated, and so on. Here is how you can tellstraight.el that you would like to use the Emacs-provided copy ofOrg, rather than cloning it from the upstream repository if anotherpackage declares it as a dependency:

(straight-use-package '(org:type built-in))

You can also use:type nil, which has the same effect as:type 'built-in, except that the package is still loaded from itsconfigured:local-repo.

  • :source

Overridesstraight-recipe-repositories on a per-recipe basis.Its value may be:

  • a symbol representing a recipe repository
  • a list of such symbolsThe order of the symbols determines their precedence. For example:
(straight-use-package '(package:sourcemelpa))

Will search only the melpa recipe repository for package's recipe. While:

(straight-use-package '(package:source (melpa gnu-elpa-mirror)))

will search for package's recipe first in melpa.If it is not found there it will check gnu-elpa-mirror next.

  • backend-specific keywords

    Depending on the value of:type, additional keywords (relevant tohow the package's repository is cloned and managed) will bemeaningful. See the next section.

    Thebuilt-in andnil pseudo-backends do not take any otherkeywords.

  • :includes

Informsstraight.el that a package is a superset of another package.For exampleorg-contrib includesol-vm.The following will preventstraight.el from attempting to installol-vmafterorg-contrib has been installed:

(straight-use-package '(org-contrib:includes ol-vm))

Its value may also be a list of symbols indicating multiple packages:

(straight-use-package '(example:includes (foo bar)))
  • :inherit

Overridesstraight-allow-recipe-inheritance on a per-recipe basis.If its value is non-nil, inheritance is enabled for the recipe.Otherwise it is not.

Version-control backends

Defining a version-control backend consists of declaring a number offunctions named asstraight-vc-BACKEND-METHOD, whereBACKEND isthe name of the version-control backend being defined andMETHOD isa backend API method. The relevant methods are:

  • clone: given a recipe and a commit object, clone the repositoryand attempt to check out the given commit.
  • commit-present-p: given a recipe and a commit object, returnwhether the commit can be checked out offline, i.e., withoutfetching from the remote.
  • normalize: given a recipe, "normalize" the repository (thisgenerally means reverting it to a standard state, such as a cleanworking directory, but does not entail checking out any particularcommit).
  • fetch-from-remote: given a recipe, fetch the latest version fromits configured remote, if one is specified.
  • fetch-from-upstream: given a recipe, fetch the latest version fromits configured upstream, if the package is forked.
  • merge-from-remote: given a recipe, merge the latest versionfetched from the configured remote, if any, to the local copy.
  • merge-from-upstream: given a recipe, merge the latest versionfetched from the configured upstream, if the package is forked, tothe local copy.
  • push-to-remote: given a recipe, push the current version of therepository to its configured remote, if one is specified.
  • check-out-commit: given a recipe and a commit object, attempt tocheck out that commit in the repository for that recipe.
  • get-commit: given a local repository name, return the commitobject that is currently checked out, or nil if the local repositoryshould not be included in a lockfile.
  • local-repo-name: given a recipe, return a good name for the localrepository, or nil.
  • keywords: return a list of keywords which are meaningful for thisversion-control backend.

Most of these methods are highly interactive: they don't actually doanything without prompting you to confirm it, and very often they willoffer you a number of different options to proceed (including startinga recursive edit and allowing you to do whatever you would like).

Also, all of the methods in this section takestraight.el-stylerecipes; see the section ondefining VCbackends in the developer manual for more details.

Git backend

These are the keywords meaningful for thegit backend:

  • :repo: the clone URL for the Git repository.

  • :host: either nil or one of the symbolsgithub,gitlab,bitbucket,codeberg, orsourcehut.

    • If nil, then:repo should be a string which is the full URL ofthe target repository. For example:
    (:package"package":hostnil:type git:repo"http://myhost.tld/repo")
    • If non-nil, then:repo should be a string "username/repo",and the URL is constructed automatically. For example:
    (:package"package":host github:type git:repo"username/repo")
  • :branch: the name of the branch used for primary development, as astring. If your version lockfiles do not specify a commit to checkout when the repository is cloned, then this branch is checked out,if possible. This branch is also viewed as the "primary" branch forthe purpose of normalization and interaction with the remote.

  • :remote: the name to use for the Git remote. If the package isforked, this name is used for the upstream remote.

  • :nonrecursive: if non-nil, then submodules are not cloned. This isparticularly important for the Emacsmirror recipe repository, whichcontains every known Emacs package in existence as submodules.

  • :fork: the settings for a fork, if desired.This causes thefetch-from-remote method to operate on the fork;you can use thefetch-from-upstream method to operate on theupstream instead.

    Note: the following section assumesstraight-host-usernameshas a value of:

'((github."githubUser")  (gitlab."gitlabUser")  (codeberg."codebergUser")  (sourcehut."sourcehutUser")  (bitbucket."bitbucketUser")))

Its value may be:

  • t:Look up the username instraight-host-usernames.Inherit the repository name from the upstream repository.For example:
(:package"package":host github:type git:repo"upstream/repo":forkt)

computes the fork's:repo value asgithubUser/repo.

  • a string (optionally ending with "/"):Use the string as the username.Inherit repository name from the upstream repository.For example:
(:package"package":host github:type git:repo"upstream/repo":fork"user")

computes the fork's:repo value asuser/repo.

  • a string starting with "/":Look up the username instraight-host-usernames.Use the string as the repository name.For example:
(:package"package":host github:type git:repo"upstream/repo":fork"/renamed")

computes the fork's:repo value asgithubUser/renamed.

  • a string with both the recipe and repository specified:Use string as the:repo value for the fork.For example:
(:package"package":host github:type git:repo"upstream/repo":fork"user/renamed")

computes the fork's:repo value asuser/renamed.

  • a plist:The allowed keywords are:repo,:host,:branch, and:remote.The same rules as above apply for the:repo string.Likewise, if the:host is overridden and the:repo does notprovide the username, it is looked up instraight-host-usernames.For example:
(:package"package":host github:type git:repo"upstream/repo":fork (:host gitlab))

computes the fork's:repo value asgitlabUser/repo.

(:package"package":host github:type git:repo"upstream/repo":fork (:host gitlab:repo"/renamed"))

computes the fork's:repo value asgitlabUser/renamed.

(:package"package":host github:type git:repo"upstream/repo":fork (:host gitlab:repo"user"))

computes the fork's:repo value asuser/repo.

  • :depth: either the symbolfull or an integer. Iffull, thenthe repository is cloned with its whole history. If an integerN,then the repository is cloned with the option--depth N. Thisworks even when a commit is specified (e.g. by version lockfiles).The default value isfull.
  • :protocol: If non-nil, force this protocol to be used wheninteracting with the remote repository. Takes the same values asstraight-vc-git-default-protocol.

This section tells you how thegit backend, specifically, implementsthe version-control backend API:

  • clone: clones the repository, including submodules if:nonrecursive is not provided. Checks out the commit specified inyour revision lockfile, or the:branch (from the:forkconfiguration, if given), ororigin/HEAD. If a:fork isspecified, also fetches from the upstream.
  • commit-present-p: checks if the commit SHA is among the revisionsthat are present locally.
  • normalize: verifies that remote URLs are set correctly, that nomerge is in progress, that the worktree is clean, and that theprimary:branch (from the:fork configuration, if given) ischecked out.
  • fetch-from-remote: checks that remote URLs are set correctly, thenfetches from the primary remote (the fork, if the package isforked).
  • fetch-from-upstream: checks that remote URLs are set correctly,then fetches from the upstream remote. If the package is not a fork,does nothing.
  • merge-from-remote: performs normalization, then merges from theprimary remote (the fork, if the package is forked) into the primarylocal:branch.
  • merge-from-upstream: performs normalization, then merges from theupstream remote into the primary local:branch. If the package isnot a fork, does not attempt to merge.
  • push-to-remote: performs normalization, pulls from the primaryremote if necessary, and then pushes if necessary. This operationacts on the fork, if the package is forked.
  • check-out-commit: verifies that no merge is in progress and thatthe worktree is clean, then resets the worktree to the specifiedcommit.
  • get-commit: returns HEAD as a 40-character string.
  • local-repo-name: if:host is non-nil, then:repo will be ofthe form "username/repository", and "repository" is used. Otherwise,if the URL is of the form.../<something>.git, then<something>is used. Otherwise, nil is returned.
  • keywords: see the list of keywords above.

You can customize the following user options:

  • straight-vc-git-default-remote-name: the name to use for theprimary remote, or the upstream remote if the package is forked.Defaults to "origin". The:remote keyword may be used to overridethe value of this variable on a per-repository basis.

  • straight-vc-git-default-fork-name: the name to use for the forkremote, if the package is forked. Defaults to "fork". The:remotekeyword may be used to override the value of this variable on aper-repository basis.

  • straight-vc-git-default-protocol: the default protocol to use forautomatically generated URLs when:host is non-nil. It can beeitherhttps orssh, and defaults tohttps because thisrequires less work to set up.

  • straight-vc-git-force-protocol: if this is non-nil, then HTTPS andSSH URLs are not treated as equivalent, so that bulk version-controloperations will offer to re-set your remote URLs from HTTPS to SSHor vice versa, depending on the value ofstraight-vc-git-default-protocol. This is nil by default.

  • straight-vc-git-auto-fast-forward: if this is non-nil, pullingwill quietly do fast-forward, to suppress asking for instructions oneach package with updates, unless they're not trivial. Set to nil ifyou'd prefer to inspect all changes.

  • straight-vc-git-default-clone-depth: the default value for the:depth keyword. It can be either the symbolfull or an integer,and defaults tofull. Setting this variable to a small integer willreduce the size of repositories. This variable affects all packages,even those whose versions are locked.

    Please be careful with settingstraight-vc-git-default-clone-depth,which may break some packages' installing processes such aselfeedthat depend onorg.

Deprecated:upstream keyword

straight.el previously supported fork configuration in recipes usingan:upstream keyword rather than a:fork keyword. For variousreasons, this was more complex to handle, which is why the change wasmade. For backwards compatibility, the:upstream keyword is stillaccepted, with the following behavior.

Whenstraight.el processes a recipe which uses the:upstreamkeyword, it moves the:repo,:host, and:branch keywords fromthat sub-plist to the top level, and moves those top-level keywords toa new:fork sub-plist. Then it sets the top-level and:forksub-plist values of:remote to the values of the deprecatedvariablesstraight-vc-git-upstream-remote (defaults to "upstream")andstraight-vc-git-primary-remote (defaults to "origin"),respectively.

For backwards compatibility, ifstraight-vc-git-primary-remotediffers from its default value of "origin", then its value is used inplace ofstraight-vc-git-default-remote-name.

Recipe lookup

If you only provide a symbol (package name) tostraight-use-package,then the recipe is looked up automatically. By default,MELPA,GNUELPA, andEmacsmirror are searched for recipes, in thatorder. This means that one or more of them may need to be cloned.Recipe repositories are actually just the same as ordinary packages,except that their recipes specify:build nil, so they are notsymlinked or added to theload-path.

Note that dependencies always use the default recipes, since the onlyinformationstraight.el gets about a package's dependencies aretheir names.

This leads to a few interesting questions regarding requesting apackage multiple times. For example, you might need to load twofeatures usinguse-package that are provided from thesame package, or one of the packages you have installed is alsorequested as a dependency by another package.straight.el uses anumber of heuristics to try to make these interactions as intuitiveand painless as possible:

  • The first time a package is registered withstraight.el, itsrecipe (either the recipe that you provided, or the one that waslooked up from a recipe repository) is recorded. In futureregistration, if you just provide the package name tostraight-use-package, the existing recipe is reused.

    Note, however:if you want to use a custom recipe for a givenpackage, you must load itbefore all of its dependencies.Otherwise, the package will first be registered as a dependency,using the default recipe.

  • If a package has already been registered withstraight.el, and youattempt to load it again with an explicit recipe which is differentfrom the one previously registered, the new recipe is used but awarning is signalled.

  • If you attempt to register a package which shares a:local-repo(either by default, or due to explicit specification) with apreviously registered package, and the two packages specifydifferent values for their version-control keywords (seeversion-control backends), then the newrecipe is used but a warning is signalled. If the repository wasalready cloned, this means the second recipe will have no effect.

    But if the second recipe was fetched automatically from a reciperepository, all of its version-control keywords will be silentlyoverwritten with the ones from the first recipe, to avoid conflicts(although if there are conflicts in other parts of the recipe, awarning will still be displayed).

Updating recipe repositories

As mentioned in theconceptual overview, reciperepositories are just regular packages, with some extra code to lookup recipes in the relevant local repository.

This means that updating a recipe repository may be done the same way asupdating a regular package, i.e. withM-x straight-pull-package.A convenience command with interactive completion for recipe repositories,straight-pull-recipe-repositories, is provided as well.You should use one of these if you find that a package isn't listed byM-x straight-use-package—perhaps it was added recently.

Note that there is currently some potentially surprising behavior ifyou update all packages at once usingM-x straight-pull-all orM-x straight-merge-all, and this bulk update includes recipe repositoryupdates: see#323.

Customizing recipe repositories

The recipe repository system is designed to be extended. Firstly, youcan control which recipe repositories are searched, and in what orderof precedence, by customizingstraight-recipe-repositories. Thedefault value is defined by thestraight-use-recipes declarationspresent in the filebootstrap.el in thestraight.el version youare using, as customized by the user options you configure in yourinit-file before loading the bootstrap snippet. As of the time of thiswriting, with no custom user options set, that works out to be:

(org-elpamelpa gnu-elpa-mirror nongnu-elpa el-get emacsmirror-mirror)
GNU ELPA

You can customize the following user options:

  • straight-recipes-gnu-elpa-url: The Git URL to use for thegnu-elpa recipe repository.
  • straight-recipes-gnu-elpa-use-mirror: GNU ELPA uses a stupidlycomplex build system for no good reason, and it's unlikely to changeany time soon. What this means for you is that you have to run theElisp-powered Makefile of the GNU ELPA repository (which has a fatalbug last I checked, so you'd have to patch it locally)and have afull checkout of the Emacs source repository (more than 1GB) if youwant all the packages to work correctly. To work around thisproblem, I maintain afull mirror of GNU ELPA onGitHub. (The tooling used to maintain this mirroris locatedhere.) By default,straight.elretrieves packages from this mirror instead of the sourcerepository; this behavior is controlled by the value ofstraight-recipes-gnu-elpa-use-mirror. You must do anycustomization of this variablebefore thestraight.elbootstrap. Note that setting the value of this useroption to nil causes the default value ofstraight-recipe-repositories to shift to:
(org-elpamelpa gnu-elpa el-get emacsmirror)
Emacsmirror

You can customize the following user option:

  • straight-recipes-emacsmirror-use-mirror: Yes, there is also amirror for Emacsmirror. This is because theepkgs repositorycontains a fair amount of metadata, which means it can take a littleon the long side to clone with slow network connections (see#356and#700). My solution to this problem is to generate a newrepository which contains the information thatstraight.el needsbut which is much smaller. By default,straight.el uses theofficialepkgs repository to find packages on Emacsmirror, but youcan tell it to use my mirror by configuring the value of thisvariable to non-nil. You must do any customization of this variablebefore thestraight.elbootstrap. Note thatsetting the value of this user option to non-nil causes the defaultvalue ofstraight-recipe-repositories to shift to:
(org-elpamelpa gnu-elpa-mirror el-get emacsmirror-mirror)
Defining new recipe repositories

To define a new recipe repository calledNAME, you should do thefollowing things:

  • Define a functionstraight-recipes-NAME-retrieve, which takes apackage name as a symbol and returns a recipe for that package if itis available, else nil. This is used for recipe lookup. Thisfunction may assume that the local repository for the reciperepository has already been cloned, and thatdefault-directory hasbeen set to that local repository. This is used for recipe lookupduring the course ofstraight-use-package.

    If the returned recipe is a backquoted list, it will be evaluatedduringstraight--convert-recipe. This is useful for specifyingdynamic elements within the recipe such as system-specificbuild commands. For example, ifstraight-recipes-NAME-retrievereturns:

'`(package:type git:repo"host/repo":pre-build ,(pcase system-type                  (`berkeley-unix '("gmake"))                  (_ '("make"))):files (:defaults))

The recipe is converted to:

(package:type git:repo"host/repo":pre-build ("make"):files (:defaults))

on agnu/linux system, and:

(package:type git:repo"host/repo":pre-build ("gmake"):files (:defaults))

on aberkely-unix system.

The recipe could be read from a file in the recipe repository aswell. In this case, the quote isnot included in the recipe, asstraight-recipes-NAME-retrieve would make use ofread, whichwill return the literal Lisp object. For example, considering thefollowing retrieval function:

(defunstraight-recipes-example-retrieve (name)  (with-temp-buffer    (insert-file-literally"./recipes/example.recipe")    (read (buffer-string))))

The recipe from above could be stored in the file,example.recipe, as:

`(package:type git:repo"host/repo":pre-build ,(pcase system-type                 (`berkeley-unix '("gmake"))                 (_ '("make"))):files (:defaults))
  • Define a functionstraight-recipes-NAME-list, which takes noarguments and returns a list of strings representing packages forwhich recipes are available. It is permissible to return somestrings for which recipes are actually not available, forperformance reasons. However, this is discouraged. (TheMELPAbackend uses this functionality, since all files in therecipesdirectory are potentially recipes, but only the Git-based ones canactually be used.)
  • (Optional) Define a functionstraight-recipes-NAME-version whichreturns a non-nil value indicating the current version of the logicin yourstraight-recipes-NAME-retrieve function. Each time youchange the logic, this version value must be changed. If thisfunction is defined, thenstraight.el automatically andtransparently caches calls tostraight-recipes-NAME-retrievepersistently, using your version value (and its detection ofmodifications to the recipe repository) to decide when to invalidatethe cache.
  • Callstraight-use-recipes with the recipe for your reciperepository. Make sure to include:build nil in the recipe, unlessyou also want to use the recipe repository as an executable EmacsLisp package. Alternatively, you can take the manual approach:
    • Callstraight-use-package-lazy with the recipe for your reciperepository.
    • Add the symbol for your recipe repository's name (the car of therecipe you provided, that is) tostraight-recipe-repositories,at the appropriate place.

Overriding recipes

You can always usestraight-register-package to specify a specificrecipe for a package without cloning or building it, so that just incase that package is requested later (possibly as a dependency, or insomebody else's code) your recipe will be used instead of the defaultone. However, this does not help in the case that a specific recipe ispassed tostraight-use-package.

Also, it is obviously impossible to callstraight-register-packagebeforestraight.el has been loaded, so you can't use it to specify acustom recipe forstraight.el itself.

To remedy these difficulties,straight.el provides a mechanism forspecifically overriding the recipe for a particular package. You canuse it by customizingstraight-recipe-overrides, or by callingstraight-override-recipe.

straight-recipe-overrides is an association list fromprofilenames tooverride alists. If you don'tcare about the profile system, you can just use a single overridespecification, with the profile name nil. Each override alist is justa list of recipes. Because the car of a recipe is just the packagename as a symbol, this list of recipes is also an alist whose keys arerecipe names and whose values are the plists for those recipes.

Even if an explicit recipe is supplied tostraight-use-package, theone given instraight-recipe-overrides will be used instead, if sucha recipe is specified there.

For convenience, you may add tostraight-recipe-overrides by passinga recipe tostraight-override-recipe. This will register it in theoverride alist for the current profile. Note that if you do this, youwill probably want to explicitly setstraight-recipe-overrides tonil before bootstrappingstraight.el. This will make it so that ifyou remove a call tostraight-override-recipe from your init-fileand then reload it, the entry will actually be removed fromstraight-recipe-overrides.

Overriding the recipe forstraight.el

As was briefly mentioned earlier, you can actually override the recipeofstraight.el itself usingstraight-recipe-overrides! How doesthis work? Well, it's basically black magic. If you want the details,go read thedeveloper manual. All you need toknow is that you can setstraight-recipe-overrides, and it willmagically work. The only caveat is that if you change the:local-repo forstraight.el, then you will also need to adjust thevalue ofbootstrap-file in thebootstrap snippetaccordingly, since otherwise your init-file will not know where tofindstraight.el. (You must usestraight-recipe-overrides insteadofstraight-override-recipe, since the latter function definitionhasn't been loaded yet beforestraight.el is installed andbootstrapped.)

Here is the default recipe used forstraight.el, if you don'toverride it:

(straight:type git:host github:repo ,(format"%s/straight.el" straight-repository-user):files ("straight*.el"):branch,straight-repository-branch)

Note that even though the bootstrap snippet references thedevelopbranch ofstraight.el, the default recipe installs frommaster.

If all you want to do is change which branch you are installingstraight.el from, simply customize the variablestraight-repository-branch, which is provided for this purpose.(Although usingstraight-recipe-overrides will work just as well, atleast until the recipe happens to be changed upstream and yourinit-file isn't updated.)

Similarly, if all you want to do is switch to your own fork ofstraight.el on GitHub, simply customize the variablestraight-repository-user to your GitHub username.

There is one minor caveat to the above discussion. If your fork makeschanges to the way in which recipes are interpreted, then thosechanges will not be effective during the interpretation of your ownrecipe forstraight.el. If you wish for them to be, then you willhave to follow the same procedure that is followed instraight.elitself for making changes to recipe interpretation. These details areoutlined in thedeveloper manual; see alsoinstall.el for an explanation of this aspect of the bootstrapmechanism.

Interactive usage

The primary usage ofstraight.el is expected to be in yourinit-file. For example, this is where you will need to put thebootstrap code as well as any packages that you always want to beinstalled. However, there are three important interactive uses ofstraight.el: temporary installation of packages, various helpfulutility functions, andversion controloperations.

To install a package temporarily, runM-x straight-use-package. Allregistered recipe repositories will be cloned, and you will bepresented with a combined list of all recipes available from them.Simply select a package and it will be cloned, built, and loadedautomatically. This does not affect future Emacs sessions.

If you provide a prefix argument toM-x straight-use-package, thenyou are presented with a list of registered recipe repositories. Afteryou select one, you are shown a list of recipes specifically from thatrecipe repository. This is helpful if you do not want to clone allregistered recipe repositories, or you have a particular reciperepository in mind.

You can also callM-x straight-get-recipe, which has the sameinterface asM-x straight-use-package, except that instead of thepackage being cloned, built, and loaded, its recipe is copied to thekill ring. If you are writing a custom recipe, this may be helpful,because you may be able to reuse parts of the existing recipe,particularly the:files directive.

Normally, packages are rebuilt automatically if needed, when Emacsrestarts. If you for some reason want them to be rebuilt at anothertime, you can callM-x straight-check-all to rebuild all packagesthat have been modified since their last build. Alternatively, useM-x straight-rebuild-all to unconditionally rebuild all packages.Note that this will probably take a while. There are alsoM-x straight-check-package andM-x straight-rebuild-package, whichallow you to select a particular package to check or rebuild.

Finally, you may useM-x straight-prune-build in order to tellstraight.el to forget about any packages which were not registeredsince the last time you loaded your init-file. This may improveperformance, although only slightly, and will clean up stale entriesin thebuild directory. You can call this function in your init-fileif you really wish your filesystem to be as clean as possible,although it's not particularly recommended as the performanceimplications are uninvestigated. If you do call it in your init-file,be sure to only call it on a fully successful init; otherwise, anerror during init will result in some packages' build informationbeing discarded, and they will need to be rebuilt next time.

If you have enabledautoloads caching, it isadvisable to callstraight-prune-build occasionally, since otherwisethe build cache may grow quite large over time.

Version control operations

straight.el provides a number of highly interactive workflows formanaging your package's local repositories, using the configuredversion-control backends. They are asfollows:

  • M-x straight-normalize-package: normalize a package
  • M-x straight-normalize-all: normalize all packages
  • M-x straight-fetch-package: fetch from a package's configuredremote; with prefix argument, then for forks also fetch from theupstream
  • M-x straight-fetch-package-and-deps: fetch from the configuredremotes of a package and all of its dependencies (including thedependencies of its dependencies); with prefix argment, then forforks also fetch from the upstream
  • M-x straight-fetch-all: fetch from all packages' configuredremotes; with prefix argument, then for forks also fetch from theupstreams
  • M-x straight-merge-package: merge the latest version fetched froma package's configured remote into the local copy; with prefixargument, then for forks also merge from the upstream
  • M-x straight-merge-package-and-deps: merge the latest versionsfetched from the configured remotes of a package and all of itsdependencies (including the dependencies of its dependencies); withprefix argment, then for forks also merge from the upstreams
  • M-x straight-merge-all: merge the latest versions fetched fromeach package's configured remote into its local copy; with prefixargument, then for forks also merge from the upstreams
  • M-x straight-pull-package: combination ofM-x straight-fetch-package andM-x straight-merge-package
  • M-x straight-pull-package-and-deps: combination ofM-x straight-fetch-package-and-deps andM-x straight-merge-package-and-deps
  • M-x straight-pull-all: combination ofM-x straight-fetch-all andM-x straight-merge-all
  • M-x straight-push-package: push a package to its remote, ifnecessary
  • M-x straight-push-all: push all packages to their remotes, ifnecessary

See the sections onversion-controlbackends and theGitbackend in particular for more information aboutthe meanings of these operations.

Lockfile management

straight.el determines your package management configuration fromtwo, and only two, sources: the contents of your init-file, and yourversion lockfiles (which are optional). Your init-file specifies theconfiguration ofstraight.el (for example, the values ofstraight-recipe-overrides andstraight-default-vc), the packagesyou want to use, and their recipes. Your version lockfiles specify theexact revisions of each package, recipe repository, and evenstraight.el itself. Together, they lock down your Emacsconfiguration to a state of no uncertainty: perfect reproducibility.

To write the current revisions of all your packages into versionlockfiles, runM-x straight-freeze-versions. This will first checkthatstraight.el has an up-to-date account of what packages areinstalled by your init-file, then ensure that all your local changesare pushed (remember, we are aiming for perfect reproducibility!). Ifyou wish to bypass these checks, provide a prefix argument.

Note: reloading your init-file must have the effect of running allof the samestraight.el-related functions again. For example, if youbootstrapstraight.el in a sub-file that you onlyrequire insteadofload, then the reloading functionality will not work correctlyand you may receive the messageCaches are still outdated; something is seriously wrong. See#437 for discussion.

Version lockfiles are written into~/.emacs.d/straight/versions. Bydefault, there will be one, calleddefault.el. It is recommendedthat you keep your version lockfiles under version control with therest of your Emacs configuration. If you symlink your init-file into~/.emacs.d from somewhere else, you should also make sure to symlinkyour version lockfiles into~/.emacs.d/straight/versions. On a newmachine, do thisbefore launching Emacs: that way,straight.el canmake sure to check out the specified revisions of each package whencloning them for the first time.

To install the versions of the packages specified in your versionlockfiles, runM-x straight-thaw-versions. Thawing willinteractively check for local changes before checking out the relevantrevisions, so don't worry about things getting overwritten.

The profile system

straight.el has support for writing multiple version lockfiles,instead of just one. Why? Consider a large Emacs configuration such asRadian,Spacemacs, orPrelude, which is used by many differentpeople. There are two parts to the configuration that is actuallyloaded: the "default" part, and the local customizations that eachuser has added. Generally, these configurations have a mechanism formaking local customizations without forking the entire project.

So Radian will have some set of packages that it requires, and mylocal customizations of Radian have some other set of packages thatthey require. In order for me to maintain Radian, I need to be able toseparate Radian's packages (which go into a versions lockfile in theRadian repository) from my own local packages (which go into aversions lockfile in my own private local dotfiles repository).straight.el provides this ability through theprofile system.

The idea is that whenever a package is registered, either directly oras a dependency, it is associated with a given profile. Any givenpackage can be associated with multiple profiles.

When you callstraight-use-package, which profile the registeredpackages are associated with is determined by the value ofstraight-current-profile, which defaults to nil. In Radian, forexample,straight-current-profile is bound toradian while theRadian libraries are being loaded, and it is bound toradian-localwhile the user's local customizations are being loaded. This resultsin Radian packages being associated with theradian profile, and theuser's local packages being associated with theradian-localprofile.

When you callM-x straight-freeze-versions, one or more versionlockfiles are written, according to the value ofstraight-profiles.This variable is an association list whose keys are symbols namingprofiles and whose values are filenames for the corresponding versionlockfiles to be written into~/.emacs.d/straight/versions. Youshould make sure that each potential value ofstraight-current-profile has a corresponding entry instraight-profiles, since otherwise some packages might not bewritten into your lockfiles.

When customizingstraight-recipe-overrides, notethat if multiple profiles are set to override the same recipe, thenthe last one listed instraight-profiles will take precedence.Similarly, when usingM-x straight-thaw-versions, if differentlockfiles specify revisions for the same local repository, the lastone instraight-profiles will take precedence.

Packages and the init-file

Package managers likepackage.el store mutable state outside yourinit-file, including the set of packages that are installed.straight.el does not do this, so it has a rather different way ofdetermining what packages are installed. Tostraight.el, a packageis part of your Emacs configuration if it is passed tostraight-use-package when your init-file is loaded.

Note that this means packages installed interactively (usingM-x straight-use-package) are not considered part of your Emacsconfiguration, since the invocation ofstraight-use-package does nothappen in your init-file.

This raises an interesting question: if youadd a package to yourinit-file, how can you convincestraight.el that it really is partof your init-file, and not just part of a temporarystraight-use-package form that you evaluated ad-hoc? The answer issimple:reload your entire init-file. That way,straight.el willsee whether or not that package is registered during your init-file.

One might ask howstraight.el determines that you have finishedloading your init-file. The answer is simple:post-command-hook isused to execute code only after the current interactive operation hasfinished. The implementation of this concept is part of thetransaction system ofstraight.el, and it is also used to amortizecertain performance costs when many calls tostraight-use-packageare made sequentially. However, since the transaction system (at leastin recent versions ofstraight.el) operates transparently, itsdetails are relegated to thedeveloper manual.

Usingstraight.el to reproduce bugs

... in other packages

One of the major reasons I wanted to writestraight.el was thatexisting package managers were not good for reproducing bugs. Forinstance, some of them would load all installed packages when thepackage manager was initialized! Obviously that is not acceptable fora "minimal test case".

On the contrary, bootstrappingstraight.el does not load anythingexcept forstraight.el itself (the default recipe repositories areregistered, but not cloned until needed). You should normally beloadingstraight.el by means of thebootstrapsnippet, but when you are inemacs -Q, here is how youcan initializestraight.el:

M-x load-file RET ~/.emacs.d/straight/repos/straight.el/bootstrap.el RET

You can also do this from the command line, perhaps by creating analias for it:

$ emacs -Q -l ~/.emacs.d/straight/repos/straight.el/bootstrap.el

Let's say you are making a bug report for Projectile. To load justProjectile and all of its dependencies, run:

M-x straight-use-package RET projectile RET

Note that this will use the currently checked-out revisions ofProjectile and all of its dependencies, so you should take note ofthose in order to make your bug report.

... instraight.el itself

straight.el provides a macro,straight-bug-report, to teststraight.el in a clean environment. If possible, please use thiswhen creating bug reports.

straight-bug-report accepts the following keyword value pairs:

  • :pre-bootstrap (Form)... Forms evaluated before bootstrappingstraight.el e.g.
(setq straight-repository-branch"develop")
Note this example is already in the default bootstrapping code.
  • :post-bootstrap (Form)... Forms evaluated in the testingenvironment after boostrapping. e.g.
(straight-use-package '(example:type git:host github))
  • :interactive Boolean If nil, the subprocess will immediately exitafter the test. Output will be printed tostraight-bug-report--process-buffer Otherwise, the subprocesswill be interactive.

  • :preserve Boolean If t, the test directory is left in thedirectory stored in the variable `temporary-file-directory'.Otherwise, it is immediately removed after the test is run.

  • :executable String Indicate the Emacs executable to launch.Defaults to"emacs".

  • :raw Boolean If t, the raw process output is sent tostraight-bug-report--process-buffer. Otherwise, it is formattedas markdown for submitting as an issue."

For example:

(straight-bug-report:pre-bootstrap  (message"before bootstrap")  (message"multiple forms allowed"):post-bootstrap  (message"after bootstrap")  (message"multiple forms allowed")  (straight-use-package '(my-broken-package))  (message"bye"))

The above will run your test in a clean environment and produce abuffer with information you can paste directly into the issue body.

Usingstraight.el to develop packages

The workflow for developing a package usingstraight.el is quitestraightforward:

  • Add the package to your configuration as usual, via a call tostraight-use-package.
  • UseM-x find-function or a similar command to jump to the code youwish to edit.
  • Edit the code.
  • Either evaluate the edited code usingM-x eval-buffer,M-x eval-defun, or a similar command, or just restart Emacs to pick upyour changes.
  • When you are satisfied with your changes, useMagit or just Gitdirectly in order to commit and possibly push them. I suggest usingForge to create pull requests directly from Emacs, with Magitintegration.

Integration with other packages

Integration withuse-package

By default,straight.el installs a new keyword:straight foruse-package which may be used to install packages viastraight.el.The algorithm is extremely simple. This:

(use-package el-patch:straightt)

macroexpands (essentially) to:

(straight-use-package'el-patch)

And this:

(use-package el-patch:straight (:host github:repo"radian-software/el-patch":branch"develop"))

becomes:

(straight-use-package '(el-patch:host github:repo"radian-software/el-patch":branch"develop"))

If the feature you are requiring withuse-package is different fromthe package name, you can provide a full recipe:

(use-package tex-site:straight (auctex:host github:repo"emacsmirror/auctex":files (:defaults (:exclude"*.el.in"))))

And you may also provide just the package name:

(use-package tex-site:straight auctex)

If you don't provide:straight, then by default nothing happens. Youmay customizestraight-use-package-by-default to make it so that:straight t is assumed unless you explicitly override it with:straight nil.

Previously,straight.el used a different syntax for itsuse-package integration. For backwards compatibility, you can usethis syntax instead by customizingstraight-use-package-version.

You can disableuse-package integration entirely by customizingstraight-enable-use-package-integration.

Loading packages conditionally

use-package has various features intended to support code beingexecuted conditionally for a package. For example, the:when keywordlets you provide a form that will essentially disable theuse-package form if it evaluates to nil.

However, when using the:straight keyword, either explicitly or viastraight-use-package-by-default, then:when has no effect on it.straight.el is invoked unconditionally. The reason for this behavioris that if you invokestraight-use-package on a different set ofpackages during different init sessions, then your version lockfilewould end up containing different sets of packages depending on whichsession you generated it in.

Currently, the officially recommended pattern for conditionallyloading a package is the following:

(straight-register-package'foobar)(when some-condition  (use-package foobar:straightt))

This ensures that the package is registered tostraight.el, so itwill be cloned if absent, and will be added to the lockfile, but itwill not be compiled or loaded unless the subsequentuse-packageform is evaluated. You can also invokestraight-register-packageonly in the case thatsome-condition is nil; either way will producethe same result with roughly the same performance due to idempotencyand caching.

If you do this for a lot of packages, it may be advisable to wrap itin a macro, asmy own Emacs configuration Radiandoes in the macroradian-use-package. It wouldbe a good idea ifstraight.el did this by default in itsuse-package integration but this has not been implemented yet.

If you want to not even clone a package when it is disabled, you canalso technically achieve it by simply making the entireuse-packageform conditional, without usingstraight-register-package. However,this is not recommended because it will cause the generated lockfileto be deterministic, sostraight.el will not be changed to make:when act that way by default.

It would be desirable if you could clone a package conditionallywithout breaking the lockfile functionality; this is a hopefullyplanned future feature, but it needs design work.

"Integration" withpackage.el

By default,package.el will automatically insert a call topackage-initialize into your init-file as soon as Emacs starts,which is ridiculous. It will also do this when you perform any packagemanagement operation. A separate system inserts somecustom formsinto your init-file when you install a package.straight.el disablesall of these "features" by settingpackage-enable-at-startup to niland enabling some advices. You can override this behavior bycustomizingstraight-enable-package-integration, however.

To help avoid you shooting yourself in the foot by using both:ensure and:straight at the same time in ause-package form(which would cause the same package to be installed twice using twodifferent package managers),straight.el will helpfully disable:ensure whenever you include:straight in ause-package form.See#425.

Integration with Flycheck

Flycheck sometimes creates temporary files in order to performsyntax checking. This is a problem forstraight.el because creationof temporary files will causestraight.el to think that you havemodified a package when you actually have not. (You might ask whystraight.el cannot recognize temporary files and ignore them. Theanswer is that for eager modification checking, all we see is that thedirectory mtime for the repository has been updated, and there's noway to disambiguate between temporary file shenanigans versus if you,say, deleted a file.)

To work around the problem, a user optionstraight-fix-flycheck isprovided, disabled by default (for now). You can enable itbeforeloadingstraight.el, and it will work around the Flycheck problem inthe following way. When you first visit a buffer, any Flycheck checkerthat involves creation of temporary files will be inhibitedautomatically, although other checkers will still run. (In practicethis means no byte-compilation errors for Emacs Lisp, but you stillget Checkdoc errors.) However, after you make a change to the buffer(by typing, etc.) then all checkers will be re-enabled. This meansthatstraight.el won't think the package was modified unless youactually modify the buffer of a file inside it, which I think is areasonable compromise.

See#508 for discussion.

Integration with Hydra

Seethe Hydra wiki.

Miscellaneous

  • By default,straight.el explains what it is doing in the echoarea, like this:
Looking for cider recipe → Cloning melpa...

If your terminal does not support Unicode characters nicely, you cancustomizestraight-arrow to display something else for the arrow.

  • By default,straight.el reports process output the*straight-process* buffer. You can customize the name of thisbuffer via thestraight-process-buffer user option. If you want tohide this buffer by default, consider adding a leading space to thename.

  • You can preventstraight.el from making any modifications to thefilesystem (though it may still read) by customizing the user optionstraight-safe-mode to non-nil. This may be useful for runningtasks automatically in batch mode, to avoid multiple concurrentEmacs processes all making changes to the filesystem. For an exampleof how this feature may be used to safely implement asynchronousbyte-compilation of the init-file on successful startup, seeRadian.

Developer manual

This section tells you about all the interesting implementationdetails and design decisions that powerstraight.el behind thescenes. It assumes you have already read theuser manual andtheconceptual overview.

More to be written here in future. See#51.

Low-level functions

  • The functionstraight-chase-emulated-symlink is provided in orderfor external packages to correctly handle the emulated symlinkscreated bystraight.el whenstraight-use-symlinks is nil. See,for example,#520.

Trivia

This section has random, (possibly) interesting tidbits aboutstraight.el that don't fit in the other sections.

Comments and docstrings

How did I get that statistic about the percentage ofstraight.elthat is comments and docstrings? Simple: by abusing the syntaxhighlighting.

(let ((lines (make-hash-table:test#'equal)))  (goto-char (point-min))  (while (< (point) (point-max))    (when (memq (face-at-point)                '(font-lock-comment-facefont-lock-doc-face))      (puthash (line-number-at-pos)t lines))    (forward-char))  (* (/ (float (length (hash-table-keys lines)))        (line-number-at-pos))100))

Note that you will have to scroll through the entire buffer first,sincefont-lock-mode computes syntax highlighting lazily.

Contributing

Please do! Development takes place on thedevelop branch. You canswitch to that branch with

(setq straight-repository-branch"develop")

and base your pull requests from it. If you have an outstanding pullrequest whose features you would like to use in your configuration,there is full support for definingstraight.el as coming from anybranch in any fork:

(setq straight-repository-user"my-github-username")(setq straight-repository-branch"feat/my-cool-feature")

For additional information, please seethe contributor guide for myprojects. Notethatstraight.el has not yet had an initial release, so you don'thave to worry about a changelog.

FAQ

My init time got slower

Your first step should be to customize the value ofstraight-check-for-modifications. The best setting is(watch-files find-when-checking); this is not enabled by default because it isimpolite to spawn persistent background processes without asking, andbecause you must installPython 3 andwatchexec for it to work. If you can't stand the extradependencies and background process, consider the setting(check-on-save find-when-checking) instead, which is just as fastbut won't catch package modifications unless they are made withinEmacs via thesave-buffer command.

Even with lazy modification detection, as described above,straight.el is not quite as fast aspackage.el (by a fewpercentage points). There are some planned changes which will makestraight.el just as fast aspackage.el, if not faster. See#9.

"Could not find package in recipe repositories"

Assuming that the package you're trying to install actually exists,you need to update your recipe repositories (most likely MELPA,possibly Emacsmirror). See the next FAQ entry. This is like runningpackage-refresh-contents underpackage.el.

Another possibility is that you are providingstraight.el with afeature name rather than a package name. Features are what you loadwithrequire orload, or find in files. For example,org-agendaandorg-capture are features. Packages, on the other hand, canprovide one or more features. They are what are listed on MELPA et al.or byM-x straight-get-recipe. For example,org andorg-contrib are packages.

When you write(use-package foo ...), thefoo is afeature, nota package. You can give a different package namebar by saying(use-package foo :straight bar). And when you write(straight-use-package 'bar), thebar is apackage, not afeature.

How do I update MELPA et al.?

UsingM-x straight-pull-package, like forany other package.Read more.

Myuse-package form isn't working properly

There are a number of common problems you might be encountering. Checkout the following list to see if there is an easy fix.

  • Make sure you're not using:ensure oruse-package-always-ensure.Those are forpackage.el and using them withstraight.el willproduce weird results (namely bothpackage.el andstraight.elwill be invoked for the same package).
  • Make sure you knowboth the name of the feature and the name ofthe package. These are usually the same but not always (packages mayprovide more than one feature, ...). You giveuse-package the nameof afeature, not a package (despite the name of the macro). Withstraight-use-package-by-default or with:straight t, the defaultis to try installing a package by the same name as the feature.
    • If you don't actually need to install a package, then pass:straight nil to overridestraight-use-package-by-default.
    • If the package name is different from the feature name, thenpass:straight <package-name>.
  • If the package or your configurations aren't being loaded, youprobably have something wrong with your usage of:init and:config. By default, the behavior ofuse-package is unusablyinconsistent. You must set eitheruse-package-always-defer(override with:demand t) oruse-package-always-demand (overridewith:defer t) to set a default for whether evaluating ause-package form will load the package and your configurations.
    • If you've set a package to be deferred, you then need to makesure there's a way for it to get loaded when needed, for exampleby means of an autoload (either provided by the package, or setup automatically byuse-package via:bind, or set upmanually throughuse-package via:commands) or by anexplicitrequire in one of your custom commands.

How do I uninstall a package?

My first question is: do you really need to uninstall the package?Underpackage.el, every package on disk gets loaded into Emacs,whether you asked for it or not. However, understraight.el, onlythe packages you explicitly mention in your init-file get loaded intoEmacs. So theonly problem with leaving a package on disk is that ittakes up a little bit of disk space. (But the advantage is if youdecide you want to use that package again later then you won't have toredownload it.)

If you really want to uninstall a package, simply delete its localrepository from~/.emacs.d/straight/repos or run thestraight-remove-unused-repos command.

The wrong version of my package was loaded

To explain this problem, let us consider a concrete example. Inthisissue, a user found that the code

(straight-use-package'company-lsp)(straight-use-package'eglot)

sometimes resulted in runtime errors because an old version of Flymakewas being used.

The root problem here is that you want the most recent version ofFlymake to be installed bystraight.el, but Emacs also ships anolder version, and that older version is getting loaded instead.

The older version will be loaded if(require 'flymake) (or similar)is invoked beforestraight.el has made Flymake available (by meansof(straight-use-package 'flymake) or similar). But why wouldstraight.el not make Flymake available?

The only way thatstraight.el knows to make Flymake available is ifeither you manually invokestraight-use-package in your init-file,or if one of the packages that you request in your init-file declaresFlymake as a dependency. Now, any package that uses Flymake ought todeclare it as a dependency. Thus, there should be no way for a packageto load the Emacs-provided version of Flymake. However, sometimespackage authors overlook this problem (it does not always cause anerror, and sometimes package authors do not test exhaustively enough).

In this case, the problem was thatcompany-lsp declared a dependencyonlsp-mode, andlsp-mode used Flymake without declaring adependency onflymake. There are two ways to work around theproblem:

  • (Preferable) Fixlsp-mode to declare a dependency onflymake.
  • (Workaround) Manually invoke(straight-use-package 'flymake)before(straight-use-package 'company-lsp).

If you test this yourself, you might find it difficult to reproducethe problem. That is because there is only an issue when Flymake isactually loaded, and this doesn't necessarily happen when invoking(straight-use-package 'company-lsp)unlessstraight.el needs torebuild the relevant packages (which includes byte-compilation, whichsometimes means actually loading dependencies). Keep this in mind whentesting.

This problem commonly occurs with Org, since (1) Org is popular, (2)Emacs ships an obsolete version of Org, (3) many users want to use theup-to-date version, and (4) Org breaks backwards compatibilityfrequently. To solve it, simply make sure that you invoke(straight-use-package 'org) before running any code that could loadOrg, including installing any package that lists it as a dependency.

Seethis issue for discussion about ways of mitigating the badUX of this situation.

I get "could not read username/password" errors

This is becausestraight.el is not currently able to detect when SSHor Git asks for your username and/or password/passphrase and then pipethat prompt through to the minibuffer (#334).

To work around the problem, set upgit-credential-cache if you useHTTPS, andssh-agent if you use SSH. That way, you won't be promptedfor your username/password. When setting up ssh-agent, be careful tomake sure that the relevant environment variables get set in Emacs.This might be tricky since starting Emacs from the desktop (ratherthan from the command line) sometimes results in it not inheriting anyenvironment variables from your shell.

How do I pin package versions or use only tagged releases?

This is a planned feature. In the meantime, contributors have proposedvarious workarounds. See#246 and#31.

straight-x.el now contains an experimental solution. In order to useit you will need to add similar snippets to your Emacs configuration.

First you need to add a new profile tostraight-profiles which alsoneeds to be the last profile in the list. This should be done beforeyou bootstrapstraight.el.

;; Tell straight.el about the profiles we are going to be using.(setq straight-profiles      '((nil."default.el");; Packages which are pinned to a specific commit.        (pinned."pinned.el")))

After straight's install procedure you will need to addstraight-x.el and load the required commands.

(autoload#'straight-x-pull-all"straight-x")(autoload#'straight-x-freeze-versions"straight-x")

A variable calledstraight-x-pinned-packages has been defined instraight-x.el and will contain your list of pinned packages.

From now on, you can pin a package to a specific commit like in thefollowing example which will pinorg-mode to the 9.2.3 releaseversion:

(let ((straight-current-profile'pinned))  (straight-use-package'org)  (straight-use-package'org-contrib);; Pin org-mode version.  (add-to-list'straight-x-pinned-packages               '("org"."924308a150ab82014b69c46c04d1ab71e874a2e6")))

If you invokestraight-x-freeze-versions it will first write thedefault lockfile and then pinned lockfile which takes precedence overthe default one if packages are thawed.straight-x-pull-all willfirst invokestraight-pull-all and then restore all pinned packages.

You might want to assign the following aliases for more convenience:

(defalias'straight-pull-all#'straight-x-pull-all)(defalias'straight-freeze-versions#'straight-x-freeze-versions)

Please keep in mind that this is only a temporary solution andexperimental!

How can I use the built-in version of a package?

To tellstraight.el that you want to use the version of Org shippedwith Emacs, rather than cloning the upstream repository:

(straight-use-package '(org:type built-in))

Note that:type is a keyword forstraight.el, not foruse-package. If you are usinguse-package, then use:

(use-packageorg:straight (:type built-in))

Read more.

News

Jan 1, 2021

Breaking change: The previous behavior of the:build keyword is nowassociated with the:pre-build keyword.:build is now used tospecify build steps (generating autoloads and texinfo, byte/nativecompilation, etc). For more information on both of these keywords seethe recipe format.

The following customization variable names have changed:

  • straight-disable-byte-compilation is nowstraight-disable-compile

  • straight-disable-native-compilation is nowstraight-disable-native-compile

April 19, 2020

Shallow clones are now compatible with lockfiles, so you can safelysetstraight-vc-git-default-clone-depth to1 and get massivesavings on network bandwidth and disk space.

About

🍀 Next-generation, purely functional package manager for the Emacs hacker.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages


[8]ページ先頭

©2009-2025 Movatter.jp