Skip to content
System One

mrnugget/jev-shell-history

Fish-style autosuggestions for zsh ranked by Jev. As you type, the plugin sends your last 100 distinct history entries and asks which one you are most likely completing, then shows the best match in grey with its score for you to accept.

Image from mrnugget/jev-shell-history
Image from github.com

mrnugget/jev-shell-history on GitHub

Stars
108
Forks
8
Language
TypeScript
Last push
18 Sep 2026

Read from GitHub on . Counts change daily.

jev-shell-history brings fish-style autosuggestions to zsh and ranks the candidates with Jev. As you type, the plugin looks at your last 100 distinct history entries. If some start with what you typed, only those go to Jev; if none do, all of them go (fuzzy mode), and a single prefix match is suggested without a request. One request asks two questions: a choice of which entry you are most likely completing, and a noul on whether any entry completes the input at all. The best match appears in grey after the cursor with its score attached, and pressing the right arrow, Control-E, or End accepts it.

Every keystroke cancels any in-flight request and starts a new one in the background, so the prompt never blocks waiting on a network call, and a result is only applied if the buffer still matches what was typed when the request started. A fuzzy mode adds separate thresholds: a minimum probability that any candidate completes the input at all, a minimum score for the top candidate, and a score high enough to override the first threshold outright. History limit, minimum characters before it activates, and the model used are all configurable. The README puts latency at roughly 0.7 to 0.9 seconds per request, almost all of it API time.

It needs zsh 5.9 or newer, Node 22 or newer, and a TypeSafe API key; the demo in the README runs against a fabricated history generated for the recording.

How it uses Jev

const { state, questions } = buildRequest(typed, candidates);
const response = await client.systemOne(
  options.model ? { state, questions, model: options.model } : { state, questions },
  options.timeoutMs !== undefined ? { timeout: options.timeoutMs } : {},
);

const probabilities = response.answers.completion.probabilities;
const ranked = candidates
  .map((c) => ({
    command: c.command,
    score: probabilities[c.id] ?? 0,
    isPrefix: c.command.startsWith(typed),
  }))
  .sort((a, b) => b.score - a.score);

View in src/suggest.ts

Open on GitHub

More like this

Use cases this is tagged with