I use Atuin, but unlike the author actually find it more valuable since I use it across many machines. I have 7 different machines (of various make and OS though all *NIX) in my house right now that I regularly SSH in to or use directly, and Atuin's sync keeps my history on all of them. If I want to narrow down by host I can still do that. I also keep similar directory structures so I can narrow down by directory even if I performed a command on a different machine most of the time.
That said, some form of advanced history search is a game changer, no matter how you get it. It's one of those "can't understand how I lived without it" things once you get it going.
I’ve started using Atuin based on a recommendation from here a few weeks ago. I generally like it, but feel like the fuzzy matching is bad - maybe I either misconfigured something or nobody else cares about it?
If the command I want to match against is within the last few days or so, the fuzzy match performs ok, but anything from months ago which I know for a fact is in the history, it just doesn’t match it and instead shows irrelevant items (which technically I’m sure according to some algorithm are correct). Another one is I often have to put a ^ to ensure the ‘curl’ I’m searching for starts looking for matches at beginning of line.
Often times I still fall back to using fzf on ~/.zsh_history which seems to get what I want.
There is this thread which is same issues I’m seeing, and I did try smart_sort=True but it’s still not great.
If using Nix, you can get Atuin working basically for free by just enabling it in the config. I love it. Does everything I'd every hoped for with history search.
I don't really like nix (yeah I tried it for a couple of months), but I'd like to point out that atuin is exceptionally easy to set up even without using nix as well in case someone gets an idea that it is difficult.
I'm also in this boat. I have atuin as part of my zsh config that is distributed to all new machines, whether they run NixOS or some other operating system with Nix on them (e.g. MacOS). After switching to NixOS I found an interest in maintaining a custom setup again, since it wouldn't fall apart every time I moved machine.
{ pkgs, ... }:
{
users.defaultUserShell = pkgs.zsh;
environment.systemPackages = with pkgs; [
atuin # ^R
eza # ls
git
zsh
];
programs.direnv.enable = true;
programs.nix-direnv.enable = true;
programs.zsh = {
enable = true;
enableCompletion = true;
enableBashCompletion = true;
enableGlobalCompInit = true;
# https://github.com/zsh-users/zsh-syntax-highlighting/blob/master/docs/highlighters.md
syntaxHighlighting.enable = true;
syntaxHighlighting.highlighters = [ "main" "brackets" ];
# See `man zshoptions` for more details.
setOptions = [
# Remove duplicates continuously from command history (preserve newest entry).
"HIST_IGNORE_DUPS"
# Instantly share command history between all active shells.
"SHARE_HISTORY" # Alternative to: "APPEND_HISTORY", "INC_APPEND_HISTORY",
# Disable ^S and ^Z for less accidental freezing.
"FLOW_CONTROL"
# Save timestamp and duration of each command in command history.
"EXTENDED_HISTORY"
];
shellAliases = {
# Navigation
rm = "rm -iv";
ls = "eza -lg";
tree = "eza -lgT";
# git aliases
# ...
};
promptInit = ''
autoload -U promptinit
promptinit
prompt off
# Simple:
# PS1='[%n@%m:%~] %(!.#.$) '
# Colorful:
# PS1='[%F{green}%n@%m%f:%F{blue}%~%f] %(!.#.$) '
# Colorful with git branch:
function git_branch_name() {
branch=$(git symbolic-ref HEAD --short 2>/dev/null)
if [ ! -z "$branch" ]; then
echo -n " [%F{red}$branch%f]"
fi
}
# Omit username, print hostname + '$' with red when root, otherwise green:
prompt='[%(!.%F{red}.%F{green})%m%f:%F{blue}%~%f]$(git_branch_name) %(!.%F{red}#%f.$) '
# See: https://zsh.sourceforge.io/Doc/Release/Options.html#Prompting
setopt prompt_cr
setopt prompt_sp
setopt prompt_subst
export PROMPT_EOL_MARK=""
'';
interactiveShellInit = ''
# Prevent user-level "config missing" message.
touch $HOME/.zshrc
# MacOS
bindkey '^[[7~' beginning-of-line
bindkey '^[[8~' end-of-line
# Linux
bindkey '^[[1;3D' beginning-of-line # alt+left
bindkey '^[[1;3C' end-of-line # alt+right
bindkey '^[[1;5D' backward-word # ctrl+left
bindkey '^[[1;5C' forward-word # ctrl+right
# Both
bindkey '^R' history-incremental-search-backward
bindkey '^U' kill-whole-line
bindkey '^Y' yank
# My SSH endpoints don't recognize modern terminals
export TERM=xterm-256color
# ^R only
eval "$(atuin init zsh --disable-up-arrow)"
'';
};
}
Did you really need to share 108 lines of code, inline, rather than a link to gist/similar?
The chances of people reading this discussion running NixOS are small, and of those I'm sure the ones who were interested could search the internet for examples.
NixOS and Kagi user here. Hacker News often is the most reliable search result there is. Gists aren’t (they become easily deleted, unlike HN comments).
Curious on this: "Atuin's sync keeps my history on all of them"
I just checked on their GitHub and it says "Additionally, it provides optional and fully encrypted synchronisation of your history between machines, via an Atuin server."
So you trust all of your shell commands to be stored on a server that you don't control?
I love fzf but no need to invent the wheel here if you are using zsh. check out one of these zle plugins. (Demo https://asciinema.org/a/155704)
I prefer these two, you get good performance, search that is semi-shell syntax aware, ranking that takes age somewhat into account, and syntax hilighting.
Also one of fzf major yet non obvious feature is that you can use fzf in many places, which means that the fuzzy search algorithm and behaviour is exactly the same whether I search for shell history or project files in vim or commit messages or...
There's nothing more annoying than having two fuzzy search implementations that behave mostly the same except in this or that case which subtly breaks your implicit mental model of it.
Right, and fzf is usable across all major shells, which is a big plus. For example I use zsh at home, but at work I'm forced to use bash for everything, but it works there just the same. Plus you can bend it to other purposes than just a fancy history lookup
I've been using McFly [1] recently, and like it a lot.
> McFly replaces your default ctrl-r shell history search with an intelligent search engine that takes into account your working directory and the context of recently executed commands. McFly's suggestions are prioritized in real time with a small neural network.
the neural network is pretty broken. It prioritizes things that I did weeks ago over a command that I just ran 20 times. Be a bit critical of it, I actually found it fairly terrible.
I know it's open source and people working on it might be reading this so let me apologize to you personally and please don't take this message as discouragement. I know how demotivating one bad review can be. It just wasn't working for me.
this sort of topic illustrates the type of vexing problems that I wish a community model was better at addressing. Chasing and solving your own pain points is cool but frequently creates new pain points for other people. I love more features for searching history, but...
the reason bash uses Ctrl-r for searching back in history is because that's EMACS for searching back in your edit buffer (like C-a, C-f, C-b, C-e, etc are emacs cursor motions). I like the features of fzf, but I hate that it suddenly changes muscle memory that I rely on that is bigger than the immediate context.
these kinds of problems show up all over. I have always relied heavily on "middle button pastes the current mouse selection". I don't know what's going on in linux--is it Wayland?--but that feature is increasingly and increasingly being broken in more and more places. one place (which may entail a different "feature creep") is "click the url-bar in the browser and it auto-selects the whole thing...uh uh uh, wait, but not anymore for the purposes of the X-selection. but you can get the X-selection back if you click again (to deselect the whole thing) then again to reselect the whole thing... or is it double click..." the mind boggles
the old way (or goal) was to have the UI be standard, everywhere used the same code. but there were always people who wanted to innovate on their own, then with the idea of UX it wasn't any longer about standardization--or ironically personalization--at all
I realize whoever are making these changes simply don't work the way I have (for the last 35 yrs (well, that's just with linux)) so they don't notice what's being thrown away. I guess it's getting close to that time I should climb on and drift away on a little ice raft...
It is possible to change the history length in most shells including bash, when I googled it I found this baeldung.com article which says it can be set to unlimited using this (or use a big number if you'd prefer!):
export HISTSIZE=-1; export HISTFILESIZE=-1
Also, one can bind the 'up' key to do the search action too, which I think is pretty convenient, my bindings are for zsh but I think it should also work in bash:
Changes that some applications made for Wayland definitely broke pasting for me. It seems Wayland added a separate clipboard so going between apps was a crapshoot if pasting would work. I haven't found a solution that covers everything at once.
> I’m also not sure the ‘fuzzy’ aspects of Atuin quite match the heights of fzf/skim).
This. I've been using atuin for a few months and this is so horrible how much better it could be with a "real" fzf matching...
I just tried skim shell integration ( https://github.com/skim-rs/skim/tree/master/shell ) and it's great.
I kind of like the extra metadata atuin saves (cwd, session context), but I think I was just waiting to stumble into this to turn atuin back off...
You can have the best of both worlds - use atuin and fzf.
I use fish shell, so you'll have to forgive any fishisms.
First, when you start atuin, don't bind to ctrl-r, instead manually bind it to something else. I use ctrl-t. This brings up the "standard" atuin interface which you can use to get the more detailed history - in particular the command inspector can be super helpful as is the ability to limit scope of history searches.
Next, bind ctrl-r to something like this: `commandline -r (atuin history list --print0 -f "{time} | {command}" | fzf --read0 --delimiter="|" --accept-nth 2 | sed 's/^ *//')`
In fish-speak, that's saying replace the command line with a command that fzf selects from your atuin history (which has been pretty printed to show the time of the command, but that won't end up on the command line).
Probably 95% of the time I'm using my new ctrl-r which searches atuin history using fzf. The other 5% of the time I'm looking for a command that I know I've ran in a particular directory, or using the atuin history to remove problematic entries from my history.
I've considered this, but I'm running on a potato, and fetching the whole atuin history seems to take a while:
$ time atuin history list --print0 -f "{time} | {command}" > /dev/null
real 0m1.849s
(for some reason the built-in atuin search command doesn't take so long to show up? It might only fetch the last few entries from the db first... Eh, actually `atuin search` without argument which lists roughly the same thing run in less than half the time (0.85s), but -i is still another order of magnitude faster)
Personnally I use bash, so I made so my history is eternal (as is the content never get deleted) and I use FZF_CTRL_R_OPTS to customize the ctrl-r of fzf.
Also the history is reloaded after each command so if I type multiple commands in a tmux pane x, and then go to another tmux pane y I just have to type something (just press the enter key) in pane y and I have the full history of what happened in pane x.
Here is how to do it, just add the following to your .bashrc for the eternal history :
```
export HISTFILESIZE=
export HISTSIZE=
export HISTTIMEFORMAT="[%F %T] "
export HISTFILE=~/.bash_eternal_history
export HISTCONTROL=ignoreboth
shopt -s histappend
shopt -s checkwinsize
filtered_history_save() {
local last_command=$(history 1 | awk '{print $4}')
# Don't store some commands in the history.
if [[ ! "$last_command" =~ (mpv|pass|yt-dlp|wtwitch) ]]; then
history -a
fi
history -c
history -r
}
export PROMPT_COMMAND="filtered_history_save; $PROMPT_COMMAND"
# Sources :
# http://stackoverflow.com/questions/9457233/unlimited-bash-history
# http://superuser.com/questions/575479/bash-history-truncated-to-500-lines-on-each-login
# http://superuser.com/questions/20900/bash-history-loss
```
And for the custom fzf ctrl-r :
```
# Source fzf (should already be here if fzf is installed)
if [ -f /usr/share/fzf/completion.bash ]; then
. /usr/share/fzf/completion.bash
fi
if [ -f /usr/share/fzf/key-bindings.bash ]; then
. /usr/share/fzf/key-bindings.bash
fi
# Customize ctrl-r
export FZF_CTRL_R_OPTS="
--preview 'echo {2..} | bat --color=always -pl sh'
--preview-window right:wrap
--bind 'ctrl-/:toggle-preview'
--bind 'ctrl-t:track+clear-query'
--bind 'ctrl-y:execute-silent(echo -n {2..} | pbcopy)+abort'
--color header:italic
--header 'Press CTRL-Y to copy command into clipboard'"
I've been using Eli Bandersky Persistent History in Bash since more than 10+ years ago [1]. It's definitely given the biggest productivity boost when using
the shell. There's definitely newer solutions, but as the old adage goes if it aint broke don't fix it (and for the same reason I use bash because I know most of the quirks). The only addition is adding the fzf reverse history search for my current session.
> The network aspects of Atuin also gave me the heebie-jeebies. Reasonable people can differ on such matters.
The networking stuff can be fully compiled out of Atuin. The client and sync feature flags[1] control this, and it's fairly trivial to confirm that the networking crate (reqwest) is only enabled when the sync feature is enabled.[2]
Atuin can also be configured to only talk to your own sync server rather than the Atuin run server, and the history is e2e encrypted, so :shrug:. There's enough good engineering there that I'd not put it as particularly high on my list of security risks.
If you install atuin to give it a try, be careful to backup your history first. I installed it once and it deleted all my zsh history for some reason. I've rarely been more aware of how much I rely on my history to get things done.
Also it made atuin useless to me since I didn't have a history anymore so couldn't even try it properly.
Seems like general good advice, but for me it was simply a matter of `atuin import auto`. The initial response was similar (as in, here is no history, where is my history, this is useless). Then I read this page where it said to import, which seemed relevant:
Especially since it fits nicely into a mental model that includes !*, !^, !$, !-2 and such. ^something^somethingelse is also useful.
And the sudo !! pattern is something I do even when I realize that I need root ahead of time. There’s something about hitting enter on a command that makes me realize I’ve made a mistake, so doing that before I’ve granted root permissions is helpful. Up/ctrl-p are more awkward to use this way.
I also like typing `!:` (in zsh) and hitting tab and getting some helpful hints:
$ !:
& -- repeat substitution
A -- as ':a', then resolve symlinks
P -- realpath, resolve '..' physically
Q -- strip quotes
a -- absolute path, resolve '..' lexically
c -- PATH search for command
e -- leave only extension
g -- globally apply s or &
h -- head - strip trailing path element
l -- lower case all words
p -- print without executing
q -- quote to escape further substitutions
r -- root - strip suffix
s -- substitute string
t -- tail - strip directories
u -- upper case all words
x -- quote words, breaking on whitespace
It goes from the latest command down by default which isn't exactly the desired behavior but hesitated to add any other commands! I'm sure there is an option to reverse the order for a cli I'm already using but I couldn't find it in a cursory search :(
> What does 5408 mean and why is it taking up valuable screen space?
For anyone who's not familiar with something as basic as the history command, please pick up a book on bash/zsh/sh and take the time to learn.
If you don't know how to use the shell, you will struggle with (or simply be unable to perform) many basic tasks that could be accomplished quickly and easily by someone who's taken the time to learn how to use the shell and a handful of basic tools like grep, sed, awk, etc.
I once saw Bram Moolenaar do a Q&A on Vim. Someone asked about some feature or the other and Bram didn't really know how it worked from the top of his head, "because I never really use it".
Shells are large programs. Everyone is unfamiliar with some bits because it just doesn't fit in their workflow.
One could say the same thing about empathy, another "basic" skill.
Imagine how you'd rush to justify your lack of it here.
Everything you'd say in your defense would equally explain why someone wouldn't know the meaning of a certain unmarked number in the output of a random shell command.
There are a lot of people learning a lot of things for the first time everyday. Time and attention are limited and must be allocated, and sometimes that means you don't read manuals for everything.
I've seen myself transition. I've read python 2 stdlib docs cover to cover, and was better for it. It was also the last language for which I did that. I skimmed kotlin stdlib, and with go these days I hit up a search engine.
If everyone spent time going through every supposedly basic thing first, nobody would get anything done.
It's not at all obvious that the number is the history entry number, and I'm not even sure if knowing that brings any value to the average user.
I’m not defending GP, but this bit from your post got me thinking:
> If everyone spent time going through every supposedly basic thing first, nobody would get anything done.
I’m not convinced that’d be so bad. We could all strive to do less. There’s too much bullshit “doing” in the world and not enough thoughtful pondering on what should be done.
If everyone spent the time to go through basic things, and thus had less time to do new things, then there would be fewer things to go through. And every new thing would be informed by what came before and not repeat its mistakes. And they would have had more thought put into it, thus be less buggy and dysfunctional, thus necessitating fewer alternatives.
It’s not going to happen, but everyone doing less and taking the time to learn the basics would likely make the world better.
I think curiosity is a nice trait to have. Whenever I have a question like the one quoted, i just do a quick search if I have the time to do so (and more often than not, you do). Or I just add it to my notes.
I don't bother reading entire manuals either, but I know where they are. And if I'm using something often, I also try to learn how to best get help and information. Knowledge of the shell isn't mandatory, but can help greatly sometimes. If someone implement a feature to scratch an itch, it's nice to know about it when the same thing frustrates you too.
The shell should just have better UX. If 5408 is the id of the command ran... just list that out in the printed table. Powershell and nushell do this really well.
I've known this since the start of my using unix shells, but it's almost useless. For example, if fzf or whichever plugin I'm using shows me the number, why would I need it when I'm going to use the list it has presented? I certainly wouldn't cancel it and use the number, nor would I type the number when I have the choice of banging one key repeatedly, or adding characters I can see in the command to narrow the search even more.
I usually only care about commands from the same session, but sometimes I need to delve into the global history. With the default bash setup on most distros, the history log isn't updated until the shell terminates--leaving the "global" history incomplete until the other shells terminate. That is, I can lookup history from "dead" shells, but not from "living" ones.
I think shell history would be more practical if it appended to the history log after each command (rather than at the end of the session), and tagged each line with some form of "session ID"--allowing us to distinguish between "local" and "global" history.
You can force a flush to the log "as-is" with things like prompt overrides, but that's an all-or-nothing solution, saddling us with history from foreign shells even when we don't want it. Adding a session ID to the history log, and another flag to the built-in "history" command (to toggle between local and global history), would be a worthwhile improvement.
I have a similar setup. I use fzf plus a unique shared history that is 10000 items long. Last time I moved machines one of the important things to take over was my shell history. I have old obscure invocations that I can‘t remember but know that I did them in the past ;)
Unique is the key for me. I don‘t care that I ran cargo test 20 times in a row. Shared history across shells is a bit polarizing depending on your workflow. For me it’s important to have access to the items I ran in a different window/tab.
But what I can‘t understand is why so many paid professionals stick to the defaults. I shows my setup a few people and they all went: „what ?!? That is possible“ And that is the end of it. Well most devs I know sadly don‘t even know how to use the default search. The fact that you have to hit CTRL-R multiple times to skip to the next search result is a mystery.
Maybe someone needs to package a shell where this kinds of options are just the default. And maybe adds a more modern key binding interface.
Having the partial search bound to the up/down arrows is the most fundamental part of the shell for me. I very rarely have to resort to Ctrl-R. Every few weeks I might need a more complex history search, but for that I can just grep in my .zsh_history.
The problem with grep for me is that it's not really interactive. fzf allows me to fuzzy search and adjust the search term and seeing a list with results I then can select from.
Ctrl-R and sorting by time since the last run is nice, but odds are you run the same commands again and again WITHIN the context provided by the current directory, so the cwd should be kept
Another important parameter is the number of successful runs: if you successfully ran the same command in the same directory 30 times in the last 30 days, it may be more useful that the one you have only run 1 time yesterday, so the exit value (like `false ;echo $?`) is another thing to keep
I have 2 bash shortcuts: one for a context-free search (Ctrl-T), while the default (Ctrl-R) is restricted to the current directory, and I throw everything (cwd, start time, stop time, exit value...) in a sqlite database to do more advanced queries (ex: on average, at which hour do I make more mistakes?)
What I'd really like is integration between fzf and bash autocompletion so that I can get more of a code completion like experience. Or maybe something smarter still. I feel I could get so much more value from kubectl and/or yq with a bit better ux in this regard.
Maybe skim does this? Or fzf does it if I configure it differently?
At $WORK most of the machines are running KSH and I ended getting used to the vi shortcuts rather than the Emacs style, so I have also turned to it on my personal computers. Just append `set -o vi` to the user .profile or .bashrc file, and then you can use all of the vi key commands: /|? for searching, n to search previous results, etc.
I lately started using copilot with eclipse I was surprise how copilot started creating complete functions for me inferring what I was trying to do.
fzf could benefit of that.
If I do:
make
./run_program
fzf could create a line for after I do the sam e sequence 3 times that goes:
I've found bash's history-search-backward and history-search-forward very useful. They complete commands that begin with what you have typed. I have them mapped to M-p and M-n.
I also find myself using bash's insert-last-argument command, which can be repeated to fill in the last argument of previous commands. I have it mapped to M-_.
Another feature I've been using is the dabbrev-expand function, which xterm (and some other terminals) have. This allows string matching on the terminal output including the scroll buffer. It's useful for forming a new command that uses previous arguments that are not last arguments, or that are outputs of previous commands. I have it mapped to M-/. I've tweaked the matching algorithm on my local xterm to allow tokens enclosed in quotes or braces (which programs often output) to be matched (xterm by default only considers non-whitespace).
LaTeX returns .tex file compilation bugs as .log files when using pdflatex [filename.tex]
Is synthetic format prior to redirection and concatenating.
Whether using /.bashrc/ or saved in local directories, when debugging is typically resolved with querying X: quit or H: help.
The fish version of history search doesn't just do a simple substring search like in bash. It's already more powerful by doing a subsequence search. See https://github.com/fish-shell/fish-shell/pull/9476
fish suggests commands as you type, shown as faded text after the cursor. But suggestions aren't replacements for history search. Only one suggestion is shown at a time, and you don't have much control over what is shown.
It's popular though, so it's also available in zsh through the autosuggestions plugin.
I use Atuin, but unlike the author actually find it more valuable since I use it across many machines. I have 7 different machines (of various make and OS though all *NIX) in my house right now that I regularly SSH in to or use directly, and Atuin's sync keeps my history on all of them. If I want to narrow down by host I can still do that. I also keep similar directory structures so I can narrow down by directory even if I performed a command on a different machine most of the time.
That said, some form of advanced history search is a game changer, no matter how you get it. It's one of those "can't understand how I lived without it" things once you get it going.
I’ve started using Atuin based on a recommendation from here a few weeks ago. I generally like it, but feel like the fuzzy matching is bad - maybe I either misconfigured something or nobody else cares about it?
If the command I want to match against is within the last few days or so, the fuzzy match performs ok, but anything from months ago which I know for a fact is in the history, it just doesn’t match it and instead shows irrelevant items (which technically I’m sure according to some algorithm are correct). Another one is I often have to put a ^ to ensure the ‘curl’ I’m searching for starts looking for matches at beginning of line.
Often times I still fall back to using fzf on ~/.zsh_history which seems to get what I want. There is this thread which is same issues I’m seeing, and I did try smart_sort=True but it’s still not great.
https://forum.atuin.sh/t/understanding-atuin-history-search/...
Try to add ' in front of words to find exact matches if the fuzzy search isn't providing the results you're looking for.
If using Nix, you can get Atuin working basically for free by just enabling it in the config. I love it. Does everything I'd every hoped for with history search.
I don't really like nix (yeah I tried it for a couple of months), but I'd like to point out that atuin is exceptionally easy to set up even without using nix as well in case someone gets an idea that it is difficult.
I'm also in this boat. I have atuin as part of my zsh config that is distributed to all new machines, whether they run NixOS or some other operating system with Nix on them (e.g. MacOS). After switching to NixOS I found an interest in maintaining a custom setup again, since it wouldn't fall apart every time I moved machine.
Or if using home manager:
Did you really need to share 108 lines of code, inline, rather than a link to gist/similar?
The chances of people reading this discussion running NixOS are small, and of those I'm sure the ones who were interested could search the internet for examples.
NixOS and Kagi user here. Hacker News often is the most reliable search result there is. Gists aren’t (they become easily deleted, unlike HN comments).
Sure, and I accept that happily enough for "small" snippets. But I had to page down multiple times and it really felt like too much content.
I could have cut down the sample a lot, I apologize.
Curious on this: "Atuin's sync keeps my history on all of them"
I just checked on their GitHub and it says "Additionally, it provides optional and fully encrypted synchronisation of your history between machines, via an Atuin server."
So you trust all of your shell commands to be stored on a server that you don't control?
Maybe I'm missing something here.
Sync is optional*, end to end encrypted, and you can self host the server so you don't really need to trust anything if you don't want to
*: nothing syncs if you don't register, and you can even compile a version with the sync code flagged out if you REALLY don't want to trust anything
Got it, thx!
[dead]
I love fzf but no need to invent the wheel here if you are using zsh. check out one of these zle plugins. (Demo https://asciinema.org/a/155704)
I prefer these two, you get good performance, search that is semi-shell syntax aware, ranking that takes age somewhat into account, and syntax hilighting.
https://github.com/zdharma-continuum/history-search-multi-wo... with https://github.com/zdharma-continuum/fast-syntax-highlightin...
or the same thing but older, for those who like older things because they have an air of stability about them: https://github.com/zsh-users/zsh-history-substring-search
They're all external plugins, meaning that they're "inventing the wheel" as much as FZF is.
Also one of fzf major yet non obvious feature is that you can use fzf in many places, which means that the fuzzy search algorithm and behaviour is exactly the same whether I search for shell history or project files in vim or commit messages or...
There's nothing more annoying than having two fuzzy search implementations that behave mostly the same except in this or that case which subtly breaks your implicit mental model of it.
Consistency is underrated.
Right, and fzf is usable across all major shells, which is a big plus. For example I use zsh at home, but at work I'm forced to use bash for everything, but it works there just the same. Plus you can bend it to other purposes than just a fancy history lookup
fzf also has a zsh plugin
I've been using McFly [1] recently, and like it a lot.
> McFly replaces your default ctrl-r shell history search with an intelligent search engine that takes into account your working directory and the context of recently executed commands. McFly's suggestions are prioritized in real time with a small neural network.
[1] https://github.com/cantino/mcfly
the neural network is pretty broken. It prioritizes things that I did weeks ago over a command that I just ran 20 times. Be a bit critical of it, I actually found it fairly terrible.
I know it's open source and people working on it might be reading this so let me apologize to you personally and please don't take this message as discouragement. I know how demotivating one bad review can be. It just wasn't working for me.
I used to use McFly too, but atuin is much better. Worth trying, takes one minute to install it.
Which features from Atuin are missing from/inferior in McFly?
for me, atuin's history sync is a huge must since i use 5 different machines across my house.
atuin is much better in what? McFly is a lot more light weight and does semantic search using a neural network and do not need a database.
this sort of topic illustrates the type of vexing problems that I wish a community model was better at addressing. Chasing and solving your own pain points is cool but frequently creates new pain points for other people. I love more features for searching history, but...
the reason bash uses Ctrl-r for searching back in history is because that's EMACS for searching back in your edit buffer (like C-a, C-f, C-b, C-e, etc are emacs cursor motions). I like the features of fzf, but I hate that it suddenly changes muscle memory that I rely on that is bigger than the immediate context.
these kinds of problems show up all over. I have always relied heavily on "middle button pastes the current mouse selection". I don't know what's going on in linux--is it Wayland?--but that feature is increasingly and increasingly being broken in more and more places. one place (which may entail a different "feature creep") is "click the url-bar in the browser and it auto-selects the whole thing...uh uh uh, wait, but not anymore for the purposes of the X-selection. but you can get the X-selection back if you click again (to deselect the whole thing) then again to reselect the whole thing... or is it double click..." the mind boggles
the old way (or goal) was to have the UI be standard, everywhere used the same code. but there were always people who wanted to innovate on their own, then with the idea of UX it wasn't any longer about standardization--or ironically personalization--at all
I realize whoever are making these changes simply don't work the way I have (for the last 35 yrs (well, that's just with linux)) so they don't notice what's being thrown away. I guess it's getting close to that time I should climb on and drift away on a little ice raft...
100% agree. FWIW I use ctrl-r all day every day in emacs and also in the shell and its... fine.
In my opinion, the one thing that would make a difference is a longer and broader history.
It is possible to change the history length in most shells including bash, when I googled it I found this baeldung.com article which says it can be set to unlimited using this (or use a big number if you'd prefer!):
export HISTSIZE=-1; export HISTFILESIZE=-1
Also, one can bind the 'up' key to do the search action too, which I think is pretty convenient, my bindings are for zsh but I think it should also work in bash:
bindkey '^[[5~' up-line-or-history
bindkey '^[[6~' down-line-or-history
Changes that some applications made for Wayland definitely broke pasting for me. It seems Wayland added a separate clipboard so going between apps was a crapshoot if pasting would work. I haven't found a solution that covers everything at once.
I use zsh-histdb, and it's amazing. It shows return statuses and which directory the command was run from.
I honestly can't remember the entire setup, but my dotfiles that have the setup are here: https://github.com/Hobadee/dotfiles/blob/master/Common/profi...
> I’m also not sure the ‘fuzzy’ aspects of Atuin quite match the heights of fzf/skim).
This. I've been using atuin for a few months and this is so horrible how much better it could be with a "real" fzf matching... I just tried skim shell integration ( https://github.com/skim-rs/skim/tree/master/shell ) and it's great. I kind of like the extra metadata atuin saves (cwd, session context), but I think I was just waiting to stumble into this to turn atuin back off...
You can have the best of both worlds - use atuin and fzf.
I use fish shell, so you'll have to forgive any fishisms.
First, when you start atuin, don't bind to ctrl-r, instead manually bind it to something else. I use ctrl-t. This brings up the "standard" atuin interface which you can use to get the more detailed history - in particular the command inspector can be super helpful as is the ability to limit scope of history searches.
Next, bind ctrl-r to something like this: `commandline -r (atuin history list --print0 -f "{time} | {command}" | fzf --read0 --delimiter="|" --accept-nth 2 | sed 's/^ *//')`
In fish-speak, that's saying replace the command line with a command that fzf selects from your atuin history (which has been pretty printed to show the time of the command, but that won't end up on the command line).
Probably 95% of the time I'm using my new ctrl-r which searches atuin history using fzf. The other 5% of the time I'm looking for a command that I know I've ran in a particular directory, or using the atuin history to remove problematic entries from my history.
I've considered this, but I'm running on a potato, and fetching the whole atuin history seems to take a while:
(for some reason the built-in atuin search command doesn't take so long to show up? It might only fetch the last few entries from the db first... Eh, actually `atuin search` without argument which lists roughly the same thing run in less than half the time (0.85s), but -i is still another order of magnitude faster)Anyway, thanks - I'll fiddle with all this :)
...i just use both atuin and fzf.fish [1] and bind them both to another key.
[1] https://github.com/PatrickF1/fzf.fish/
Personnally I use bash, so I made so my history is eternal (as is the content never get deleted) and I use FZF_CTRL_R_OPTS to customize the ctrl-r of fzf.
Also the history is reloaded after each command so if I type multiple commands in a tmux pane x, and then go to another tmux pane y I just have to type something (just press the enter key) in pane y and I have the full history of what happened in pane x.
Here is how to do it, just add the following to your .bashrc for the eternal history :
```
```And for the custom fzf ctrl-r :
```
```I've been using Eli Bandersky Persistent History in Bash since more than 10+ years ago [1]. It's definitely given the biggest productivity boost when using the shell. There's definitely newer solutions, but as the old adage goes if it aint broke don't fix it (and for the same reason I use bash because I know most of the quirks). The only addition is adding the fzf reverse history search for my current session.
[1]: https://eli.thegreenplace.net/2013/06/11/keeping-persistent-...
> The network aspects of Atuin also gave me the heebie-jeebies. Reasonable people can differ on such matters.
The networking stuff can be fully compiled out of Atuin. The client and sync feature flags[1] control this, and it's fairly trivial to confirm that the networking crate (reqwest) is only enabled when the sync feature is enabled.[2]
Atuin can also be configured to only talk to your own sync server rather than the Atuin run server, and the history is e2e encrypted, so :shrug:. There's enough good engineering there that I'd not put it as particularly high on my list of security risks.
[1]: https://github.com/atuinsh/atuin/blob/e8df3d168e7fb9d6f99d97...
[2]: https://github.com/atuinsh/atuin/blob/e8df3d168e7fb9d6f99d97...
If you install atuin to give it a try, be careful to backup your history first. I installed it once and it deleted all my zsh history for some reason. I've rarely been more aware of how much I rely on my history to get things done.
Also it made atuin useless to me since I didn't have a history anymore so couldn't even try it properly.
Seems like general good advice, but for me it was simply a matter of `atuin import auto`. The initial response was similar (as in, here is no history, where is my history, this is useless). Then I read this page where it said to import, which seemed relevant:
https://docs.atuin.sh/
Not sure if that was the missing case for you, but just in case someone reads this and gets the same feeling as me
> and I’ve come across more than one paid professional who doesn’t use the “up” key to retrieve the previous command.
Well. I prefer ctrl-p personally, but I take your point:)
I'm a `!!` man.
Especially since it fits nicely into a mental model that includes !*, !^, !$, !-2 and such. ^something^somethingelse is also useful.
And the sudo !! pattern is something I do even when I realize that I need root ahead of time. There’s something about hitting enter on a command that makes me realize I’ve made a mistake, so doing that before I’ve granted root permissions is helpful. Up/ctrl-p are more awkward to use this way.
I also like typing `!:` (in zsh) and hitting tab and getting some helpful hints:
I do <Esc>k
[dead]
A fish version: https://gist.github.com/philocalyst/b2d764d694e63bc4c5143735...
It goes from the latest command down by default which isn't exactly the desired behavior but hesitated to add any other commands! I'm sure there is an option to reverse the order for a cli I'm already using but I couldn't find it in a cursory search :(
Feedback/commits appreciated.
Fyi; I assume you already checked out fzf.fish ?
https://github.com/PatrickF1/fzf.fish
Actually I did not! That's so great then -- maybe I'll just fork it and add skim support :)
Thanks
> What does 5408 mean and why is it taking up valuable screen space?
For anyone who's not familiar with something as basic as the history command, please pick up a book on bash/zsh/sh and take the time to learn.
If you don't know how to use the shell, you will struggle with (or simply be unable to perform) many basic tasks that could be accomplished quickly and easily by someone who's taken the time to learn how to use the shell and a handful of basic tools like grep, sed, awk, etc.
I once saw Bram Moolenaar do a Q&A on Vim. Someone asked about some feature or the other and Bram didn't really know how it worked from the top of his head, "because I never really use it".
Shells are large programs. Everyone is unfamiliar with some bits because it just doesn't fit in their workflow.
One could say the same thing about empathy, another "basic" skill.
Imagine how you'd rush to justify your lack of it here.
Everything you'd say in your defense would equally explain why someone wouldn't know the meaning of a certain unmarked number in the output of a random shell command.
There are a lot of people learning a lot of things for the first time everyday. Time and attention are limited and must be allocated, and sometimes that means you don't read manuals for everything.
I've seen myself transition. I've read python 2 stdlib docs cover to cover, and was better for it. It was also the last language for which I did that. I skimmed kotlin stdlib, and with go these days I hit up a search engine.
If everyone spent time going through every supposedly basic thing first, nobody would get anything done.
It's not at all obvious that the number is the history entry number, and I'm not even sure if knowing that brings any value to the average user.
I’m not defending GP, but this bit from your post got me thinking:
> If everyone spent time going through every supposedly basic thing first, nobody would get anything done.
I’m not convinced that’d be so bad. We could all strive to do less. There’s too much bullshit “doing” in the world and not enough thoughtful pondering on what should be done.
If everyone spent the time to go through basic things, and thus had less time to do new things, then there would be fewer things to go through. And every new thing would be informed by what came before and not repeat its mistakes. And they would have had more thought put into it, thus be less buggy and dysfunctional, thus necessitating fewer alternatives.
It’s not going to happen, but everyone doing less and taking the time to learn the basics would likely make the world better.
I think curiosity is a nice trait to have. Whenever I have a question like the one quoted, i just do a quick search if I have the time to do so (and more often than not, you do). Or I just add it to my notes.
I don't bother reading entire manuals either, but I know where they are. And if I'm using something often, I also try to learn how to best get help and information. Knowledge of the shell isn't mandatory, but can help greatly sometimes. If someone implement a feature to scratch an itch, it's nice to know about it when the same thing frustrates you too.
The shell should just have better UX. If 5408 is the id of the command ran... just list that out in the printed table. Powershell and nushell do this really well.
Because you can use the ID to recall a previous command with "!". This is a feature that predates Bash+readline.
History substitution with "!" goes back to Bill Joy's csh, 1979.
I've known this since the start of my using unix shells, but it's almost useless. For example, if fzf or whichever plugin I'm using shows me the number, why would I need it when I'm going to use the list it has presented? I certainly wouldn't cancel it and use the number, nor would I type the number when I have the choice of banging one key repeatedly, or adding characters I can see in the command to narrow the search even more.
Some features just aren't worth the time.
In nushell you can use it to look up more detail about that command:
It's nice for confirming a suspicion that something is now slower than it used to be.That's fair, I might have to change my ideas ;-)
> please pick up a book on bash/zsh/sh and take the time to learn.
Or even just the man page! bash(1)'s man page is a treasure trove, and it's a fairly short read (versus an entire book, at least).
I usually only care about commands from the same session, but sometimes I need to delve into the global history. With the default bash setup on most distros, the history log isn't updated until the shell terminates--leaving the "global" history incomplete until the other shells terminate. That is, I can lookup history from "dead" shells, but not from "living" ones.
I think shell history would be more practical if it appended to the history log after each command (rather than at the end of the session), and tagged each line with some form of "session ID"--allowing us to distinguish between "local" and "global" history.
You can force a flush to the log "as-is" with things like prompt overrides, but that's an all-or-nothing solution, saddling us with history from foreign shells even when we don't want it. Adding a session ID to the history log, and another flag to the built-in "history" command (to toggle between local and global history), would be a worthwhile improvement.
I have a similar setup. I use fzf plus a unique shared history that is 10000 items long. Last time I moved machines one of the important things to take over was my shell history. I have old obscure invocations that I can‘t remember but know that I did them in the past ;) Unique is the key for me. I don‘t care that I ran cargo test 20 times in a row. Shared history across shells is a bit polarizing depending on your workflow. For me it’s important to have access to the items I ran in a different window/tab. But what I can‘t understand is why so many paid professionals stick to the defaults. I shows my setup a few people and they all went: „what ?!? That is possible“ And that is the end of it. Well most devs I know sadly don‘t even know how to use the default search. The fact that you have to hit CTRL-R multiple times to skip to the next search result is a mystery. Maybe someone needs to package a shell where this kinds of options are just the default. And maybe adds a more modern key binding interface.
Well, you can go quite far with a few simple tweaks to Ctrl+R.
And then add the partial search to arrows: All that in bash.Having the partial search bound to the up/down arrows is the most fundamental part of the shell for me. I very rarely have to resort to Ctrl-R. Every few weeks I might need a more complex history search, but for that I can just grep in my .zsh_history.
The problem with grep for me is that it's not really interactive. fzf allows me to fuzzy search and adjust the search term and seeing a list with results I then can select from.
Ctrl-R and sorting by time since the last run is nice, but odds are you run the same commands again and again WITHIN the context provided by the current directory, so the cwd should be kept
Another important parameter is the number of successful runs: if you successfully ran the same command in the same directory 30 times in the last 30 days, it may be more useful that the one you have only run 1 time yesterday, so the exit value (like `false ;echo $?`) is another thing to keep
I have 2 bash shortcuts: one for a context-free search (Ctrl-T), while the default (Ctrl-R) is restricted to the current directory, and I throw everything (cwd, start time, stop time, exit value...) in a sqlite database to do more advanced queries (ex: on average, at which hour do I make more mistakes?)
Care to share the command(s) you're using to dump all that into SQLite?
You can get the config files from https://github.com/csdvrx/bash-timestamping-sqlite
What I'd really like is integration between fzf and bash autocompletion so that I can get more of a code completion like experience. Or maybe something smarter still. I feel I could get so much more value from kubectl and/or yq with a bit better ux in this regard.
Maybe skim does this? Or fzf does it if I configure it differently?
Ah, found this now, looks really promising! https://github.com/Aloxaf/fzf-tab (Oh, zsh specific)
No one using hstr? I'm a big fan of that one, though i must admit i haven't used much else other than bash's reverse history search.
At $WORK most of the machines are running KSH and I ended getting used to the vi shortcuts rather than the Emacs style, so I have also turned to it on my personal computers. Just append `set -o vi` to the user .profile or .bashrc file, and then you can use all of the vi key commands: /|? for searching, n to search previous results, etc.
I lately started using copilot with eclipse I was surprise how copilot started creating complete functions for me inferring what I was trying to do. fzf could benefit of that. If I do:
make ./run_program
fzf could create a line for after I do the sam e sequence 3 times that goes:
make && ./run_program
That would be cool.
> but I’ll often run a tiny subset of those commands (e.g. cargo test) hundreds of time in a single day.
Bacon replaces that command entirely for me (and many other cargo commands which would otherwise be run repetitively). https://dystroy.org/bacon/
I personally find ctrl-r does everything I want it to do, though I'm working with UUIDs a lot of the time which makes things easier I'm sure.
Things I'd like added to my command history:
- where it was executed
- If it failed
- stickies/favourites
I tried various things, but keep coming back to zsh/fzf. Now I want fuzzy searching everywhere.
For non-fuzzy options:
I've found bash's history-search-backward and history-search-forward very useful. They complete commands that begin with what you have typed. I have them mapped to M-p and M-n.
I also find myself using bash's insert-last-argument command, which can be repeated to fill in the last argument of previous commands. I have it mapped to M-_.
Another feature I've been using is the dabbrev-expand function, which xterm (and some other terminals) have. This allows string matching on the terminal output including the scroll buffer. It's useful for forming a new command that uses previous arguments that are not last arguments, or that are outputs of previous commands. I have it mapped to M-/. I've tweaked the matching algorithm on my local xterm to allow tokens enclosed in quotes or braces (which programs often output) to be matched (xterm by default only considers non-whitespace).
I have `h` aliased to `history | fzf`, works well enough
LaTeX returns .tex file compilation bugs as .log files when using pdflatex [filename.tex] Is synthetic format prior to redirection and concatenating. Whether using /.bashrc/ or saved in local directories, when debugging is typically resolved with querying X: quit or H: help.
ctrl + r is the neatest trick, I think I heard about it from EmbeddedFM
ctrl+r with fzf and zoxide for quick dir jumping is all I need in the shell nowadays.
ReSH or McFly does the job.
Wat?
[dead]
Bro, just use fish shell. They have done all the heavy lifting for you.
I just ran fish, and pressing ctrl-r did exactly what the author sought to fix.
> What does 5408 mean and why is it taking up valuable screen space?
The fish version of history search doesn't just do a simple substring search like in bash. It's already more powerful by doing a subsequence search. See https://github.com/fish-shell/fish-shell/pull/9476
I use fish with one plugin - fzf.fish. It's invaluable to me and the shortcuts are second nature now.
It prefixes each line with a timestamp rather than a number, which makes most sense to me.
https://github.com/PatrickF1/fzf.fish?tab=readme-ov-file#-se...
I don’t think anyone that uses fish uses ctrl+r. You just start typing and you get (directory aware) history based completions.
So you have to remember the directory you were in when you ran a one-off task six months ago?
fish suggests commands as you type, shown as faded text after the cursor. But suggestions aren't replacements for history search. Only one suggestion is shown at a time, and you don't have much control over what is shown.
It's popular though, so it's also available in zsh through the autosuggestions plugin.
Right, but OP was suggesting that fish didn’t need history search because of.
Exactly. Lots of work to do what fish does out of the box.
Powershell too.