Pickers
A very efficient way of navigating across the filesystem and projects is not with a file tree, but rather by using pickers, which are interactive windows used to select various kinds of items.
If you know at least a few characters of the filename, then you can use a file picker to effectively teleport to that file — via typing those few characters and selecting the first result. This is possible thanks to fuzzy searching ↗.
Useful pickers
Some of the most useful pickers that are really worth knowing about.
File Picker
Suppose we have the following directory structure, and we’re located in the my-project
directory:
Directorymy-project ⟵ you are here
Directorysrc
Directoryapp
- page.tsx
- globals.css ⟵ you want to go here
- layout.tsx
Directorycomponents
- button.tsx
- tsconfig.json
- package.json
- README.md
If we open a specific file e.g. with hx README.md
, then it’ll just open normally.
But if we open the directory, then it’ll actually open a file picker at that location. For instance, if we run hx src
:
┌──────────────────────────┐ │ 4/4 │ │──────────────────────────│ │ > app/globals.css │ │ app/layout.tsx │ │ app/page.tsx │ │ components/button.tsx │ │ │ └──────────────────────────┘ NOR [scratch] 1 sel 1:1
It opens a file picker in the src
directory, allowing us to perform a fuzzy search, recursively matching against every file in the directory, and any sub-directory.
Typing just a few characters of the file that we want to go then pressing Enter to select the first result will teleport us there. Extremely handy when you know the name of a file and just want to go there, without wasting time traversing directories.
You can also manually open a file picker by using Space + f. This will open it at the root project directory, so Helix will traverse up the tree to find whatever it considers the “project root”, usually if there is a .git
folder.
To open a file picker at the current working directory, use Space + f.
Open last picker
Suppose we navigated through a few more files, and now we want to go back.
We could just repeat the last steps, but there’s a better way. Space + ’ opens the exact picker that you last used, left in its previous state:
1 ┌──────────────────────────────────┐┌───────────────────────────────────┐ │ className 17/17 ││ import Image from "next/image"; │ │──────────────────────────────────││ │ │ path ││ export default function Home() │ │ app/layout.tsx:29 ││ return ( │ │ > app/page.tsx:5 ││ <div className="grid grid-row │ │ app/page.tsx:6 ││ <main className="flex flex- │ │ app/page.tsx:8 ││ <Image │ 1│ app/page.tsx:15 ││ className="dark:invert" │ 1│ app/page.tsx:16 ││ src="/next.svg" │ 1└──────────────────────────────────┘└───────────────────────────────────┘ 13 "react-dom": "19.0.0-rc-66855b96-20241106", NOR ~/r/my-app/package.json 1 sel 1:1
Buffer picker
Say we opened several files and we’d like to go work on one of the files we already opened. But we don’t want to perform the task of finding that file again, as it’s buried somewhere very deep within the project.
You can open a picker that shows your currently open buffers with Space + b:
1 This is a [Next.js](https://nextjs.org) project bootstrapped with [`create- ┌──────────────────────────────────┐┌───────────────────────────────────┐ │ 4/4 ││ │ │──────────────────────────────────││ "name": "my-app", │ │ id flags path ││ "version": "0.1.0", │ │ 5 * ~/r/my-app/README.md ││ "private": true, │ │ 4 …/my-app/tsconfig.json││ "scripts": │ │ 3 app/page.tsx ││ "dev": "next dev --turbopack" │ │ > 2 …r/my-app/package.json││ "build": "next build", │ 1│ ││ "start": "next start", │ 1│ ││ "lint": "next lint" │ 1└──────────────────────────────────┘└───────────────────────────────────┘ 13 # or NOR ~/r/my-app/README.md 1 sel 1:1
Usage
Most pickers perform fuzzy matching using fzf syntax ↗.
Two exceptions are:
- Global search picker, which uses regex
- Workspace symbol picker, which passes search terms to the LSP.
Keymap
Within a picker, the following commands are useful:
- Enter opens the selected file
- Ctrl + v opens as a horizontal split
- Ctrl + s opens as a vertical split
For more keymaps that you can use in a picker, see the picker keymap reference.
Using registers in pickers
You can insert the contents of a register using Ctrl + r followed by a register name.
For example, one could insert the currently selected text using Ctrl + r + ., or the directory of the current file using Ctrl + r + % followed by Ctrl w to remove the last path section.
The global search picker will use the contents of the search register if you press Enter without typing a filter.
For example, pressing * + Space + / + Enter will start a global search for the currently selected text.
Next steps
- More pickers can be found in the keymap reference.