← All Guides

Dotfiles Guide

shellterminalconfig

A reference for the dotfiles we recommend. Copy what works for you, ignore the rest.

Fish Config (~/.config/fish/config.fish)

Fish is our recommended shell. Clean syntax, great defaults.

if status is-interactive
    starship init fish | source
    atuin init fish | source
end

# OrbStack integration
source ~/.orbstack/shell/init2.fish 2>/dev/null; or :

# bun
set --export BUN_INSTALL "$HOME/.bun"
set --export PATH $BUN_INSTALL/bin $PATH

# 1Password CLI plugins (routes aws through 1Password)
source ~/.config/op/plugins.sh

# Aliases
alias gs "git status"
alias gd "git diff"
alias gl "git log --oneline -20"
alias gco "git checkout"
alias gcb "git checkout -b"
alias gp "git pull --rebase"
alias k "kubectl"
alias kgp "kubectl get pods"
alias kgs "kubectl get svc"
alias kns "kubectl config set-context --current --namespace"
alias kctx "kubectl config use-context"
alias dc "docker compose"
alias dps 'docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"'
alias ll "ls -la"

Zsh Config (~/.zshrc)

If you prefer zsh:

# Atuin (better shell history)
. "$HOME/.atuin/bin/env"
eval "$(atuin init zsh)"

# Starship prompt
eval "$(starship init zsh)"

# Homebrew
eval "$(/opt/homebrew/bin/brew shellenv)"

# fzf keybindings and completion
source <(fzf --zsh)

# bun
export BUN_INSTALL="$HOME/.bun"
export PATH="$BUN_INSTALL/bin:$PATH"

# bun completions
[ -s "$HOME/.bun/_bun" ] && source "$HOME/.bun/_bun"

# krew
export PATH="${KREW_ROOT:-$HOME/.krew}/bin:$PATH"

# 1Password CLI plugins
source ~/.config/op/plugins.sh

# History
HISTSIZE=50000
SAVEHIST=50000
HISTFILE=~/.zsh_history
setopt SHARE_HISTORY
setopt HIST_IGNORE_DUPS
setopt HIST_IGNORE_SPACE

# Aliases - Git
alias gs="git status"
alias gd="git diff"
alias gl="git log --oneline -20"
alias gco="git checkout"
alias gcb="git checkout -b"
alias gp="git pull --rebase"

# Aliases - Kubernetes
alias k="kubectl"
alias kgp="kubectl get pods"
alias kgs="kubectl get svc"
alias kgd="kubectl get deployments"
alias kns="kubectl config set-context --current --namespace"
alias kctx="kubectl config use-context"

# Aliases - Docker
alias dc="docker compose"
alias dps="docker ps --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}'"

# Aliases - General
alias ll="ls -la"
alias ..="cd .."
alias ...="cd ../.."

Fish Plugins

We use Fisher as the plugin manager:

brew install fisher

Recommended plugins (add to ~/.config/fish/fish_plugins):

jethrokuan/z                          # directory jumping (like zoxide)
franciscolourenco/done                # notification when long commands finish
jorgebucaran/autopair.fish            # auto-close brackets and quotes
jhillyerd/plugin-git                  # git abbreviations and completions
gazorby/fish-abbreviation-tips        # shows when you could use an abbreviation
nickeb96/puffer-fish                  # expand ... to ../.. and !! to last command
patrickf1/colored_man_pages.fish      # coloured man pages
eth-p/fish-plugin-sudo               # press Esc twice to prepend sudo
edc/bass                              # run bash scripts in fish
evanlucas/fish-kubectl-completions    # kubectl completions
blackjid/plugin-kubectl               # kubectl abbreviations
ankitsumitg/docker-fish-completions   # docker completions
halostatue/fish-macos@v6              # macOS utilities (Finder, apps)
halostatue/fish-rust                  # Rust/cargo completions

Install all plugins:

fisher update

Fish Configuration Files

Fish uses conf.d/ for auto-loaded config. Useful files to create:

~/.config/fish/conf.d/aliases.fish - tool aliases:

# Use modern replacements when available
if type -q eza
  alias ls='eza --icons'
end

if type -q nvim
  alias vim='nvim'
end

~/.config/fish/conf.d/paths.fish - PATH setup:

# Prefer GNU coreutils over macOS defaults
fish_add_path --prepend /opt/homebrew/opt/coreutils/libexec/gnubin
fish_add_path --prepend /opt/homebrew/opt/findutils/libexec/gnubin
fish_add_path --prepend /opt/homebrew/opt/gawk/libexec/gnubin
fish_add_path /Users/(whoami)/.local/bin

~/.config/fish/conf.d/editor.fish - editor defaults:

set -gx EDITOR "vim"
set -gx VISUAL "code"

Atuin (Shell History)

Atuin replaces your shell history with a searchable, syncable database. Much better than ctrl+r.

brew install atuin

Search history with ctrl+r or up arrow. It shows timestamps, exit codes, and duration. You can sync across machines if you want.

Starship Config (~/.config/starship.toml)

Needs a Nerd Font installed (JetBrainsMono or FiraCode). Without one the icons will show as boxes.

# --- Prompt character ---
[character]
success_symbol = "[](bold green)"         # tick on success (U+EAB2)
error_symbol = "[](bold red)"          # cross on error (U+EA76)

# --- User / host ---
[username]
show_always = true
style_user = 'white bold'
style_root = 'red bold'

[hostname]
style = "bold dimmed blue"

[localip]
ssh_only = false                        # show IP even when not SSHed in
format = '[$localipv4](bold dimmed red) '
disabled = false

# --- Directory ---
[directory]
truncation_length = 4
truncation_symbol = '…/'

# --- Git ---
[git_branch]
symbol = " "                           # nerd font git branch icon (U+E725)
format = "[$symbol$branch]($style) "

[git_metrics]
disabled = false
added_style = 'bold blue'
format = '[+$added]($added_style)/[-$deleted]($deleted_style) '

[git_status]
ahead = '⇡${count}'
diverged = '⇕⇡${ahead_count}⇣${behind_count}'
behind = '⇣${count}'
up_to_date = '✓'

[git_commit]
only_detached = true                    # show commit hash when HEAD is detached
tag_symbol = '  '                     # nerd font tag icon (U+F412)

# --- Command duration ---
# Shows how long the last command took. Useful for builds, terraform, etc.
[cmd_duration]
min_time = 2_000                        # only show if command took >2s
format = '[$duration]($style) '
style = 'dimmed yellow'

# --- Exit status ---
[status]
symbol = "[](bold red)"
success_symbol = ""
format = '[$symbol$common_meaning$signal_name$maybe_int]($style) '
map_symbol = true
disabled = false

# --- Docker ---
[docker_context]
symbol = ' '                          # nerd font Docker icon (U+F308)
format = '[$symbol$context]($style) '
only_with_files = true                  # only show when Dockerfile or compose.yaml present

# --- Package version ---
[package]
disabled = false                        # shows version from package.json, Cargo.toml, etc.

# --- Cloud & infra ---
[kubernetes]
symbol = '☸ '                           # helm wheel
format = '[$symbol$context( \($namespace\))](dimmed green) '
disabled = false

[aws]
symbol = ' '                           # nerd font AWS icon (U+F0EF)

[azure]
symbol = '󰠅 '                          # nerd font Azure icon (U+F0805)

[terraform]
symbol = ' '                          # nerd font Terraform icon (U+E8BD)
format = '[$symbol$version - $workspace]($style) '

[helm]
symbol = ' '                          # nerd font Helm icon (U+E7FB)


[pulumi]
disabled = false                        # show Pulumi stack info in IaC projects

# --- Languages & runtimes ---
[bun]
symbol = ' '                           # nerd font Bun icon (U+E76F)
format = '[$symbol($version)]($style) '

[deno]
symbol = ' '                           # nerd font Deno icon (U+E7C0)
format = '[$symbol($version)]($style) '

[rust]
symbol = '󱘗 '                          # nerd font Rust icon (U+F1617)
format = '[$symbol($version)]($style) '

[python]
symbol = ' '                           # nerd font Python icon (U+E73C)
format = '[$symbol($version)]($style) '

[golang]
symbol = ' '                           # nerd font Go icon (U+E627)
format = '[$symbol($version)]($style) '

[nodejs]
disabled = true                         # we use bun, not node

[ruby]
disabled = true

[gcloud]
disabled = true                         # too noisy, we don't use it much

# --- Battery ---
[[battery.display]]
threshold = 15
style = 'bold red'

[[battery.display]]
threshold = 30
style = 'bold yellow'

[[battery.display]]
threshold = 50
style = 'bold green'

Shows: git branch with icon and metrics (lines added/removed), Kubernetes context with namespace, cloud provider (AWS/Azure), Terraform workspace, battery warnings, and local IP. Uses nerd font icons throughout so the prompt stays compact.

Git Config (~/.gitconfig)

[user]
    name = Your Name
    email = your.name@gremlin.group

[init]
    defaultBranch = main

[push]
    autoSetupRemote = true

[branch]
    autosetupmerge = true

[pull]
    rebase = true

[fetch]
    prune = true

[gpg "ssh"]
    program = /Applications/1Password.app/Contents/MacOS/op-ssh-sign

[commit]
    gpgsign = true

[core]
    pager = delta
    editor = vim

[interactive]
    diffFilter = delta --color-only

[delta]
    navigate = true
    line-numbers = true

[merge]
    conflictstyle = zdiff3

[url "ssh://git@github.com/"]
    insteadOf = https://github.com/

[alias]
    l = log --pretty=oneline -n 50 --graph --abbrev-commit
    save = !git add -A && git commit -v -m 'SAVEPOINT'
    undo = reset HEAD~1 --mixed
    findcommit = "!f() { git log --pretty=format:'%C(yellow)%h  %Cblue%ad  %Creset%s%Cgreen  [%cn] %Cred%d' --decorate --date=short -S$1; }; f"
    findmessage = "!f() { git log --pretty=format:'%C(yellow)%h  %Cblue%ad  %Creset%s%Cgreen  [%cn] %Cred%d' --decorate --date=short --grep=$1; }; f"

[filter "lfs"]
    clean = git-lfs clean -- %f
    smudge = git-lfs smudge -- %f
    process = git-lfs filter-process
    required = true

Notable Settings

  • push.autoSetupRemote - automatically sets upstream when you push a new branch. No more git push -u origin feature/thing.
  • delta as the pager - syntax-highlighted, line-numbered diffs. Install with brew install git-delta.
  • merge.conflictstyle = zdiff3 - shows the original text alongside both sides in merge conflicts. Makes resolving conflicts much easier.
  • url.insteadOf - forces SSH for all GitHub operations. No HTTPS auth prompts.
  • findcommit / findmessage - search git history by code content or commit message.

Per-Client Git Config

Use includeIf to automatically switch your email and settings per client:

# ~/.gitconfig
[includeIf "gitdir:~/git/gremlin/**"]
    path = ~/git/gremlin/.gitconfig

[includeIf "gitdir:~/git/clients/acme/**"]
    path = ~/git/clients/acme/.gitconfig
# ~/git/gremlin/.gitconfig
[user]
    email = your.name@gremlin.group
# ~/git/clients/acme/.gitconfig
[user]
    email = your.name@acme.com

This means you never accidentally commit with the wrong email.

Commit Message Template (~/.gitmessage)

Set up a commit template as a reminder:

git config --global commit.template ~/.gitmessage
# <type>(<scope>): <subject> (max 50 chars)
# |<----  Using a Maximum Of 50 Characters  ---->|


# Explain why this change is being made
# |<----  Try To Limit Each Line to a Maximum Of 72 Characters  ---->|

# Provide links to any relevant tickets, articles or other resources
# Example: Github issue #23

# Types: feat fix refactor style docs test chore ci build perf revert

Global Gitignore (~/.gitignore_global)

git config --global core.excludesfile ~/.gitignore_global
.DS_Store
Thumbs.db
*.swp
*.swo
*~
.idea/
.vscode/
*.iml
.env
.env.local

1Password CLI Plugins

1Password can wrap CLI tools so they authenticate through your vault:

# Set up the AWS plugin
op plugin init aws

# This creates ~/.config/op/plugins.sh which aliases aws through 1Password
# Source it in your shell config:
source ~/.config/op/plugins.sh

Now aws commands authenticate via 1Password with biometric approval. No plain-text credentials.

Managing Your Dotfiles

We recommend mackup to sync dotfiles via iCloud:

brew install mackup
mackup backup    # backs up to iCloud
mackup restore   # on a new machine

Mackup symlinks your config files to iCloud, so they stay in sync across machines automatically. It supports hundreds of applications out of the box.

Alternatively, keep a git repo:

mkdir -p ~/git/dotfiles
cd ~/git/dotfiles
git init

# Symlink configs
ln -sf ~/git/dotfiles/config.fish ~/.config/fish/config.fish
ln -sf ~/git/dotfiles/starship.toml ~/.config/starship.toml
ln -sf ~/git/dotfiles/.gitconfig ~/.gitconfig