I have a hobby server with a significant numbr of USB hard drives. I have aggressive power management enabled, and a short spin-down timeout, as these drives are basically meant to be cold storage with quick accessibility when needed. So most of them spend 99.9% of their time in APM standby until I need to access them, at which point they spin up, and for single drives I have access within ten seconds, for drives in RAID, up to 30 seconds.

The ZSH completion system is giving me headaches in this regard, since the arguably fantastic auto-completion magic it offers has some sort of automatic path validation going on as well, even when I don't press TAB, and even if I use my arrow keys to traverse the shell command history.

For instance, I can type rsync, then press the up key to start traversing the history for my previous rsync commands, and immediately the completion magic starts to access filesystem paths in those commands to validate and do magic stuff on them. This not only causes huge pauses where zsh blocks and becomes unresponsive, it also spins up sleeping drives which increases wear on those spinners. Any paths to network mounts also cause delays due to their network nature.

It also kicks in while writing a path, with me just typing letters, slashes and wildcards.

I have found a lot of questions about similar gripes, like this one, but I've yet to find something that addresses this precisely.

On the mentioned post above, there's a link to the zsh Completion System docs, and while reading them I find myself still confused. From the docs I'm not even sure what the syntax for zstyle is, and I'm confused about a lot of the terminology.

Basically I'm just looking for a way to say to zsh, "listen mate, I love what you're doing, but could you wait with all you wonderful magic until I press TAB?"

2 Answers 2


Zsh doesn't start doing any kind of completion magic until you press Tab in a “normal” configuration. It can be done but it would take some serious extension.

If you're using a zsh configuration framework, it might come standard with that feature. You'd have to look up the documentation of that framework to see how to disable it, not the documentation of zsh itself.

Going by your description of this feature, the line editor must have been customized in some way. I'm not sure if there's a hook somewhere you can define to achieve this behavior, or if self-insertion has to be overridden. Try listing key bidings with bindkey and see if anything stands out. Maybe compare with what you get with zsh -f (this starts zsh without reading .zshrc and other configuration files).

If you're puzzled about what's going on, you can tell it to log all the commands it runs to a file. (A plain set -x logs on the terminal, but it's likely to be too much to make any practical use.)

exec 2>zsh.log; set -x

To undo:

set +x; exec 2>/dev/tty

If you want to trace the completion process (as opposed to the process by which something like completion gets triggered in a non-completion scenario), you can run the command _complete_debug (bound to ^X? by default) instead of pressing Tab.

The zsh documentation is pretty hard to read. I recommend looking up examples of something close to what you want to do, and then looking at the documentation once you've found the likely command/variable/function/… you need. The zstyle documentation explains how it works, but to understand how it's used in the completion system you need to know the syntax of zstyle contexts used by completion, and then to know where it's used you need to look up the documentation of functions that use it, or sometimes read the source. You do not need to understand anything about zstyle to solve your problem anyway: getting automatic behavior outside of completion can't be triggered by the completion configuration alone (and probably not at all, although that automatic behavior might mimic completion and reuse its settings). There has to be some configuration of the line editor, probably a bunch of custom key bindings.

  • What a wonderful answer! Thank you so much for this extensive text. And of course, you're right, I don't know why I hadn't even considered this, but I'm using "Oh My ZSH" along with zsh, and using zsh -f for a vanilla experience as you suggest removes all issues. I feel so dumb not even remembering "Oh My," but I guess since it's how I initially came to zsh, it's simply what zsh "is" to me. I'm using your debugging tips to have a (oh-my) zsh session while logging, trying to detect the culprit. I'll update my original question once I find out. Once again, thank you so much for this help. Aug 29, 2022 at 10:30

(WARNING: Only read this if you like story hour and if you're interested in how I debugged and found the culprit. Some people don't deal well with verbosity — if that's you, this isn't for you).

Okay, so I'm adding this as an "answer" instead of updating the original question, since I'm gonna document how I figured out who the culprit was. The real answer to the actual question ("Who is causing my (oh my) zsh to lag" is Gilles' answer above, this is just an addendum to his tips, which I think could be useful to someone else debugging "Oh My ZSH." Put your likes there (please don't dislike this).

Here's a couple of specific problems I've encountered that I've using to test against changes I made to configs along the way:

  • I have an open session in a folder path residing on a drive that has been spun down, such as /media/drive-f/Apps. I've been away from this session long enough for the drive to have spun down, but the zsh session is still at that path. I want to go back to my home folder, so I start to type cd. As soon as I hit c, zsh blocks and the drive spins up. Something wants to examine the current dir as a reaction to my typing on the keyboard.
  • When typing a path, or pasting a full path, to a location on a spun-down drive, something running in the zsh environment wants to look at the drive in the before I press enter or TAB, and it blocks while the drive spins up. E.g. I'm navigating to /media/drive-k/Apps. If I paste the path, the shell blocks. If I type it, the shell blocks as soon as I type the A in "Apps."

So, first test, as commented on Gilles' answer, was to use his zsh -f tip and get a complete vanilla zsh session. Absolute nothing blocks unless, for instance, I press TAB or ls a spun-down location. I can even TAB my way to a spun-down location without spinning up the drive, so long as that location has been cached somewhere. E.g., I could TAB to /media/drive-d/Projects with /media/drive-d/P<TAB>, and drive d remained spun down. Only when I then did an ls -l did the drive spin up.

Good. Next step was to try the logging tip from Gilles. This logging is very verbose, and having the plugin z enabled, I got a lot of confusing logs about directories that had absolutely nothing to do with where I was at the time. Also, while navigating to a path that blocked the shell, the logs remained silent until the block was released, at which point the log presented a huge amount of output, so it seemed the blocking is part of a single "outer operation" (perhaps not the best phrasing) that encapsulates the collecting of all debug output as well. I had hoped to see the log present a series of lines up to when the culprit for the block started running and then a pause followed by more lines.

This not being the case, I decided to simply disable all plugins and try to re-enable them one by one, while trying to repeat the two problems above. I set the spin-down timeout on all drives to 30 seconds, using sudo hdparm -S 6 /dev/disk/by-id/usb-*0:0 (I'm targeting all drives that are on the USB bus here, using the 0:0 suffix to avoid trying to use hdparm against partitions on those drives (-S <num> is seconds in num multiples of 5, so 30 seconds).

The procedure from here was then to edit ~/.zshrc, disable all plugins (I had plugins=(colored-man-pages git-extras history pj redis-cli urltools z zsh-syntax-highlighting)). Then, in two NEW SHELLS (so as to read the updated config), navigate to /media/drive-b/Projects in one to be able to reproduce issue number two, and a blank one in /home/daniel to be ready to reproduce issue number one. Then wait 30 seconds and try to do just that.

I could confirm that having no plugins loaded, the shells reproduced neither of the two issues.

I then simply reenabled each plugin in sequence until I found the culprit, then opening new zsh sessions as described and waiting more than 30 seconds (while immediately thinking that urltools was the culprit (because URLs ~ paths) (full disclaimer, I'm writing along in the past tense while debugging this, so I don't know yet, let's see if I'm right [suspenseful music])).

I was wrong. I made it all the way to the end, re-enabling every plugin, ending at zsh-syntax-highlighting. And then the issues reappeared. I immediately thought I'd somehow missed something or mis-tested something along the way (maybe I forget to open a new shell reading in the changes?), so I removed zsh-syntax-highlighting, and tried to reproduce the problem even more extensively. No problems. Everything as normal.

Actually, this makes sense. This is the plugin that turns cd into green when a command. When you're in a directory with cdroms in it, it wants to print it gray. I like that feature. But DEFINITELY not enough to live with these drawbacks XD.

OMG, I'm so happy my server is back to normal. Thank you, Gilles, for helping me out. Hope someone else can use this.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .