Hacker News new | past | comments | ask | show | jobs | submit login
My shell setup with Fish and Tmux (2021) (milanvit.net)
167 points by behnamoh on April 23, 2023 | hide | past | favorite | 80 comments



I installed Fish last night, first non-default shell I've used ever, because I saw Scott Hanselman's very pretty prompt and realised I'd been missing out. Those custom Bash prompts back in the day were positively primitive compared to what people have been doing with custom fonts and Unicode emoji symbols.

Researched a bunch of themes/prompts, initially wanted oh-my-posh (which Hanselman uses), then Starship.rs because it was fast, then powerlevel10k because it was faster, then saw opinions in favour of Fish over Zsh, sidetripped to r/UnixPorn along the way, and finally settled on Fish + Fisher (plugin manager) + Tide (a Fish port of powerlevel10k) + Catppuccin Fish (a pastel theme). The configuration wizard in Tide makes it very simple to pick the prompt's design and colours, and further customisation is easy too. Quite a rabbithole, but I'm pretty satisfied now!


I used to do that very custom setup for a few years... Lately I've settled for https://starship.rs/ doesn't matter the shell the experience is the same. I find it difficult sometimes to use loops or variable creation on fish, so jumping to bash real quick without changing experience is so convenient... Another thing I don't like is that if I create a one liner at work to process batches of files/hosts in fish, then I must translate that to bash in wikis, otherwise people would be forced to use fish to replicate...


I use Starship for the same reason. It's great getting the same UX in Fish on macOS and PowerShell on Windows.


starship looks cool, but the syntax of the shells is still different. so how can the user experience be the same?

for me syntax, search and autosuggestions are the key features of fish which no other shell has and starship doesn't seem provide those.


starship is a prompt, not a shell.

for consistent shell across os i recommend zsh (mingw on windows), or nushell or fish.


yes, i got that. my thought was that UX is more than just the prompt. although it is nice to have a consistent prompt over different systems


I’ve recently discovered ChatGPT is pretty good at translating Bash -> Fish. Can be a time saver.


Also on the Fish + Fisher + Tide train. I've been using fish for some years now, always been a fan of the autocomplete and highlighting, but Tide feels like a step up. Really like the way it shows my node version on the right is a relevant project.


Also a fish user here, but didn't find a need for Fisher yet. What packages did you install? I used it to install z but every upgrade with fisher just messed things up, so I killed it from my setup and settled on zoxide which has proper fish bindings

Now I just use fish + starship and don't mess around with packages


I like https://github.com/meaningful-ooo/sponge

> Sponge quietly runs in the background and keeps your shell history clean from typos, incorrectly used commands and everything you don't want to store due to privacy reasons.

___

Also here is a nice list you can take a lookt at: https://github.com/jorgebucaran/awsm.fish


Here's mine:

fisher install PatrickF1/fzf.fish fisher install urbainvaes/fzf-marks

# These two to get sdkman and nvm to work in fish, IIRC fisher install reitzig/sdkman-for-fish@v1.4.0 fisher install jorgebucaran/nvm.fish


I got it when I started needing nvm a while back. Tide is the second thing I've added - I tend to keep things fairly minimal.


modern fanxy zsh/bash and even fish and nushell prompt is starship.


there's also /r/unixart for more screenshots!


Instead of tmux, I personnally use Wez's Terminal (Wezterm: https://wezfurlong.org/wezterm/) because it is both a capable terminal and a capable multiplexer and I like to have one less layer to care about.

One thing I personally like very much is that it supports a command line tab and pane navigation/management : https://github.com/cassepipe/dot-git/blob/8b300524021cc74f67...


I use wezterm and love it, too - BUT, it doesn't yet support SSH agent forwarding, which are an integral part of my workflow for some machines.

So it's great -- for me -- for local connections, or remote ones where I don't need to pass an SSH agent, but it's not yet there "fully" for me the way KiTTY is.


Lua-scripted config with event dispatch is a huge win, totally not interested in polling and sed'ing just to get automatic dark mode


Nice, I was just about to dive into tmux for the first time but I hate too much configuration, will check this out!


> Capable terminal emulator (macOS’ Terminal.app doesn’t qualify)

Why doesn't Terminal.app qualify? I used to use iTerm 2 because I liked its pane management, but after switching to using tmux several years ago, I've solely used Terminal.app + tmux without any issues in my workflow. What am I missing out on?


I'm sure everyone has a favorite, mine is simply able to slide out iTerm2 from the top of the screen with a hotkey (tilde ofc.) à la Quake console.

https://apple.stackexchange.com/questions/48796/iterm-as-a-s...


Same, lol; that really is the only unique selling point for me at the moment. Although I'm sure there's a lot of subtle things (performance, font rendering, tabs, etc) that do it for me as well.


performance

The latency of iTerm has traditionally been much worse than Terminal.app. It got a bit better with GPU rendering, but it still trails behind Terminal.app quite a bit.

https://danluu.com/term-latency/

https://www.lkhrs.com/blog/2022/07/terminal-latency/

I tried iTerm for a while because Terminal.app does not support true color. But the difference in latency is definitely noticeable to me.


I use Alacritty as my terminal emulator plus hammerspoon to get the same effect.


Would you be willing to share your Hammerspoon config, or at least that part? Would love to do this with Alacritty!



I used to be an iTerm user long ago but haven't used anything but Terminal.app the last decade. Can't really say I miss the bells and whistles.


kitty’s completely borderless mode, hyperconfigurability, and general aesthetics (and GPU rendering but it matters little)


GPU rendering matters a lot. For the experienced developer who does all their programming in a terminal, being able to get crisp instant feed back with each key press is critical for a pleasant experience. Other terminals without this just feel too sluggish.


After spending the beginning of my career remoting onto mainframes via low baud serial connections, all terminal emulators now feel responsive to me :)

One of my colleagues at my first job didn’t even have a direct connection to the mainframe when he started. He used to write his code on paper, get a typist to then enter that into the mainframe and he would get the output a day or two later. Which meant he had to put a lot more care into checking for syntax errors before handing the code off to be entered and compiled.


I really like iterm2 integration with tmux when windows are native.


True colour support and decent custom bindings are what keep me off of Terminal.app.


iTerm's session restoration. It just works, without manually saving or anything. Saved me tons of time from reboots or crashes.


I wrote a similar article years ago based on my setup to explain folks that asked how I organized projects and worked on them via tmux. The text is from 2015, but I still work mostly like that… although I’ve added VSCode and Doom Emacs into the mix.

If you are curious: https://jmmv.dev/2015/09/my-coding-workflow.html


I've been giving fish a try on a periodic basis every 6 months or so.

The pattern is always the same: I read an amazing article on how fish makes X easier/fancier than bash/zsh, I install it again, I spend half a day trying to export my two decades of bash/zsh customizations, and eventually I just give up overwhelmed by the amount of required work.

Fish is a great shell, but I don't know why they decided to go all the way and completely break the compatibility with anything that POSIX has produced over the past four decades.

I won't rewrite all of my shell functions, aliases, for loops, string concatenations and environment variables to comply with a shell that is only compliant with itself, sorry. And I don't know why they decided to go the nuclear way and break compatibility so hard where they could have at least guaranteed a back-compatibility layer with (at least) zsh. Reinventing the whole wheel to make it look exactly the way you want, while disregarding compatibility with everything that already exists, is probably the biggest violation of the UNIX philosophy.


One idea: Maybe your shell functions do not all need to be shell functions, maybe they can be shell scripts instead.

Put them in ~/bin, then you can use them regardless of the shell you're using.

Of course, if the shell function or alias needs to modify the shell state, then it won't work as a shell script.


then fish is maybe not for you for now. i like fish exactly because it broke out of the limitations imposed by POSIX. in my view, POSIX should have never even gone as far as specifying any kind of shell syntax. imagine what we'd do if it had gone even as far as specifying programming languages. that stuff just doesn't belong there.

compatibility should be limited to interoperability. but it should not limit how we can design our tools.

and the tools do adapt. more and more of them work just fine with fish. maybe some day in the future your tools will work with fish too.

I spend half a day trying to export my two decades of bash/zsh customizations

don't. if you switch to fish, you should not want/need those customizations, because if you want to make fish look or work like your old shell, why are you even switching? you are learning a new environment with new features. get used to fish as it is first. after a while you may discover fish's own customization options, and the many tools that provide customizations across multiple shells. your own handcoded adaptions are probably not even portable to any other shell.

Reinventing the whole wheel to make it look exactly the way you want, while disregarding compatibility with everything that already exists, is probably the biggest violation of the UNIX philosophy

fish is not reinventing the wheel. it is creating new wheels with features that we never had before.

the popularity of fish just shows that this incompatibility is not a problem to many. if it were, fish would be dead by now. other shells are gaining ground that also break compatibility and maybe we'll find a future where these compatibility issues are not issues anymore because we will have learned to build environments that don't depend on that compatibility.


What broke fish for me is behaviour bugs. e.g https://github.com/fish-shell/fish-shell/issues/1786 but there are more that makes it a no go for me.


not really a bug but a missing feature but i get your point. i find psub one of the weak spots of fish, and i'd prefer if fish could support >() and <() as syntax instead.

it's much more intuitive (foo) is clearly a command and > and < are in and out respectively. if i look at (foo | psub) i am wondering what that is supposed to mean.


I am using fish full time for about 2 years. I have to switch to zsh very occasionally, my main frustration was with py venv activate but apparently there's a fish activate script now. I am enjoying it otherwise. I use Starship though, not OMF. I didn't have too many custom functions to migrate too.


The main inconvenience of fish is not even having to go into another shell for some tasks like virtual env activation, but wondering whether some command you just ran silently did something wrong because of shell incompatibility. (Edited)

Also, I wonder how fast is OMF compared to Starship?


> The main inconvenience of fish is not even having to go into another shell for some tasks like virtual env activation

For stuff like "in this directory, I want this virtual env activated", I'd recommend using direnv.

https://direnv.net/

> wondering whether some command you just ran silently did something wrong because of shell incompatibility

I don't recall running into silent incompatibities. Do you have examples in mind?

Although, yeah, you can't just copy-paste most sh/bash snippets into fish.


I'm sure there are some ways it can fail silently, but excluding that I think of a function that fails loudly but higher-level function does not check that.


> The main inconvenience of fish is not even having to go into another shell for some tasks like virtual env activation, but wondering whether some command you just ran silently did something wrong because of shell incompatibility.

I have the impression that you just overlook all the rest of the things that can go wrong when using Bash, because you are simply used to it, you know it and you know how it will behave. In the sense that with Dash you would perhaps have a similar problem. Fish is really pleasant and forgives a lot.

> Also, I wonder how fast is OMF compared to Starship?

Those are two total different projects. During my hypomania on Fish (yup), I didn't even use OMF, but added things manually and only those really needed, so that there was as little code to maintain as possible. Fish does not have a huge number of scripts, plug-ins. If Starship is too slow for you, you might like Tide. I found nothing more interesting, after which I returned to Starship anyway, but it's really fast.

https://github.com/IlanCosman/tide

Perhaps you don't need something faster than Starship, just to configure Fish in such a way that it cleans itself of garbage and runs asynchronously?


> I have the impression that you just overlook all the rest of the things that can go wrong when using Bash, because you are simply used to it, you know it and you know how it will behave

I don't write much of bash or fish, I mean scripts written by others. Encounter cryptic error messages then realize script is just assuming shell is POSIX

> Starship is too slow

Starship plenty fast for me. You say it's completely different than OMF but from what I see they both exist to customize your prompt, no?


If the script doesn't have a shebang I'd be extremely suspicious of it. If it does include a shebang, it will run under the chosen interpreter and your login or default shell won't matter.

If it's something you're trying to `source` then it can go wrong, but `bass` takes care of that if it's a POSIX-compatible script being sourced. If it's some other sort of script being sourced (PowerShell, NuShell, etc) you can have issues, though `fish` will usually fail to parse it and exit with error.


> I don't write much of bash or fish, I mean scripts written by others. Encounter cryptic error messages then realize script is just assuming shell is POSIX

I run most of my scripts in Bash, but what I can, I convert to Fish. If the advantages of Fish are less important than POSIX compliance, I won't suggest anything, because I have no need to be POSIX compliant, so maybe I don't really have the same concerns. :)

> Starship plenty fast for me. You say it's completely different than OMF but from what I see they both exist to customize your prompt, no?

Forgive me, I mistakenly assumed you meant that Starship runs too slowly. It depends on how you define prompt. Strictly it will be whatever is shown in the terminal when it waits for user input. OMF is a multi-tool that, in addition to modifying the appearance, acts as something like a plugin manager. Starship gives you "just the look". I think a good analogy would be to compare systemd and runit in 1 category.


How do you run scripts in bash while using fish as your shell?


you execute them like any other script. the script is not interpreted by your interactive shell but it specifies which shell/interpreter will be used to run it. that interpreter is then started for this script. your interactive shell does not limit what kind of scripts you can run. there was never a requirement that bash scripts need to be started from a bash shell. otherwise you could not even run python or other scripts from your shell.


Ah. I meant cases where lazy third-party scripts just assume my current shell is POSIX and don't explicitly make themselves run in bash.


Run "bash thirdparty.sh" instead of "./thirdparty.sh" to force bash.


if there is a bash script that does not start with #!/bin/bash where the instructions say to run it in bash, then it can be run as bash scriptfile; or cat scriptfile | bash;. both these forms work from any commandline shell


Yes. But I need to inspect the script to know to do it (or hope that if it didn't fail then it truly didn't fail). I am not saying it's an insurmountable challenge, just that there is some friction when using fish.


not really, unless there is a clear indication that it is a fish script, i's just asume it is bash and run it with that.

it's only work if the commands need to be run within fish itself and not a subshell. there are tools for that but i agree that sometimes i can't be bothered and then i'll just work in bash to do that job.


For example if I follow some README I may not even know whether it's a script or binary, so I guess I would need to know at least that before I run something with bash (or get "cannot execute binary":)


scripts begin with a line like

    #!/usr/bin/env bash
which works regardless of the executing shell


Virtualenv supports fish just fine.

. venv/bin/activate.fish


Interesting, I didn't know they have a separate activate script now


I tried Fish for a while, and found the three things I liked most about it were all available as addons for zsh, so I went back to zsh with just these three lines appended to .zshrc:

  source /usr/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh
  source /usr/share/zsh-autosuggestions/zsh-autosuggestions.zsh
  source /usr/share/zsh-abbr/zsh-abbr.zsh
(In case it's not clear, install them with your system package manager.)


i love it when innovations in a new application are carried over to older tools. zsh seems especially suitable for that. it soaks up good ideas like a sponge and finds a way to integrate them. on the other hand it does make zsh feel kind of overwhelming at times in terms of options available.

my favorite part besides autosuggestions is the way history works, not incremental but i can type out a search term, and then start searching up and down the history.

incremental search is always irritating me by showing me irrelevant stuff while i am still typing, which i find distracting because i have to process it while at the same time focusing on typing the search term right.

now if only i could also have multiple search terms...

(i also prefer the fish syntax, but that is more of a matter of taste and getting used to)


> (i also prefer the fish syntax, but that is more of a matter of taste and getting used to)

IMO one of the biggest advantages of zsh is it's almost 100% compatible with Bash. If I'm in my shell and want to run an adhoc command with a for loop I want to do it with Bash's syntax, not learn a new Fish syntax. Having to manually drop into `bash` to run a bunch of commands is too inconvenient. Also you'll find most examples online using POSIX shell or Bash compatible syntax. You can carry over those to your dedicated scripts and adhoc commands. Your knowledge becomes shared.


A Fish for loop is near identical to a Bash for loop, it simply omits the "do".


Use bass to drop down to bash from fish :)

https://github.com/edc/bass


Here is another great plugin that pairs nicely with the above.

https://github.com/Aloxaf/fzf-tab


My trivial setup with tmux + oh-my-zsh + mosh(if firewall allows). Enjoying it in every machine I touch. https://gitlab.com/outluch/osetup


For the ones that love a more lightweight setup I recommend yash [0].

It is more lightweight than zsh, fish, or bash and comes with a decent auto-completion and line prediction a-la fish.

For my prompt, I am using polygot [1]. However, I am looking for another one.

I was previously a zsh user. I already tried fish, however, its non-POSIX-compliance was a hard stop for me.

[0] https://yash.osdn.jp/

[1] https://github.com/agkozak/polyglot


I’ve got a random question for the terminal folk: I’m often testing a web server hosted on a remote server that hot reloads, but I have to wait for it to finish compiling.

I can tell it’s done if I have a tab open looking at the logs, but ideally I’d like some kind of icon that’s yellow when compiling, green when compiled, etc.

What could I use for that?


If I understand correctly, you have a remote server with a logfile, and some markers in this log file tells you whether the build is in process or finished.

I would suggest you keep it simple and simply poll the logfile for the latest occurrence of either "Build started" or "Build finished" and display a pop-up for each case.

Very roughly that would look like:

  while true
  do
    MATCH=$(ssh remote@host 'cat /logfile' | grep -P 'started|finished' | tail -1)
    case "$MATCH" in
      *started*)
        notify-send "Build started"
        ;;
      *finished*)
        notify-send "Build finished"
        ;;
    esac
    sleep 1s
  done
That's dirty bash written in an HN comment on my phone, but the idea is here. It's a bit wasteful to initiate ssh sessions so often, so you could improve it with a single "ssh remote@host tail -f /logfile", pipe that to "grep", then to a while read, but I left that as an exercise.

There is some option to notify-send so that pop-ups replace one another instead of creating new ones.


I should have clarified I’m usually looking at another tab in tmux. Any way to pop up there?


You can ask tmux to update the window status — for instance to show red or green based on the exit code of the last command. Example here:

https://unix.stackexchange.com/a/597367/63035


Nice! I was able to do just that, with a solution like the one you wrote, except I'm grepping a local (instead of remote) log, and changing the status bar color based on log output.

Was exactly what I wanted, thanks.


tmux. If a bell, or ctrl-g, is output on the terminal, the tmux status line will indicate this fact if you are viewing a different terminal. It will stay indicating until you switch back to that terminal.

tmux will also show you the name of the command that's currently running, so if it's a make file or other script that finishes, you can observe that on it's own, but if you add an `echo -e "\007"` to the end of your script, you'll get the indicator.


Nice! I already use tmux. I’m not sure if the log file outputs anything like that though.

There’s a way to hook into the build process and run commands after it completes. I’m guessing I might have to do that to get the status line wired in.


this is not tmux specific, basically every terminal out there would react to the bell char. e.g Terminal.app adds a bell icon to the tab, makes the dock icon bounce, and a badge on it.

if you want to hack a bit and have a specific log line outputted yo the terminal you can stuff the bell char right in the string!

one could also display notifications, there are more advanced CLI programs but here's a crude way: https://apple.stackexchange.com/questions/238814/send-notifi...

These things can also be done on Linux. A bit of web searching should give you ideas.

I frequently use them with long running commands or fswatch.


In some cases you can get away with simple solutions like just printing the BEL character a few times:

  make install; printf \\a\\a\\a


I think the bell character suggestion might be the simplest, but depending on how long the build takes you might want to check ntfy.sh

I alias the build command to POST a notification using curl and get it on the browser/phone


If you mean to mix in GUI, on macOS, there is BitBar and another one (forgot the name) that just puts a big coloured dot in the menubar that you can curl to change its color. Something along that line would work.


What about Linux?


You can change the tab title with ansi escapes. These days you can use Unicode chars as well, and some have colors, say with a emoji font.


If you're on a mac that sounds doable with iterm. I have some code in my fish config to bounce the dock icon when a longrunning command ends


I used fish extensively a few months ago, had to switch back to bash for some reasons, but yeah fish is incredible.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: