dumb-jump: Definition Jumping in Emacs Without an Index
an Emacs "jump to definition" package for 60+ languages
At a glance
- What is it?
- Dumb Jump answers M-. by shelling out to ag, rg or grep and scoring the matches with per-language regexes. It is a text search with heuristics layered on top, and the trade-offs that come with that approach are visible in the README.
- Who is it for?
- Dumb Jump fits Emacs users who want M-. to work across many languages with no server processes and no index to keep fresh, especially in polyglot repositories where setting up a language server per language is not worth the effort. It is the wrong choice when you need type-aware results, since the README itself frames the package as a text search with heuristics rather than an analyzer, and it will be slow on large projects if you are stuck on grep.
- 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 104 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 September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
What Problem Dumb Jump Solves, and for Whom
Jumping to a definition in Emacs has historically required either a TAGS file built by etags and regenerated as the code changes, or a language server that parses the project and answers queries over a protocol. Both approaches ask you to set something up per project or per language, and both can go stale. Dumb Jump takes the opposite position. Its README describes the package as favoring "just working", with "absolutely no stored indexes (TAGS) or persistent background processes". Nothing is built ahead of time and nothing keeps running in the background. The package requires at least GNU Emacs 26.1, and version 0.5.5 is the last release that supports Emacs 24 or 25, so anyone on an older Emacs is pinned to that release.
The audience is the Emacs user who works across several languages in one session and does not want to maintain tooling for each of them. The README lists basic support for more than 60 languages, from C, Go, Rust and Python to COBOL, Coq, Faust, OpenSCAD and Terraform. That breadth is the point. A language server setup gives you better answers in the languages it covers, but it covers fewer of them, and each one is a separate installation. Dumb Jump trades precision for coverage and zero setup.
How the Search and Scoring Pipeline Works
The mechanism is a shell search followed by scoring. Dumb Jump takes the symbol under point and searches the project with The Silver Searcher (ag), ripgrep (rg) or grep. Which regexes it uses to describe a potential definition depends on the file extension or the major mode of the current buffer. The matches that come back are then passed through a shared set of heuristic methods, and those heuristics pick the best candidate to jump to.
When the heuristics cannot settle on one candidate, behavior depends on the path in use. On the legacy selector path, the package presents a list through completing-read, helm or ivy, controlled by the dumb-jump-selector variable. The xref path, added in version 0.5.4, uses the xref UI instead. The README describes the xref integration separately, and that separation matters: the two paths do not have identical selection behavior.
Find references is the same machinery run in reverse. The package performs a broad symbol search and then filters out the results that match definition patterns. Because the filter is pattern-based rather than semantic, it works for all supported languages with no extra configuration, but it also means a reference that happens to look like a definition can be dropped from the list. The README does not document a way to recover those.
Getting It Running: package.el, xref and the Searcher
Installation goes through MELPA. The README gives the command M-x package-install dumb-jump. Spacemacs users already have the package by default and only need to install ag or rg for the best experience.
The searcher is the part worth attention. Dumb Jump performs best with ag or rg installed on the system, and the README links to install instructions for both. If neither is present it falls back to grep, and the README states plainly that the package can be slow in that case, particularly on large projects.
The recommended entry point is the xref backend. Add this to your initialization file:
(add-hook 'xref-backend-functions #'dumb-jump-xref-activate)
With that in place, M-. jumps to definitions and M-? finds references. To route candidate selection through a completion framework instead of the default pop-up buffer, set:
(setq xref-show-definitions-function #'xref-show-definitions-completing-read)
The README notes that xref-show-definitions-completing-read requires at least Xref 1.1.0, available from ELPA or bundled with Emacs 28.1 or newer. Consult users can set xref-show-definitions-function to consult-xref for live preview while cycling candidates. The README's use-package example combines :ensure t, a custom setting of dumb-jump-prefer-searcher to 'rg, the consult-xref selection function, and the xref-backend-functions hook in :config.
Project Roots, .dumbjump and the git-grep Restriction
Dumb Jump looks for a project root automatically. The README lists the markers it accepts: .dumbjump, .projectile, .git, .hg, .fslckout, .bzr, _darcs, .svn, Makefile, PkgInfo, -pkg.el, _FOSSIL_ and Cargo.toml. If the detected root is wrong, an empty .dumbjumpignore file in a directory stops that directory from registering as the root and the search continues upward.
A .dumbjump file in the project root serves two purposes: it marks the root, and it optionally lists paths to exclude, which the README presents as a way to make searches faster. The example format uses a leading minus for exclusions and a leading plus for paths outside the project:
-tests -node_modules -build -images +../some-lib/src +/usr/lib/src
The plus entries carry a constraint that is easy to miss. The README warns that when adding paths outside the project you must use a searcher that can search outside the project root. git-grep cannot, so if dumb-jump-force-searcher or dumb-jump-prefer-searcher is set to 'git-grep, switch to 'ag or 'rg. The automatic searcher selection does not include git-grep, so this caveat applies only when git-grep has been configured explicitly.
Two other options are documented. dumb-jump-default-project changes the project used when none is found and defaults to ~. dumb-jump-quiet set to t reduces the package's output.
Where the Heuristic Approach Breaks Down
The name is honest. Dumb Jump does not parse your code; it searches text and guesses. Every definition it finds is a line that matched a regex for the language, and every ranking decision comes from heuristics shared across languages. That design is what makes 60+ languages feasible with no per-language tooling, and it is also the source of the failure modes.
The README's own framing is that the package "seems to do a good job" for supported languages, which is a weaker claim than a language server can make. A symbol that appears in a comment, a string, or a generated file can be offered as a candidate. A macro-generated or metaprogrammed definition may never appear as a line of text that matches any pattern. In those cases the xref UI will show you what the search found, and what it found may be wrong or empty.
Speed is the second limit. The README states that the package can be slow when it has to use grep, and on a large project that cost is paid on every jump, because nothing is cached between invocations. That is the deliberate trade: no index means no stale index, and also no warm start. A .dumbjump exclusion list and a switch to rg or ag are the two remedies the README offers. If your project is large, has no .dumbjump, and has no rg or ag installed, the experience will be poor, and the README does not pretend otherwise.
How It Differs from a Language Server
The obvious alternative for Emacs users is a language server through Eglot or lsp-mode. The difference is not one of quality settings; it is a different model of what a definition is. A language server parses the project, understands scopes and types, and answers queries from that model. It can distinguish a local variable from a method with the same name, follow re-exports, and resolve overloads. Dumb Jump cannot do any of that, because it never builds a model. It matches patterns in text.
The cost side is inverted. A language server needs a server binary per language, a project root it can identify, and a process running while you edit, and it needs to index or at least parse the project before it answers well. Dumb Jump needs a searcher binary and nothing else. For a repository in one mainstream language, the language server is the better tool and the gap is large. For a repository that mixes a handful of the languages on Dumb Jump's list, including ones with immature or nonexistent servers, the setup cost of the server route is real and Dumb Jump covers all of them with one configuration.
The two are not mutually exclusive. The xref backend mechanism means Dumb Jump registers itself as one backend among others, and the README's installation step is exactly that registration. A user can keep a language server for the language where precision matters and let Dumb Jump handle the rest, though the README does not document backend priority rules, so which one answers first is something to check in your own configuration.
Maintenance, Releases and the GPL-3.0 Licence
The release history is uneven. Version 0.5.3 landed in September 2019, 0.5.4 in October 2021, and 0.5.5 in February 2026. The repository is not archived and the last push recorded is June 2026, so the project is alive, but a four-year gap between 0.5.4 and 0.5.5 is the shape of a package that is maintained rather than actively developed. For a tool whose core is a search invocation plus regex tables, that is not automatically a problem. Language regexes do not decay quickly, and the package has no server component that needs to track upstream protocol changes.
The practical upgrade cost is low. Installation is through MELPA, and the README notes that Spacemacs ships the package already. Upgrading is a package.el operation, and the only compatibility boundary the README calls out is the Emacs version: 0.5.5 is the last release supporting Emacs below 26, so anyone on Emacs 24 or 25 should stay on 0.5.5 or earlier rather than upgrade. The xref backend requires Emacs 26.1 at minimum, and the completing-read selection function requires Xref 1.1.0, which means Emacs 28.1 or a separate ELPA install.
On licensing, Dumb Jump is GPL-3.0. That is the same licence family as GNU Emacs itself, which is the ordinary situation for Emacs packages distributed through MELPA. If you are considering bundling the package into a larger distribution or modifying and redistributing it, the GPL-3.0 terms apply to that redistribution, and the specifics are a question for your own counsel rather than something to settle from a README.
Editorial conclusion
Dumb Jump fits Emacs users who want M-. to work across many languages with no server processes and no index to keep fresh, especially in polyglot repositories where setting up a language server per language is not worth the effort. It is the wrong choice when you need type-aware results, since the README itself frames the package as a text search with heuristics rather than an analyzer, and it will be slow on large projects if you are stuck on grep. Before adopting it, install rg or ag, confirm that a project root is detected, and decide whether a .dumbjump exclusion list is needed. If you want precise definitions in one language, a language server through Eglot or lsp-mode is the better fit.
Community notes