DEV Community

Cover image for Improving my terminal setup
Alex Hyett
Alex Hyett

Posted on • Originally published at alexhyett.com on

Improving my terminal setup

I spend quite a lot of time on my terminal throughout the day, whether it be running build scripts, git commands or SSHing (is that a word?) into servers.

However, until this week I have been just using the default Terminal app that comes with MacOS. I had customised a little by using zsh and oh-my-zsh with the power10k plugin, but I have never been that happy with it, and it has always felt a little slow.

This week I have switched to using Ghostty with the fish shell, and the speed difference is definitely noticeable. It looks quite nice too!

My new terminal

Ghostty #

If you are not aware of Ghostty it is a new terminal emulator written by Mitchell Hashimoto who previously cofounded HashiCorp, the company that makes Terraform.

I must admit I have barely scratched the surface of what Ghostty can do, and I have mainly just been using it as it comes. As such my Ghostty config file (~/.config/ghostty/config) just has this:

theme = rose-pine
command = /opt/homebrew/bin/fish

Enter fullscreen mode Exit fullscreen mode

Fish #

I have been meaning to try the fish shell for a while. I heard great things about it from the likes of Julia Evans, but I thought it would be a pain to migrate from zsh so never tried it. Actually it was surprisingly simple.

Fish comes with a lot of great defaults and already includes things like autocompletion which is actually very good and git integration too.

My Setup #

If you like how my terminal looks and wanted to set up something similar then this how to do it. You will need to be on a Mac to be able to follow this, but I am sure the steps will be similar if you are using Windows or Linux.

  1. Install Ghostty by downloading it from the website (sorry Windows users you will need to skip this step).
  2. Install fish, fisher, grc and fastfetch: brew install fish fisher grc fastfetch
  3. Add fish to the available shells by editing /etc/shells and adding /opt/homebrew/bin/fish to the bottom.
  4. Make fish the default shell by running chsh -s /opt/homebrew/bin/fish
  5. Restart Ghostty and make sure you are now in the fish shell.
  6. Install some fish plugins:
fisher install oh-my-fish/plugin-brew
fisher install oh-my-fish/plugin-osx
fisher install oh-my-fish/theme-bobthefish
fisher install oh-my-fish/plugin-grc
Enter fullscreen mode Exit fullscreen mode
  1. Generate a config for fastfetch: fastfetch --gen-config-force. This will be created as ~/.config/fastfetch/config.jsonc.
  2. Edit the config removing anything you don't want. This is what mine looks like:
{
  "$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
  "modules": [
    "title",
    "separator",
    "os",
    "host",
    "kernel",
    "uptime",
    "packages",
    "shell",
    "display",
    "terminal",
    "cpu",
    "gpu",
    "memory",
    "disk",
    "localip",
    "battery",
    "poweradapter",
    "break",
    "break"
  ]
}
Enter fullscreen mode Exit fullscreen mode
  1. Edit your fish config file ~/.config/fish/config.fish. Mine looks like this:
## Settings
set -g theme_display_git_stashed_verbose yes
set -g theme_display_git_master_branch yes
set -g theme_display_git_untracked yes
set -g theme_display_git_dirty yes
set -g theme_display_nvm yes
set -g theme_display_virtualenv yes
set -g theme_display_user yes
set -g theme_display_hostname yes
set -g theme_color_scheme zenburn
set -g theme_date_format "+%Y-%m-%d %H:%M:%S"

function fish_greeting
    fastfetch
end

function ls
    /bin/ls -G $argv
end
Enter fullscreen mode Exit fullscreen mode

If you are wondering about the ls mapping, for some reason ls had no colours when running it. So folders and executables where all grey, this seemed to fix it.

If you want you can also store your fish config somewhere else and just reference it from the main fish file:

source ~/Projects/setup/fish/main.fish
Enter fullscreen mode Exit fullscreen mode

I often do this, so I can put my config file in a git repository and share it amongst my computers.

Migrating from zsh #

I have some aliases set up for work. Fish does support simple aliases but if you need to pass arguments then you have to create functions.

For example, I have a script that I run that trashes my local DB and recreates it:

alias newdb='~/Work/scripts/newdb.sh'
Enter fullscreen mode Exit fullscreen mode

This can just be copied as is into your fish config file. However if you have a command that takes an argument like this one:

alias tfapply='f() { terraform apply -var-file=env-$1.tfvars ;}; f'
Enter fullscreen mode Exit fullscreen mode

Then you have to write it as function like this:

function tfapply
    terraform apply -var-file=env-$argv.tfvars
end
Enter fullscreen mode Exit fullscreen mode

I actually think this is a lot neater and easier to read than the bash equivalent.

Fish isn't POSIX compatible so a lot of the bash syntax that you are used to won't necessarily work. You can still run bash scripts provided they declare the shell to use at the top #!/bin/bash.

Setting variables has to be done with the set command for example. There are a bunch of other oddities that you can find here: Fish for bash users

I am quite happy with my setup, but I am sure there will be some more tweaks and plugins I find along the way.


❤️ Picks of the Week #

📝 ArticleBe Aware of the Makefile Effect — I have been guilty of this in the past especially with cake files. It was often a lot easier to copy a working one and tweak it than to start from scratch.

📝 ArticleWhat's involved in getting a "modern" terminal setup? — Reading this prompted me to actually switch to fish.

📝 ArticleTrack your devices via Apple FindMy network in Go/TinyGo — This is quite cool. I am already embedded with the Apple ecosystem but if you aren't being able to use the FindMy network is useful.

📝 ArticleNix: Death by a Thousand Cuts — I have yet to go down the nix rabbit hole. I can see if being great for servers that don't change that often. I can see how using it on the desktop could be frustrating though.

📝 TutorialLearn Yjs Interactively — This looks like a great way to learn Yjs. I spent far too long clicking through all the icons at the top changing them to 🌵. I clearly have a problem 🤣. Learn Yjs all cacti

🐝 ArticleWhy do bees die when they sting you? (2021) — I have always wondered this and it is quite an interesting read.

📝 ArticleWhy is Git Autocorrect too fast for Formula One drivers? — I don't have this setting turned on, so I hadn't noticed this, but it is an fascinating read how something like this comes about.

📝 ArticleUK's hardware talent is being wasted — I think this is true for a lot of jobs. I have always been interested in computers, but I do sometimes think that doing robotics would have been more fulfilling. My plan is to make my money in FinTech and then spend my retirement doing robotics like Tony Stark.

📝 ArticleI'll think twice before using GitHub Actions again — GitHub Actions aren't as simple as they could be. I was thinking of doing a series of videos on GitHub Actions are quite complicated.

🤖 AIDeepSeek-R1 — I have been using Claude more and more for helping with programming. I need to try DeepSeek and see how well it works to run locally.

📝 ArticleMetacognitive laziness: Effects of generative AI on learning motivation — I feel seen after the above comment! I must admit I spend a lot less time “researching” for solutions by going through forums or reading documentation. If I can describe my problem with a code snippet and get an answer that works in a few seconds I think it is worth it. We will have to see how things develop in the future.

🤖 AIIs anyone doing anything cool with tiny language models? — I think the future of AI is going to be personal AI that is tailored to your own preferences and can understand you. If you are going to give something so much access to your life you don't want it owned by OpenAI, Google or Meta. I want a JARVIS or even a Samantha from Her, not ChatGPT.

🛠️ ToolTabBoo: add random jumpscares to websites you're trying to avoid — Spending too much time on Reddit, Facebook or HackerNews? Maybe spilling coffee on yourself in fright every now and again would help cut the habit.

🛠️ ToolTailwind CSS v4.0 — I use Tailwind at work, and it looks like there are some interesting improvements in this release.


💡 Today I Learned (TIL) #

At work, we have some scripts to seed the database with some dummy data. I always end up writing the INSERT scripts by hand, but I wondered if there was a better way. In pgAdmin there isn't a way to create an INSERT script from the results that I could find so I asked AI to help me and it came up with this function:

CREATE OR REPLACE FUNCTION generate_insert_script(query text, table_name text)
RETURNS text AS $$
DECLARE
    result_row record;
    column_names text[];
    column_values text[];
    insert_script text;
BEGIN
    -- Execute the query and fetch the single row
    EXECUTE query INTO result_row;

    -- Get column names and values
    SELECT array_agg(key), array_agg(quote_nullable(value))
    INTO column_names, column_values
    FROM json_each_text(row_to_json(result_row));

    -- Construct the INSERT statement
    insert_script := format(
        'INSERT INTO %I (%s) VALUES (%s);',
        table_name,
        array_to_string(column_names, ', '),
        array_to_string(column_values, ', ')
    );

    RETURN insert_script;
END;
$$ LANGUAGE plpgsql;
Enter fullscreen mode Exit fullscreen mode

You can then use it like this to generate an insert script from a query:

SELECT generate_insert_script($$
    SELECT * FROM users 
    WHERE name = 'O''Brien' AND email LIKE '%@example.com' 
    LIMIT 1
$$, 'users');
Enter fullscreen mode Exit fullscreen mode

💬 Quote of the Week #

That is the reason it is so hard to motivate kids in school today. They know that professional success is no longer solely linked to academic success, as it once was.

From the book Rich Dad Poor Dad by Robert T. Kiyosaki.

Top comments (0)