Directory jumpers such as z.sh and zoxide need to rank candidate directories from a stream of past navigation events. Most implementations use some form of frecency: a score combining historical visit count with recency.The details vary, but the basic idea is always score = frequency × recency where frequency measures how often a directory has been visited and recency depends on last visit time. After evaluating some tools, I have become convinced that this scoring model is wrong. The reason concerns the structure of the formula itself.## Problem 1: historical visits never really disappearSuppose a directory visited many times before but now dormant for months. A frecency system typically preserves the large historical count and only reduces the recency term. The directory therefore retains a large amount of latent weight .When visited again, the recency term resets while the historical count remains intact. Consequently, a directory that has been irrelevant for months can jump straight back to a top rank after a single revisit. Many users of directory jumpers have observed this behavior. It is one of the reasons people occasionally edit the database manually.The underlying issue is that the scoring model stores (total historical usage) × (current recency) rather than the decayed contribution of individual visits.## Exponential moving sum (EMS)A more natural model is to treat visits as unit impulses and let each individual impulse decay exponentially until query time score(t) = Σ exp(-λ(t - ti)) and to sum over all past visits. A long dormant directory, if revisited once, will get score≈1, independent of ancient visit history. This is exactly the same mathematical formalism that appears throughout signal processing and streaming statistics. Unix load averages are one example.A remarkable property of EMS is that storing the full history is not required. Rather, recursive score computation is possible: score(t) = score(tlast) · exp(-λ(t - tlast)) + 1 requiring only the previous score and the timestamp of the last event.## Problem 2: wall-clock time is not always meaningfulmost directory jumpers use wall-clock time as their notion of time. Therefore, scores continue to decay during periods where no shell activity occurs (e.g. holidays). After a sufficiently long absence, all scores are pushed toward zero. The first few directories visited after returning then dominate the ranking, without good reason to treat the previously visited ones as having lost relevance in the meantime.One alternative is to replace wall-clock time with an event-driven clock. This clock advances once per navigation event: tick = tick + 1 Under this model, time stops when the user is inactive. Decay reflects actually ongoing navigation activity rather than elapsed wall-clock time. This addresses a failure mode that is different from the frecency issue above. In fact, the two ideas are largely orthogonal:* exponential moving sums solve the reanimation of long-dormant high-frequency entries* event clocks prevent rankings from being distorted by long inactive periodsWhy I ended up implementing thisI previously wrote a directory-navigation tool that stores complete event history and uses an event-clock exponential moving sum internally. Later I wondered how much of that behavior could be reproduced in a much simpler aggregate-state database similar to z.sh. That experiment became ze.sh.The implementation turned out to be surprisingly small and tt accurately produces the desired EMS ranking behavior without need for retaining the full event stream.What surprised me most is not that the approach works, but that exponential moving sums seem relatively uncommon in this category of tools despite being a standard solution in many other domains involving event streams and ranking.