Cached at:
05/31/26, 08:17 AM
# A simple project switcher for Kakoune
Source: [https://bhoot.org/2026/kakoune-project-switcher/](https://bhoot.org/2026/kakoune-project-switcher/)
## Table of contents
1. [Table of contents](https://bhoot.org/2026/kakoune-project-switcher/#table-of-contents)
2. [How other editors implement a project switcher](https://bhoot.org/2026/kakoune-project-switcher/#how-other-editors-implement-a-project-switcher)
3. [Elements of a project switcher](https://bhoot.org/2026/kakoune-project-switcher/#elements-of-a-project-switcher)
4. [How I manifested the elements in Kakoune](https://bhoot.org/2026/kakoune-project-switcher/#how-i-manifested-the-elements-in-kakoune)1. [Registering a new project with the interface](https://bhoot.org/2026/kakoune-project-switcher/#registering-a-new-project-with-the-interface) 2. [Switching to a registered project](https://bhoot.org/2026/kakoune-project-switcher/#switching-to-a-registered-project)
5. [Bonus \- file picker](https://bhoot.org/2026/kakoune-project-switcher/#bonus---file-picker)
6. [Bonus \- keybindings](https://bhoot.org/2026/kakoune-project-switcher/#bonus---keybindings)
7. [In closing](https://bhoot.org/2026/kakoune-project-switcher/#in-closing)
I always appreciate a project\-switching interface in my editor\.
I didn't expect[Kakoune](https://kakoune.org/), a barebones terminal editor, to have a built\-in project switcher\. But, after executing`cd $project\_dir; kak`for the nth time, I started looking for a solution\.
## How other editors implement a project switcher
VS Code provides a project switcher through*Open Recent*action, bound toCtrl\+Ron Linux\. In my experience, any file or folder opened with VS Code's*Open File*or*Open Folder*dialogs show up here\. So its a bit of a stretch to call it a project switcher if you frequently open files directly\.
The following video snippet demonstrates VS Code's switcher:
JetBrains IDEs offer an unbounded*Open Recent Project*action, which opens the switcher at the tip of the cursor\. though I use a[FrameSwitcher plugin](https://plugins.jetbrains.com/plugin/7138-frameswitcher)which performs the job better\.
The following video snippet demonstrates WebStorm's switcher:
## Elements of a project switcher
I identify two essential elements of a project switcher interface:
1. Display a list of projects already registered with the interface, through which one can fuzzy find and switch to a project\. Once switched, the selected project's directory becomes the current directory within the editor's context, so that editor actions happen in the selected project directory's context\. So, for instance, a file finder would now look for a file within the selected project's directory\. And so on\.
2. Add a new project to the interface\. Usually this is automatic\. When user opens a new project in JetBrains IDEs or VS Code, the editor automatically register the project to the switcher interface\.
## How I manifested the elements in Kakoune
Kakoune's scripting primitives, combined with its philosophy to use shell scripting to extend itself, were adequate tools to build a simple project switcher\.
I needed a place to persistently register opened project directories in Kakoune\. I chose a plaintext`projects`file that sits besides kakoune's config file`~/\.config/kak/kakrc`\. Each line in`projects`store a path to a project dir\.
### Registering a new project with the interface
I wrote a Kakoune command:project\-addthat:
1. lets user choose a directory from their filesystem, using Kakoune's path completion interface
2. appends the path of the chosen directory in`projects`file
3. uses Kakoune's:change\-directoryprimitive to set the chosen directory as Kakoune's working directory
Here is the implementation:
```
define-command project-add \
-docstring "Add a project" \
-params 1 %{
nop %sh{ printf "%s\n" "$1" >> ~/.config/kak/projects }
change-directory %arg{1}
exec ":file-picker "
}
complete-command project-add file
```
### Switching to a registered project
I implemented a Kakoune command:project\-pickthat:
1. lists the paths stored in`projects`file using Kakoune's completion interface
2. sets the working directory of Kakoune to the selected path using its:change\-directoryprimitive
Here is the implementation:
```
define-command project-pick \
-docstring "Pick a project" \
-params 1 %{
change-directory %arg{1}
exec ":file-picker "
}
complete-command project-pick \
shell-script-candidates \
%{ cat ~/.config/kak/projects }
```
## Bonus \- file picker
Both:project\-addand:project\-pickcommands lands the user on a file picker interface, which again builds on top of Kakoune's completion interface, so that they can start working right away on their project\.
```
define-command file-picker \
-docstring "Pick a file from current directory" \
-params 1 %{ edit %arg{1} }
complete-command file-picker \
shell-script-candidates \
%{ git ls-files -c -o --exclude-standard }
```
## Bonus \- keybindings
Both the commands received their own keybindings for quick execution\. Kakoune offers custom user modes which can act as namespaces to neatly tuck away related keybindings\. I created a*project*user mode to do just that for my project switcher\.
```
declare-user-mode project
map global user p ":enter-user-mode project
" \
-docstring "Project commands"
map global project p ":project-pick " \
-docstring "Pick a project"
map global project a ":project-add " \
-docstring "Add a project"
```
## In closing
I could implement guardrails like checking for existence of the`projects`file, or add a`:project\-delete`command, but I'm satisfied with the current state\. Any comments are welcome\.