Migrating from project.el
A short guide for people who’ve been using Emacs’s built-in project.el and want to try Projectile. For the bigger picture (philosophical differences, feature gaps in either direction) see Projectile versus project.el; for a side-by-side mapping of commands and config knobs see the "Concept and command concordance" section there.
Quick start
Install Projectile from MELPA (or NonGNU ELPA), enable the global mode, and bind a prefix key:
(require 'projectile)
(projectile-mode +1)
(define-key projectile-mode-map (kbd "C-c p") 'projectile-command-map)
project.el’s `C-x p keymap continues to work; Projectile’s keymap is independent. The prefix doesn’t have to be C-c p — many people use s-p or whatever else fits their setup.
That’s enough to get going. Most of project.el’s commands have a direct Projectile counterpart (e.g. `C-x p f becomes C-c p f, C-x p p becomes C-c p p).
Behavioral differences worth knowing
A handful of places where Projectile doesn’t behave like project.el:
-
Switching projects.
project-switch-projectopens a command menu; Projectile instead runs whatever’s inprojectile-switch-project-actionafter picking a project (find-file by default). If you miss the menu UX, press C-u s-p p to get theprojectile-dispatchmenu after selecting a project (requires the optionaltransientdependency). -
Indexing strategies. Projectile has three (
native,hybrid,alien) controlled byprojectile-indexing-method. The default isalienand behaves likeproject.el’s VC backend (delegates to `git ls-files,fd,findetc.). Picknativeif you need to work somewhere external tools aren’t available. -
.projectile. Projectile’s native config file is consulted only undernativeorhybridindexing. Underalien(the default) it’s mostly ignored — the external tool’s ignore rules (.gitignoreetc.) take over. So in most modern setups,.projectiledoesn’t do much. -
Project types. Projectile auto-detects ~60 project types (Cargo, Maven, Mix, npm, etc.) and pre-fills
projectile-compile-project,projectile-test-project,projectile-run-project,projectile-install-project,projectile-package-project, andprojectile-configure-projectwith sensible defaults for each. There’s no equivalent inproject.el—project-compileruns whatevercompile-commandhappens to be. -
Buffer ownership. Projectile and
project.eluse slightly different rules to decide which buffers belong to a project. Don’t expectprojectile-kill-buffersandproject-kill-buffersto act on identical sets. -
Persistent caches. Projectile maintains a project-file cache (controlled by
projectile-enable-caching) and a known-projects file (projectile-known-projects-file). The latter is roughly analogous toproject-list-file, but the format differs.
Configuration knob translation
Most knob-for-knob mappings are in the concordance table in the comparison page. A few common ones:
| If you had | Use |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
Things that don’t have a direct equivalent (yet)
A few project.el features have no real Projectile counterpart at the time of writing:
-
project-find-matching-buffer(jump to the equivalent buffer in another project) -
project-file-history-behavior'relativize(file-name history rewritten across projects) -
project-other-window-command/-other-frame-command/-other-tab-command(prefix-style display redirection — we duplicate commands instead) -
Sparse-index support for Git
-
project-vc-merge-submodules(explicit Git submodule strategy)
See the comparison page for the full list.
Coexisting with project.el
You don’t have to pick one. project.el ships with Emacs and won’t go away, and several other packages (xref, eglot, modern compilation buffers) will reach for project-current regardless of whether Projectile is loaded.
In practice this means: enabling projectile-mode doesn’t disable project.el. Both keymaps coexist, both sets of commands are available via M-x. Just keep in mind that some features (e.g. modeline integration, idle file-existence caching) come from projectile-mode itself, so if you turn the mode off you lose them.