···11+#!/bin/sh
22+33+# The $NAME variable is passed from sketchybar and holds the name of
44+# the item invoking this script:
55+# https://felixkratz.github.io/SketchyBar/config/events#events-and-scripting
66+77+sketchybar --set "$NAME" label="$(date '+%m/%d %l:%M %p')"
···11+#!/bin/bash
22+33+# Script to sum up the "Used" column from df -k output
44+# Usage: ./df-k-usage-sum.sh
55+66+# No conversion function needed since df -k outputs in kilobytes
77+88+# Function to convert kilobytes to human-readable format
99+kb_to_human() {
1010+ local kb="$1"
1111+1212+ if (( kb >= 1073741824 )); then # 1 TiB in KB
1313+ echo "$kb" | awk '{printf "%.1fT", $1/1073741824}'
1414+ elif (( kb >= 1048576 )); then # 1 GiB in KB
1515+ echo "$kb" | awk '{printf "%.1fG", $1/1048576}'
1616+ elif (( kb >= 1024 )); then # 1 MiB in KB
1717+ echo "$kb" | awk '{printf "%.1fM", $1/1024}'
1818+ else
1919+ echo "${kb}K"
2020+ fi
2121+}
2222+2323+# Get df -k output and process it
2424+total_kb=$(df -k | awk '
2525+ BEGIN { total = 0 }
2626+ NR > 1 && $3 ~ /^[0-9]+$/ { total += $3 }
2727+ END { print total }
2828+')
2929+3030+total_kb_human=$(kb_to_human $total_kb)
3131+3232+sketchybar --set "$NAME" icon="" label="$total_kb_human"
···11+#!/bin/sh
22+33+# Some events send additional information specific to the event in the $INFO
44+# variable. E.g. the front_app_switched event sends the name of the newly
55+# focused application in the $INFO variable:
66+# https://felixkratz.github.io/SketchyBar/config/events#events-and-scripting
77+88+if [ "$SENDER" = "front_app_switched" ]; then
99+ sketchybar --set "$NAME" label="$INFO"
1010+fi
···11+#!/bin/sh
22+33+# The $SELECTED variable is available for space components and indicates if
44+# the space invoking this script (with name: $NAME) is currently selected:
55+# https://felixkratz.github.io/SketchyBar/config/components#space----associate-mission-control-spaces-with-an-item
66+77+sketchybar --set "$NAME" background.drawing="$SELECTED"
···11+# This is a demo config to showcase some of the most important commands.
22+# It is meant to be changed and configured, as it is intentionally kept sparse.
33+# For a (much) more advanced configuration example see my dotfiles:
44+# https://github.com/FelixKratz/dotfiles
55+66+PLUGIN_DIR="$CONFIG_DIR/plugins"
77+88+##### Bar Appearance #####
99+# Configuring the general appearance of the bar.
1010+# These are only some of the options available. For all options see:
1111+# https://felixkratz.github.io/SketchyBar/config/bar
1212+# If you are looking for other colors, see the color picker:
1313+# https://felixkratz.github.io/SketchyBar/config/tricks#color-picker
1414+1515+sketchybar --bar position=top height=40 blur_radius=30 color=0x40000000
1616+1717+##### Changing Defaults #####
1818+# We now change some default values, which are applied to all further items.
1919+# For a full list of all available item properties see:
2020+# https://felixkratz.github.io/SketchyBar/config/items
2121+2222+default=(
2323+ padding_left=5
2424+ padding_right=5
2525+ icon.font="Hack Nerd Font:Bold:17.0"
2626+ label.font="Hack Nerd Font:Bold:14.0"
2727+ icon.color=0xffffffff
2828+ label.color=0xffffffff
2929+ icon.padding_left=4
3030+ icon.padding_right=4
3131+ label.padding_left=4
3232+ label.padding_right=4
3333+)
3434+sketchybar --default "${default[@]}"
3535+3636+##### Adding Mission Control Space Indicators #####
3737+# Let's add some mission control spaces:
3838+# https://felixkratz.github.io/SketchyBar/config/components#space----associate-mission-control-spaces-with-an-item
3939+# to indicate active and available mission control spaces.
4040+4141+# SPACE_ICONS=("1" "2" "3" "4" "5" "6" "7" "8" "9" "10")
4242+# for i in "${!SPACE_ICONS[@]}"
4343+# do
4444+# sid="$(($i+1))"
4545+# space=(
4646+# space="$sid"
4747+# icon="${SPACE_ICONS[i]}"
4848+# icon.padding_left=7
4949+# icon.padding_right=7
5050+# background.color=0x40ffffff
5151+# background.corner_radius=5
5252+# background.height=25
5353+# label.drawing=off
5454+# script="$PLUGIN_DIR/space.sh"
5555+# click_script="yabai -m space --focus $sid"
5656+# )
5757+# sketchybar --add space space."$sid" left --set space."$sid" "${space[@]}"
5858+# done
5959+6060+##### Adding Left Items #####
6161+# We add some regular items to the left side of the bar, where
6262+# only the properties deviating from the current defaults need to be set
6363+6464+sketchybar --add item chevron left \
6565+ --set chevron icon= label.drawing=off \
6666+ --add item front_app left \
6767+ --set front_app icon.drawing=off script="$PLUGIN_DIR/front_app.sh" \
6868+ --subscribe front_app front_app_switched
6969+7070+##### Adding Right Items #####
7171+# In the same way as the left items we can add items to the right side.
7272+# Additional position (e.g. center) are available, see:
7373+# https://felixkratz.github.io/SketchyBar/config/items#adding-items-to-sketchybar
7474+7575+# Some items refresh on a fixed cycle, e.g. the clock runs its script once
7676+# every 10s. Other items respond to events they subscribe to, e.g. the
7777+# volume.sh script is only executed once an actual change in system audio
7878+# volume is registered. More info about the event system can be found here:
7979+# https://felixkratz.github.io/SketchyBar/config/events
8080+8181+sketchybar --add item clock right \
8282+ --set clock update_freq=10 icon= script="$PLUGIN_DIR/clock.sh" \
8383+ --add item volume right \
8484+ --set volume script="$PLUGIN_DIR/volume.sh" \
8585+ --subscribe volume volume_change \
8686+ --add item battery right \
8787+ --set battery update_freq=120 script="$PLUGIN_DIR/battery.sh" \
8888+ --subscribe battery system_woke power_source_change \
8989+ --add item disk right \
9090+ --set disk update_freq=20 script="$PLUGIN_DIR/disk.sh" \
9191+9292+9393+9494+##### Aerospace Configuration #####
9595+sketchybar --add event aerospace_workspace_change
9696+9797+# Get all aerospace workspaces and reverse them
9898+WORKSPACES=($(aerospace list-workspaces --all))
9999+REVERSED_WORKSPACES=()
100100+101101+# Reverse the array
102102+for ((i=${#WORKSPACES[@]}-1; i>=0; i--)); do
103103+ REVERSED_WORKSPACES+=("${WORKSPACES[i]}")
104104+done
105105+106106+source "${CONFIG_DIR}/graphs/cpu.sh"
107107+108108+sketchybar --add item spacer q \
109109+ --set spacer \
110110+ padding_right=25
111111+112112+# Add workspace items to sketchybar in reversed order
113113+for sid in "${REVERSED_WORKSPACES[@]}"; do
114114+ sketchybar --add item space.$sid q \
115115+ --subscribe space.$sid aerospace_workspace_change \
116116+ --set space.$sid \
117117+ background.color=0x44ffffff \
118118+ background.corner_radius=5 \
119119+ background.height=20 \
120120+ background.drawing=off \
121121+ icon="◉" \
122122+ label.padding_left=0 \
123123+ label.padding_right=0 \
124124+ click_script="aerospace workspace $sid" \
125125+ script="$CONFIG_DIR/plugins/aerospace.sh $sid"
126126+done
127127+128128+129129+source "${CONFIG_DIR}/graphs/memory.sh"
130130+source "${CONFIG_DIR}/graphs/network.sh"
131131+132132+##### Force all scripts to run the first time (never do this in a script) #####
133133+sketchybar --update
···11+22+# Setup Nix
33+44+# We need to distinguish between single-user and multi-user installs.
55+# This is difficult because there's no official way to do this.
66+# We could look for the presence of /nix/var/nix/daemon-socket/socket but this will fail if the
77+# daemon hasn't started yet. /nix/var/nix/daemon-socket will exist if the daemon has ever run, but
88+# I don't think there's any protection against accidentally running `nix-daemon` as a user.
99+# We also can't just look for /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh because
1010+# older single-user installs used the default profile instead of a per-user profile.
1111+# We can still check for it first, because all multi-user installs should have it, and so if it's
1212+# not present that's a pretty big indicator that this is a single-user install. If it does exist,
1313+# we still need to verify the install type. To that end we'll look for a root owner and sticky bit
1414+# on /nix/store. Multi-user installs set both, single-user installs don't. It's certainly possible
1515+# someone could do a single-user install as root and then manually set the sticky bit but that
1616+# would be extremely unusual.
1717+1818+set -l nix_profile_path /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh
1919+set -l single_user_profile_path ~/.nix-profile/etc/profile.d/nix.sh
2020+if test -e $nix_profile_path
2121+ # The path exists. Double-check that this is a multi-user install.
2222+ # We can't just check for ~/.nix-profile/… because this may be a single-user install running as
2323+ # the wrong user.
2424+2525+ # stat is not portable. Splitting the output of ls -nd is reliable on most platforms.
2626+ set -l owner (string split -n ' ' (command ls -nd /nix/store 2>/dev/null))[3]
2727+ if not test -k /nix/store -a $owner -eq 0
2828+ # /nix/store is either not owned by root or not sticky. Assume single-user.
2929+ set nix_profile_path $single_user_profile_path
3030+ end
3131+else
3232+ # The path doesn't exist. Assume single-user
3333+ set nix_profile_path $single_user_profile_path
3434+end
3535+3636+if test -e $nix_profile_path
3737+ # Source the nix setup script
3838+ # We're going to run the regular Nix profile under bash and then print out a few variables
3939+ for line in (command env -u BASH_ENV bash -c '. "$0"; for name in PATH "${!NIX_@}"; do printf "%s=%s\0" "$name" "${!name}"; done' $nix_profile_path | string split0)
4040+ set -xg (string split -m 1 = $line)
4141+ end
4242+4343+ # Insert Nix's fish share directories into fish's special variables.
4444+ # nixpkgs-installed fish tries to set these up already if NIX_PROFILES is defined, which won't
4545+ # be the case when sourcing $__fish_data_dir/share/config.fish normally, but might be for a
4646+ # recursive invocation. To guard against that, we'll only insert paths that don't already exit.
4747+ # Furthermore, for the vendor_conf.d sourcing, we'll use the pre-existing presence of a path in
4848+ # $fish_function_path to determine whether we want to source the relevant vendor_conf.d folder.
4949+5050+ # To start, let's locally define NIX_PROFILES if it doesn't already exist.
5151+ set -al NIX_PROFILES
5252+ if test (count $NIX_PROFILES) -eq 0
5353+ set -a NIX_PROFILES $HOME/.nix-profile
5454+ end
5555+ # Replicate the logic from nixpkgs version of $__fish_data_dir/__fish_build_paths.fish.
5656+ set -l __nix_profile_paths (string split ' ' -- $NIX_PROFILES)[-1..1]
5757+ set -l __extra_completionsdir \
5858+ $__nix_profile_paths/etc/fish/completions \
5959+ $__nix_profile_paths/share/fish/vendor_completions.d
6060+ set -l __extra_functionsdir \
6161+ $__nix_profile_paths/etc/fish/functions \
6262+ $__nix_profile_paths/share/fish/vendor_functions.d
6363+ set -l __extra_confdir \
6464+ $__nix_profile_paths/etc/fish/conf.d \
6565+ $__nix_profile_paths/share/fish/vendor_conf.d \
6666+6767+ ### Configure fish_function_path ###
6868+ # Remove any of our extra paths that may already exist.
6969+ # Record the equivalent __extra_confdir path for any function path that exists.
7070+ set -l existing_conf_paths
7171+ for path in $__extra_functionsdir
7272+ if set -l idx (contains --index -- $path $fish_function_path)
7373+ set -e fish_function_path[$idx]
7474+ set -a existing_conf_paths $__extra_confdir[(contains --index -- $path $__extra_functionsdir)]
7575+ end
7676+ end
7777+ # Insert the paths before $__fish_data_dir.
7878+ if set -l idx (contains --index -- $__fish_data_dir/functions $fish_function_path)
7979+ # Fish has no way to simply insert into the middle of an array.
8080+ set -l new_path $fish_function_path[1..$idx]
8181+ set -e new_path[$idx]
8282+ set -a new_path $__extra_functionsdir
8383+ set fish_function_path $new_path $fish_function_path[$idx..-1]
8484+ else
8585+ set -a fish_function_path $__extra_functionsdir
8686+ end
8787+8888+ ### Configure fish_complete_path ###
8989+ # Remove any of our extra paths that may already exist.
9090+ for path in $__extra_completionsdir
9191+ if set -l idx (contains --index -- $path $fish_complete_path)
9292+ set -e fish_complete_path[$idx]
9393+ end
9494+ end
9595+ # Insert the paths before $__fish_data_dir.
9696+ if set -l idx (contains --index -- $__fish_data_dir/completions $fish_complete_path)
9797+ set -l new_path $fish_complete_path[1..$idx]
9898+ set -e new_path[$idx]
9999+ set -a new_path $__extra_completionsdir
100100+ set fish_complete_path $new_path $fish_complete_path[$idx..-1]
101101+ else
102102+ set -a fish_complete_path $__extra_completionsdir
103103+ end
104104+105105+ ### Source conf directories ###
106106+ # The built-in directories were already sourced during shell initialization.
107107+ # Any __extra_confdir that came from $__fish_data_dir/__fish_build_paths.fish was also sourced.
108108+ # As explained above, we're using the presence of pre-existing paths in $fish_function_path as a
109109+ # signal that the corresponding conf dir has also already been sourced.
110110+ # In order to simulate this, we'll run through the same algorithm as found in
111111+ # $__fish_data_dir/config.fish except we'll avoid sourcing the file if it comes from an
112112+ # already-sourced location.
113113+ # Caveats:
114114+ # * Files will be sourced in a different order than we'd ideally do (because we're coming in
115115+ # after the fact to source them).
116116+ # * If there are existing extra conf paths, files in them may have been sourced that should have
117117+ # been suppressed by paths we're inserting in front.
118118+ # * Similarly any files in $__fish_data_dir/vendor_conf.d that should have been suppressed won't
119119+ # have been.
120120+ set -l sourcelist
121121+ for file in $__fish_config_dir/conf.d/*.fish $__fish_sysconf_dir/conf.d/*.fish
122122+ # We know these paths were sourced already. Just record them.
123123+ set -l basename (string replace -r '^.*/' '' -- $file)
124124+ contains -- $basename $sourcelist
125125+ or set -a sourcelist $basename
126126+ end
127127+ for root in $__extra_confdir
128128+ for file in $root/*.fish
129129+ set -l basename (string replace -r '^.*/' '' -- $file)
130130+ contains -- $basename $sourcelist
131131+ and continue
132132+ set -a sourcelist $basename
133133+ contains -- $root $existing_conf_paths
134134+ and continue # this is a pre-existing path, it will have been sourced already
135135+ [ -f $file -a -r $file ]
136136+ and source $file
137137+ end
138138+ end
139139+end