Self-hosted service
oantolin/embark avatar
oantolin/embark

Embark turns the thing at point into a prefix key for contextual actions

Emacs Mini-Buffer Actions Rooted in Keymaps

1,233 stars73 forksEmacs LispGPL-3.0

At a glance

What is it?
Embark is an GPL-3.0 licensed Emacs package that binds one command, embark-act, as a prefix key over a keymap of actions chosen for whatever is near point, whether that is the current minibuffer candidate, a file, a URL, a symbol or the active region. It ships with more than a hundred actions, and target types are mapped to action keymaps through one alist variable.
Who is it for?
Embark fits an Emacs user who wants a contextual action menu without leaving the keyboard, who already uses completion, and who is willing to bind one key and read the default actions list. It does not fit a setup where completion metadata is unreliable, because the whole action set is selected from the target type, and the README is blunt that many Emacs commands do not set useful metadata.
Can I use it commercially?
Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
Is it still maintained?
Yes. The repository last received commits 72 days ago.
What is it written in?
Mainly Emacs Lisp, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

One command behaves like a prefix key over the target at point

The idea is best described by the README's own analogy: think of embark-act as a keyboard-based version of a right-click contextual menu.

You bind the command embark-act to a convenient key, and it acts as a prefix for a keymap offering you relevant actions to use on a target determined by the context. The target is the thing the actions will operate on, and the action set is chosen by the target's type. The default configuration covers files, buffers, identifiers, s-expressions, sentences and more, with over a hundred actions preconfigured for common target types, and the README says it is easy to add more actions and more target types.

The concrete example the README gives is a URL. With point on a URL in a buffer, you can open the URL in a browser, or in eww, or download the file it points to. Another example is switching buffers: if while switching buffers you spot an old one, you can kill it right there and continue to select another.

The primary interaction is a prefix key. That matters for anyone used to Helm or Counsel, because the minibuffer behaviour here is familiar to those users, and the README notes that the same actions work in normal buffers, not only during completion.

What counts as the target depends on where you are

The rules for the target are short, and they are the whole mental model.

* In the minibuffer, the target is the current top completion candidate. * In the *Completions* buffer the target is the completion at point. * In a regular buffer, the target is the region if active, or else the file, symbol, URL, s-expression or defun at point.

The third case is the interesting one, because it means the same key does the sensible thing wherever you are. In a file buffer it finds the file name; in code it finds the symbol, the s-expression or the defun; on a link it finds the URL. The package does the classification for you.

There is a refinement. Multiple targets can be present at the same location, and you can cycle between them by repeating the embark-act key binding. That handles the ambiguous case where point is simultaneously inside a symbol and inside an s-expression, and it means you are never stuck with the classification the package happened to pick first.

The set of actions offered depends on the type of the target. The README gives a sample of the defaults. For files, actions include deleting, copying, renaming, visiting in another window and running a shell command on the file. For buffers, switching to or killing the buffer. For package names, installing, removing or visiting the homepage. For Emacs Lisp symbols, finding the definition, looking up documentation and evaluating, where evaluating a variable immediately shows the value while evaluating a function lets you pass it arguments first, plus actions specific to variables, such as setting the value directly or through the customize system, and actions specific to commands, such as binding it to a key.

embark-keymap-alist is the entire configuration surface

Configuring which actions are offered for a type is particularly easy and requires no programming. The variable embark-keymap-alist associates target types with variables containing keymaps, and those keymaps contain the bindings for the actions.

elisp
embark-keymap-alist
embark-file-map
embark-general-map
embark-indicators
embark-act

The example the README gives is the file type. In the default configuration the type file is associated with the symbol embark-file-map, and that symbol names a keymap with single-letter key bindings for common Emacs file commands, for instance c is bound to copy-file. So if you are in the minibuffer after running a command that prompts for a file, such as find-file or rename-file, you can copy a file by running embark-act and then pressing c.

To examine the available categories and their associated keymaps, you can use C-h v embark-keymap-alist, or customize that variable.

Everything is configurable in the same spirit. Determining the current target, classifying it, and deciding which actions are offered for each type are all variable-driven, and the README is explicit that the introduction it gives only mentions part of the default configuration.

The keys involved are worth listing because they are the interface: embark-act is the command you bind, embark-keymap-alist is where types map to keymaps, embark-general-map holds the actions that are always available, and embark-indicators controls the visual feedback.

Any command that reads the minibuffer can be an action

The keymap configuration is a convenience rather than a requirement, and the README makes that point clearly. The action keymaps are very convenient but not strictly necessary when using embark-act: you can use any command that reads from the minibuffer as an action, and the target of the action will be inserted at the first minibuffer prompt.

After running embark-act, all of your key bindings and even execute-extended-command can be used to run a command. The example is M-%, the standard query-replace binding, used to replace all occurrences of the symbol at point, with no need to bind query-replace in one of the Embark keymaps.

That is the design decision with the widest consequences. Instead of maintaining a catalogue of every command you might want on a target, Embark hands you the minibuffer and lets the existing bindings do the work, and the per-type keymaps are there for the actions you reach for constantly so you can have them on single letters.

The general map is the exception. The actions in embark-general-map are available no matter what type of completion you are in the middle of. By default this includes bindings to save the current candidate in the kill ring and to insert the current candidate in the previously selected buffer, meaning the buffer that was current when you executed a command that opened up the minibuffer. Those two are useful precisely because they are context independent.

There is also a way to choose an action by name. Instead of selecting an action via its key binding, you can select it by name with completion by typing C-h after embark-act. And by default, if you do not immediately select an action, after a short delay Embark will pop up a buffer showing a list of actions and their corresponding key bindings, and if you are using embark-act outside the minibuffer it will also highlight the current target. Both behaviours are configurable via embark-indicators.

Candidates can be collected into a buffer that matches their type

The second half of the feature is about leaving the minibuffer entirely. Embark can collect all the candidates in a minibuffer to an occur-like buffer, or export them to a buffer in a major mode specific to the type of candidates, such as dired for a set of files, ibuffer for a set of buffers, or customize for a set of variables.

That is a genuinely different model from the usual completion interface. The candidates are not a list you scroll and pick from, they are a set you can act on with the tools that already exist for that kind of thing. A set of files in dired means you can mark them and act on the marked set with the dired commands you already know. A set of variables in customize means you can set several of them in one session. A set of buffers in ibuffer means you can kill or display several at once.

The repository layout shows where this lives. embark.el is the main file, and the tree also contains embark-consult.el, embark-org.el and avy-embark-collect.el.

The pattern is consistent with the rest of the package. Embark does not invent a new vocabulary for acting on things; it routes into the existing one, which is why the collect feature targets dired and ibuffer rather than a bespoke list view.

Marginalia is what makes the target types correct

The detail that decides whether Embark feels right in your setup is the relationship between a completion's category and a target's type.

Emacs's minibuffer completion system includes metadata indicating the category of what is being completed. find-file's metadata indicates a category of file, and switch-to-buffer's metadata indicates a category of buffer. Embark has the related notion of the type of a target for actions, and by default, when category metadata is present, it is taken to be the type of the minibuffer completion candidates when used as targets.

The catch is stated just as plainly. Emacs commands often do not set useful category metadata, so the Marginalia package, which supplies this missing metadata, is highly recommended for use with Embark.

So the dependency is not optional in practice. Without Marginalia, a completion from a command that does not announce its category has no type, and the action set offered for it is either the general set or nothing useful. With Marginalia, the same completion is typed, and the actions appear.

That is a real dependency for an adopter, and it is a light one, since Marginalia is a metadata annotation package rather than a replacement for anything. But it changes the evaluation: Embark without Marginalia is a partial feature, and Embark with it is the full one.

The other target types, the ones detected by position in a regular buffer, do not depend on metadata. A file name, a URL or a symbol at point is found by looking at the buffer, so those actions work regardless of whether Marginalia is installed.

GPL-3.0, packaged on four archives, and version 1.2

The licence is GPL-3.0, with the LICENSE file at the repository root, and the README is an Org mode document that also exports to Texinfo, with the export file name embark.texi and the Texinfo category set to Emacs misc features. The README.org and the texinfo source are both in the tree, alongside NEWS.org for the release notes and a .dir-locals.el file.

The package is distributed on four archives, and the badges in the README show all of them. There is GNU ELPA, the package archive built into Emacs, and GNU-devel ELPA for development versions. There is MELPA, the community archive, and MELPA Stable for the released versions. The fact that the package is on MELPA is what makes it installable with a few lines in your init file without a package.el entry, and the fact that it is on GNU ELPA as well means it can be installed without any third-party archive at all.

The release history is small and unhurried. The recent versions are 1.2 on 2026-04-04, 1.1 on 2024-05-13 and 1.0 on 2023-12-08. A 1.0 in December 2023, a 1.1 in May 2024 and a 1.2 in April 2026 is the pace of a mature, stable package rather than an actively churning one.

The repository is not archived, the default branch is master, and the last push was on 2026-08-12, so work continues, but the version number is the honest summary of the project's pace. For an Emacs user, that is a good sign rather than a worrying one, since a package that changes its behaviour every month is a package that breaks your init file every month.

Editorial conclusion

Embark fits an Emacs user who wants a contextual action menu without leaving the keyboard, who already uses completion, and who is willing to bind one key and read the default actions list. It does not fit a setup where completion metadata is unreliable, because the whole action set is selected from the target type, and the README is blunt that many Emacs commands do not set useful metadata. Before adopting it, install Marginalia, bind embark-act, and try the buffer and file targets first, since those are the ones whose type is known without any metadata.

Frequently asked questions

What does the Embark Emacs package do?

It binds one command, embark-act, which acts as a prefix key over a keymap of actions relevant to the target near point. The target is the current minibuffer candidate, the completion at point in the *Completions* buffer, or in a regular buffer the region if active, or else the file, symbol, URL, s-expression or defun at point.

How do I configure which actions Embark offers for a target type?

Through the variable embark-keymap-alist, which associates target types with variables containing keymaps, and those keymaps hold the action bindings. In the default configuration the file type is associated with embark-file-map, where c is bound to copy-file. You can inspect it with C-h v embark-keymap-alist or customize it.

Do I need Marginalia to use Embark?

The README says the Marginalia package, which supplies missing category metadata, is highly recommended for use with Embark, because many Emacs commands do not set useful category metadata. Without it, completion candidates from those commands have no type, so the matching actions are not offered, though targets detected by position in a regular buffer do not depend on metadata.

Can I use any Emacs command as an Embark action?

Yes. The action keymaps are not strictly necessary, because any command that reads from the minibuffer can be used as an action, with the target inserted at the first minibuffer prompt. After embark-act, all of your key bindings and even execute-extended-command work, so M-% replaces all occurrences of the symbol at point without any special binding.

Where can I install the Embark package from?

The README carries badges for GNU ELPA, GNU-devel ELPA, MELPA and MELPA Stable, so it is installable from the built-in GNU archive, the development archive or the two community archives. The project is GPL-3.0 licensed and the current version is 1.2, released on 2026-04-04.

Official sources

  1. Issues
  2. License: GPL-3.0
  3. oantolin/embark on GitHub
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/oantolin-embark.svg)](https://hysenlabs.com/projects/oantolin-embark)

Was this useful?