# Changelog

## master (unreleased)

## 3.1.0 (2026-07-04)

### New features

* Add declarative "file kinds", letting a project type describe categories of files (e.g. Rails models, controllers and views) via the new `:file-kinds` keyword of `projectile-register-project-type`.
  * `projectile-find-file-of-kind` (`j`) prompts for a kind and completes over just the project files of that kind.
  * `projectile-toggle-related-file` (`J`) generalizes `projectile-toggle-between-implementation-and-test`: it jumps to related files of other kinds, jumping straight when there's one, prompting when there are several, and cycling through them on repeated presses.
  * The `rails-test`, `rails-rspec` and `django` project types ship with ready-made `:file-kinds` tables. Related files are keyed by their namespaced path, so a top-level `UsersController` relates to the top-level `User` model rather than an `Admin::User`.
* `projectile-find-file` and `projectile-find-file-dwim` now rank the files you work with first, ordering completion candidates by how often and how recently you've visited them (with decay).
  * The ranking is applied through completion metadata, so it works with any completion UI and under every indexing method, including `alien` (which `projectile-sort-order` never reached).
  * Controlled by `projectile-enable-frecency` (default on); the per-project history is persisted in `projectile-frecency-file` and capped by `projectile-frecency-max-files`.
* [#1992](https://github.com/bbatsov/projectile/issues/1992), [#1587](https://github.com/bbatsov/projectile/issues/1587), [#1553](https://github.com/bbatsov/projectile/issues/1553), [#1794](https://github.com/bbatsov/projectile/issues/1794): Add named project tasks - shell commands (or functions returning them) that you can run by name.
  * `projectile-tasks` maps task names to commands and can be set globally, per project type via the new `:tasks` keyword of `projectile-register-project-type`, or per project via `.dir-locals.el`.
  * `projectile-run-task` (`c x`) picks a task with completion and runs it like the lifecycle commands, in a per-task compilation buffer; a prefix argument lets you edit the command first (e.g. to pass ad-hoc arguments).
  * `projectile-repeat-last-task` (`c X`) re-runs the project's last task.
* [#978](https://github.com/bbatsov/projectile/issues/978): Add `projectile-project-changed-functions`, run whenever the current project changes - including implicitly via visiting a file or directory of another project - with the new and previous project root as arguments.
* [#1442](https://github.com/bbatsov/projectile/pull/1442): `projectile-sort-order` can now be set to a function that receives the list of project files and returns them in the desired order.
* [#1984](https://github.com/bbatsov/projectile/pull/1984): The VCS markers are now customizable via `projectile-vcs-markers`, whose order breaks ties between markers in the same directory - so colocated `jj`+`git` repositories can be detected as `jj` by moving `.jj` first.
* [#1890](https://github.com/bbatsov/projectile/pull/1890): Recognize osc (openSUSE Build Service) checkouts: `.osc` is now a VCS marker, a top-down-recurring root marker, and globally ignored; file listing uses the generic indexing command.
* [#1694](https://github.com/bbatsov/projectile/issues/1694): Add `projectile-invalidate-cache-all`, which invalidates the caches of all known projects at once (handy when commands like `projectile-find-file-in-known-projects` serve stale results).
* [#1075](https://github.com/bbatsov/projectile/issues/1075): Add experimental opt-in automatic cache updates via filesystem notifications, so files created, deleted or renamed outside Emacs update the cache without a manual `projectile-invalidate-cache`.
  * Enable it with `projectile-auto-update-cache-with-watches`; only local, cached projects are watched.
  * Each project uses one `file-notify` watch per directory, bounded by `projectile-watch-directory-limit`.
...
...
