guard is an Emacs package for modular, hierarchical configuration management. It allows you to organize your Emacs configuration into sections with dependency tracking, inheritance, conditional loading, mutual exclusion, and live introspection tools.
Call guard-initialize early in your init.el. Then call guard-config to load the tweak-file. After that, wrap setup code in guard-section blocks:
(require 'guard)
(guard-initialize)
(guard-config) ; Loads local tweaks from `guard-tweak-file`
(guard-section ui ()
"Various ui options"
(tool-bar-mode -1)
(scroll-bar-mode -1))
(guard-section themes (:parents (ui))
(load-theme 'modus-vivendi t))A section is defined using the guard-section macro:
(guard-section [name] (<options>)
<optional docstring>
<optional body>)If a section starts with a string, that string acts as its docstring.
A section can have any number of parent sections.
Sub-sections can be declared explicitly via :parents:
(guard-section lisp (:parents (programming))
(add-hook 'emacs-lisp-mode-hook #'enable-paredit-mode))or implicitly by nesting guard-section blocks within each other:
(guard-section programming ()
(guard-section lisp ()
(add-hook 'emacs-lisp-mode-hook #'enable-paredit-mode)))- Automatic Definition: Parents do not have to be declared beforehand. If a section is first introduced as a parent of a section currently being defined, the parent is defined at that moment.
- Default Parent: If a section has no explicit parents, its parent is either
guard-parent-nodeor the wrapping section (the wrapping section has precedence). - Transitive Inheritance: A section wrapped in another section will always have the wrapping section as a (maybe transitive) parent.
Allowed sections will run during initialization, while disallowed sections will not.
- A section is allowed if it is explicitly allowed OR if all of its parents are allowed.
- A section can also be explicitly disallowed, in which case it will not run.
- All sections are transitive children of
guard-parent-node, which is allowed by default. Therefore, with no extra configuration, all sections are allowed. - Explicitly allowing/disallowing a section affects all transitive dependencies of that section.
(guard-allow (section1 ...)
<optional body>)(guard-disallow (section1 ...)
<optional body>)Both operations accept an optional body that executes after explicitly allowing or disallowing the argument sections. This allows nesting logic cleanly:
;; Disallow all programming languages except python
(guard-disallow (programming-languages)
(guard-allow (python)))Note that the block syntax above is equivalent to sequential calls:
(guard-disallow (programming-languages))
(guard-allow (python))The optional body is provided as a visual convenience for logical grouping.
A section can specify a :default-child attribute to create mutually exclusive (xor) behavior:
(guard-section completion (:default-child vertico))In this case, completion becomes a xor section, and all of its child sections will be disabled except vertico.
To override the selected child (as an alternative to using guard-allow / guard-disallow), use guard-choose:
(guard-choose completion helm)This makes helm the default selected child section instead.
You can modify or override the behavior of an existing section using guard-override:
(guard-override <place> <section>
<body>)Valid values for <place>:
before<body>runs before the code in the target section.after<body>runs after the code in the target section.over<body>runs instead of the code in the target section.
Guard provides built-in interactive commands for inspecting your configuration graph and runtime status:
M-x guard-dot- Opens the
*guard-dot*buffer containing a Graphviz DOT representation of your configuration hierarchy, along with runtime execution details for each section. M-x guard-look- Inspects the status of a specific section along with its parent and child relationships.