Back to blog

How I taught my terminal to find any folder

I’ve been seeing Herdr — a new terminal-native agent runtime — on my TL for a while now, and I decided to try it out yesterday night. As expected, the install was a single curl command, and within a minute, I had it running in my terminal.

Then I hit the wall I didn’t see coming. I wanted to open one of my projects the way I would in any graphical user interface (GUI) editor — click File, click Open Folder, browse to the project, done. In fact, one of the reasons I hesitated trying it out is because I thought it was just another cmux, which I was enjoying. However, Herdr lives entirely inside the terminal, so there was no menu to click & definitely no folder picker. As is now apparent, to “open” a folder in Herdr, I had to already be standing inside that folder when I launched it.

And that’s when I realised I didn’t actually know how to do that.

I’m so used to apps handing me a folder picker on a silver platter that I’d never properly learnt how to navigate to a project from the terminal. Well, I never had to. So I tried what I’d seen before — cd handwriting-converter — and the terminal cheerfully replied with cd: no such file or directory: handwriting-converter.

I knew the folder existed because I had been editing files inside it throughout the weekend. Yet here was my terminal, swearing that this folder was a figment of my imagination. I even pasted the name from Finder to rule out a typo, but I got the same response.

So I did what I do when I’m clearly missing something obvious, especially stuff like this — I laid the problem out to Zuri. “I just started using Herdr in terminal. How do I open a specific project/folder?” What followed was an hour of wrong turns, a fancy auto-learning tool that couldn’t actually help me yet, and a single-line wrapper that finally meant I never have to remember a project path again.

TL;DR: the wrapper that finally stuck

Install fzf, then append this small function to your ~/.zshrc:

brew install fzf
echo '
fcd() {
  local dir
  dir=$(find ~ -maxdepth 5 -type d 2>/dev/null | fzf)
  if [ -n "$dir" ]; then
    cd "$dir"
  fi
}' >> ~/.zshrc

Reload your shell with source ~/.zshrc, then type fcd from anywhere. The picker pops up with every folder five levels deep into your home directory. Type a fragment of the name, hit enter, and you’re inside — even on your first visit, and without setting up a single alias.

Setting up Herdr was the easy part

Once Herdr is installed, launching it is just herdr. The terminal user interface (TUI) opens with an empty workspace. What I like is how mouse-friendly it’s, which isn’t that common in my likkle experience, and I also liked that the basic commands were spelt at the bottom of the screen:

  • Press n to create a new workspace, give it a name, hit enter.

  • Inside the workspace, you get a terminal pane.

  • cd into your project from that pane.

  • Press q to quit, and Herdr remembers each pane’s working directory so the next launch restores you to where you left off.

But that cd step was where everything fell apart. Herdr was happy to remember any folder I gave it. The problem was that I didn’t know how to give it the right folder to display.

Why my cd kept slamming into walls

This is probably something you learn at bootcamps, or if you’re able to finish those online programming courses that I never got to the end of. Apparently, cd is shockingly literal, and it only looks inside the room you’re currently standing in.

For noobs like me, think of your computer like a multi-storey compound. Every time you open the terminal, you get dropped at your own front door — your home directory, /Users/yourname, which the terminal lets you shorten to ~. From there, you can walk into any room directly off your hallway (cd Documents, cd Downloads). But if you ask for a room that lives inside your cousin’s flat three streets away (cd handwriting-converter), the terminal just shrugs because it doesn’t have native facilities to search the whole estate. It only looks at the doors right in front of it.

My handwriting-converter project wasn’t in my home folder and it was buried a few levels down inside another folder. To cd, that may as well have been on another continent.

Getting reacquainted with where I actually was

Before fixing the navigation, I had to stop guessing about my location. There are really only three commands that matter here:

pwd

pwd (aka, present working directory) tells you exactly which compound you’re standing in. When I’m three folders deep and lose track, this is the first thing to type.

ls

ls lists every door visible from where you are. If cd handwriting-converter fails, running ls first will show you what folders actually exist at your current spot, and immediately tell you whether you’re in the right neighbourhood at all.

ls -la

The -la flag is the same list but with the hidden doors revealed and the full details printed. Useful when you’re hunting for things like .zshrc or .git that the terminal politely hides by default.

When the project lives four streets away

ls only showed me the rooms I was already standing in. My handwriting-converter project wasn’t one of them, as it was inside a specific folder holding all my active projects. The terminal couldn’t find it from where I was standing, and I couldn’t remember the full path, which isn’t surprising tbh. Who keeps full paths in their head?

The other option is to drag and drop the folder, which I didn’t even know was a thing before. But that also meant a likkle more work than I’d like, and I really just felt someone somewhere must’ve smartly solved this problem. So I asked Zuri for more options.

A wrong-OS install I had to redo

Zuri’s first suggestion was a fuzzy finder called fzf. Instead of typing exact folder names, you give fzf a list of folders and it filters them interactively as you type — close enough is good enough.

The recommended install command came back as:

apt install fzf

I ran it, and the terminal coughed up zsh: command not found: apt.

This is the moment I would’ve been stuck for an hour without a peer, because apparently, apt is the Debian/Ubuntu package manager. I’m on a Mac, and macOS uses Homebrew. Because my VPS is a Linux environment, Zuri’s first instinct had quietly assumed a Linux box, and neither of us caught it until the terminal pushed back.

The real command, on macOS, is:

brew install fzf

After that finished, Zuri suggested I also run the optional setup script to wire up shell keybindings:

$(brew --prefix)/opt/fzf/install

The script asked if I wanted fuzzy auto-completion, key bindings, and shell config updates. I said yes to all three. It dropped a .fzf.zsh file into my home directory and added one source line to my .zshrc. After a quick source ~/.zshrc, fzf was live — Ctrl+T for fuzzy file search, Alt+C for fuzzy cd.

But raw fzf still felt like too much work for me

Fzf worked exactly as advertised. But every single time I wanted to jump to a project, the dance was:

  1. Hit Alt+C to open the fuzzy directory picker.
  2. Wait for the giant list of folders to populate.
  3. Start typing letters to narrow it.
  4. Eyeball the result, arrow up or down if needed.
  5. Hit enter.

Five steps to do something that, in a GUI, took less clicks. The fuzzy picker also pulled in every directory it could find — node_modules, hidden config folders, system paths — and I had to mentally filter through the noise each time. Compared to my old File → Open Folder flow, this didn’t feel like an upgrade. It felt like I’d swapped one kind of friction for another.

So I went back to Zuri with this: “opening a project seems to be too technical for me. I can’t remember project paths, and fuzzy search feels like more work than I’d like.”

Introducing the auto-learner that couldn’t actually help me yet

Zuri offered two alternatives. The first was shell aliases — hardcode each project’s path under a short name in your .zshrc:

alias handwriting-converter="cd ~/workspace/projects/handwriting-converter"
alias my-website="cd ~/workspace/projects/my-website"

This is like saving each restaurant’s number under a custom name in your contacts. Works beautifully if you have five regular spots. Painful if you have fifty, and worse, you have to manually maintain the list every time a project moves or gets renamed.

The second was a tool called zoxide. The pitch was almost magical, to my noob self at least — zoxide quietly watches every cd you run, builds a little memory of where you go and how often, and then lets you jump to any of those folders by typing a fragment of the name. Just z handwriting and you’re inside, with no exact spelling required and no picker to scroll through. See, I knew someone smart must’ve thought about this.

Installing zoxide was three quick commands:

brew install zoxide
eval "$(zoxide init zsh)"
echo 'eval "$(zoxide init zsh)"' >> ~/.zshrc

Excited, I immediately typed:

z handwriting converter

The terminal replied with zsh: command not found: z.

The first cause was easy; I hadn’t reloaded my config. source ~/.zshrc taught the running shell about the new function. But then Zuri explained the real problem that for some reason wasn’t mentioned before & I was guilty of the thing developers do when they don’t read the docs.

Zoxide builds its memory from your cd history, so on a fresh install, that memory is completely empty. It’ll only let you jump to folders you’ve already cd-ed into at least once after installing it. The official docs spell it out plainly: the database is populated as you change directories.

Which meant zoxide couldn’t help me. The whole reason I was stuck was that I didn’t know how to cd into handwriting-converter in the first place. Zoxide is the takeaway joint that remembers your order, but it can’t remember an order you’ve never actually placed. Brilliant for the second visit. Useless for the first.

Zuri’s workaround was honest, but dumb & I had to do a policy update afterwards to curb suggestions like this: cd manually into all my projects once, just to seed the database. But that meant I still had to find the full paths somehow, which was the original problem I was trying to solve. The auto-learner couldn’t help me until I’d already solved the discovery problem by hand.

So I put zoxide on the wishlist for later, when I’d have a healthy cd history, and went back to fzf with a sharper question.

Going back to fzf, but smarter this time

The fix turned out to be wrapping fzf around a tool that already knew where every folder was — find. Instead of typing folder names blindly, I’d have find enumerate every directory on my disk and pipe that list into fzf for instant fuzzy filtering.

Zuri walked me through the one-liner first:

cd $(find ~ -maxdepth 5 -type d 2>/dev/null | fzf)

The pieces are quietly logical once you spell them out:

  • find ~ searches starting from my home directory.

  • -maxdepth 5 caps the search at five folders deep, which keeps it fast and stops it spelunking forever into node_modules.

  • -type d says “only show me directories, not files.”

  • 2>/dev/null quietly bins the “permission denied” complaints that pop up when find pokes into system folders.

  • | fzf pipes whatever survives into the fuzzy picker.

  • $(...) feeds my final selection back to cd so it walks me there.

The critical difference from zoxide was that find doesn’t need any prior history. It walks the disk fresh each time, so even folders I’d never visited showed up immediately. So now, Zoxide’s chicken-and-egg problem disappeared.

But still, no sane human is going to retype that one-liner every day. So we wrapped it into a tiny shell function called fcd (fuzzy cd) and made it permanent by appending it to my .zshrc:

echo '
fcd() {
  local dir
  dir=$(find ~ -maxdepth 5 -type d 2>/dev/null | fzf)
  if [ -n "$dir" ]; then
    cd "$dir"
  fi
}' >> ~/.zshrc

One reload — source ~/.zshrc — and fcd was available from anywhere. I typed fcd, the picker popped up, I typed hand, handwriting-converter floated to the top, I hit enter, and I was finally inside the folder I’d been chasing for an hour. From there, herdr launched the workspace exactly where I needed it.

What I keep in my head now

After all that, my mental cheat sheet is genuinely small. These are the only things I carry around:

CommandWhat it does
pwdTells me which compound I’m in
lsShows me the doors I can see
cd foldernameWalks me into that room
cd ..Steps back one level
cd ~Teleports me home
cd -Snaps back to my last spot
TabLets the terminal finish my sentence
fcdFuzzy-finds any folder anywhere and walks me there

Working with personal agents is teaching me the benefits of pushing back and the importance of a wide imagination. I can imagine this process coming off as being stubborn with a crowd that believes in “you can’t have everything” and “manage it like that”, but I’ve been on a run to simplify my work this year. I don’t always get what I’d like, but it’s often closer than I particularly knew was possible.

The willingness to ditch a tool — like zoxide — that wasn’t ready for me yet is also key, as sunk cost fallacy is a real drawback in many cases. Now when I want to start work, I type fcd, mumble part of a project name, and hit enter. Once I’ve used the fcd-and-cd-into-things flow long enough, I’ll probably revisit zoxide and let it inherit the muscle memory. For now, fcd and Herdr are all I need to open the whole herd.

See you in the next one. Cheers 🥂