straight.el

repository·main·Indexed 25 days ago

https://github.com/radian-software/straight.el

A purely functional package manager for Emacs focusing on 100% reproducibility through version lockfiles. It treats packages as Git repositories, allowing for direct local editing and easy upstream contribution. It supports packages from MELPA, GNU ELPA, Emacsmirror, and custom recipes, and provides full integration with use-package.

Tokens
12.2K
Snippets
17
Records
76
Agent score
35%

What's inside straight.el

  1. Overview of straight.el features

    main

    straight.el is a purely functional package manager for Emacs designed for reproducibility and flexibility. Key features include:

    • Repository Support: Install packages from MELPA, GNU ELPA, Emacsmirror, or custom recipes.
    • Git-based Management: Packages are cloned as Git repositories rather than opaque tarballs, allowing you to edit source code directly and contribute upstream easily.
    • Reproducibility: Uses version lockfiles to ensure 100% reproducible configurations based solely on your init-file and lockfile.
    • Interactive Workflows: Provides Magit-style popups for bulk maintenance of package Git repositories.
    • Integration: Full support for use-package.
    • Modular Design: Supports manual installation, explicit recipe provision, or automatic recipe fetching.
  2. Guiding principles of straight.el

    main

    straight.el is built on several core principles:

    • Single Source of Truth: The init-file and version lockfiles are the only sources of truth; no persistent state is kept elsewhere.
    • 100% Reproducibility: Accounts for changes in packages, recipe repositories, configuration, and the package manager itself.
    • Direct Editing: Allows users to edit package code directly without extra steps.
    • Compatibility: Maintains compatibility with MELPA, GNU ELPA, and Emacsmirror.
    • Isolation: Designed to make it easy to reproduce issues using emacs -Q.
  3. Conceptual overview of straight.el

    main

    straight.el is a purely functional package manager that operates by cloning Git repositories and symlinking files into Emacs' load path.

    Key concepts:

    • Package: A collection of files (usually .el) defined by a recipe. A package is not necessarily a 1:1 mapping to a Git repository or a MELPA entry.
    • Recipe: A set of instructions that defines how to obtain and build a package. It consists of a fetch recipe (how to get the local repository) and a build recipe (how to symlink files and build the package).
    • Local Repository: The actual directory containing the source files, stored in ~/.emacs.d/straight/repos.
    • Built Package: The processed version of a package (with symlinks and byte-compilation) stored in ~/.emacs.d/straight/build.
    • Recipe Repository: A special type of package that acts as a backend to provide recipes for other packages. These are registered in straight-recipe-repositories.
  4. Choose the right Emacs package manager

    main

    Deciding whether to use straight.el depends on your workflow requirements. Use straight.el if you prioritize:

    • Reproducibility: You want 100% reproducible configurations using version lockfiles.
    • Upstream Contributions: You regularly modify packages locally and want to contribute those changes back to the original Git repositories.
    • Custom Sources: You need to install packages from specific Git branches, revisions, or forks.
    • Configuration Portability: You are writing an Emacs configuration intended for others to use.

    When to avoid straight.el:

    • If you do not have Git installed (it is a requirement).
    • If you want a built-in solution (use package.el).
    • If you require a graphical user interface for package management (use package.el, el-get, Cask, or Borg).
    • If you need to install only stable/tagged versions (this is a planned feature; currently, it supports any Git revision).
    • If you need to manage packages from non-Git version control systems.
  5. Configure `use-package` with `straight.el`

    main

    When using use-package with straight.el, follow these rules to avoid conflicts and loading issues:

    • Do NOT use :ensure: Using :ensure or use-package-always-ensure will cause both package.el and straight.el to attempt to manage the package, leading to errors. Use :straight t instead.
    • Specify Package Names: If the package name is different from the feature name, use :straight <package-name>. To prevent straight.el from attempting to install a package that is already available, use :straight nil.
    • Manage Loading/Deferring: To ensure consistent behavior, set use-package-always-defer (override with :demand t) or use-package-always-demand (override with :defer t). If a package is deferred, ensure it is loaded via an autoload (e.g., :bind, :commands) or an explicit require.
  6. Manage package version lockfiles

    main

    To ensure perfect reproducibility, straight.el uses version lockfiles to specify exact revisions of packages, recipes, and straight.el itself. Lockfiles are stored in ~/.emacs.d/straight/versions (default filename is default.el). It is highly recommended to keep these lockfiles under version control alongside your Emacs configuration.

    Important: When reloading your init-file, ensure that all straight.el-related functions are re-run. If you bootstrap straight.el in a sub-file using require instead of load, reloading may fail with the error Caches are still outdated; something is seriously wrong.

  7. Implement a custom recipe repository

    main

    To create a custom recipe repository for straight.el, you must implement a specific set of functions that allow the package manager to discover and retrieve recipes.

    1. straight-recipes-NAME-list: A function that returns a list of strings representing available package names.
    2. straight-recipes-NAME-retrieve: A function that returns the Lisp recipe object for a given package name.
    3. straight-recipes-NAME-version (Optional): A function returning a non-nil value used for cache invalidation. If the logic in your retrieve function changes, you must increment this version.

    To use your repository, call straight-use-recipes with the recipe for your repository. It is recommended to include :build nil in the recipe unless the repository itself is an Emacs Lisp package.

  8. Override the recipe for straight.el

    main

    To override the recipe for straight.el itself (e.g., to use a fork or a different branch), you must use straight-recipe-overrides because straight.el must be installed before straight-override-recipe is available.

    If you change the :local-repo for straight.el, you must also manually adjust the bootstrap-file path in your bootstrap snippet so your init-file can locate the package.

  9. Install and use packages with straight-use-package

    main

    The primary way to manage packages is by calling straight-use-package. When invoked, it performs three sequential actions:

    1. Register: Records the package's recipe in its internal cache. This ensures dependencies can reuse the same recipe and prevents conflicts.
    2. Clone: If the local repository is missing, it uses the fetch recipe (via straight-vc-clone) to download the source.
    3. Build and Load: If files have changed since the last build (detected via find(1)), it recreates symlinks, byte-compiles the files, generates autoloads, and adds the directory to the Emacs load path.

    Note on Loading: straight.el does not automatically require the package after building to keep Emacs startup fast. You must manually require the package or rely on its autoloads to load it on-demand.

  10. Update recipe repositories

    main

    Recipe repositories are treated as regular packages. To update them, use:

    • M-x straight-pull-package
    • M-x straight-pull-recipe-repositories (provides interactive completion for recipe repositories).

    Use these commands if a package you need is not found by M-x straight-use-package (e.g., it was recently added to a repository).

  11. Conditionally load packages with `straight.el`

    main

    Because straight.el must maintain a deterministic lockfile, the standard use-package :when keyword does not prevent straight.el from being invoked.

    To conditionally load a package while ensuring it is registered in the lockfile, use the following pattern:

    1. Call straight-register-package to ensure the package is cloned and added to the lockfile.
    2. Use a standard when block with use-package to control actual loading/compilation.
    (straight-register-package 'foobar)
    (when some-condition
      (use-package foobar
        :straight t))
  12. Register packages via the init-file

    main

    Unlike package.el, straight.el does not store mutable state of installed packages outside your init-file. A package is considered part of your configuration only if it is passed to straight-use-package during the loading of your init-file.

    Note: Packages installed interactively via M-x straight-use-package are not considered part of your configuration. To add a package to your configuration, add it to your init-file and reload the entire init-file.