Usage

Everything in this section assumes you’ve enabled projectile-mode.

Basic setup

In this section we’ll cover the bare minimum of setup you might want to do. Projectile works fine with no setup, but if you tweak the configuration a bit you’ll get more out of it.

Check out the "Configuration" section of the manual for a lot more information about configuring Projectile.

Automated Project Discovery

To add a project to Projectile’s list of known projects, open a file in the project. If you have a projects directory, you can tell Projectile about all of the projects in it with the command M-x projectile-discover-projects-in-directory.

You can go one step further and set a list of folders which Projectile is automatically going to check for projects on startup.

Recursive discovery is configured by specifying the search depth in a cons cell:

(setq projectile-project-search-path '("~/projects/" "~/work/" ("~/github" . 1)))

You can suppress the auto-discovery of projects on startup by setting projectile-auto-discover to nil. You can manually trigger the project discovery using M-x projectile-discover-projects-in-search-path.

Minibuffer Completion

While Projectile works fine with Emacs’s default minibuffer completion system you’re highly encouraged to use some powerful alternative like ido, ivy, selectrum or vertico.

If you’re going to use the ido completion it’s highly recommended that you install the optional flx-ido package, which provides a much more powerful alternative to ido's built-in flex matching. Similarly, for selectrum it’s a good idea to enable prescient (a package similar to flx).

Installing External Tools

Windows users can ignore this section unless they are using Emacs via WSL or cygwin.

Projectile will work without any external dependencies out of the box. However, if you have various tools installed, they will be automatically used when appropriate to improve performance.

Inside version control repositories, VC tools are used when installed to list files more efficiently. The supported tools include git, hg, fossil, bzr, darcs, pijul, svn, sapling and jujutsu.

Outside version control repositories, file search tools are used when installed for a faster search than pure Elisp. The supported tools include fd and GNU/BSD find.

By default, if fd is installed, it is also used inside Git repositories as an alternative to git ls-files, because git ls-files has the limitation that it also lists deleted files until the deletions are staged, which can be confusing. You can eliminate the use of fd in this circumstance by setting projectile-git-use-fd to nil.

To benefit from the projectile-ag and projectile-ripgrep commands to perform file search, it’s recommended to install ag (the_silver_searcher) and/or rg (ripgrep)

You should also install the Emacs packages ag, ripgrep or rg if you want to make sure of Projectile’s commands projectile-ag and projectile-ripgrep.

Basic Usage

Just open some file in a version-controlled (e.g. git) or a project (e.g. maven) directory that’s recognized by Projectile and you’re ready for action. Projectile happens to recognize out of the box every common VCS and many popular project types for various programming languages. You can learn more about Projectile’s notion of a project here.

The extent of the support for every VCS differs and Git is the best supported one. Projectile supports some advanced features like working with Git submodules and using git-grep instead GNU grep.

You need to know only a handful of Projectile commands to start benefiting from it.

  • Find file in current project (s-p f)

  • Switch project (s-p p) (you can also switch between open projects with s-p q)

  • Grep (search for text/regexp) in project (s-p s g)

  • Replace in project (s-p r)

  • Find references in project (s-p ? or s-p s x)

  • Invoke any Projectile command via the Projectile Commander (s-p m)

  • Toggle between implementation and test (s-p t)

  • Toggle between related files (e.g. foo.h <→ foo.c and Gemfile <→ Gemfile.lock) (s-p a)

  • Run a shell command in the root of the project (s-p ! for a sync command and s-p & for an async command)

  • Run various pre-defined project commands like:

    • build/compile project (s-p c)

    • test project (s-p T)

The next section lists many more commands, but the basics can get you pretty far.

Interactive Commands

Projectile doesn’t have a default key prefix for its commands, but all the examples in the manual assume you’ve opted for s-p (super-p).

Here’s a list of the interactive Emacs Lisp functions, provided by Projectile:

Keybinding Description

s-p f

Display a list of all files in the project. With a prefix argument it will clear the cache first.

s-p F

Display a list of all files in all known projects.

s-p g

Display a list of all files at point in the project. With a prefix argument it will clear the cache first.

s-p 4 f

Jump to a project’s file using completion and show it in another window.

s-p 4 g

Jump to a project’s file based on context at point and show it in another window.

s-p 5 f

Jump to a project’s file using completion and show it in another frame.

s-p 5 g

Jump to a project’s file based on context at point and show it in another frame.

s-p d

Display a list of all directories in the project. With a prefix argument it will clear the cache first.

s-p 4 d

Switch to a project directory and show it in another window.

s-p 5 d

Switch to a project directory and show it in another frame.

s-p T

Display a list of all test files(specs, features, etc) in the project.

s-p l

Display a list of all files in a directory (that’s not necessarily a project)

s-p s g

Run grep on the files in the project.

M-- s-p s g

Run grep on projectile-grep-default-files in the project.

s-p s s

Runs ag (the_silver_searcher) on the project, performing a literal search. Requires the presence of ag.el. With a prefix argument it will perform a regex search.

s-p s r

Runs rg (ripgrep) on the project, performing a literal search. Requires the presence of rg.el or ripgrep.el. With a prefix argument it will perform a regex search.

s-p s x

Find references to the symbol at point within the project. Uses internally the xref library.

s-p v

Run vc-dir on the root directory of the project.

s-p V

Browse dirty version controlled projects.

s-p b

Display a list of all project buffers currently open.

s-p 4 b

Switch to a project buffer and show it in another window.

s-p 5 b

Switch to a project buffer and show it in another frame.

s-p 4 C-o

Display a project buffer in another window without selecting it.

s-p a

Switch between files with the same name but different extensions.

s-p 4 a

Switch between files with the same name but different extensions in other window.

s-p 5 a

Switch between files with the same name but different extensions in other frame.

s-p o

Runs multi-occur on all project buffers currently open.

s-p r

Runs interactive query-replace on all files in the projects.

s-p i

Invalidates the project cache (if existing).

s-p R

Regenerates the projects TAGS file.

s-p j

Find tag in project’s TAGS file.

s-p k

Kills all project buffers.

s-p D

Opens the root of the project in dired.

s-p 4 D

Opens the root of the project in dired in another window.

s-p 5 D

Opens the root of the project in dired in another frame.

s-p e

Shows a list of recently visited project files.

s-p left

Switch to the previous project buffer.

s-p right

Switch to the next project buffer.

s-p E

Opens the root dir-locals-file of the project.

s-p !

Runs shell-command in the root directory of the project.

s-p &

Runs async-shell-command in the root directory of the project.

s-p C

Runs a standard configure command for your type of project.

s-p c

Runs a standard compilation command for your type of project.

s-p P

Runs a standard test command for your type of project.

s-p t

Toggle between an implementation file and its test file.

s-p 4 t

Jump to implementation or test file in other window.

s-p 5 t

Jump to implementation or test file in other frame.

s-p z

Adds the currently visited file to the cache.

s-p p

Display a list of known projects you can switch to.

s-p q

Display a list of open projects you can switch to.

s-p S

Save all project buffers.

s-p m

Run the commander (an interface to run commands with a single key).

s-p x e

Start or visit an eshell for the project.

s-p x i

Start or visit an ielm (Elisp REPL) for the project.

s-p x t

Start or visit an ansi-term for the project.

s-p x s

Start or visit a shell for the project.

s-p x g

Start or visit a gdb for the project.

s-p x v

Start or visit a vterm for the project.

s-p ESC

Switch to the most recently selected Projectile buffer.

If you ever forget any of Projectile’s keybindings just do a:

s-p C-h

Customizing Projectile’s Keybindings

It is possible to add additional commands to projectile-command-map referenced by the prefix key in projectile-mode-map. You can add multiple keymap prefix for all commands. Here’s an example that adds super-, as a command prefix:

(define-key projectile-mode-map (kbd "s-,") 'projectile-command-map)

You can also bind the projectile-command-map to any other map you’d like (including the global keymap).

For some common commands you might want to take a little shortcut and leverage the fairly unused Super key (by default Command on Mac keyboards and Windows on Win keyboards).

Here’s something you can add to your Emacs config:

(define-key projectile-mode-map [?\s-d] 'projectile-find-dir)
(define-key projectile-mode-map [?\s-p] 'projectile-switch-project)
(define-key projectile-mode-map [?\s-f] 'projectile-find-file)
(define-key projectile-mode-map [?\s-g] 'projectile-grep)
Note that the Super keybindings are not usable in Windows, as Windows makes heavy use of such keybindings itself. Emacs Prelude already adds those extra keybindings.

Projectile Commander

Projectile’s Commander (projectile-commander) is a nifty utility for those of you who are struggling to remember a lot of keybindings. It provides a simple interface to most of Projectile’s commands via 1-character shortcuts that you need to press after invoking the commander (e.g. via s-p m).

The commander was created with the idea to provide a powerful project switching command (it will be triggered if you press C-u s-p p), but it’s very useful on its own as well.

Keybinding

Description

?

Commander help buffer.

D

Open project root in dired.

R

Regenerate the project’s etags/gtags.

T

Find test file in project.

V

Browse dirty projects

a

Run ag on project.

b

Switch to project buffer.

d

Find directory in project.

e

Find recently visited file in project.

f

Find file in project.

g

Run grep on project.

j

Find tag in project.

k

Kill all project buffers.

o

Run multi-occur on project buffers.

r

Replace a string in the project.

s

Switch project.

v

Open project root in vc-dir or magit.

You can add additional commands to the commander like this:

(def-projectile-commander-method ?f
  "Find file in project."
  (projectile-find-file))

Place such snippets after projectile-mode's init code.

Using Projectile with project.el

Starting with version 2.7 Projectile bundles some integration with project.el that makes project.el use Projectile’s project lookup function (projectile-project-root) and project file lookup function (projectile-project-files) whenever projectile-mode is enabled. You can also enable the integration manually like this:

(add-hook 'project-find-functions #'project-projectile)
You can read more about the implementation details of the integration here.

That’s useful as some packages (e.g. eglot) support natively only project.el's API for project discovery. Fortunately, project.el makes it easy to install additional project lookup functions and that’s exactly what Projectile does.

The popular xref package also relies on project.el to infer the project for helpful commands like xref-find-references (M-?), so it’s useful to teach it about Projectile’s project discovery logic.

Projectile provides its own alternative to xref-find-references that’s named projectile-find-references (s-p ? or s-p s-x) and is using xref internally.

You can disable the project.el integration like this:

(remove-hook 'project-find-functions #'project-projectile)