Skip to content

Latest commit

 

History

History

emacs

README.org

Emacs configuration

Source and activation

config.org is the canonical literate configuration. Its code blocks tangle to the init files of a named Emacs profile; generated profile files are not edited in this repository. After changing config.org, tangle it through the live profile machinery:

emacsclient -e '(init-build-profile (file-name-directory user-init-file))'

This command matters because the target paths are computed by the profile. A plain org-babel-tangle-file can write to the wrong profile. The active profile name is available as init-current-profile and should be queried rather than hard-coded:

emacsclient -e 'init-current-profile'

The bin/emacs wrapper starts Emacs with optional profile selection, and the command index documents the related launchers.

Extras packages and manuals

The files in extras/ are personal packages that extend built-in or external packages. Most use the -extras suffix. Their Org manuals live in extras/doc/; generated Texinfo counterparts are tracked beside the manuals that produce them. Tests live in extras/test/, and the full development and reload procedure is documented in the Elisp development workflow.

The main configuration declares extras with use-personal-package. Elpaca therefore installs them from this repository and loads them from the active profile’s checkout, normally:

~/.config/emacs-profiles/<profile>/elpaca/sources/dotfiles/

That checkout is a read-only runtime mirror. All edits belong in ~/My Drive/dotfiles/. bin/elpaca-package-path dotfiles resolves this special case to the canonical repository; other packages resolve to the active Elpaca profile.

Snippets, dictionaries, and package state

Public snippets are under yasnippets/. Private snippets are under yasnippets-private/ and are encrypted with git-crypt. The configuration adds both directories to yas-snippet-dirs, together with the installed yasnippet-snippets collection. abbrev/abbrev_defs is the tracked Emacs abbreviation file.

lockfile.el records the Elpaca package revisions used for a dotfiles release. The release workflow rewrites it from the current profile with elpaca-extras-write-lock-file-excluding; it should not be maintained by hand.

Package cooldown

Every package runs unsandboxed, and a fresh dev profile used to clone all third-party packages at upstream HEAD. bin/elpaca-cooldown keeps a compromised upstream commit from reaching a profile on the day it is pushed:

CommandBehavior
observeRuns daily from a LaunchAgent owned by the separate launchd repository. Records the tip of every third-party remote named in lockfile.el and when that tip was first seen, in ~/.local/state/elpaca-cooldown/observations.json. It runs git ls-remote only.
plan --out FILEWrites the candidate lockfile a dev profile is built from. Packages whose remote owner is listed in exempt-owners.txt move to their remote tip. Third-party packages move to the newest tip first seen at least seven days ago, provided it is still in the branch and descends from the pinned commit; otherwise they keep the previous release’s ref and the report says why. A package whose recipe in config.org carries :ref or :tag is planned at that pin, which Elpaca honours over the lockfile. --take-now PACKAGE bypasses the wait for one package and is named in the report.
verify-build --candidate FILE --built FILEFails when a profile built from the candidate checked out any other ref, and lists packages that are new in the release, which are built at upstream HEAD.
unused [--days N]Lists the third-party packages that the package usage log (~/.config/emacs-profiles/var/package-usage.log, written by the “package usage log” section of config.org) has not seen loaded in the last 60 days. It reports nothing until the log itself covers that many days. A package that the configuration loads eagerly at startup always counts as loaded.

First-seen time is recorded locally because commit dates can be forged. Until an observation is seven days old a package stays where the last release pinned it. The cooldown does not protect against a maintainer who waits it out, nor cover binaries that a package downloads or compiles.

Commit-time synchronization and reload

The canonical Git directory has post-commit and post-rewrite hooks that delegate to sync-elpaca-clone.sh. They fetch the committed current-branch state into the active profile’s dotfiles checkout and reset that mirror to the fetched commit; pushing is unrelated to this local activation path. For changed files under emacs/extras/, the same hook creates a per-commit, per-package pending state and starts the bounded elpaca-rebuild-wait helper. The helper records finished or failed under ~/.cache/dotfiles/elpaca-reload/COMMIT/, so later verification can observe the actual reload result.

This means an uncommitted extras edit is not yet the code loaded by Emacs. The safe order is: edit the canonical file, run the source-aware batch test, commit, then run ~/My\ Drive/dotfiles/claude/bin/elisp-live-verify PACKAGE -- EXPR. That helper observes the post-commit rebuild, runs the package-named expression in live Emacs, and emits repository/package/commit-bound evidence. Batch evidence is separately bound to the repository, package, and source revision. Manual rebuilds should name the individual extras package; they should not rebuild the aggregate dotfiles package.

Verification and agent support

The complete extras suite runs with:

bash emacs/extras/test/run-tests.sh

Individual packages have focused batch commands described in the development workflow. The GitHub copy of the extras suite is defined in test-extras.yml.

Project-local Emacs skills live under emacs/.claude/ and emacs/.codex/. Their names and trigger descriptions are generated in the tracked agent skill inventory rather than copied into this README.

The project-local document-elisp-extras entries load the matching runtime’s global workflow from this repository. They keep local discovery without a second procedure that can drift from the maintained documentation rules.

The emacs-freeze skill is global (claude/skills/ and codex/skills/), because freezes are reported from sessions in any project. It reads the freeze incident record first. The workflow binds evidence to a specific process and distinguishes UI responsiveness from server replies. Its client helper bounds only its owned child process; timeouts do not establish recovery or cancel queued Emacs work. Recovery requires explicit authority and checks for session data and debugger state, without treating sampled stacks or shutdown autosaving as guarantees.

The migrate-profile workflow inventories exact profile/project mappings and uses the runtime-specific move-session-log adapters for offline history relocation. It preserves unsupported memory/configuration merges and conflicting sources, keeps trust transfer and additional deletion separately authorized, and distinguishes metadata checks from live history/resume verification.

The rename-package workflow separates library/API edits from hosted repository renames, publication, checkout relocation and live activation. It resolves the actual package registry/source and verification support before changing a main library, and preserves unrelated commits, trust state and older profiles.