# Changelog

<!-- Entries are one line per item and section headings repeat for every release,
     so the line-length and duplicate-heading rules don't fit this file. -->
<!-- markdownlint-disable MD013 MD024 -->

## master (unreleased)

## 3.4.0 (2026-08-10)

### New features

- [#2148](https://github.com/bbatsov/projectile/pull/2148): Add `projectile-switch-sibling-project` (`s-p n`), which offers only the projects related to the one you're in, rather than every project on the machine.
  - Relatedness comes from `projectile-project-groups` if you've configured it, then from the owner of the upstream remote, then from the leading word of the directory name - see `projectile-sibling-project-functions`.
  - The remote's owner is what relates projects whose names have nothing in common; an inferred group covering more than `projectile-sibling-max-group-share` of your projects is dropped, since "we're all under the same account" relates nothing.
- [#2151](https://github.com/bbatsov/projectile/pull/2151): `projectile-switch-worktree` also offers Jujutsu workspaces, and a jj repository is now identified through its git backing store, so a workspace and the colocated git checkout agree on being the same thing and jj projects get siblings like any other.
- [#2147](https://github.com/bbatsov/projectile/pull/2147): Add `projectile-switch-worktree` (`s-p W`), which offers the other checkouts of the current project's repository, each annotated with whatever tells it apart - the branch for git and Mercurial, the workspace name for Jujutsu.
  - Git worktrees and separate clones of the same upstream both count as checkouts, since they're the same workflow with and without the plumbing; `projectile-worktree-functions` is where other ways of finding them plug in.
- [#2138](https://github.com/bbatsov/projectile/pull/2138): Better support for OCaml, Erlang and F#.
  - `projectile-run-test-at-point` learns `erlang-ts-mode` (EUnit's `_test`/`_test_` functions, run as `rebar3 eunit --test=module:name`) and `fsharp-ts-mode` (bindings attributed `[<Fact>]`, `[<Theory>]`, `[<Test>]`, `[<TestCase>]` or `[<Property>]`, run through `dotnet test --filter`).
  - The `ocaml-dune` and `rebar` project types gained their run, install, package and source/test directory attributes, and a new `erlang-mk` type covers the other common Erlang build tool.
  - OCaml deliberately gets no test-at-point rule: its tests are ordinary values registered with Alcotest or OUnit rather than anything the syntax marks out, so there is nothing to recognize.
- [#2137](https://github.com/bbatsov/projectile/pull/2137): Ship `:file-kinds` tables for Phoenix, Laravel and Next.js, so `projectile-find-file-of-kind` (`s-p j`) and `projectile-toggle-related-file` (`s-p J`) work in those out of the box - Rails and Django were the only frameworks covered before.
  - Phoenix keys a resource's modules on the name they share (`user_controller.ex`, `user_html.ex`, `user_live.ex`), Laravel on the model's class name, Next.js on the app router's directory.
  - Adds a `nextjs` project type (`next.config.js` and friends) to hang the last of those on.
- [#2136](https://github.com/bbatsov/projectile/pull/2136): `projectile-run-test-at-point` now knows Ruby (RSpec and Minitest), Rust, Elixir and Java, on top of the Python, Go and JS/TS rules it shipped with.
  - Ruby is written the same way whichever framework you use, so the project type picks the runner; Java's picks between Maven and Gradle, and takes the class name from the file.
  - ExUnit can't select a test by name from the command line, so Elixir tests are addressed as `FILE:LINE`.
- [#2135](https://github.com/bbatsov/projectile/pull/2135): Add `projectile-ignored-project-patterns`, the regexp-matching sibling of `projectile-ignored-projects` (exact paths) and `projectile-ignored-project-function` (a predicate), so keeping whole areas of a machine out of the known projects doesn't need a lambda.
- [#2134](https://github.com/bbatsov/projectile/pull/2134): Add `projectile-find-changed-file` (`s-p C`), which completes over the files git reports as staged, unstaged or untracked - or, with a prefix argument, over everything that differs from a revision you pick.
...
...
