pathaction.el: An Emacs package for executing pathaction rules, the universal Makefile for the entire filesystem

Build Status License

The pathaction.el Emacs package provides an interface for executing .pathaction.yaml rules directly from Emacs through the pathaction cli, a flexible tool for running commands on files and directories.

Think of pathaction like a Makefile for any file or directory in the filesystem. It uses a .pathaction.yaml file to figure out which command to run, and you can even use Jinja2 templating to make those commands dynamic. You can also use tags to define multiple actions for the exact same file type, like setting up one tag to run a script, and another to debug it.

This tool is for software developers who manage multiple projects across diverse ecosystems and want to eliminate the cognitive load of switching between different build tools, environment configurations, and deployment methods. Just run one single command on any file and trust that it gets handled correctly.

If this package helps your workflow, please show your support by ⭐ starring pathaction.el on GitHub to help more software developers discover its benefits.

Requirements

Installation

To install pathaction from MELPA:

  1. If you haven’t already done so, add MELPA repository to your Emacs configuration.

  2. Add the following code to your Emacs init file to install pathaction from MELPA:

(use-package pathaction
  :config
  (add-to-list 'display-buffer-alist '("\\*pathaction:"
                                       (display-buffer-at-bottom)
                                       (window-height . 0.33))))

Usage

Allow the directory

By default, pathaction does not read rule-set files such as .pathaction.yaml from arbitrary directories. The target directory must be explicitly permitted.

For example, to allow Pathaction to load .pathaction.yaml rules from ~/projects and its subdirectories, run the following command:

pathaction --allow-dir ~/projects

Run

To execute the pathaction action that is tagged with main, you can call the following Emacs function:

(pathaction-run "main")
  • pathaction-run: This is the main function for triggering pathaction actions.
  • "main": This is the tag used to identify a specific action. The tag you provide to the function determines which set of actions will be executed. In this case, "main" refers to the actions that are specifically tagged with this name.

Edit .pathaction.yaml

To edit a .pathaction.yaml file located in a parent directory, run the command: M-x pathaction-edit

The command prompts for selection of one of the rule-set files found in the current directory or in one of its parent directories.

Customization

Configuration Options

pathaction-term-shell (Default: explicit-shell-file-name or shell-file-name)

The shell used by the terminal emulator to execute the pathaction command (e.g., "/bin/bash" or "/bin/zsh").

pathaction-term-function (Default: #'pathaction-ansi-term)

The function used to create and execute the terminal. By default, it uses #'pathaction-ansi-term. You can customize this to use faster, third-party terminal emulators like:

  • #'pathaction-eat
  • #'pathaction-vterm

pathaction-cleanup-buffer-at-process-exit (Default: t)

If non-nil, automatically closes the terminal and kills the buffer when the process exits. Set this to nil if you want the window to remain open so you can inspect the output.

pathaction-close-window-after-execution (Default: t)

If non-nil, the pathaction window will be closed once execution is complete.

pathaction-keep-buffer-when-process-running (Default: t)

If non-nil, keeps hidden pathaction buffers alive if they have an active process.

Making pathaction open a window under the current one

To configure pathaction to open its window under the current one, you can use the display-buffer-alist variable to customize how the pathaction buffer is displayed. Specifically, you can use the display-buffer-at-bottom action, which will display the buffer in a new window at the bottom of the current frame.

Here’s the code to do this:

(add-to-list 'display-buffer-alist '("\\*pathaction:"
                                     (display-buffer-at-bottom)
                                     (window-height . 0.33)))

Hooks

  • pathaction-before-run-hook: This hook is executed by pathaction-run before the pathaction command is executed.
  • pathaction-after-create-buffer-hook: This hook is executed after the pathaction buffer is created. It runs from within the pathaction buffer, enabling further customization or actions once the buffer is available.

Saving all buffers before executing pathaction

By default, pathaction-before-run-hook only calls the pathaction-save-buffer function to save the current buffer before executing actions or commands that affect the current or any other edited buffer.

To make pathaction save all buffers, use the following configuration:

(defun my-save-some-buffers ()
  "Prevent `save-some-buffers' from prompting by passing 1 to it."
  ;; The first argument means to save all buffers without prompting
  (save-some-buffers t))

(add-hook 'pathaction-before-run-hook #'my-save-some-buffers)

Author and License

The pathaction Emacs package has been written by James Cherti and is distributed under terms of the GNU General Public License version 3, or, at your choice, any later version.

Copyright (C) 2025-2026 James Cherti

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program.

Links

  • pathaction.el, an Emacs package that allows executing the pathaction command-line tool directly from Emacs.
  • The pathaction command-line tool (requirement): pathaction cli
  • For Vim users: vim-pathaction, a Vim plugin that allows executing the pathaction command-line tool directly from Vim.

Other Emacs packages by the same author:

  • compile-angel.el: Speed up Emacs! This package guarantees that all .el files are both byte-compiled and native-compiled, which significantly speeds up Emacs.
  • outline-indent.el: An Emacs package that provides a minor mode that enables code folding and outlining based on indentation levels for various indentation-based text files, such as YAML, Python, and other indented text files.
  • easysession.el: Easysession is lightweight Emacs session manager that can persist and restore file editing buffers, indirect buffers/clones, Dired buffers, the tab-bar, and the Emacs frames (with or without the Emacs frames size, width, and height).
  • vim-tab-bar.el: Make the Emacs tab-bar Look Like Vim’s Tab Bar.
  • elispcomp: A command line tool that allows compiling Elisp code directly from the terminal or from a shell script. It facilitates the generation of optimized .elc (byte-compiled) and .eln (native-compiled) files.
  • tomorrow-night-deepblue-theme.el: The Tomorrow Night Deepblue Emacs theme is a beautiful deep blue variant of the Tomorrow Night theme, which is renowned for its elegant color palette that is pleasing to the eyes. It features a deep blue background color that creates a calming atmosphere. The theme is also a great choice for those who miss the blue themes that were trendy a few years ago.
  • Ultyas: A command-line tool designed to simplify the process of converting code snippets from UltiSnips to YASnippet format.
  • dir-config.el: Automatically find and evaluate .dir-config.el Elisp files to configure directory-specific settings.
  • flymake-bashate.el: A package that provides a Flymake backend for the bashate Bash script style checker.
  • flymake-ansible-lint.el: An Emacs package that offers a Flymake backend for ansible-lint.
  • inhibit-mouse.el: A package that disables mouse input in Emacs, offering a simpler and faster alternative to the disable-mouse package.
  • quick-sdcv.el: This package enables Emacs to function as an offline dictionary by using the sdcv command-line tool directly within Emacs.
  • enhanced-evil-paredit.el: An Emacs package that prevents parenthesis imbalance when using evil-mode with paredit. It intercepts evil-mode commands such as delete, change, and paste, blocking their execution if they would break the parenthetical structure.
  • stripspace.el: Ensure Emacs Automatically removes trailing whitespace before saving a buffer, with an option to preserve the cursor column.
  • persist-text-scale.el: Ensure that all adjustments made with text-scale-increase and text-scale-decrease are persisted and restored across sessions.
  • kirigami.el: The kirigami Emacs package offers a unified interface for opening and closing folds across a diverse set of major and minor modes in Emacs, including outline-mode, outline-minor-mode, outline-indent-minor-mode, org-mode, markdown-mode, vdiff-mode, vdiff-3way-mode, hs-minor-mode, hide-ifdef-mode, origami-mode, yafolding-mode, folding-mode, and treesit-fold-mode. With Kirigami, folding key bindings only need to be configured once. After that, the same keys work consistently across all supported major and minor modes, providing a unified and predictable folding experience.
  • buffer-guardian.el: Automatically saves Emacs buffers without requiring manual intervention. By default, it triggers a save when the user switches to another buffer, switches to another window or frame, Emacs loses focus, or the minibuffer is opened. Beyond standard file buffers, buffer-guardian also manages specialized editing buffers such as org-src and edit-indirect. Additional features, disabled by default, include periodic or idle-time saving of all buffers, automatic exclusion of remote, nonexistent, or large files, and support for custom exclusion rules via regular expressions or predicate functions.

ultisnips-mode.el: An Emacs major mode for editing Ultisnips snippet files (*.snippets files)

Build Status MELPA MELPA Stable License

The ultisnips-mode is an Emacs major mode for editing Ultisnips snippet files (*.snippets files). This mode provides syntax highlighting to facilitate editing Ultisnips snippets.

(Vim’s UltiSnips is a snippet solution for Vim, and its snippets can be used in Emacs by converting them to the Yasnippet format using Ultyas.)

Features

  • Syntax highlighting for UltiSnips: snippet, endsnippet, global, endglobal, priority, comments, and placeholders in the form of ${1:value} or $1
  • Integration with outline-minor-mode or hs-minor-mode to enable folding of snippet -> endsnippet and global -> endglobal blocks.
  • Support for commenting and uncommenting UltiSnips snippets using standard Emacs commands, such as comment-or-uncomment-region.
  • Add *.snippets to auto-mode-alist to automatically enable ultisnips-mode.

Installation

To install ultisnips-mode from MELPA:

  1. If you haven’t already done so, add MELPA repository to your Emacs configuration.

  2. Add the following code to your Emacs init file to install ultisnips-mode from MELPA:

(use-package ultisnips-mode
  :commands ultisnips-mode
  :mode ("\\.snippets\\'" . ultisnips-mode))

Frequently Asked Questions

Folding snippet blocks with hs-minor-mode

Activating hs-minor-mode provides the ability to collapse and expand snippet -> endsnippet blocks, making navigation in large snippet files much easier.

To enable hs-minor-mode automatically for Ultisnips files, add the following to the Emacs configuration:

(add-hook 'ultisnips-mode-hook #'hs-minor-mode)

NOTE: As an alternative to hs-minor-mode, ultisnips-mode also supports outline-minor-mode; however, hs-minor-mode is recommended because it can reliably fold entire blocks from snippet to endsnippet. In contrast, outline-minor-mode uses only the snippet line as a header and may hide everything between the first snippet and the next one, including comments.

For a better and more intuitive way to fold and unfold snippets, it is recommended to use the kirigami.el emacs package.

Hiding all snippets with hs-minor-mode when opening *.snippets files

The following configuration automatically folds all code blocks when ultisnips-mode is enabled, collapsing all snippets:

(defun my-ultisnips-mode-fold-all ()
  "Fold all snippet blocks using `hs-minor-mode'."
  (hs-minor-mode 1)
  (hs-hide-all))

(add-hook 'ultisnips-mode-hook #'my-ultisnips-mode-fold-all)

This ensures a cleaner view of snippets, collapsing all regions by default and allowing selective expansion as needed.

Is there a package that allows using UltiSnips directly in Emacs, or is it necessary to first convert them to the Yasnippet format?

Yes, conversion to Yasnippet is required.

A command-line tool called Ultyas facilitates the conversion of snippets from UltiSnips to Yasnippet format.

How does the author use ultisnips-mode and Ultyas?

The author maintains all snippets in their original UltiSnips format for Vim and developed a shell script that automatically scans the UltiSnips directory, generating the corresponding Yasnippet files using Ultyas.

He uses the ultisnips-mode Emacs package to edit snippets, which provides syntax highlighting and code folding via hs-minor-mode.

This workflow allows editing and storing a single set of snippets while making them available in Vim and Emacs.

Author and License

The ultisnips-mode Emacs package has been written by James Cherti and is distributed under terms of the GNU General Public License version 3, or, at your choice, any later version.

Copyright (C) 2025-2026 James Cherti

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program.

Links

Other Emacs packages by the same author:

  • minimal-emacs.d: This repository hosts a minimal Emacs configuration designed to serve as a foundation for your vanilla Emacs setup and provide a solid base for an enhanced Emacs experience.
  • compile-angel.el: Speed up Emacs! This package guarantees that all .el files are both byte-compiled and native-compiled, which significantly speeds up Emacs.
  • easysession.el: Easysession is lightweight Emacs session manager that can persist and restore file editing buffers, indirect buffers/clones, Dired buffers, the tab-bar, and the Emacs frames (with or without the Emacs frames size, width, and height).
  • vim-tab-bar.el: Make the Emacs tab-bar Look Like Vim’s Tab Bar.
  • elispcomp: A command line tool that allows compiling Elisp code directly from the terminal or from a shell script. It facilitates the generation of optimized .elc (byte-compiled) and .eln (native-compiled) files.
  • tomorrow-night-deepblue-theme.el: The Tomorrow Night Deepblue Emacs theme is a beautiful deep blue variant of the Tomorrow Night theme, which is renowned for its elegant color palette that is pleasing to the eyes. It features a deep blue background color that creates a calming atmosphere. The theme is also a great choice for those who miss the blue themes that were trendy a few years ago.
  • dir-config.el: Automatically find and evaluate .dir-config.el Elisp files to configure directory-specific settings.
  • flymake-bashate.el: A package that provides a Flymake backend for the bashate Bash script style checker.
  • flymake-ansible-lint.el: An Emacs package that offers a Flymake backend for ansible-lint.
  • inhibit-mouse.el: A package that disables mouse input in Emacs, offering a simpler and faster alternative to the disable-mouse package.
  • quick-sdcv.el: This package enables Emacs to function as an offline dictionary by using the sdcv command-line tool directly within Emacs.
  • enhanced-evil-paredit.el: An Emacs package that prevents parenthesis imbalance when using evil-mode with paredit. It intercepts evil-mode commands such as delete, change, and paste, blocking their execution if they would break the parenthetical structure.
  • stripspace.el: Ensure Emacs Automatically removes trailing whitespace before saving a buffer, with an option to preserve the cursor column.
  • persist-text-scale.el: Ensure that all adjustments made with text-scale-increase and text-scale-decrease are persisted and restored across sessions.
  • pathaction.el: Execute the pathaction command-line tool from Emacs. The pathaction command-line tool enables the execution of specific commands on targeted files or directories. Its key advantage lies in its flexibility, allowing users to handle various types of files simply by passing the file or directory as an argument to the pathaction tool. The tool uses a .pathaction.yaml rule-set file to determine which command to execute. Additionally, Jinja2 templating can be employed in the rule-set file to further customize the commands.
  • kirigami.el: The kirigami Emacs package offers a unified interface for opening and closing folds across a diverse set of major and minor modes in Emacs, including outline-mode, outline-minor-mode, outline-indent-minor-mode, org-mode, markdown-mode, vdiff-mode, vdiff-3way-mode, hs-minor-mode, hide-ifdef-mode, origami-mode, yafolding-mode, folding-mode, and treesit-fold-mode. With Kirigami, folding key bindings only need to be configured once. After that, the same keys work consistently across all supported major and minor modes, providing a unified and predictable folding experience.
  • buffer-guardian.el: Automatically saves Emacs buffers without requiring manual intervention. By default, it triggers a save when the user switches to another buffer, switches to another window or frame, Emacs loses focus, or the minibuffer is opened. Beyond standard file buffers, buffer-guardian also manages specialized editing buffers such as org-src and edit-indirect. Additional features, disabled by default, include periodic or idle-time saving of all buffers, automatic exclusion of remote, nonexistent, or large files, and support for custom exclusion rules via regular expressions or predicate functions.

kirigami.el – A Unified Interface for Text Folding across a diverse set of Emacs modes (outline-mode, outline-minor-mode, outline-indent-mode, org-mode, markdown-mode, vdiff-mode, hs-minor-mode, treesit-fold-mode…)

Build Status MELPA MELPA Stable License

The kirigami Emacs package provides a unified method to fold and unfold text in Emacs across a diverse set of Emacs modes.

Supported modes include: outline-mode, outline-minor-mode, outline-indent-minor-mode, org-mode, markdown-mode, gfm-mode, outli-mode, embark-collect-mode, vdiff-mode, vdiff-3way-mode, hide-ifdef-mode, vimish-fold-mode, TeX-fold-mode (AUCTeX), fold-this-mode, origami-mode, yafolding-mode, folding-mode, ts-fold-mode, treesit-fold-mode, hs-minor-mode (hideshow), ibuffer-mode (M-x ibuffer), and profiler-report-mode (M-x profile-report).

With Kirigami, folding key bindings only need to be configured once. After that, the same keys work consistently across all supported major and minor modes, providing a unified and predictable experience for opening and closing folds. The available interactive commands include:

  • kirigami-open-fold: Open the fold at point.
  • kirigami-open-fold-rec: Open the fold at point recursively.
  • kirigami-close-fold: Close the fold at point.
  • kirigami-open-folds: Open all folds in the buffer.
  • kirigami-close-folds: Close all folds in the buffer.
  • kirigami-toggle-fold: Toggle the fold at point.

It features both a buffer-local minor mode (kirigami-mode) and an editor-wide global minor mode (kirigami-global-mode) that expose all text-folding operations through keybindings, a menu bar entry, and context menus.

In addition to providing a unified interface, the kirigami package enhances folding behavior in the outline, markdown-mode, and org-mode packages. It ensures that deep folds open reliably, allows folds to be closed even when the cursor is positioned inside the content, and ensures that sibling folds at the same level are visible when a sub-fold is expanded. For org-mode specifically, Kirigami now provides native folding support for elements such as source blocks (#+begin_src), drawers (:TEST_DRAWER:), and results (#+RESULTS:). When Kirigami closes outline folds, it preserves the visibility of folded headings in the window. Additionally, it resolves upstream Emacs issues, such as bug#79286.

If kirigami enhances your workflow, please show your support by ⭐ starring kirigami.el on GitHub to help more Emacs users discover its benefits.

Features

Here are the features that kirigami offers:

  • Uniform commands: The same commands and keys can be used to open, close, toggle, or check folds, no matter what mode is active. (Commands: kirigami-open-fold, kirigami-open-fold-rec, kirigami-open-folds, kirigami-close-fold, kirigami-toggle-fold, kirigami-close-folds)
  • Automatic handler selection: Kirigami automatically chooses the right folding method based on the mode being used.
  • Extensible fold list: Users can easily add or customize folding methods for different modes through the kirigami-fold-list alist.
  • Support for multiple folding backends, including:
    • outline-mode, outline-minor-mode (built-in), and external packages based on outline such as outli (outli-mode) or outline-indent (outline-indent-minor-mode), a package that enables code folding based on indentation.
    • hs-minor-mode (hideshow, built-in)
    • outline-indent-minor-mode (outline-indent.el, a package that enables code folding based on indentation)
    • org-mode (built-in)
    • markdown-mode and gfm-mode (markdown-mode)
    • vdiff-mode and vdiff-3way-mode
    • treesit-fold-mode (treesit-fold, which provides intelligent code folding by using the structural understanding of the built-in tree-sitter parser)
    • embark-collect-mode
    • hide-ifdef-mode
    • vimish-fold-mode
    • origami-mode
    • TeX-fold-mode (AUCTeX)
    • fold-this-mode
    • yafolding-mode
    • ts-fold-mode
    • ibuffer-mode (toggle filter groups in M-x ibuffer)
    • profiler-report-mode (expand/collapse M-x profile-report tree entries)
  • In addition to unified interface for opening and closing folds, the kirigami package:
    • Visual Stability: Avoids the disruptive window jump by preserving the cursor’s exact vertical position when expanding or collapsing headings, maintaining a constant relative distance between the cursor and the window start.
    • Enhances outline and org-mode: Improves folding in outline-mode, outline-minor-mode, markdown-mode, gfm-mode, and org-mode by ensuring deep folds open reliably, keeping folded headings visible, and collapsing to the shallowest heading level. In org-mode, it intercepts folding commands to natively toggle source blocks (#+begin_src), drawers (:TEST_DRAWER:), and results (#+RESULTS:) sections without falling back to standard heading behavior.
    • Hooks: kirigami-pre-action-predicates and kirigami-post-action-functions run before and after each fold, allowing actions to be allowed or blocked and enabling UI or external updates after changes.

The kirigami package supports Emacs version 26.3 and above.

Installation

To install kirigami from MELPA:

  1. If you haven’t already done so, add MELPA repository to your Emacs configuration.

  2. Add the following code to your Emacs init file to install kirigami from MELPA:

(use-package kirigami
  :custom
  ;; Add Kirigami to the menu bar and context menu (`context-menu-mode').
  (kirigami-show-menu-bar t)
  (kirigami-show-context-menu t)
  :init
  (kirigami-global-mode 1))

Usage

Vanilla Emacs Key bindings

Here is an example of default key bindings:

(global-set-key (kbd "C-c z o") 'kirigami-open-fold)     ; Open fold at point
(global-set-key (kbd "C-c z O") 'kirigami-open-fold-rec) ; Open fold recursively
(global-set-key (kbd "C-c z r") 'kirigami-open-folds)    ; Open all folds
(global-set-key (kbd "C-c z c") 'kirigami-close-fold)    ; Close fold at point
(global-set-key (kbd "C-c z m") 'kirigami-close-folds)   ; Close all folds
(global-set-key (kbd "C-c z a") 'kirigami-toggle-fold)   ; Toggle fold at point

Evil-mode Key Bindings

Evil-mode users can override the default folding keys with the following configuration:

;; Configure Kirigami to replace the default Evil-mode folding key bindings
(with-eval-after-load 'evil
  (define-key evil-normal-state-map "zo" 'kirigami-open-fold)
  (define-key evil-normal-state-map "zO" 'kirigami-open-fold-rec)
  (define-key evil-normal-state-map "zc" 'kirigami-close-fold)
  (define-key evil-normal-state-map "za" 'kirigami-toggle-fold)
  (define-key evil-normal-state-map "zr" 'kirigami-open-folds)
  (define-key evil-normal-state-map "zm" 'kirigami-close-folds))

Configuring and Enabling Folding Backends

Kirigami acts as a unified interface and requires an underlying folding backend to be active in the current buffer.

The following article provides a comprehensive guide on installing and enabling the supported folding backends: The Definitive Guide to Code Folding in Emacs.

Commands

Kirigami defines several interactive commands. These commands abstract over all supported folding systems:

  • kirigami-open-fold: Open the fold at point.
  • kirigami-open-fold-rec: Open the fold at point recursively.
  • kirigami-open-folds: Open all folds in the buffer.
  • kirigami-close-fold: Close the fold at point.
  • kirigami-toggle-fold: Toggle the fold at point.
  • kirigami-close-folds: Close all folds in the buffer.

Extending Kirigami: Adding other fold methods

The core behavior is driven by kirigami-fold-list, a customizable list that associates folding actions with sets of major or minor modes. Each entry in the list specifies:

  • A list of modes that act as a predicate.
  • A property list describing supported folding actions.

Properties include:

  • :open-all Function to open every fold in the current buffer.

  • :close-all Function to close every fold in the current buffer.

  • :toggle Function to toggle the fold at point.

  • :open Function to open the fold at point.

  • :open-rec Function to open the fold at point recursively.

  • :close Function to close the fold at point.

Each property must specify a function. A value of nil indicates that the corresponding action is ignored for that handler.

Here is an example using the built-in hs-minor-mode, which Kirigami supports by default. This example demonstrates how additional folding actions can be configured:

(push
 '((hs-minor-mode)
   :open-all    hs-show-all
   :close-all   hs-hide-all
   :toggle      hs-toggle-hiding
   :open        hs-show-block
   :open-rec    nil
   :close       hs-hide-block)
 kirigami-fold-list)

Frequently Asked Questions

Why code folding?

Code folding is about managing cognitive load, preserving spatial memory, and controlling screen real estate:

  • Navigating through code (e.g., with LSP) can create a vacuum of context. Folding an entire file to its top-level headings allows the manipulation of the file skeleton directly in the main buffer. Revealing only a specific entry and its parents provides an immediate understanding of the hierarchy without losing position.
  • When tasked with debugging a 20,000 line legacy file, immediate refactoring is rarely an option. Folding enables the visual modularization of massive files on the fly, making hostile codebases readable.
  • Every visible line of code on the screen requires a fraction of subconscious attention to ignore. During deep debugging sessions, folding adjacent functions or complex implementations acts as a visual garbage collector.
  • Moving or deleting a massive function or block is prone to selection errors. When a block is folded, it behaves as a single logical unit. Large chunks of logic can be cut, copied, or moved safely and cleanly without manually highlighting hundreds of lines.
  • Folding is effective for tracking progress during extensive pull requests. Collapsing previously examined functions or blocks actively filters out visual noise and enforces a strict focus on the unreviewed code.

Why the author developed the kirigami package?

Code folding in Emacs has historically suffered from reliability issues, which led to the development of kirigami. Even built-in modes such as outline-mode and outline-minor-mode which are also used by org-mode, gfm-mode, and markdown-mode contain bugs that have not yet been addressed upstream, and kirigami fixes them.

The kirigami package also provides a unified interface for opening and closing folds. Without it, users must manually configure keybindings for each individual mode, a tedious process. It functions as a set-and-forget enhancement for code folding. It requires configuration only once. Subsequently, the same keys and functions enable consistent folding and unfolding across all supported major and minor modes.

(The kirigami package is highly recommended for use with outline-based modes, such as markdown-mode, gfm-mode, org-mode, outline-minor-mode, or outline-indent-minor-mode. This package resolves persistent inconsistencies and prevents incorrect folding behavior.)

Preventing Emacs search from matching text within folded blocks

By default, search operations can match text within folded blocks, which often causes Emacs to automatically expand the hidden content.

To instruct Emacs to strictly ignore invisible text during search operations, add the following configuration to your init file:

(setq-default search-invisible nil)

Alternatively, to restrict this behavior to specific modes, apply a buffer-local configuration via a mode hook:

(add-hook 'prog-mode-hook (lambda ()
                            (setq-local search-invisible nil)))

Integrating display-line-numbers-mode with code folding

The built-in display-line-numbers-mode renders line numbers in the side margin of the window. By default, it uses absolute line numbering, which tracks the absolute line count in the buffer. Consequently, when a block is folded, the line numbers skip the hidden range (e.g., jumping from 15 to 120).

For users who prefer visual line numbering, display-line-numbers-mode can be configured to ignore collapsed content and assign numbers sequentially based only on what is currently rendered on the screen.

To implement visual line numbering as your global default, set the following variable in your configuration:

(setq-default display-line-numbers-type 'visual)

Note that you must still enable the mode itself (for example, via M-x global-display-line-numbers-mode) for the line numbers to appear.

Maintaining independent folding states in separate windows via indirect buffers (clones)

Opening the same buffer in multiple windows results in synchronized folding states; any folding or unfolding action performed in one window is immediately reflected in all others.

This occurs because folding engines use buffer-local overlays, which are shared across all windows associated with that specific buffer.

Indirect buffers provide a robust solution to this limitation. An indirect buffer shares the underlying text of its parent buffer but maintains an independent set of overlays. This distinction allows for the maintenance of different folding configurations for the same file simultaneously.

To create an indirect buffer (clone) of the current buffer in a separate window, execute:

M-x clone-indirect-buffer-other-window

Creating an indirect buffer provides a separate buffer object that references the same text while maintaining its own isolated set of opened/closed folds.

Discouraged Emacs Folding Engines

Choosing an appropriate folding engine is important for maintaining performance and stability within Emacs. While several third-party and legacy options exist, the following packages and methods are generally discouraged in favor of more modern or integrated alternatives:

  • Origami: This package is slow and largely unmaintained. Origami uses a non-standard API and a complex implementation that frequently conflicts with other overlay-based minor modes. Its overhead can lead to performance degradation, especially when handling large buffers or deeply nested code. (Modern alternatives to origami: outline-indent, treesit-fold, outline-minor-mode, hs-minor-mode)
  • Yafolding: This package is also unmaintained and suffers from performance issues. (Modern alternative to yafolding: outline-indent)
  • Semantic (CEDET): Part of the legacy CEDET suite, Semantic folding is widely regarded as heavyweight. The parsing overhead required for its operation often introduces noticeable latency, making it vastly less efficient than modern built-in alternatives like Tree-sitter. (Modern alternatives to CEDET code folding: treesit-fold, outline-minor-mode, hs-minor-mode, outline-indent)
  • Selective Display (set-selective-display): This is Emacs’ oldest built-in folding method (often bound to C-x $). It causes unpredictable cursor jumping, and lacks any contextual awareness.
  • Folding-mode: This ancient package relies on explicit structural markers placed manually inside code comments (e.g., {{{ and }}}). While robust for the user, markers pollute the source code with editor-specific metadata. This is heavily frowned upon in modern collaborative environments where team members use varying IDEs.
  • Vimish-fold: Although useful for manual, ad-hoc text folding, vimish-fold is not recommended as a primary automated folding engine. Unlike Vim’s set foldmethod=marker, the vimish-fold implementation does not support recursive markers, such as {{{ inside of {{{. Additionally, like folding-mode, vimish-fold also uses markers that pollute the source code with editor-specific metadata, a practice discouraged in collaborative environments where team members use a variety of editors and IDEs.

What code folding packages does the author use in addition to kirigami.el?

In addition to the kirigami package, the author uses two reliable code folding packages:

  1. Indentation-based folding (Python, YAML, Haskell, etc.): outline-indent
  2. Tree-sitter-based folding: treesit-fold (The integration of Tree-sitter allows Emacs to operate on the Abstract Syntax Tree, making folding structurally accurate rather than heuristic.)
  3. The built-in outline-minor-mode for emacs-lisp-mode, markdown-mode, and conf-mode/conf-unix-mode.

NOTE: The author prefers using outline-indent for languages like Python, despite having treesit-fold installed. The advantage of outline-indent is that it allows for infinite folding depth; it enables the folding of classes, functions within them, and even nested structures like while loops and if statements.

Maintaining Vertical Cursor Position During Folding

Folding packages such as Outline, Outline Indent, and Org mode depend on the native Emacs redisplay engine to handle visibility changes. Expanding or collapsing folds can cause window-start to shift relative to the current line. When this displacement moves the cursor off-screen, Emacs triggers an abrupt recentering. This visual discontinuity disrupts spatial context and requires manual effort to relocate the cursor.

To address these issues, the following option can be used to eliminate visual discontinuities by preventing window shifts and suppressing forced recentering when headings are expanded or collapsed:

(setq kirigami-preserve-visual-position t)

What is the meaning of the word Kirigami?

Kirigami is a form of Origami, the Japanese art that transforms a flat sheet of paper into a figure through controlled folds. In kirigami, the sheet is both folded and cut to form a three-dimensional structure that rises from the surface.

Kirigami and code folding in Emacs share a structural analogy based on selective concealment and controlled revelation. In kirigami, cuts and folds create regions that can be collapsed or expanded, revealing depth or hiding detail depending on how the paper is manipulated.

Code folding in Emacs operates on a similar principle. Blocks of text remain present in the buffer, but their visibility is adjusted by folding or unfolding sections.

Comments from users

  • neurolit on GitHub: “Thank you very much for this package!”

  • jcs090218: “Thanks for this great package!”

  • RideAndRoam3C: “I enabled it today while doing some Org technical docs work. Solid.”

  • mickeyp: “Nice job. So many different packages.”

  • Anthea_Likes: “I’ve been using Kirigami for a few months now, and it’s absolutely gorgeous! Thank you for this quality work 🙏”

Author and License

The kirigami Emacs package has been written by James Cherti and is distributed under terms of the GNU General Public License version 3, or, at your choice, any later version. Special thanks to the developers of Evil mode. Kirigami builds upon the idea and function from Evil mode to provide enhanced and unified code folding functionality to all Emacs users.

Copyright (C) 2025-2026 James Cherti

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program.

Links

Other Emacs packages by the same author:

  • minimal-emacs.d: This repository hosts a minimal Emacs configuration designed to serve as a foundation for your vanilla Emacs setup and provide a solid base for an enhanced Emacs experience.
  • compile-angel.el: Speed up Emacs! This package guarantees that all .el files are both byte-compiled and native-compiled, which significantly speeds up Emacs.
  • outline-indent.el: An Emacs package that provides a minor mode that enables code folding and outlining based on indentation levels for various indentation-based text files, such as YAML, Python, and other indented text files.
  • easysession.el: Easysession is lightweight Emacs session manager that can persist and restore file editing buffers, indirect buffers/clones, Dired buffers, the tab-bar, and the Emacs frames (with or without the Emacs frames size, width, and height).
  • vim-tab-bar.el: Make the Emacs tab-bar Look Like Vim’s Tab Bar.
  • elispcomp: A command line tool that allows compiling Elisp code directly from the terminal or from a shell script. It facilitates the generation of optimized .elc (byte-compiled) and .eln (native-compiled) files.
  • tomorrow-night-deepblue-theme.el: The Tomorrow Night Deepblue Emacs theme is a beautiful deep blue variant of the Tomorrow Night theme, which is renowned for its elegant color palette that is pleasing to the eyes. It features a deep blue background color that creates a calming atmosphere. The theme is also a great choice for those who miss the blue themes that were trendy a few years ago.
  • Ultyas: A command-line tool designed to simplify the process of converting code snippets from UltiSnips to YASnippet format.
  • dir-config.el: Automatically find and evaluate .dir-config.el Elisp files to configure directory-specific settings.
  • flymake-bashate.el: A package that provides a Flymake backend for the bashate Bash script style checker.
  • flymake-ansible-lint.el: An Emacs package that offers a Flymake backend for ansible-lint.
  • inhibit-mouse.el: A package that disables mouse input in Emacs, offering a simpler and faster alternative to the disable-mouse package.
  • quick-sdcv.el: This package enables Emacs to function as an offline dictionary by using the sdcv command-line tool directly within Emacs.
  • enhanced-evil-paredit.el: An Emacs package that prevents parenthesis imbalance when using evil-mode with paredit. It intercepts evil-mode commands such as delete, change, and paste, blocking their execution if they would break the parenthetical structure.
  • stripspace.el: Ensure Emacs Automatically removes trailing whitespace before saving a buffer, with an option to preserve the cursor column.
  • persist-text-scale.el: Ensure that all adjustments made with text-scale-increase and text-scale-decrease are persisted and restored across sessions.
  • pathaction.el: Execute the pathaction command-line tool from Emacs. The pathaction command-line tool enables the execution of specific commands on targeted files or directories. Its key advantage lies in its flexibility, allowing users to handle various types of files simply by passing the file or directory as an argument to the pathaction tool. The tool uses a .pathaction.yaml rule-set file to determine which command to execute. Additionally, Jinja2 templating can be employed in the rule-set file to further customize the commands.
  • kirigami.el: The kirigami Emacs package offers a unified interface for opening and closing folds across a diverse set of major and minor modes in Emacs, including outline-mode, outline-minor-mode, outline-indent-minor-mode, org-mode, markdown-mode, vdiff-mode, vdiff-3way-mode, hs-minor-mode, hide-ifdef-mode, origami-mode, yafolding-mode, folding-mode, and treesit-fold-mode. With Kirigami, folding key bindings only need to be configured once. After that, the same keys work consistently across all supported major and minor modes, providing a unified and predictable folding experience.
  • buffer-guardian.el: Automatically saves Emacs buffers without requiring manual intervention. By default, it triggers a save when the user switches to another buffer, switches to another window or frame, Emacs loses focus, or the minibuffer is opened. Beyond standard file buffers, buffer-guardian also manages specialized editing buffers such as org-src and edit-indirect. Additional features, disabled by default, include periodic or idle-time saving of all buffers, automatic exclusion of remote, nonexistent, or large files, and support for custom exclusion rules via regular expressions or predicate functions.

Google Home Script for announcing door open and close events using Matter door/window sensors

The Matter standard enables smart home devices from different manufacturers to work together in a reliable and secure way. One common use case is detecting when a door is opened or closed and announcing this event through Google Home speakers or sending notifications to connected devices.

This article demonstrates how to configure Google Home to announce door events using Matter-compatible sensors such as the Aqara Door and Window Sensor P2. The example uses Google Home script automations to broadcast voice announcements and trigger mobile notifications whenever the entrance door changes state.

Requirements

  • A Matter-compatible door and window sensor.
  • A Google Speaker for announcements.
  • The Google Home application with the script editor enabled, accessible via the web interface at https://home.google.com/ .

Door Closed Announcement Script

The following script broadcasts a voice message and sends a notification when the door transitions to the closed state (sensor reports openPercent = 0):

metadata:
  name: Door closed announcement
  description: Announce when the door is closed
automations:
  - starters:
      - type: device.state.OpenClose
        device: Entrance door - Entryway
        state: openPercent
        is: 0
    actions:
      - type: assistant.command.Broadcast
        message: The door was closed

      - type: home.command.Notification
        title: The door was closed
        body: The door was closedCode language: YAML (yaml)

Note: Replace "Entrance door - Entryway" in the scripts with the actual name of the Matter-compatible door and window sensor as configured in Google Home. The device name must match exactly for the automations to work correctly.

When the door closes, the Google Assistant broadcasts “The door was closed” on all Google Home devices in the household, and a push notification with the same text is sent to connected mobile devices.

Door Open Announcement Script

The following script performs the same action when the door opens (sensor reports openPercent = 100):

metadata:
  name: Door open announcement
  description: Announce when the door is open
automations:
  - starters:
      - type: device.state.OpenClose
        device: Entrance door - Entryway
        state: openPercent
        is: 100
    actions:
      - type: assistant.command.Broadcast
        message: The door was opened

      - type: home.command.Notification
        title: The door was opened
        body: The door was openedCode language: YAML (yaml)

Note: Replace "Entrance door - Entryway" in the scripts with the actual name of the Matter-compatible door and window sensor as configured in Google Home. The device name must match exactly for the automations to work correctly.

In this case, Google Assistant announces “The door was opened” and the same message is sent as a push notification.

Conclusion

Combining a Matter-compatible door sensor with Google Home scripts provides real-time feedback whenever a door is opened or closed. It delivers both audible alerts throughout the home and push notifications to mobile devices, enhancing awareness and security.

ansible-role-auto-upgrade – An Ansible role that automates upgrading Linux operating systems

The ansible-role-auto-upgrade Ansible role automates regular upgrades of supported operating systems:

  • Debian-based systems (e.g., Ubuntu, Debian, Linux Mint). This role provides a simpler alternative to unattended-upgrades for applying system updates.

(In future versions, Arch Linux and Gentoo will also be supported.)

License

Copyright (c) 2025-2026 James Cherti.

Distributed under terms of the MIT license.

Do you like ansible-role-auto-upgrade?

Please star ansible-role-auto-upgrade on GitHub.

Links

ansible-role-reniced – An Ansible role that configures reniced on Debian and Ubuntu based operating systems

The ansible-role-reniced Ansible role configures reniced on Debian and Ubuntu based operating systems.

Customizations

When reniced_conf is defined, it is used as the configuration content.

Include the role using:

- name: Import role reniced
  when: ansible_facts.os_family == "Debian"
  ansible.builtin.import_role:
    name: reniced

Variables:

reniced_conf: |
  # high prio network services
  0 ^apache
  0 ^nfsd
  0 ^ntpd
  0 ^openvpn
  0 ^portmap
  0 ^ppp
  0 ^rpc.
  0 ^sshd

  # medium prio network services
  5 ^inn$
  5 ^mysqld

  # low prio network services
  15i ^amavisd-new
  15i ^clamd
  15 ^controlchan
  15 ^exim4
  15 ^freshclam
  15 ^innwatch
  12 ^mailman
  15 ^rc.news
  15i ^spamd

  # long running user processes (screen)
  3 ^irssi

  # test OOM settings
  o1 bash

Author and license

Copyright (C) 2024-2026 James Cherti.

Distributed under terms of the MIT license.

Links

ansible-role-apt – An Ansible role that manages the APT configuration and updates the /etc/apt/sources.list for Debian and Ubuntu systems

License

The ansible-role-apt Ansible role manages the APT configuration and updates the /etc/apt/sources.list for Debian and Ubuntu systems.

Role variables

Important variables:

Variable Description Default
apt_debian_community Enables community repositories (Debian contrib and main, or Ubuntu universe) true
apt_debian_nonfree Enables non-free repositories (Debian non-free, non-free-firmware, or Ubuntu multiverse) true
apt_debian_backports Enables the backports repository on Debian (no effect on Ubuntu systems) false
apt_deb_src Enables source package repositories (deb-src entries) false

Other variables:

Variable Description Default
apt_mirror_url_debian Debian mirror URL "http://deb.debian.org/debian"
apt_mirror_url_debian_security Debian security mirror URL "http://deb.debian.org/debian-security"
apt_mirror_url_ubuntu Ubuntu mirror URL "http://archive.ubuntu.com/ubuntu"

Author and license

The ansible-role-apt role has been written by James Cherti and is distributed under terms of the MIT license.

Copyright (C) 2000-2026 James Cherti

Distributed under terms of the MIT license.

Links

quick-sdcv.el, a package that enables Emacs to function as an offline dictionary using sdcv

Build Status MELPA MELPA Stable License

The quick-sdcv.el package provides a lightweight interface for the sdcv command-line tool, enabling Emacs to function as an offline dictionary.

This package allows for immediate word definitions and translations without requiring an internet connection.

Key interactive functions include:

  • quick-sdcv-search-at-point: Searches the word under the cursor and displays the result in a dedicated buffer.
  • quick-sdcv-search-input: Prompts for a custom input string and presents the corresponding dictionary entry in a buffer.

If this package enhances your workflow, please show your support by ⭐ starring quick-sdcv on GitHub to help more Emacs users discover its benefits.

Prerequisite

  • The sdcv command. (It can usually be installed by installing the sdcv package.)
  • Download dictionaries from: http://download.huzheng.org/ . Once the dictionaries are downloaded, extract them into /usr/share/stardict/dic/, or configure the variable quick-sdcv-dictionary-data-dir in the Emacs configuration to specify an alternative dictionary path.

Installation

To install quick-sdcv on Emacs from MELPA:

  1. If you haven’t already done so, add MELPA repository to your Emacs configuration.

  2. Add the following code at the very beginning of your init.el file, before all other packages:

(use-package quick-sdcv
  :init
  ;; When non-nil, a distinct buffer is created for each word searched.
  (setq quick-sdcv-unique-buffers t)

  ;; Change the prefix character used before dictionary names, replacing the
  ;; default `-->`:
  (setq quick-sdcv-dictionary-prefix-symbol "►")

  ;; Change the quick-sdcv dictionaries ellipsis from … to " ▼"
  ;; (In quick-sdcv buffers, `outline-minor-mode' is enabled by default, which
  ;; allows sections corresponding to individual dictionaries to be folded. The
  ;; ellipsis … indicates a folded section, making it easy to collapse all
  ;; dictionaries and expand only those of interest.)
  (setq quick-sdcv-ellipsis " ▼")

  ;; Automatically fold all dictionary entries when performing a search.
  ;; You can then unfold the dictionaries you want to read.
  (setq quick-sdcv-fold-on-search t))

Usage

To retrieve the word under the cursor and display its definition in a buffer:

(quick-sdcv-search-at-point)

To prompt the user for a word and display its definition in a buffer:

(quick-sdcv-search-input)

Customizations

To create a unique buffer for each word lookup, set the following:

;; Controls whether each word lookup creates a separate buffer.
;; Its default value is nil, but it can be set to t to enable unique buffers.
;;
;; When non-nil, a distinct buffer is created for each word searched. For
;; example, searching for the word "computer" produces a buffer named
;; "*sdcv:computer*". When nil, all lookups share the same buffer, typically
;; named "*sdcv*".
;;
;; The naming of unique buffers can be further customized using the variables:
;; - 'quick-sdcv-buffer-name-prefix'
;; - 'quick-sdcv-buffer-name-separator'
;; - 'quick-sdcv-buffer-name-suffix'
(setq quick-sdcv-unique-buffers t)

To perform exact word searches (as opposed to fuzzy searches), use:

;; To perform exact word searches (as opposed to fuzzy searches), use:
(setq quick-sdcv-exact-search t)

To change the prefix character used before dictionary names, replacing the default -->, set:

;; To change the prefix character used before dictionary names, replacing the
;; default `-->`, set:
(setq quick-sdcv-dictionary-prefix-symbol "►")

Customize the quick-sdcv dictionaries ellipsis display:

;; Customize the *quick-sdcv* dictionaries ellipsis display. In quick-sdcv
;; buffers, `outline-minor-mode' is enabled by default, which allows sections
;; corresponding to individual dictionaries to be folded. The ellipsis (…)
;; indicates a folded section, making it easy to collapse all dictionaries and
;; expand only those of interest
(setq quick-sdcv-ellipsis " ▼")

To automatically fold all dictionary entries when a search is performed:

;; Automatically fold all dictionary entries when a search is performed.
;; This is useful if you use many dictionaries and want to see a clean list
;; of dictionary names first.
(setq quick-sdcv-fold-on-search t)

To customize the sdcv history size:

;; Customize the sdcv history size
(setq quick-sdcv-hist-size 100)

To specify the path to the sdcv executable:

;; Specify the path to the sdcv executable:
(setq quick-sdcv-program "/path/to/sdcv")

To customize the naming convention of the SDCV buffer:

;; Customize the naming convention of the SDCV buffer:
(setq quick-sdcv-buffer-name-prefix "*sdcv"
      quick-sdcv-buffer-name-separator ":"
      quick-sdcv-buffer-name-suffix "*")

To specify a list of dictionaries (NOT RECOMMENDED. It is better to let sdcv show all dictionaries):

;; To specify a list of dictionaries (NOT RECOMMENDED. It is better to let sdcv
;; show all dictionaries):
(setq quick-sdcv-dictionary-complete-list '("stardict-WordNet"
                                            "stardict-Webster"
                                            "stardict-eng_eng_main"))

Frequently asked question

Why not dictd?

The primary advantage of sdcv is its direct compatibility with the StarDict format. Over the years, the StarDict ecosystem has accumulated a massive, easily accessible repository of freely distributed dictionaries (e.g, huzheng), including highly specialized, technical, and bilingual databases. Using StarDict dictionaries is easier and offers a richer selection of reference materials compared to finding or manually converting formats to support a native dictd setup.

How can dictionary entries be folded and unfolded?

The quick-sdcv mode enables outline-minor-mode by default, allowing sections corresponding to individual dictionaries to be folded.

To automatically collapse all dictionary entries upon search initialization, enable the following variable:

(setq quick-sdcv-fold-on-search t)

Since quick-sdcv inherits the standard outline keybindings, you should be able to toggle the visibility of a single dictionary section by placing your cursor on the header line and pressing TAB (which calls outline-toggle-children). If TAB is not working as expected, it is possible that another package in your configuration is shadowing that binding in the sdcv-mode buffer.

While the built-in outline-minor-mode functions can be used to open and close these folds, installing kirigami.el is highly recommended. It enhances the folding experience by providing a more robust and unified interface for folding text.

How to customize the buffer display?

By default, Emacs typically opens the *sdcv* results in a standard split window, occupying half of the frame. The placement and behavior of this buffer can be precisely controlled by customizing the display-buffer-alist variable.

Below are two common configurations to add to the Emacs initialization file:

Option 1: Display at the bottom with a fixed height

To create a less intrusive interface, Emacs can be configured to display the dictionary buffer at the bottom of the frame while maintaining the current window arrangement:

(add-to-list 'display-buffer-alist
             '("\\*sdcv"
               (display-buffer-reuse-window display-buffer-at-bottom)
               (window-height . 0.33)))

Option 2: Replace the current window entirely

Alternatively, to have the dictionary results fully replace the active window rather than creating a split, the following configuration applies:

(add-to-list 'display-buffer-alist '("\\*sdcv"
                                     (display-buffer-same-window)))

How to make links appear as links in an sdcv buffer?

To ensure that links appear as clickable links in the SDCV buffer while using quick-sdcv, add the following hook:

(add-hook 'quick-sdcv-mode-hook #'goto-address-mode)

Evil mode: How to configure the default K key to search for words using quick-sdcv?

In Evil-mode, the K key in normal mode typically triggers a help function. While viewing a word’s definition in a quick-sdcv buffer, pressing K in normal mode jumps to the definition of the word at point.

This behavior can be configured in other modes, allowing, for instance, the definition of a word to be displayed by pressing K while editing a Markdown or Org file.

For example, to configure K to search for a word using quick-sdcv when editing Markdown or Org files, use the following customization:

(dolist (mode-hook '(markdown-mode-hook org-mode-hook))
  (add-hook mode-hook
            (lambda ()
              (setq-local evil-lookup-func #'quick-sdcv-search-at-point))))

What is the difference between sdcv and quick-sdcv Emacs packages?

The quick-sdcv Emacs package is a fork of sdcv.el version 3.4, which is available on MELPA. The primary differences between the two packages are as follows:

  • Less dependencies: Quick-sdcv does not require any external dependencies; sdcv, on the other hand, installs popup, pos-tip, and showtip.
  • Customize the buffer name:: New variables to customize whether the word is included in the buffer name, as well as the prefix, separator, and suffix of the buffer name (quick-sdcv-unique-buffers, quick-sdcv-buffer-name-prefix, quick-sdcv-buffer-name-separator, and quick-sdcv-buffer-name-suffix). When the buffer is dedicated to a specific word, refresh it only when the buffer is created.
  • Improved Outline Minor Mode: The quick-sdcv package fixes the outline minor mode for dictionary folding, enabling users to collapse all definitions for quicker navigation through dictionaries.
  • Default Language Settings: Various issues have been addressed, including changing the default language setting from Chinese (zh) to nil, providing a more neutral starting point.
  • Buffer Customization: The quick-sdcv package employs display-buffer, allowing users to customize the display of the sdcv buffer and control its placement through display-buffer-alist.
  • Removal of bugs and Warnings: All Emacs warnings have been eliminated and bugs fixed. (e.g., when sdcv-search-at-point cannot locate the word under the cursor)
  • Code Simplification: The code has been simplified by removing unused variables and omitting features like posframe, text-to-speech using the ‘say’ command, the quick-sdcv-env-lang variable, and functions such as (quick-sdcv-scroll-up-one-line, quick-sdcv-scroll-down-one-line, quick-sdcv-next-line and quick-sdcv-prev-line) which are similar Emacs features. This simplification makes quick-sdcv easier to understand, maintain, and use by focusing solely on dictionary lookup functionality. Features like posframe and text-to-speech, which are not essential to core usage, are better suited as separate packages.
  • Keybindings removal: The default keybindings have been removed from quick-sdcv-mode to prevent conflicts with other modes and keeps the mode lightweight and adaptable for users’ preferences.
  • New options: quick-sdcv-fold-on-search, quick-sdcv-ellipsis, quick-sdcv-hist-size, quick-sdcv-exact-search, quick-sdcv-buffer-name-prefix, quick-sdcv-buffer-name-separator, quick-sdcv-buffer-name-suffix, quick-sdcv-verbose.
  • Various improvements: Unset the SDCV_PAGER environment variable, Ensure the buffer and the SDCV output are in UTF-8, Enhance dictionary representation with UTF-8 characters, Implement error handling for cases when the sdcv program is not found.

Community contribution: How I use quick-sdcv to get the Oxford English Dictionary entirely offline

Mingey, a quick-sdcv user, shared a workflow demonstrating how to integrate the massive Oxford English Dictionary (OED) directly into Emacs:

How I use quick-sdcv to get the Oxford English Dictionary (OED) in my Emacs

His workflow stack:

  • quick-sdcv: For instantaneous, offline dictionary queries. Mingey configured it to act like a native Emacs help buffer, allowing for ‘Do What I Mean’ (DWIM) searches that automatically look up the word under the cursor, display results in a collapsible outline, and cleanly restore the previous window layout when dismissed.
  • nov.el: For a in-editor EPUB reading experience. Binding a custom shortcut (K) directly to the dictionary tool within the reader creates an ergonomic workflow where the user can look up obscure words without ever breaking focus or leaving the book.
  • olivetti-mode: For distraction-free visual centering of the dense dictionary output.

Comments from users

  • ecraven on GitHub: Thank you very much for this mode, it is proving very helpful!

  • mingey on GitHub: “I don’t know if this is the appropriate place, but I wanted to thank you for writing this mode — I’ve been using Emacs about a year now, and it’s still constantly surprising me with its depth, and the richness of the added value the community brings. This package is a perfect example; I do a lot of reading in Emacs now, and with minimal configuration, I can be reading an epub and, with a keystroke, instantly get the OED article for a word I’m curious about…it’s one of those Emacs things that feels miraculous. I’m so grateful to you for taking the time to write the mode and for sharing it so generously; I hope (and expect) I’ll be using it with pleasure for years to come.”

Links

Related links:

  • How I use quick-sdcv to get the The Oxford English Dictionary entirely offline: Mingey, a quick-sdcv user, shares a workflow to get the Oxford English Dictionary entirely offline by combining quick-sdcv for rapid dictionary queries, nov.el for an EPUB reading experience, and olivetti-mode for distraction-free visual centering. This workflow transforms Emacs into a sophisticated research workstation where centuries of linguistic evolution are accessible at a single keystroke.

Other Emacs packages by the same author:

  • minimal-emacs.d: This repository hosts a minimal Emacs configuration designed to serve as a foundation for your vanilla Emacs setup and provide a solid base for an enhanced Emacs experience.
  • compile-angel.el: Speed up Emacs! This package guarantees that all .el files are both byte-compiled and native-compiled, which significantly speeds up Emacs.
  • outline-indent.el: An Emacs package that provides a minor mode that enables code folding and outlining based on indentation levels for various indentation-based text files, such as YAML, Python, and other indented text files.
  • vim-tab-bar.el: Make the Emacs tab-bar Look Like Vim’s Tab Bar.
  • easysession.el: Easysession is lightweight Emacs session manager that can persist and restore file editing buffers, indirect buffers/clones, Dired buffers, the tab-bar, and the Emacs frames (with or without the Emacs frames size, width, and height).
  • elispcomp: A command line tool that allows compiling Elisp code directly from the terminal or from a shell script. It facilitates the generation of optimized .elc (byte-compiled) and .eln (native-compiled) files.
  • tomorrow-night-deepblue-theme.el: The Tomorrow Night Deepblue Emacs theme is a beautiful deep blue variant of the Tomorrow Night theme, which is renowned for its elegant color palette that is pleasing to the eyes. It features a deep blue background color that creates a calming atmosphere. The theme is also a great choice for those who miss the blue themes that were trendy a few years ago.
  • Ultyas: A command-line tool designed to simplify the process of converting code snippets from UltiSnips to YASnippet format.
  • dir-config.el: Automatically find and evaluate .dir-config.el Elisp files to configure directory-specific settings.
  • flymake-bashate.el: A package that provides a Flymake backend for the bashate Bash script style checker.
  • flymake-ansible-lint.el: An Emacs package that offers a Flymake backend for ansible-lint.
  • inhibit-mouse.el: A package that disables mouse input in Emacs, offering a simpler and faster alternative to the disable-mouse package.
  • enhanced-evil-paredit.el: An Emacs package that prevents parenthesis imbalance when using evil-mode with paredit. It intercepts evil-mode commands such as delete, change, and paste, blocking their execution if they would break the parenthetical structure.
  • stripspace.el: Ensure Emacs Automatically removes trailing whitespace before saving a buffer, with an option to preserve the cursor column.
  • persist-text-scale.el: Ensure that all adjustments made with text-scale-increase and text-scale-decrease are persisted and restored across sessions.
  • pathaction.el: Execute the pathaction command-line tool from Emacs. The pathaction command-line tool enables the execution of specific commands on targeted files or directories. Its key advantage lies in its flexibility, allowing users to handle various types of files simply by passing the file or directory as an argument to the pathaction tool. The tool uses a .pathaction.yaml rule-set file to determine which command to execute. Additionally, Jinja2 templating can be employed in the rule-set file to further customize the commands.
  • kirigami.el: The kirigami Emacs package offers a unified interface for opening and closing folds across a diverse set of major and minor modes in Emacs, including outline-mode, outline-minor-mode, outline-indent-minor-mode, org-mode, markdown-mode, vdiff-mode, vdiff-3way-mode, hs-minor-mode, hide-ifdef-mode, origami-mode, yafolding-mode, folding-mode, and treesit-fold-mode. With Kirigami, folding key bindings only need to be configured once. After that, the same keys work consistently across all supported major and minor modes, providing a unified and predictable folding experience.
  • buffer-guardian.el: Automatically saves Emacs buffers without requiring manual intervention. By default, it triggers a save when the user switches to another buffer, switches to another window or frame, Emacs loses focus, or the minibuffer is opened. Beyond standard file buffers, buffer-guardian also manages specialized editing buffers such as org-src and edit-indirect. Additional features, disabled by default, include periodic or idle-time saving of all buffers, automatic exclusion of remote, nonexistent, or large files, and support for custom exclusion rules via regular expressions or predicate functions.

inhibit-mouse.el – Deactivate mouse input in Emacs (Alternative to disable-mouse)

Build Status MELPA MELPA Stable License

The inhibit-mouse package allows the disabling of mouse input in Emacs using inhibit-mouse-mode.

Instead of modifying the keymap of its own mode as the disable-mouse package does, enabling inhibit-mouse-mode only modifies input-decode-map to disable mouse events, making it more efficient and faster than disable-mouse.

Additionally, the inhibit-mouse package allows for the restoration of mouse input when inhibit-mouse-mode is disabled.

If this enhances your workflow, please show your support by ⭐ starring inhibit-mouse on GitHub to help more Emacs users discover its benefits.

Installation

To install inhibit-mouse from MELPA:

  1. If you haven’t already done so, add MELPA repository to your Emacs configuration.
  2. Add the following code to the Emacs init file:
(use-package inhibit-mouse
  :custom
  ;; Disable highlighting of clickable text such as URLs and hyperlinks when
  ;; hovered by the mouse pointer.
  (inhibit-mouse-adjust-mouse-highlight t)

  ;; Disables the use of tooltips (show-help-function) during mouse events.
  (inhibit-mouse-adjust-show-help-function t)

  :init
  (if (daemonp)
      (add-hook 'server-after-make-frame-hook #'inhibit-mouse-mode)
    (inhibit-mouse-mode 1)))

Customization

Customizing the mouse buttons disabled by inhibit-mouse?

The inhibit-mouse custom variables allow you to fine-tune which mouse interactions are disabled.

You can use the following configuration to specify which mouse buttons and events you want to disable:

;; This variable specifies which mouse buttons should be inhibited from
;; triggering events.
(setq inhibit-mouse-button-numbers '(1 2 3 4 5))

;; List of mouse button events to be inhibited.
(setq inhibit-mouse-button-events '("mouse"
                                    "up-mouse"
                                    "down-mouse"
                                    "drag-mouse"))

;; List of miscellaneous mouse events to be inhibited.
(setq inhibit-mouse-misc-events '("wheel-up"
                                  "wheel-down"
                                  "wheel-left"
                                  "wheel-right"
                                  "pinch"))

;; List of mouse multiplier events to be inhibited.
(setq inhibit-mouse-multipliers '("double" "triple"))

;; List of key modifier combinations to be inhibited for mouse events.
(setq inhibit-mouse-key-modifiers '((control)
                                    (meta)
                                    (shift)
                                    (control meta shift)
                                    (control meta)
                                    (control shift)
                                    (meta shift)))

Allowing mouse in specific major modes

To allow mouse input in specific major modes (e.g., when viewing a PDF document or an image), add those modes to the inhibit-mouse-excluded-modes list.

When the mouse pointer hovers over a window containing a buffer that matches any mode in this list, mouse events will pass through completely unmodified. This allows clicking links inside a PDF or navigating an image without needing to turn off the global mode.

(setq inhibit-mouse-excluded-modes '(pdf-view-mode image-mode))

Enabling/Disabling the context menu

To enable or disable the context menu based on the state of inhibit-mouse-mode, the following code dynamically toggles context-menu-mode accordingly:

(add-hook 'inhibit-mouse-mode-hook
          #'(lambda()
              ;; Enable or disable the context menu based on the state of
              ;; `inhibit-mouse-mode', the following code dynamically toggles
              ;; `context-menu-mode' accordingly.
              (when (fboundp 'context-menu-mode)
                (if (bound-and-true-p inhibit-mouse-mode)
                    (context-menu-mode -1)
                  (context-menu-mode 1)))))

This ensures that the context menu is disabled when inhibit-mouse-mode is active and enabled when it is inactive.

Enabling/Disabling tooltip-mode

When tooltip-mode is enabled, Emacs displays certain UI hints (e.g., help text and mouse-hover messages) as popup windows near the cursor, instead of in the echo area. This behavior is useful in graphical Emacs sessions.

To toggle tooltip-mode dynamically based on the state of inhibit-mouse-mode, you can use the following hook:

(add-hook 'inhibit-mouse-mode-hook
          #'(lambda()
              ;; Enable or disable `tooltip-mode'. When tooltip-mode is
              ;; enabled, certain UI elements (e.g., help text, mouse-hover
              ;; hints) will appear as native system tooltips (pop-up
              ;; windows), rather than as echo area messages. This is useful
              ;; in graphical Emacs sessions where tooltips can appear near
              ;; the cursor.
              (when (fboundp 'tooltip-mode)
                (if (bound-and-true-p inhibit-mouse-mode)
                    (tooltip-mode -1)
                  (tooltip-mode 1)))))

Enabling/disabling pixel scroll precision mode

The following configuration toggles pixel-scroll-precision-mode based on the state of inhibit-mouse-mode, excluding macOS Carbon environments where pixel scrolling is natively supported and does not require explicit activation.

(add-hook 'inhibit-mouse-mode-hook
          #'(lambda()
              (unless (and
                       ;; Exclude macOS Carbon environments where pixel
                       ;; scrolling is natively supported and does not
                       ;; require explicit activation.
                       (eq window-system 'mac)
                       (bound-and-true-p mac-carbon-version-string))
                (when (fboundp 'pixel-scroll-precision-mode)
                  (if (bound-and-true-p inhibit-mouse-mode)
                      (pixel-scroll-precision-mode -1)
                    (pixel-scroll-precision-mode 1))))))

Frequently Asked Question

What motivates the author to disable the mouse in Emacs?

The author disables the mouse in Emacs:

  • To prevent accidental clicks or cursor movements that can change the cursor position unexpectedly.
  • To reinforce a keyboard-centric workflow, helping to avoid the habit of relying on the mouse for navigation.

Some may suggest that the author could modify the touchpad settings at the OS level. However, he prefers not to disable the touchpad entirely, as it remains useful in other applications, such as web browsers.

Is it not enough to simply avoid touching the mouse?

It is not always as simple as just deciding not to touch the mouse. When transitioning to a fully keyboard-driven workflow, existing habits can be surprisingly persistent.

In the author’s case, he often found himself unconsciously reaching for the mouse, even though they had deliberately chosen to keep his hands on the home row. The home row, the middle row of keys on a standard keyboard layout, is where the fingers rest in the touch typing method. Keeping the hands on the home row minimizes unnecessary hand movement, preserves typing rhythm, and allows immediate access to the majority of keys. In contrast, reaching for the mouse interrupts the workflow, introduces delays, and shifts focus away from the keyboard, reducing overall efficiency.

The inhibit-mouse Emacs package provided a practical solution. By disabling mouse input entirely, it removed the possibility of falling back on that habit. Over time, this enforced constraint trained the author to rely exclusively on the keyboard.

This package acted as a form of behavioral reinforcement for the author: each attempt to use the mouse proved unproductive, gradually reshaping habits until the keyboard-driven workflow became natural and automatic.

What is the difference between the disable-mouse and inhibit-mouse packages?

The inhibit-mouse package is a efficient alternative to the disable-mouse package, as it only modifies input-decode-map to disable mouse events.

In contrast, disable-mouse applies mouse events to its own mode, and sometimes the user has to apply it to other modes that are not affected by the disable-mouse mode using the disable-mouse-in-keymap function (e.g, evil-mode, tab-bar…).

Additionally, inhibit-mouse:

  • Allows re-enabling mouse functionality when the mode is disabled, which is not supported by disable-mouse when the disable-mouse-in-keymap function is used. The disable-mouse-in-keymap function overwrites the key mappings of other modes (e.g., evil, tab-bar), and there is no straightforward way to make disable-mouse restore them.
  • It resolves issues that disable-mouse does not, such as the “C-c C-x is not bound” problem, where the user intended to enter C-c C-x j but accidentally touched the touchpad.

This concept of using input-decode-map to disable the mouse was introduced by Stefan Monnier in an emacs-devel mailing list thread initiated by Daniel Radetsky, who proposed a patch to the Emacs developers. Additionally, here is an interesting discussion on GitHub: Add recipe for inhibit-mouse.

Author and License

The inhibit-mouse Emacs package has been written by James Cherti and is distributed under terms of the GNU General Public License version 3, or, at your choice, any later version.

Copyright (C) 2024-2026 James Cherti

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program.

Links

Other Emacs packages by the same author:

  • minimal-emacs.d: This repository hosts a minimal Emacs configuration designed to serve as a foundation for your vanilla Emacs setup and provide a solid base for an enhanced Emacs experience.
  • compile-angel.el: Speed up Emacs! This package guarantees that all .el files are both byte-compiled and native-compiled, which significantly speeds up Emacs.
  • outline-indent.el: An Emacs package that provides a minor mode that enables code folding and outlining based on indentation levels for various indentation-based text files, such as YAML, Python, and other indented text files.
  • vim-tab-bar.el: Make the Emacs tab-bar Look Like Vim’s Tab Bar.
  • easysession.el: Easysession is lightweight Emacs session manager that can persist and restore file editing buffers, indirect buffers/clones, Dired buffers, the tab-bar, and the Emacs frames (with or without the Emacs frames size, width, and height).
  • elispcomp: A command line tool that allows compiling Elisp code directly from the terminal or from a shell script. It facilitates the generation of optimized .elc (byte-compiled) and .eln (native-compiled) files.
  • tomorrow-night-deepblue-theme.el: The Tomorrow Night Deepblue Emacs theme is a beautiful deep blue variant of the Tomorrow Night theme, which is renowned for its elegant color palette that is pleasing to the eyes. It features a deep blue background color that creates a calming atmosphere. The theme is also a great choice for those who miss the blue themes that were trendy a few years ago.
  • Ultyas: A command-line tool designed to simplify the process of converting code snippets from UltiSnips to YASnippet format.
  • dir-config.el: Automatically find and evaluate .dir-config.el Elisp files to configure directory-specific settings.
  • flymake-bashate.el: A package that provides a Flymake backend for the bashate Bash script style checker.
  • flymake-ansible-lint.el: An Emacs package that offers a Flymake backend for ansible-lint.
  • quick-sdcv.el: This package enables Emacs to function as an offline dictionary by using the sdcv command-line tool directly within Emacs.
  • enhanced-evil-paredit.el: An Emacs package that prevents parenthesis imbalance when using evil-mode with paredit. It intercepts evil-mode commands such as delete, change, and paste, blocking their execution if they would break the parenthetical structure.
  • stripspace.el: Ensure Emacs Automatically removes trailing whitespace before saving a buffer, with an option to preserve the cursor column.
  • persist-text-scale.el: Ensure that all adjustments made with text-scale-increase and text-scale-decrease are persisted and restored across sessions.
  • pathaction.el: Execute the pathaction command-line tool from Emacs. The pathaction command-line tool enables the execution of specific commands on targeted files or directories. Its key advantage lies in its flexibility, allowing users to handle various types of files simply by passing the file or directory as an argument to the pathaction tool. The tool uses a .pathaction.yaml rule-set file to determine which command to execute. Additionally, Jinja2 templating can be employed in the rule-set file to further customize the commands.
  • kirigami.el: The kirigami Emacs package offers a unified interface for opening and closing folds across a diverse set of major and minor modes in Emacs, including outline-mode, outline-minor-mode, outline-indent-minor-mode, org-mode, markdown-mode, vdiff-mode, vdiff-3way-mode, hs-minor-mode, hide-ifdef-mode, origami-mode, yafolding-mode, folding-mode, and treesit-fold-mode. With Kirigami, folding key bindings only need to be configured once. After that, the same keys work consistently across all supported major and minor modes, providing a unified and predictable folding experience.
  • buffer-guardian.el: Automatically saves Emacs buffers without requiring manual intervention. By default, it triggers a save when the user switches to another buffer, switches to another window or frame, Emacs loses focus, or the minibuffer is opened. Beyond standard file buffers, buffer-guardian also manages specialized editing buffers such as org-src and edit-indirect. Additional features, disabled by default, include periodic or idle-time saving of all buffers, automatic exclusion of remote, nonexistent, or large files, and support for custom exclusion rules via regular expressions or predicate functions.

The Importance of Backups: Why Failing to Create or Test Them Leads to Regret

Data loss is an inevitable reality in the digital age. It is not a matter of “if,” but “when.” Whether you’re managing critical infrastructure for a large enterprise or simply storing personal documents, photos, and legal files on your own computer, the risk of data loss is ever-present. Despite this, many people and organizations fail to prioritize backups until it is too late.

Throughout my career as an IT specialist, I have witnessed this problem repeatedly. The pattern is always the same: individuals and companies lose data, panic ensues, and attempts are made to recover what could have been easily protected with minimal cost and effort.

Data loss

On a daily basis, I encounter numerous instances of data loss across various sectors. Companies pay for bare-metal servers or cloud compute instances to run their production workloads, but when these systems crash, experience filesystem corruption, or are compromised by security breaches, the response is typically one of outrage. Support tickets are submitted with complaints that their data is lost, with no backups, no snapshots, and no contingency plan in place.

This issue is not exclusive to large enterprises. Consider personal devices. How many individuals store years of important tax records, legal documents, irreplaceable family photos, or critical work files on their laptops, with no backup strategy whatsoever? Hardware failure, malware attacks, accidental deletion, theft, and simple human error can result in irreversible data loss in an instant.

Some of the cases I handled…

The cases I handled professionally can be truly staggering. For example, I worked with a client paying tens of thousands of dollars per month for a bare-metal server to host highly sensitive data, yet they had no backup strategy in place. When hardware failure inevitably occurred, the result was outrage, threats of legal action, and attempts to assign blame. Unfortunately, without a backup policy, disaster recovery plan, and monitoring system in place, these situations are often beyond repair.

In this particular instance, I worked closely with the client to establish a comprehensive backup procedure. This involved selecting an appropriate backup solution adapted to their infrastructure, setting up regular backups, and ensuring the backups were stored securely and off-site. Additionally, we implemented a monitoring system to alert the client to any potential issues before they became critical. The result is now a much more resilient system, where data loss is no longer a risk, and the client has a clear disaster recovery plan in place.

To make matters worse, I’ve witnessed scenarios where the financial cost of data loss has reached tens of thousands of dollars per day. This is not a matter of insufficient resources. It’s a matter of misplaced priorities and negligence. For a fraction of the cost of their monthly expenses, these individuals and organizations could have secured a robust backup solution that would have prevented the catastrophe.

The reality is simple: backups are inexpensive. Data loss, on the other hand, is costly, stressful, and often irreversible. The barriers to implementing reliable, automated backup solutions today are negligible. Whether you choose cloud storage, external drives, remote servers, the tools are readily available, and there is no excuse for neglecting to protect your data.

Restores have to be tested

It is a common misconception that having a backup in place means data is secure, simply because a tool reports, “Your backups were successful.” However, the true test of a backup’s reliability occurs when it is needed most, during a restore attempt. This is when many realize that despite the “successful” alert, the backup may be incomplete, corrupted, or otherwise unusable.

It is concerning that many individuals in technical roles lack the necessary expertise to properly set up and manage infrastructure within an organization. While foundational knowledge is readily available through online resources, there is a tendency for some to set up systems with minimal effort, a few clicks, and the system is presumed to be functioning. However, the true measure of proficiency in IT infrastructure lies not in the ability to configure a system, but in the ability to resolve issues when things inevitably fail.

Conclusion

If you are reading this, I encourage you to take a moment to assess your backup strategy. If you do not have one, create one today. If you already have a backup system in place, ensure that it is functioning correctly. Whether you are managing a business with critical client data or simply safeguarding personal files on your laptop, the importance of backups cannot be overstated.

Feel free to share your own experiences with data loss, lessons learned, or helpful backup solutions in the comments.

Pathaction, a universal Makefile for your entire filesystem: Run rule-driven commands on any file or directory

License: GPL v3

The pathaction tool is a flexible command-line utility for running commands on files and directories. Pass a file path as an argument, and the tool handles the rest, whether you are working with code, media, or configurations.

Think of pathaction like a Makefile for any file or directory in the filesystem. It uses a .pathaction.yaml file to determine which command to run, and you can use Jinja2 templating to make those commands dynamic. You can also use tags to define multiple actions for the exact same file type. For example, you can set up one tag to run a script, another to debug it, and a third to run a linter.

This tool is built for software engineers who manage multiple projects across diverse environments. It eliminates the cognitive load of switching between different build tools, environment configurations, and deployment methods. Run a single unified command on any file and trust that it gets handled correctly.

If this tool helps your workflow, please show your support by ⭐ starring pathaction on GitHub and sharing it on your website, blog, Mastodon, Reddit, X, LinkedIn, or other social media platforms to help more Git users discover its benefits.

Example

You can execute a file with the following commands:

pathaction -t main file.py

Or:

pathaction -t edit another-file.jpg

The -t option specifies the tag, allowing you to apply a tagged rule.

Here is an example of what a .pathaction.yaml rule-set file looks like:

---
actions:
  - path_match: "*.py"
    tags: main
    command:
      - "python"
      - "{{ file }}"

  - path_match: "*.jpg"
    tags:
      - edit
      - show
    command: "gimp {{ file|quote }}"

There are many ways to match paths, including using regular expressions and MIME types. See below for more details.

Editor Plugins

Installation

Here is how to install pathaction using pip:

pip install --user pathaction

The pip command above will install the pathaction executable in the directory ~/.local/bin/.

(Python requirements: jinja2, schema, PyYAML.)

Optional Dependencies

The pathaction CLI offers optional dependencies that extend its functionality. These extras can be installed according to environment requirements.

  • Colored Terminal Output (colors): Installs colorama to provide consistent cross-platform ANSI color support. This enhances the readability of standard output and error messages.

    pip install "pathaction[colors]"
  • Custom Process Title (proctitle): Installs setproctitle to rename the running process from python to pathaction. This simplifies identification in system monitoring tools such as top, htop, and ps.

    pip install "pathaction[proctitle]"

To install both extras at once, use a comma-separated list:

pip install "pathaction[colors,proctitle]"

Getting Started

1. Authorize your working directory

By default, pathaction does not read rule-set files from arbitrary directories for security reasons. The allowed directories must be explicitly permitted. To allow pathaction to load rules from your projects folder and its subdirectories, run:

pathaction --allow-dir ~/projects

2. Create a rule-set file

Navigate to your project root and create a .pathaction.yaml file (e.g., ~/projects/my-app/.pathaction.yaml). Here is a basic example to run Python files:

---
actions:
  - path_match: "*.py"
    tags: main
    command:
      - "python"
      - "{{ file }}"

3. Execute the file

Now, instead of manually invoking the Python interpreter, you can pass the file directly to pathaction. It will read the rule, match the .py extension, and execute the command.

pathaction ~/projects/my-app/dir1/dir2/file.py

Because the default tag is main, pathaction automatically targets the block we just defined.

You can also specify the tag:

pathaction -t main ~/projects/my-app/dir1/dir2/file.py

Comprehensive Examples

The real value of pathaction comes from defining complex, multi-tag workflows across different file types. Here are detailed examples of how to configure .pathaction.yaml for various scenarios.

Example 1: Full Python and Bash Workflow

Instead of memorizing different tools and their command-line arguments, you can define them as actions.

---
actions:
  # Execute the Python script
  - path_match: "*.py"
    tags: main
    command:
      - "python"
      - "{{ file }}"

  # Run tests
  - path_match: "*.py"
    tags: test
    command: "pytest -v {{ file|quote }}"

  # Type checking
  - path_match: "*.py"
    tags: typecheck
    command: "mypy {{ file|quote }}"

  # Execute Bash shell scripts
  - path_match: "*.sh"
    tags:
      - main
    command: "bash {{ file|quote }}"

You can invoke these specific actions by passing the -t (tag) flag:

pathaction -t typecheck src/utils.py
pathaction -t test src/test_utils.py

Example 2: Managing Infrastructure with Ansible

You can set up rules to apply Ansible playbooks directly.

---
actions:
  - path_match: "*playbook.yml"
    tags: main
    command: "ansible-playbook -i inventory.ini {{ file|quote }}"

Example 3: C/C++ Compilation and Execution

You can use pathaction to compile files on the fly and put the output binary in the correct directory.

---
actions:
  # Compile C++ source code
  - path_match: "*.cpp"
    tags: build
    cwd: "{{ file|dirname }}"
    command: "g++ -Wall -O2 {{ file|quote }} -o {{ file|basename|replace('.cpp', '') }}"

  # Run the compiled binary
  - path_match: "*.cpp"
    tags: run
    cwd: "{{ file|dirname }}"
    command: "./{{ file|basename|replace('.cpp', '') }}"

Command-Line Arguments

The pathaction utility accepts several arguments to control execution behavior:

  • -t, --tag: Execute the action associated with this tag (default is main).
  • -b, --confirm-before: Prompt for confirmation before executing the defined action.
  • -a, --confirm-after: Ask the user if they want to execute the action again after it finishes (respects the confirm_after_timeout configuration).
  • -l, --list: List all the .pathaction.yaml configuration files that apply to the given file path. Useful for debugging rule resolution.
  • -d, --allow-dir: Permanently allow pathaction to execute rules from the provided directory and its subdirectories.
  • --disallow-dir: Revoke access and remove a specific directory from your allowed list.
  • --list-allowed-dirs: Print a list of all permanently allowed directories.

Configuration Guide (.pathaction.yaml)

The rule-sets cascade hierarchically. When you execute a file, pathaction looks for .pathaction.yaml in the file’s current directory, and then walks up the filesystem tree (parent directories) to find and merge all other .pathaction.yaml files. This loading behavior is similar to that of a .gitignore file. In case of conflicting rules or configurations, priority is given to the rule set that is located in the directory closest to the specified file.

Each rule defined in the rule-set file must include at least the matching rule and the command.

Match Methods

You can target files using various matching strategies. Every match method also has a corresponding _exclude variant (e.g., path_match_exclude) to explicitly ignore files that would otherwise match.

  • path_match: Standard glob pattern matching (e.g., *.py).
  • path_match_case: Case-sensitive glob pattern matching.
  • path_regex: Regular expression path matching (case-insensitive by default).
  • path_regex_case: Case-sensitive regular expression matching.
  • mimetype: Strict MIME type matching (e.g., text/x-python).
  • mimetype_match: Glob pattern matching for MIME types (e.g., text/*).
  • mimetype_regex: Regular expression matching for MIME types.

Action Configuration

An action block can include the following optional attributes:

  • tags: A string or list of strings indicating the tag names.
  • comment: An informative string describing what the action does.
  • timeout: An integer specifying the maximum execution time in seconds.
  • cwd: The current working directory for the command.
  • stdout: Redirect the standard output of the command to the specified file path.
  • stderr: Redirect the standard error of the command to the specified file path. (If both stdout and stderr point to the exact same file path, they are combined).
  • shell: Boolean indicating if the command should be executed within a shell environment.
  • command / list_commands: The command string/array to execute. These two are mutually exclusive.

Global Options

You can define an options block at the root of your .pathaction.yaml to specify execution defaults:

  • shell_path: The absolute path to the shell executable used when shell: true (defaults to the user’s login shell).
  • verbose: Enable verbose logging.
  • debug: Enable debug mode.
  • timeout: A global timeout constraint in seconds.
  • confirm_after_timeout: The timeout in seconds when waiting for user input during a --confirm-after prompt.
  • last: If set to true, pathaction stops loading configurations from higher parent directories.

Jinja2 Variables and Filters

Jinja2 Variables

Variable Description
{{ file }} Replaced with the full absolute path to the targeted file.
{{ cwd }} Refers to the current working directory of the matched action.
{{ env }} Represents the operating system environment variables (dictionary).
{{ pathsep }} Denotes the path separator (e.g., / on Linux, \ on Windows).

Jinja2 Filters

  • quote: Escapes a string for use as a shell argument by wrapping it in single quotes and escaping internal single quotes. This prevents shell injection vulnerabilities. Example: "/home/user/my file.txt" | quote evaluates to '/home/user/my file.txt'.
  • basename: Extracts the trailing filename or leaf component of a filesystem path. Example: "/home/user/src/main.py" | basename evaluates to "main.py".
  • dirname: Returns the parent directory portion of a filesystem path. Example: "/home/user/src/main.py" | dirname evaluates to "/home/user/src".
  • file_only_dirname: Returns the parent directory if the path is a file, or returns the path itself if it is already a directory.
  • realpath: Resolves all symbolic links, relative segments (like ..), and duplicate separators to return the canonical absolute path. Example: "/usr/bin/../local/bin/python" | realpath evaluates to "/usr/local/bin/python".
  • abspath: Converts a relative path into an absolute path by prefixing it with the current working directory. Example: "src/main.py" | abspath evaluates to "/home/user/project/src/main.py".
  • relpath: Computes the relative path between two directories.
  • joinpath: Combines one or more path segments using the system filesystem separator. Example: "/var/log" | joinpath("nginx", "error.log") evaluates to "/var/log/nginx/error.log".
  • joincmd: Converts an array of command-line tokens into a single properly escaped shell command string. Example: ["grep", "-i", "error log"] | joincmd evaluates to 'grep -i "error log"'.
  • splitcmd: Parses a raw shell command string into an array of distinct arguments while honoring quotation rules and escape sequences. Example: "git commit -m 'initial release'" | splitcmd evaluates to ["git", "commit", "-m", "initial release"].
  • expanduser: Replaces a leading tilde notation (~ or ~user) with the absolute path of the corresponding user home directory. Example: "~/config/tmux.conf" | expanduser evaluates to "/home/user/config/tmux.conf".
  • expandvars: Substitutes environment variables within a string matching $VARIABLE or ${VARIABLE} with their current active system values. Example: "$HOME/.config" | expandvars evaluates to "/home/user/.config".
  • shebang: Inspects a file and extracts the first line directly if it begins with an executable script prefix (#!). Example: "/home/user/script.sh" | shebang evaluates to "#!/usr/bin/env bash".
  • shebang_list: Extracts the shebang line from a file, discards the initial #! marker, and parses the remaining contents into a clean token array. Example: "/home/user/script.sh" | shebang_list evaluates to ["/usr/bin/env", "bash"].
  • shebang_quote: Extracts the shebang line from a file, strips the #! marker, and returns the runtime interpreter directive as a safely balanced, shell-quoted string. Example: "/home/user/script.sh" | shebang_quote evaluates to "/usr/bin/env bash".
  • which: Searches the system environment variable PATH to locate the absolute path of an executable binary. Raises an error if the binary cannot be found. Example: "emacs" | which evaluates to "/usr/bin/emacs".
  • startswith: Evaluates to true if the string starts with the given prefix.
  • endswith: Evaluates to true if the string ends with the given suffix.

Frequently Asked Questions

Does pathaction walk the filesystem from the current directory to the top in search of .pathaction.yaml ruleset files?

Pathaction walks from the directory containing the file passed to it and merges .pathaction.yaml rules from all allowed parent directories.

There is a security measure by default: loading rules is allowed only in directories that have been explicitly permitted using pathaction --allow-dir ~/dir/projects/, which enables access to ~/dir/projects/ and all its subdirectories. If the entire home directory is allowed with pathaction --allow-dir ~/, rules can be loaded from any directory within the home directory.

What are the differences between make and pathaction?

The make tool centers on targets and dependency tracking, making it good for compiling software based on file timestamps. In contrast, the pathaction tool acts as a universal file execution router. Passing a file path directly to Pathaction determines the correct command to run based on defined file extensions or patterns.

While make relies on project-specific files with strict syntax, Pathaction uses YAML files that cascade hierarchically across your filesystem. Much like how Git handles ignore files, Pathaction loads and merges all .pathaction.yaml rule-set files found in parent directories. This allows you to define rules in your home directory that can be overridden by specific settings within individual project folders.

For example, a Python script in ~/project_a can be routed to a local virtual environment, while a Python script in ~/project_a/project_b can trigger a Docker execution simply by defining different .pathaction.yaml files in those directories. Pathaction loads and merges all .pathaction.yaml ruleset files found in parent directories. This means that any rule in ~/project_a/project_b/.pathaction.yaml that does not match a file falls back to the rules defined in ~/project_a/.pathaction.yaml, similar to how Git handles .gitignore files.

What is the difference between Pathaction and a command such as find | xargs?

It is very different from find | xargs. The pathaction tool functions like a customizable, developer-focused xdg-open. It acts as the intelligent router that receives each file path and automatically determines the correct command to execute based on your defined rules. Just as xdg-open relies on rigid system MIME types to launch GUI applications, Pathaction uses your hierarchical .pathaction.yaml configurations and Jinja2 templating to dynamically run commands.

How is pathaction different from a shebang?

Shebangs are fine for basic execution, but they have limitations that Pathaction was built to address.

A shebang only defines how to execute a script. It cannot tell your system how to lint, format, debug, or test files. With pathaction, you can use tags. Passing pathaction -t main file.py executes it, while passing pathaction -t test file.py can run it through pytest.

How is pathaction different from xdg-open?

File associations such as xdg-open apply globally. Pathaction uses cascading YAML files similar to how Git handles .gitignore files. A Python script in ~/project_a can be routed to a local virtual environment, while a Python script in ~/project_a/project_b can trigger a Docker execution simply by defining different .pathaction.yaml files in those directories. Pathaction loads and merges all .pathaction.yaml ruleset files found in parent directories. This means that any rule in ~/project_a/project_b/.pathaction.yaml that does not match a file falls back to the rules defined in ~/project_a/.pathaction.yaml.

In addition to that, Pathaction uses Jinja2 templating, allowing you to dynamically build complex shell commands based on the file name, its parent directory, or environment variables.

How does the author use pathaction?

The author’s .pathaction.yaml rules function as a universal bridge across distinct software environments.

  • For Python, Bash, C, C++, and related languages, rules are defined to install dependencies, build projects, execute binaries, run test suites, and launch debuggers.
  • For Ansible, rules automatically upload playbooks to remote servers, execute them, and validate their results.
  • For Emacs, rules integrate file-based actions directly with editor workflows, enabling evaluation, compilation, or linting based on context.
  • For Vim, rules provide similar editor integration, allowing files to trigger build, run, or formatting actions without manual command construction.

Pathaction operates as an IDE-like action layer for the filesystem. Instead of embedding logic inside each editor or build system, actions are described declaratively and applied uniformly across tools.

The primary advantage is cognitive simplicity. There is no need to memorize complex command-line flags or tool-specific invocation patterns. A file is passed to Pathaction with a semantic tag such as main, install, or debug, and the corresponding rule determines how the operation is executed.

License

Copyright (c) 2021-2026 James Cherti

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see https://www.gnu.org/licenses/.

Links

Plugins for editors:

  • pathaction.el (Emacs package): Executing the pathaction command-line tool directly from Emacs.
  • vim-pathaction (Vim plugin): Executing the pathaction command-line tool directly from Vim.

bash-stdops – A collection of Bash helper scripts that facilitate operations

License

The bash-stdops project is a collection of helpful Bash scripts, written by James Cherti, that simplify various operations, including file searching, text replacement, and content modification.

The author uses these scripts in conjunction with text editors like Emacs and Vim to automate tasks, including managing Tmux sessions, replacing text across a Git repository, securely copying and pasting from the clipboard by prompting the user before executing commands in Tmux, fix permissions, among other operations.

Install bash-stdops scripts

System-wide installation

To install bash-stdops scripts system-wide, use the following command:

git clone https://github.com/jamescherti/bash-stdops
cd bash-stdops

sudo ./make.sh install

Alternative installation: Install in your home directory

If you prefer to install the scripts locally in your home directory, you can use the ~/.local/bin directory. This method avoids requiring administrative privileges and keeps the installation isolated to your user environment.

Use the following command to install the scripts into the ~/.local/bin directory:

PREFIX=~/.local ./make.sh install

Ensure that ~/.local/bin is included in your $PATH by adding the following line to your ~/.bashrc:

export PATH=$PATH:~/.local/bin

Install dependencies

Instructions for installing dependencies are provided below. Note that not all of these dependencies are mandatory for every script.

Install dependencies on Debian/Ubuntu based systems

# Requirements
sudo apt-get install coreutils parallel ripgrep sed

# Git
sudo apt-get install git

# SSH
sudo apt-get install openssh-client

# Clipboard
sudo apt-get install xclip

Install dependencies on RedHat/CentOS/Fedora based systems

# Requirements
sudo dnf install coreutils parallel ripgrep sed git openssh-clients

# Git
sudo dnf install git

# SSH
sudo dnf install openssh-clients

# Clipboard
sudo dnf install xclip

Install dependencies on Gentoo based systems

# Requirements
sudo emerge sys-apps/coreutils sys-process/parallel sys-apps/ripgrep sys-apps/sed

# Git
sudo emerge dev-vcs/git

# SSH
sudo emerge net-misc/openssh

# Clipboard
sudo emerge x11-misc/xclip

Install dependencies on Arch Linux based systems

# Requirements
sudo pacman -S coreutils parallel ripgrep sed

# Git
sudo pacman -S git

# SSH
sudo pacman -S openssh

# Clipboard
sudo pacman -S xclip

Scripts

Script category: tmux

Script: tmux-cbpaste

The tmux-cbpaste: script enables pasting clipboard content into the current tmux window. It ensures safety by requiring user confirmation before pasting, preventing accidental insertion of data.

Script: tmux-run

This script executes a command in a new tmux window, which functions similarly to a tab in other applications.

  • If run within an existing tmux session, it creates a new window in the same session.
  • If run outside of tmux, it creates a new window in the first available tmux session.
  • If the environment variable TMUX_RUN_SESSION_NAME is set, the script will create the new window in the specified tmux session.

Usage:

  tmux-run <command> [args...]

Example:

tmux-run bash

Example 2:

tmux-run bash -c htop

Script: tmux-session

The tmux-session script attempts to attach to an existing tmux session. If the session does not exist, it creates a new session with that name.

If no session name is provided, it defaults to creating or attaching to a session named “0”.

Script category: files, paths, and strings

Script: walk

The walk bash script recursively search the specified directory and print the list of file or directory paths to standard output.

Script: walk-run

Recursively execute a command on all files listed by the rg --files command. For example, to recursively cat all text files in /etc, use the following command:

walk-run /etc cat {}

({} is replaced with the path to each file.)

Here is an example of how you can combine walk-run and sed to replace “Text1” with “Text2” in a Git repository:

walk-run /path/to/git-repository/ sed -i -e "s/Text1/Text2/g" {}

Script: sre

The sre script replaces occurrences of a specified string or regular expression pattern with support for exact string matching, regular expressions, and case-insensitive matching. Unlike sed, which uses a single argument for replacements, this script allows specifying the text-to-find and text-to-replace as two distinct arguments.

To replace text in the standard input and output the result to the standard output:

echo "text-before" | sre "text-before" "text-after"

To replace text directly in a file (overwriting the file):

sre "text-before" "text-after" file

Here are the sre options:

Usage: sre [-ierdh] <string-before> <string-after>

  -i    Ignore case when comparing files
  -e    Use regular expressions instead of exact strings.
  -r    Use extended regular expressions.
  -d    Show the sed command
  -h    Show this help message and exit

Here is an example of how you can combine walk-run and sre to replace Text1 with Text2 in a Git repository:

walk-run /path/to/git-repository/ sre Text1 Text2 {}

Script: git-sre

Execute sre at the root directory of a Git repository.

(The sre script replaces occurrences of a specified string or regular expression pattern with support for exact string matching, regular expressions, and case-insensitive matching.)

Example usage:

git sre TextBefore TextAfter /path/to/git/repo

(sre also supports regular expressions.)

Scripts: path-tr, path-uppercase, path-lowercase

  • path-tr: This script processes a given file path, extracts the directory and filename, converts the filename using the specified tr options (e.g., to lowercase), and prints the modified full path. Example usage: path-tr /Path/TO/FILE '[:upper:]' '[:lower:]' This will convert the filename to lowercase, producing: /Path/TO/file.

  • path-uppercase: This script processes a given file path, extracts the directory and filename, converts the filename to uppercase. Example usage: path-uppercase /Path/TO/FILE This will convert the filename to uppercase, producing: /Path/to/FILE.

  • path-lowercase: This script processes a given file path, extracts the directory and filename, converts the filename to lowercase. Example usage: path-lowercase /Path/TO/FILE. This will convert the filename to lowercase, producing: /Path/TO/file.

Script: autoperm

This script sets permissions for files or directories:

  • If it’s a directory: 755
  • If it’s a file with a shebang (e.g., “#!/bin/bash”): 755
  • If it’s a file: 644

Usage:

autoperm /path/to/file-or-directory

Script: path-is

Print the Path to stdout and exit with the code 0 if it is a binary or text file.

Example usage:

path-is /Path/TO/FILE binary
path-is /Path/TO/FILE text

Script category: git

git-checkout-default

The git-checkout-default script automatically checks out the default branch of the current Git repository, regardless of its name. It works in repositories where the default branch may be main, master, or any custom branch.

The script first verifies that the current directory is a Git repository, determines the default branch from the remote origin, fetches the latest changes, and then switches to that branch.

This ensures the local repository is aligned with the remote default branch without requiring manual specification of the branch name.

git-check-gpg

The git-check-gpg script validates GPG signatures for all commits in the current branch history.

It iterates through the commit history of the current HEAD and verifies that every single commit has a valid GPG signature.

To optimize performance and handle exceptions, the script caches results:

  • Validated commits are cached to skip redundant verification in future runs.
  • Unsigned or invalid commits can be interactively ignored, tracking exceptions permanently across runs.

Modes of Operation:

  • Non-interactive (Default): Validates history cleanly. If an invalid or missing signature is found, the script outputs the offending commit details to stderr and terminates immediately with exit code 1.
  • Interactive (Option -i): Prompts the user upon encountering an unverified commit. Displays the signature metadata alongside the diff, allowing the user to explicitly add the specific commit hash to a permanent ignore list for future runs.

Prerequisites:

  • Must be executed inside a Git repository containing at least one commit.
  • Requires Git to be configured with access to the appropriate GPG/GSSH keys.

Exit Codes:

  • 0: Success: All checked commits have valid GPG signatures (or are explicitly ignored).
  • 1: Failure: No commits found, or an unsigned/invalidly signed commit was encountered.

git-dcommit

Script to automate common Git commit tasks:

  • Automatically add untracked files (prompted),
  • Display git diff to the user before committing,
  • Commit changes to the Git repository,
  • Optionally reuse the previous Git commit message if available.

Usage:

./script_name.sh

Run this script from within a Git repository to automate adding, reviewing, and committing changes.

git-squash

A script to squash new Git commits between the current branch and a specified branch.

Usage:
  ./script_name.sh <other-git-branch>

Features:

  • Compares the current branch with the specified branch.
  • Displays a summary of new commits to be squashed.
  • Prompts for confirmation if there are more than 4 commits.
  • Automatically squashes all new commits into one, retaining the message of the first commit.

git-finder

This script recursively locates all Git repositories starting from a specified directory or the current directory if none is provided.

It first checks for fd to perform faster searches; if unavailable, it defaults to find.

The script outputs the paths of all discovered Git repositories to standard output.

git-finder-exec

The git-finder-exec recursively finds all Git repositories starting from the current directory using the git-finder script.

It then executes the command provided as an argument in the directory of each Git repository.

Example usage:

git-finder-exec pwd

git-ourstheir

This script extracts the ‘ours’ and ‘theirs’ versions of a file involved in a Git merge conflict. It is intended to facilitate manual conflict resolution by saving both conflicting versions under distinct filenames (“ours-” and “theirs-“). This allows users to inspect and compare the conflicting changes independently of Git’s built-in merge tools.

Usage:

git-ourstheir <file-in-conflict>

git-sync-upstream

This script synchronizes the current Git branch with its upstream counterpart and force-pushes the result to the ‘origin’ remote. It is intended for workflows where a local branch is kept in sync with an upstream source of truth, and the mirror on ‘origin’ must match upstream exactly.

The script performs the following actions:

  1. Verifies that both ‘origin’ and ‘upstream’ remotes are defined.
  2. Performs a rebase of the current branch onto its upstream equivalent.
  3. Displays the diff between the rebased branch and the remote ‘origin’.
  4. Prompts for confirmation unless run in batch mode.
  5. Merges upstream changes with –ff-only and force-pushes to ‘origin’.

Intended for use in CI workflows or manual synchronization where upstream is authoritative.

Usage:
  git-sync-upstream [-h] [-b]
  -h    Show help message and exit
  -b    Run in batch mode (no interactive prompts)

git-author

The git-author script displays the Git user’s name and email by retrieving user.name and user.email from Git configuration.

git-ls-files-dates

The git-ls-files-dates script lists all tracked files in the current Git repository along with the date of their most recent commit.

The output is sorted chronologically by commit date. Each line contains the last commit date in ISO format followed by the file path.

git-is-clean

Ensure the Git working tree is pristine. Terminate with an error if any uncommitted, deleted, or untracked files are present in the repository.

Script category: ssh

Script: esa

Esa (Easy SSH Agent) simplifies starting ssh-agent, adding keys with ssh-add, and executing commands using the agent.

Usage:

Usage: esa <start|stop|ssh-add|exec>

start: Starts the ssh agent
start: Stop the ssh agent
add: Adds private keys requiring a password with ssh-add
exec: Executes a program using this agent
env: Displays the ssh-agent environment variables

Script: sshwait

This script repeatedly attempts to check the availability of the SSH server on the host provided as the first argument. It exits with a 0 status upon successfully establishing a connection at least once. Note that it only verifies if the SSH server is reachable and does not provide a shell prompt or execute any commands on the remote host.

Usage:

./script_name.sh <host>

X11/Wayland scripts

xocrshot

The xocrshot script captures a screenshot using ‘scrot’, performs optical character recognition (OCR) using ‘tesseract’ command, and:

  • Displays the extracted text in the terminal
  • Copies it to the clipboard.

Features:

  • Captures a screenshot using the ‘scrot’ command,
  • Performs OCR on the screenshot using Tesseract,
  • Displays the extracted text in the terminal,
  • Copies the extracted text to the clipboard using ‘xclip’,
  • Provides error handling and cleanup of temporary files,
  • Supports notifications using ‘notify-send’ (if available).

Usage:

xocrshot

Script category: Emacs

emacs-diff

Compare files in Emacs using emacsclient and ediff (by default).

Usage:

emacs-diff [options] <file1> <file2>

Options:

-v, --verbose         Print the emacsclient commands being executed
-t, --tool NAME       Select the diff tool: "ediff" (default) or "vdiff"

Example:

emacs-diff file1.txt file2.txt

(This will compare file1.txt with file2.txt)

Notes:

  • Requires Emacs to be running as a server via the (server-start) function or as an Emacs daemon.
  • Paths are automatically converted to absolute paths before comparison.

Script category: Misc

Script: singleton

The singleton script functions as a mutual exclusion wrapper. It prevents concurrent executions of the same operation by using a dedicated lockfile.

Usage Example:

singleton /var/run/backup.lock /usr/local/bin/backup.sh --verbose

The above command prevents concurrent executions of the /usr/local/bin/backup.sh script. Running the command a second time while the first instance is active results in an error message and a non-zero exit code, preventing multiple executions:

singleton /var/run/backup.lock /usr/local/bin/backup.sh --verbose

The second execution outputs the following error message:

Error: Another instance of '/usr/local/bin/backup.sh' is running.

Script: haide

The haide script utilizes AIDE (Advanced Intrusion Detection Environment) to monitor the file integrity of the user’s home directory, ensuring no files are modified, added, or deleted without the user’s knowledge. Key functions handle database setup, integrity checks, and user-approved updates. The script filters non-critical changes, ensuring meaningful alerts while maintaining a secure and reliable monitoring process.

Scripts: cbcopy, cbpaste

  • cbcopy: This script copies the content of stdin to the clipboard.
  • cbpaste: This script reads the contents of the system clipboard and writes it to stdout.
  • cbwatch: Monitor the clipboard and display its content when it changes.

Script: outonerror

The outonerror script redirects the command’s output to stderr only if the command fails (non-zero exit code). No output is shown when the command succeeds.

Here is an example of how to use this script: How to make cron notify the user about a failed command by redirecting its output to stderr only when it fails (non-zero exit code).

Script: over

This program simply displays a notification. It can be used in the terminal while another command is running. Once the command finishes executing, a notification is displayed, informing the user that the process has completed.

Script: osid

Detects the current operating system and prints a short identifier.

  • On macOS, it prints “darwin”.
  • On Linux, it prints the value of $ID from /etc/os-release.
  • If the OS cannot be determined, it prints “unknown”.

Usage:

osid

Script: largs

This script reads from standard input and executes a command for each line, replacing {} with the content read from stdin. It expects {} to be passed as one of the arguments and will fail if {} is not provided.

This script is an alternative to xargs.

{ echo "file1"; echo "file2"; } | largs ls {}

Script: is-battery-discharging

Returns an exit code of 0 when the system is discharging (running on battery power) and 1 when charging or if no battery is detected.

Note: This script is specific to Linux operating systems. The state is determined by reading directly from the sysfs pseudo-file system (/sys/class/power_supply).

Because the script communicates via standard exit codes, it is designed to be used directly in conditional statements. Example using an if statement to trigger power-saving commands:

if is-battery-discharging; then
  echo "System is on battery power. Dimming screen..."
  # Insert commands to reduce power consumption here
else
  echo "System is connected to AC power."
fi

License

Copyright (C) 2012-2026 James Cherti

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program.

Links

Emacs flymake-bashate.el – A Flymake backend for bashate that provides style checking for Bash shell scripts within Emacs

Build Status MELPA MELPA Stable License

The flymake-bashate Emacs package provides a Flymake backend for bashate, enabling real-time style checking for Bash shell scripts within Emacs.

(This package can also work with Flycheck: simply use the flymake-flycheck package, which allows any Emacs Flymake backend to function as a Flycheck checker.)

If this enhances your workflow, please show your support by ⭐ starring flymake-bashate.el on GitHub to help more Emacs users discover its benefits.

Installation

To install flymake-bashate from MELPA:

  1. If you haven’t already done so, add MELPA repository to your Emacs configuration.

  2. Add the following code to your Emacs init file to install flymake-bashate from MELPA:

(use-package flymake-bashate
  :commands flymake-bashate-setup
  :hook (((bash-ts-mode sh-mode) . flymake-bashate-setup)
         ((bash-ts-mode sh-mode) . flymake-mode))
  :custom
  (flymake-bashate-max-line-length 80))

Customizations

Ignoring Bashate errors

To make bashate ignore specific Bashate rules, such as E003 (ensure all indents are a multiple of 4 spaces) and E006 (check for lines longer than 79 columns), set the following variable:

(setq flymake-bashate-ignore "E003,E006")

(This corresponds to the -i or --ignore option in Bashate.)

Setting maximum line length

To define the maximum line length for Bashate to check:

(setq flymake-bashate-max-line-length 80)

(This corresponds to the --max-line-length option in Bashate.)

Specifying the Bashate executable

To change the path or filename of the Bashate executable:

(setq flymake-bashate-executable "/opt/different-directory/bin/bashate")

(Defaults to “bashate”.)

Comments from users

  • gsotirchos: ‘Thank you for maintaining flymake-bashate, I really appreciate the work you’ve put into it.’

License

Copyright (C) 2024-2026 James Cherti

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program.

Links

Other Emacs packages by the same author:

  • minimal-emacs.d: This repository hosts a minimal Emacs configuration designed to serve as a foundation for your vanilla Emacs setup and provide a solid base for an enhanced Emacs experience.
  • compile-angel.el: Speed up Emacs! This package guarantees that all .el files are both byte-compiled and native-compiled, which significantly speeds up Emacs.
  • outline-indent.el: An Emacs package that provides a minor mode that enables code folding and outlining based on indentation levels for various indentation-based text files, such as YAML, Python, and other indented text files.
  • easysession.el: Easysession is lightweight Emacs session manager that can persist and restore file editing buffers, indirect buffers/clones, Dired buffers, the tab-bar, and the Emacs frames (with or without the Emacs frames size, width, and height).
  • vim-tab-bar.el: Make the Emacs tab-bar Look Like Vim’s Tab Bar.
  • elispcomp: A command line tool that allows compiling Elisp code directly from the terminal or from a shell script. It facilitates the generation of optimized .elc (byte-compiled) and .eln (native-compiled) files.
  • tomorrow-night-deepblue-theme.el: The Tomorrow Night Deepblue Emacs theme is a beautiful deep blue variant of the Tomorrow Night theme, which is renowned for its elegant color palette that is pleasing to the eyes. It features a deep blue background color that creates a calming atmosphere. The theme is also a great choice for those who miss the blue themes that were trendy a few years ago.
  • Ultyas: A command-line tool designed to simplify the process of converting code snippets from UltiSnips to YASnippet format.
  • flymake-ansible-lint.el: An Emacs package that offers a Flymake backend for ansible-lint.
  • inhibit-mouse.el: A package that disables mouse input in Emacs, offering a simpler and faster alternative to the disable-mouse package.
  • quick-sdcv.el: This package enables Emacs to function as an offline dictionary by using the sdcv command-line tool directly within Emacs.
  • enhanced-evil-paredit.el: An Emacs package that prevents parenthesis imbalance when using evil-mode with paredit. It intercepts evil-mode commands such as delete, change, and paste, blocking their execution if they would break the parenthetical structure.
  • stripspace.el: Ensure Emacs Automatically removes trailing whitespace before saving a buffer, with an option to preserve the cursor column.
  • persist-text-scale.el: Ensure that all adjustments made with text-scale-increase and text-scale-decrease are persisted and restored across sessions.
  • pathaction.el: Execute the pathaction command-line tool from Emacs. The pathaction command-line tool enables the execution of specific commands on targeted files or directories. Its key advantage lies in its flexibility, allowing users to handle various types of files simply by passing the file or directory as an argument to the pathaction tool. The tool uses a .pathaction.yaml rule-set file to determine which command to execute. Additionally, Jinja2 templating can be employed in the rule-set file to further customize the commands.
  • kirigami.el: The kirigami Emacs package offers a unified interface for opening and closing folds across a diverse set of major and minor modes in Emacs, including outline-mode, outline-minor-mode, outline-indent-minor-mode, org-mode, markdown-mode, vdiff-mode, vdiff-3way-mode, hs-minor-mode, hide-ifdef-mode, origami-mode, yafolding-mode, folding-mode, and treesit-fold-mode. With Kirigami, folding key bindings only need to be configured once. After that, the same keys work consistently across all supported major and minor modes, providing a unified and predictable folding experience.
  • buffer-guardian.el: Automatically saves Emacs buffers without requiring manual intervention. By default, it triggers a save when the user switches to another buffer, switches to another window or frame, Emacs loses focus, or the minibuffer is opened. Beyond standard file buffers, buffer-guardian also manages specialized editing buffers such as org-src and edit-indirect. Additional features, disabled by default, include periodic or idle-time saving of all buffers, automatic exclusion of remote, nonexistent, or large files, and support for custom exclusion rules via regular expressions or predicate functions.

Emacs enhanced-evil-paredit.el package: Preventing Parenthesis Imbalance when Using Evil-mode with Paredit

Build Status MELPA MELPA Stable License

The enhanced-evil-paredit package prevents parenthesis imbalance when using evil-mode with paredit. It intercepts evil-mode commands such as delete, change, and paste, blocking their execution if they would break the parenthetical structure. This guarantees that your Lisp code remains syntactically correct while retaining the editing features of evil-mode.

If this enhances your workflow, please show your support by ⭐ starring enhanced-evil-paredit-mode on GitHub to help more Emacs users discover its benefits.

Installation

To install enhanced-evil-paredit from MELPA:

  1. If you haven’t already done so, add MELPA repository to your Emacs configuration.
  2. Add the following code to the Emacs init file to install enhanced-evil-paredit:
;; `paredit-mode' is a requirement
(use-package paredit
  :commands paredit-mode
  :hook
  (emacs-lisp-mode . paredit-mode))

(use-package enhanced-evil-paredit
  :commands enhanced-evil-paredit-mode
  :hook (paredit-mode . enhanced-evil-paredit-mode))

Frequently asked questions

What are the differences between enhanced-evil-paredit and evil-paredit?

The enhanced-evil-paredit package is a modernized version of evil-paredit. It has been enhanced and fully functions in recent versions of Emacs (Emacs >= 28). The author decided to develop enhanced-evil-paredit because the evil-paredit package is no longer maintained and does not function in recent versions of Emacs and Evil.

Here are the enhancements in enhanced-evil-paredit:

  • Handles paste using p and P, ensuring that the pasted text has balanced parentheses.
  • Fix call to a non-existent function (evil-called-interactively-p), which has been replaced by (called-interactively-p 'any).
  • Add new functions: enhanced-evil-paredit-backward-delete and enhanced-evil-paredit-forward-delete.
  • enhanced-evil-paredit-mode only uses the paredit functions when paredit-mode is enabled. It acts as a wrapper that delegates commands to Paredit when Paredit is enabled and otherwise uses standard Evil commands. (The difference in behavior is that with paredit-mode, structural editing operations preserve balanced parentheses and Lisp structure, whereas without paredit-mode, the same operations rely on Evil motions and can disrupt parentheses and overall code structure.)
  • Add lexical binding with lexical-binding: t.
  • Suppress Emacs Lisp warnings and add Melpa tests.
  • Refactor and improve enhanced-evil-paredit.
  • Create a enhanced-evil-paredit customization group for user configuration.
  • Remove Evil state change from enhanced-evil-paredit-mode.
  • Improve error handling in enhanced-evil-paredit-check-region.
  • Enhance docstrings.
  • Remove keymap bindings that are reserved by Emacs.
  • Add &optional after the end argument to make it similar to Evil functions.
  • dd restores the column when there is a parentheses mismatch.

Author and License

The enhanced-evil-paredit Emacs package has been written by Roman Gonzalez and James Cherti. It is distributed under terms of the GNU General Public License version 3, or, at your choice, any later version.

Copyright (C) 2024-2026 James Cherti

Copyright (C) 2012-2015 Roman Gonzalez

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program.

Links

Other Emacs packages by the same author:

  • minimal-emacs.d: This repository hosts a minimal Emacs configuration designed to serve as a foundation for your vanilla Emacs setup and provide a solid base for an enhanced Emacs experience.
  • compile-angel.el: Speed up Emacs! This package guarantees that all .el files are both byte-compiled and native-compiled, which significantly speeds up Emacs.
  • easysession.el: Easysession is lightweight Emacs session manager that can persist and restore file editing buffers, indirect buffers/clones, Dired buffers, the tab-bar, and the Emacs frames (with or without the Emacs frames size, width, and height).
  • vim-tab-bar.el: Make the Emacs tab-bar Look Like Vim’s Tab Bar.
  • elispcomp: A command line tool that allows compiling Elisp code directly from the terminal or from a shell script. It facilitates the generation of optimized .elc (byte-compiled) and .eln (native-compiled) files.
  • tomorrow-night-deepblue-theme.el: The Tomorrow Night Deepblue Emacs theme is a beautiful deep blue variant of the Tomorrow Night theme, which is renowned for its elegant color palette that is pleasing to the eyes. It features a deep blue background color that creates a calming atmosphere. The theme is also a great choice for those who miss the blue themes that were trendy a few years ago.
  • Ultyas: A command-line tool designed to simplify the process of converting code snippets from UltiSnips to YASnippet format.
  • dir-config.el: Automatically find and evaluate .dir-config.el Elisp files to configure directory-specific settings.
  • flymake-bashate.el: A package that provides a Flymake backend for the bashate Bash script style checker.
  • flymake-ansible-lint.el: An Emacs package that offers a Flymake backend for ansible-lint.
  • inhibit-mouse.el: A package that disables mouse input in Emacs, offering a simpler and faster alternative to the disable-mouse package.
  • quick-sdcv.el: This package enables Emacs to function as an offline dictionary by using the sdcv command-line tool directly within Emacs.
  • enhanced-evil-paredit.el: An Emacs package that prevents parenthesis imbalance when using evil-mode with paredit. It intercepts evil-mode commands such as delete, change, and paste, blocking their execution if they would break the parenthetical structure.
  • stripspace.el: Ensure Emacs Automatically removes trailing whitespace before saving a buffer, with an option to preserve the cursor column.
  • persist-text-scale.el: Ensure that all adjustments made with text-scale-increase and text-scale-decrease are persisted and restored across sessions.
  • pathaction.el: Execute the pathaction command-line tool from Emacs. The pathaction command-line tool enables the execution of specific commands on targeted files or directories. Its key advantage lies in its flexibility, allowing users to handle various types of files simply by passing the file or directory as an argument to the pathaction tool. The tool uses a .pathaction.yaml rule-set file to determine which command to execute. Additionally, Jinja2 templating can be employed in the rule-set file to further customize the commands.
  • kirigami.el: The kirigami Emacs package offers a unified interface for opening and closing folds across a diverse set of major and minor modes in Emacs, including outline-mode, outline-minor-mode, outline-indent-minor-mode, org-mode, markdown-mode, vdiff-mode, vdiff-3way-mode, hs-minor-mode, hide-ifdef-mode, origami-mode, yafolding-mode, folding-mode, and treesit-fold-mode. With Kirigami, folding key bindings only need to be configured once. After that, the same keys work consistently across all supported major and minor modes, providing a unified and predictable folding experience.
  • buffer-guardian.el: Automatically saves Emacs buffers without requiring manual intervention. By default, it triggers a save when the user switches to another buffer, switches to another window or frame, Emacs loses focus, or the minibuffer is opened. Beyond standard file buffers, buffer-guardian also manages specialized editing buffers such as org-src and edit-indirect. Additional features, disabled by default, include periodic or idle-time saving of all buffers, automatic exclusion of remote, nonexistent, or large files, and support for custom exclusion rules via regular expressions or predicate functions.

Emacs flymake-ansible-lint.el – A Flymake backend for ansible-lint

Build Status MELPA MELPA Stable License

The flymake-ansible-lint package provides a Flymake backend for ansible-lint, enabling real-time syntax and style checking for Ansible playbooks and roles within Emacs.

(This package can also work with Flycheck: simply use the flymake-flycheck package, which allows any Emacs Flymake backend to function as a Flycheck checker.)

Requirements

Installation

To install flymake-ansible-lint from MELPA:

  1. If you haven’t already done so, add MELPA repository to your Emacs configuration.

  2. Add the following code to your Emacs init file to install flymake-ansible-lint from MELPA:

(use-package flymake-ansible-lint
  :commands flymake-ansible-lint-setup
  :hook (((yaml-ts-mode yaml-mode) . flymake-ansible-lint-setup)
         ((yaml-ts-mode yaml-mode) . flymake-mode)))

Customizations

You can configure ansible-lint parameters using the flymake-ansible-lint-args variable:

(setq flymake-ansible-lint-args '("--offline"
                                  "-x"
                                  "run-once[play],no-free-form"))

You can also enable automatic project directory detection to pass the --project-dir argument to the linter automatically. This feature detects the project or version control root and uses it as the project directory:

(setq flymake-ansible-lint-auto-project-dir t)

This ensures that Ansible caches its data inside a single .ansible directory at the project root, rather than cluttering your repository by creating an .ansible folder in every subdirectory where a file is linted, keeping your project tree clean.

Frequently asked questions

Why are some ansible-lint error messages truncated?

This issue is a known bug in ansible-lint, not in flymake-ansible-lint.

It is ansible-lint that truncates some error messages:

$ ansible-lint -p test.yaml
test.yaml:5: yaml[truthy]: Truthy value should be one of

Location of the temporary files created by the flymake-ansible-lint package

By default, the flymake-ansible-lint package creates temporary files in the same directory as the Ansible YAML file currently being edited.

For example, when editing: /home/user/test/myfile.yaml, the package may generate temporary files such as: /home/user/test/flymake_1_myfile.yaml /home/user/test/flymake_2_myfile.yaml

These temporary files are automatically removed once flymake-ansible-lint completes its analysis.

(This behavior is controlled by the variable flymake-ansible-lint-tmp-files-enabled. Keeping flymake-ansible-lint-tmp-files-enabled enabled is important because it allows Flymake to lint the most recent in-memory state of the buffer, including unsaved modifications. Without these temporary files, Flymake would have to rely on the last saved version of the file, which might not reflect the current edits. This ensures that linting diagnostics remain accurate, up to date, and synchronized with the actual buffer contents, providing immediate feedback while editing.)

License

The flymake-ansible-lint Emacs package has been written by James Cherti and is distributed under terms of the GNU General Public License version 3, or, at your choice, any later version. This package uses flymake-quickdef, by Karl Otness.

Copyright (C) 2024-2026 James Cherti

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program.

Links

Other Emacs packages by the same author:

  • minimal-emacs.d: This repository hosts a minimal Emacs configuration designed to serve as a foundation for your vanilla Emacs setup and provide a solid base for an enhanced Emacs experience.
  • compile-angel.el: Speed up Emacs! This package guarantees that all .el files are both byte-compiled and native-compiled, which significantly speeds up Emacs.
  • outline-indent.el: An Emacs package that provides a minor mode that enables code folding and outlining based on indentation levels for various indentation-based text files, such as YAML, Python, and other indented text files.
  • easysession.el: Easysession is lightweight Emacs session manager that can persist and restore file editing buffers, indirect buffers/clones, Dired buffers, the tab-bar, and the Emacs frames (with or without the Emacs frames size, width, and height).
  • vim-tab-bar.el: Make the Emacs tab-bar Look Like Vim’s Tab Bar.
  • elispcomp: A command line tool that allows compiling Elisp code directly from the terminal or from a shell script. It facilitates the generation of optimized .elc (byte-compiled) and .eln (native-compiled) files.
  • tomorrow-night-deepblue-theme.el: The Tomorrow Night Deepblue Emacs theme is a beautiful deep blue variant of the Tomorrow Night theme, which is renowned for its elegant color palette that is pleasing to the eyes. It features a deep blue background color that creates a calming atmosphere. The theme is also a great choice for those who miss the blue themes that were trendy a few years ago.
  • Ultyas: A command-line tool designed to simplify the process of converting code snippets from UltiSnips to YASnippet format.
  • flymake-bashate.el: A package that provides a Flymake backend for the bashate Bash script style checker.
  • inhibit-mouse.el: A package that disables mouse input in Emacs, offering a simpler and faster alternative to the disable-mouse package.
  • quick-sdcv.el: This package enables Emacs to function as an offline dictionary by using the sdcv command-line tool directly within Emacs.
  • enhanced-evil-paredit.el: An Emacs package that prevents parenthesis imbalance when using evil-mode with paredit. It intercepts evil-mode commands such as delete, change, and paste, blocking their execution if they would break the parenthetical structure.
  • stripspace.el: Ensure Emacs Automatically removes trailing whitespace before saving a buffer, with an option to preserve the cursor column.
  • persist-text-scale.el: Ensure that all adjustments made with text-scale-increase and text-scale-decrease are persisted and restored across sessions.
  • pathaction.el: Execute the pathaction command-line tool from Emacs. The pathaction command-line tool enables the execution of specific commands on targeted files or directories. Its key advantage lies in its flexibility, allowing users to handle various types of files simply by passing the file or directory as an argument to the pathaction tool. The tool uses a .pathaction.yaml rule-set file to determine which command to execute. Additionally, Jinja2 templating can be employed in the rule-set file to further customize the commands.
  • kirigami.el: The kirigami Emacs package offers a unified interface for opening and closing folds across a diverse set of major and minor modes in Emacs, including outline-mode, outline-minor-mode, outline-indent-minor-mode, org-mode, markdown-mode, vdiff-mode, vdiff-3way-mode, hs-minor-mode, hide-ifdef-mode, origami-mode, yafolding-mode, folding-mode, and treesit-fold-mode. With Kirigami, folding key bindings only need to be configured once. After that, the same keys work consistently across all supported major and minor modes, providing a unified and predictable folding experience.
  • buffer-guardian.el: Automatically saves Emacs buffers without requiring manual intervention. By default, it triggers a save when the user switches to another buffer, switches to another window or frame, Emacs loses focus, or the minibuffer is opened. Beyond standard file buffers, buffer-guardian also manages specialized editing buffers such as org-src and edit-indirect. Additional features, disabled by default, include periodic or idle-time saving of all buffers, automatic exclusion of remote, nonexistent, or large files, and support for custom exclusion rules via regular expressions or predicate functions.