From c79e9e77d0feb2aae29963842ff78c967b3368ad Mon Sep 17 00:00:00 2001 From: Kyle Speight Date: Mon, 27 Jul 2026 08:57:43 -0700 Subject: [PATCH] first commit --- .gitignore | 3 + LICENSE | 18 +++ PKGBUILD | 16 +++ sharkfetch | 327 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 364 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 PKGBUILD create mode 100644 sharkfetch diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1802ba9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*.tar.* +*.tar +*.sum \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..2080a0a --- /dev/null +++ b/LICENSE @@ -0,0 +1,18 @@ +MIT License + +Copyright (c) 2026 chillcog + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and +associated documentation files (the "Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the +following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial +portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT +LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO +EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/PKGBUILD b/PKGBUILD new file mode 100644 index 0000000..520bd60 --- /dev/null +++ b/PKGBUILD @@ -0,0 +1,16 @@ +# Maintainer: Chillcog +pkgname=sharkfetch +pkgver=1.71.0 +pkgrel=1 +pkgdesc="A custom system fetch script with a sharky!" +arch=('any') +url="https://git.chillcog.com/chillcog/sharkfetch" +license=('MIT') +depends=('bash') +source=("${pkgname}-${pkgver}.tar.gz::${url}/archive/refs/tags/v${pkgver}.tar.gz") + +sha256sums=('SKIP') + +package() { + install -Dm755 "${srcdir}/${pkgname}-${pkgver}/sharkfetch" "${pkgdir}/usr/bin/sharkfetch" +} \ No newline at end of file diff --git a/sharkfetch b/sharkfetch new file mode 100644 index 0000000..26a4798 --- /dev/null +++ b/sharkfetch @@ -0,0 +1,327 @@ +#!/usr/bin/env bash + +# https://chillcog.com +# Haiiiii - @chillcog +# Licensed Under The MIT License + +clear + +PRIVATE_MODE=0 + +show_help() { + cat << EOF +Usage: $(basename "$0") [OPTIONS] + +A custom system information fetch script featuring ASCII art. + +Options: + -h, --help Show this help message and exit. + -p, -private, Private mode: hides uniquely identifying information + --private (hostname, public/local IP, hardware model). + +EOF + exit 0 +} + +for arg in "$@"; do + case "$arg" in + -h|--help) + show_help + ;; + -p|-private|--private) + PRIVATE_MODE=1 + ;; + *) + echo "Unknown option: $arg" + echo "Use -h or --help for usage." + exit 1 + ;; + esac +done + +c0=$'\e[0m' +blue=$'\e[34m' +c1=$'\e[36m' +c2=$'\e[35m' + +OS_TYPE="$(uname -s)" +ARCH="$(uname -m)" + +USER_NAME="$(whoami)" +if [ "$PRIVATE_MODE" -eq 1 ]; then + HOST_NAME="[REDACTED]" +else + HOST_NAME="$(hostname 2>/dev/null || uname -n)" +fi +user_host="${USER_NAME}@${HOST_NAME}" + +get_os() { + if [ "$OS_TYPE" = "Linux" ]; then + if [ -f /etc/os-release ]; then + source /etc/os-release && echo "$NAME ($ARCH)" + else + echo "Linux ($ARCH)" + fi + elif [ "$OS_TYPE" = "Darwin" ]; then + echo "macOS $(sw_vers -productVersion 2>/dev/null) ($ARCH)" + else + echo "$OS_TYPE ($ARCH)" + fi +} +os=$(get_os) + +kernel="$(uname -r)" + +get_motherboard() { + if [ "$PRIVATE_MODE" -eq 1 ]; then + echo "[REDACTED]" + return + fi + + if [ -f /sys/devices/virtual/dmi/id/product_name ]; then + local vendor name ver + vendor=$(cat /sys/devices/virtual/dmi/id/sys_vendor 2>/dev/null) + name=$(cat /sys/devices/virtual/dmi/id/product_name 2>/dev/null) + ver=$(cat /sys/devices/virtual/dmi/id/product_version 2>/dev/null) + echo "${vendor} ${name} ${ver}" | xargs + elif command -v sysctl >/dev/null 2>&1 && [ "$OS_TYPE" = "Darwin" ]; then + sysctl -n hw.model 2>/dev/null + else + echo "N/A" + fi +} +host_model=$(get_motherboard) + +uptime_str=$(uptime 2>/dev/null | sed -E 's/.*up[[:space:]]+([^,]+).*/\1/' | xargs) +[ -z "$uptime_str" ] && uptime_str="N/A" + +get_packages() { + local pkgs="" + if command -v pacman >/dev/null 2>&1; then + pkgs="$(pacman -Qq 2>/dev/null | wc -l | xargs) (pacman)" + elif command -v dpkg >/dev/null 2>&1; then + pkgs="$(dpkg -l 2>/dev/null | grep -c '^ii') (dpkg)" + elif command -v rpm >/dev/null 2>&1; then + pkgs="$(rpm -qa 2>/dev/null | wc -l | xargs) (rpm)" + elif command -v brew >/dev/null 2>&1; then + pkgs="$(brew list --formula 2>/dev/null | wc -l | xargs) (brew)" + elif command -v nix-store >/dev/null 2>&1; then + pkgs="$(nix-store -q --requisites /run/current-system 2>/dev/null | wc -l | xargs) (nix)" + else + pkgs="N/A" + fi + echo "$pkgs" +} +packages=$(get_packages) + +get_shell() { + local sh_bin + sh_bin="$(basename "${SHELL:-bash}")" + case "$sh_bin" in + bash) echo "bash $($SHELL --version 2>/dev/null | head -n1 | awk '{print $4}')" ;; + zsh) echo "zsh $($SHELL --version 2>/dev/null | awk '{print $2}')" ;; + fish) echo "fish $($SHELL --version 2>/dev/null | awk '{print $3}')" ;; + *) echo "$sh_bin" ;; + esac +} +shell_info=$(get_shell) + +de="${XDG_CURRENT_DESKTOP:-${DESKTOP_SESSION:-N/A}}" +wm="${XDG_SESSION_DESKTOP:-N/A}" +[ "$OS_TYPE" = "Darwin" ] && de="Aqua" && wm="Quartz Compositor" + +terminal="${TERM_PROGRAM:-${TERM:-N/A}}" + +get_display() { + if command -v xrandr >/dev/null 2>&1; then + xrandr 2>/dev/null | awk '/\*/ {print $1 " @" $2 "Hz"; exit}' | tr -d '*' | xargs + elif [ "$OS_TYPE" = "Darwin" ]; then + system_profiler SPDisplaysDataType 2>/dev/null | awk -F: '/Resolution/ {print $2}' | head -n1 | xargs + else + echo "N/A" + fi +} +display_info=$(get_display) +[ -z "$display_info" ] && display_info="N/A" + +get_cpu() { + if command -v lscpu >/dev/null 2>&1; then + local model cores + model=$(lscpu | awk -F: '/Model name/ {print $2}' | xargs) + cores=$(lscpu | awk -F: '/CPU\(s\):/ {print $2}' | head -n1 | xargs) + echo "${model} (${cores} threads)" + elif [ "$OS_TYPE" = "Darwin" ]; then + local model cores + model=$(sysctl -n machdep.cpu.brand_string 2>/dev/null) + cores=$(sysctl -n hw.ncpu 2>/dev/null) + echo "${model} (${cores} cores)" + else + echo "N/A" + fi +} +cpu=$(get_cpu) +[ -z "$cpu" ] && cpu="N/A" + +get_gpu() { + if command -v lspci >/dev/null 2>&1; then + lspci 2>/dev/null | grep -E 'VGA|3D' | awk -F: '{print $3}' | sed 's/ (rev .*//' | head -n1 | xargs + elif [ "$OS_TYPE" = "Darwin" ]; then + system_profiler SPDisplaysDataType 2>/dev/null | awk -F: '/Chipset Model/ {print $2}' | head -n1 | xargs + else + echo "N/A" + fi +} +gpu=$(get_gpu) +[ -z "$gpu" ] && gpu="N/A" + +get_memory() { + if command -v free >/dev/null 2>&1; then + free -m | awk '/Mem:/ {printf "%sMB / %sMB (%.0f%%)", $3, $2, ($3/$2)*100}' + elif [ "$OS_TYPE" = "Darwin" ]; then + local total_mem + total_mem=$(sysctl -n hw.memsize 2>/dev/null) + total_mem=$((total_mem / 1024 / 1024)) + echo "${total_mem}MB Total" + else + echo "N/A" + fi +} +memory=$(get_memory) + +get_swap() { + if command -v free >/dev/null 2>&1; then + free -m | awk '/Swap:/ {if ($2>0) printf "%sMB / %sMB (%.0f%%)", $3, $2, ($3/$2)*100; else print "Disabled"}' + else + echo "N/A" + fi +} +swap=$(get_swap) + +disk=$(df -h / 2>/dev/null | awk 'NR==2 {print $3 " / " $2 " (" $5 ")"}') + +get_temp() { + if command -v sensors >/dev/null 2>&1; then + sensors 2>/dev/null | awk '/Package id 0:|Core 0:|cpu_thermal/ {print $2; exit}' | tr -d '+' + elif [ -f /sys/class/thermal/thermal_zone0/temp ]; then + local raw + raw=$(cat /sys/class/thermal/thermal_zone0/temp 2>/dev/null) + echo "$((raw / 1000))°C" + else + echo "N/A" + fi +} +cpu_temp=$(get_temp) +[ -z "$cpu_temp" ] && cpu_temp="N/A" + +load_avg=$(uptime 2>/dev/null | awk -F'load average:' '{print $2}' | xargs) +[ -z "$load_avg" ] && load_avg="N/A" + +if [ "$PRIVATE_MODE" -eq 1 ]; then + local_ip="[HIDDEN]" + public_ip="[HIDDEN]" +else + get_ip() { + if command -v ip >/dev/null 2>&1; then + ip route get 1.1.1.1 2>/dev/null | awk '{print $7}' + elif command -v ifconfig >/dev/null 2>&1; then + ifconfig 2>/dev/null | awk '/inet / && !/127.0.0.1/ {print $2}' | head -n1 + else + echo "N/A" + fi + } + local_ip=$(get_ip) + [ -z "$local_ip" ] && local_ip="N/A" + public_ip=$(curl -s --max-time 1 https://icanhazip.com 2>/dev/null || echo "Offline/N/A") +fi + +get_battery() { + if [ -d /sys/class/power_supply ]; then + local cap status + cap=$(cat /sys/class/power_supply/BAT*/capacity 2>/dev/null | head -n1) + status=$(cat /sys/class/power_supply/BAT*/status 2>/dev/null | head -n1) + if [ -n "$cap" ]; then + echo "${cap}% [${status:-Unknown}]" + else + echo "AC Powered" + fi + elif command -v pmset >/dev/null 2>&1; then + pmset -g batt 2>/dev/null | grep -o '[0-9]*%' | head -n1 + else + echo "N/A" + fi +} +battery=$(get_battery) + +locale_val="${LANG:-N/A}" + +raw_logo=$(cat << 'EOF' +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡴⠲⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣾⣷⡄⠈⢢⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣄⠀⠀⠀⠀⠀⠀⢀⣾⡀⠀⠀⠀⠀⠹⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠹⡓⠦⢄⣀⠀⠀⡼⠻⠿⢶⡄⠀⠀⠀⠘⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⢀⡤⠤⠤⣤⣤⣴⣶⣶⠶⠶⠶⠒⠒⠂⠙⠀⠀⠀⠉⠉⠓⠲⢤⣀⠀⠀⠀⠀⠀⢹⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⢸⠀⠀⠀⠈⢿⠈⠳⣤⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠙⠢⣄⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠈⡇⠀⠀⠀⠀⠀⢀⣿⡋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⣟⠁⠀⢸⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠸⡀⠀⠀⠀⠀⢈⡽⠁⠀⠀⠠⡄⠀⠀⠀⠀⠀⠀⠀⣄⠀⠀⠀⠀⠀⠀⠘⡆⠀⢸⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠱⡀⠀⠀⣠⠞⠀⠀⠀⠀⣠⢧⠀⠀⠀⠀⠀⠀⠀⠘⣆⠀⠀⠀⠀⠀⠀⢹⠀⣸⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢆⡴⠃⠀⠀⠀⢠⠞⠁⠈⢣⡀⣄⠀⠀⠀⠀⠀⠘⣆⠀⠀⠀⠀⠀⢸⣠⡇⠀⠀⠀⠀⠀⠀⠀⢀⡀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⢞⣓⣸⠀⢠⠰⣋⣀⣀⣳⢤⡙⢾⣟⠲⢤⣀⣠⠄⢯⠳⡀⠀⠀⠀⠸⠋⡇⠀⠀⠀⠀⠀⠀⢠⠏⠹⡄⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠉⠉⣿⠀⢸⢰⠋⠀⣸⣿⣿⡆⠀⠈⠃⢤⣯⣿⡶⠾⣄⠘⡦⠀⠀⢀⣦⣿⠀⠀⠀⠀⠀⢠⠃⠀⠀⢳⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⡄⢸⣼⣀⡀⠣⠽⠿⢃⠀⠀⠀⢾⣻⣿⡿⠀⣸⡸⠁⠀⢀⡼⡼⠉⠳⣄⠀⠀⣰⠃⠀⠀⠀⢸⠇ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠟⣷⡘⣿⣛⡁⠀⠀⠀⠀⠁⠀⠀⠀⠉⠍⠡⣶⡿⠁⠀⣠⠟⣇⡇⠀⠀⠈⢦⣰⠁⠀⠀⠀⠀⢸⠂ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣾⠖⢻⣣⣈⣿⣤⠤⢒⠒⠦⠖⠢⠴⢄⣀⢬⣷⠞⢁⣠⠞⣡⠞⢹⡟⠀⠀⠀⠀⠃⠀⠀⠀⠀⢀⡞⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢏⣻⡶⠞⠉⠛⢉⣆⣴⡞⠻⠦⣾⢿⣊⣉⡴⣶⠁⠀⠀⠑⢄⡀⢀⢰⠋⢦⠀⠀⣠⠞⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢨⣿⣤⣶⣦⠀⠀⡇⠀⠀⣤⣄⠹⡟⠛⢷⠀⠁⠀⠀⠀⠀⠀⠙⠺⣏⣀⠈⢷⠚⠁⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⢿⣿⣿⣝⢿⡇⠀⣧⢠⣾⣿⣿⣿⡿⡄⢸⡄⠀⠀⠀⠀⠀⠀⠀⢸⠏⠉⠁⠈⡆⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡟⠀⠀⠀⠙⠃⠀⢸⣿⠈⠱⠟⠛⠛⠃⢹⢸⣿⡄⠀⠀⠀⣤⡀⢀⡿⠛⠓⠂⢀⢱⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣸⡀⠀⠀⠀⠀⠀⣠⢟⣸⠦⣄⣀⠀⠀⠀⠘⣸⠹⣟⡆⠀⡼⠁⠙⣾⣷⣦⣄⠀⠀⢸⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⠞⠉⠀⠘⡇⠀⣀⣀⡠⠞⣱⠋⠀⠀⠀⠈⠙⢦⡀⠀⢹⡚⠉⠀⢰⠃⠀⠀⠀⠘⣆⠀⠉⠀⢸⡇⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⢀⣜⠁⠀⠀⠀⠀⠙⠉⢹⣿⠁⢰⠃⠀⠀⠀⠀⠀⠀⠀⠑⣦⣬⠇⠀⢀⡏⠀⠀⠀⠀⠉⠀⠀⠀⢀⢸⡇⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⡠⠟⠛⠛⠷⠂⠀⠀⠀⠀⠈⣿⢠⡇⣠⣤⣤⣤⣀⠀⠀⠀⠀⠘⣿⣶⣶⣿⠁⠀⠀⠀⠀⠀⠀⠀⠀⡞⢸⠃⠀⠀⠀ +⠀⠀⠀⠀⠀⢀⣾⣷⣤⣤⠀⠀⠀⠀⠀⠀⠀⠀⠛⡼⢉⢉⣉⣉⠛⠻⢷⣄⠀⠀⠀⣸⣯⠙⢿⣧⠀⠀⠀⠀⠀⠀⢀⡼⠁⡼⠀⠀⠀⠀ +⠀⠀⠀⠀⡰⠋⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡤⠀⡗⠛⠛⠻⠿⣷⣦⣀⠀⠀⠀⠀⠘⢻⠀⠀⠙⠃⠀⠀⠀⠀⡠⠊⠀⢠⠃⠀⠀⠀⠀ +⠀⣠⣖⣟⣳⣒⣆⠀⠀⠀⠀⠀⠀⠀⠀⣠⣎⠀⢸⠁⠀⠀⠀⠀⠀⠉⠉⠀⢸⠀⠀⠀⣏⠀⠀⠀⠀⠀⠠⠒⠋⠀⠀⢠⠏⠀⠀⠀⠀⠀ +⠰⣿⣿⣶⠿⠷⣾⠃⠀⠀⠀⠀⢀⡠⠚⠁⠈⠦⡞⠀⠀⠀⠀⠀⠀⠀⠀⢠⠏⠀⠀⡼⠉⠁⠀⠀⠀⠀⠀⠀⠀⣠⠔⠋⠀⠀⠀⠀⠀⠀ +⠀⠹⣦⣓⡒⠋⠉⠀⠀⠀⣀⡴⠋⠀⠀⠀⠀⡼⠁⡀⠀⠀⠀⠀⠀⠀⣠⠏⢀⣠⢾⣁⣀⣀⣀⣀⣠⠤⠒⠚⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠉⠉⠉⠁⠀⠀⠀⠀⠀⠀⠀⠀⠹⣦⣿⣯⣿⣦⢀⡴⠋⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠉⠉⠉⠉⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +EOF +) + +transparent_logo=$(echo "$raw_logo" | sed 's/⠀/ /g' | sed 's/[[:space:]]*$//') +readarray -t logo <<< "$transparent_logo" + +labels=( + "OS:" "Host Model:" "Kernel:" "Uptime:" "Packages:" "Shell:" + "DE/WM:" "Terminal:" "Resolution:" "CPU:" "CPU Temp:" "GPU:" + "Memory:" "Swap:" "Disk (/):" "Load Avg:" "Local IP:" "Public IP:" + "Battery:" "Locale:" +) +values=( + "$os" "$host_model" "$kernel" "$uptime_str" "$packages" "$shell_info" + "${de} / ${wm}" "$terminal" "$display_info" "$cpu" "$cpu_temp" "$gpu" + "$memory" "$swap" "$disk" "$load_avg" "$local_ip" "$public_ip" + "$battery" "$locale_val" +) + +info=() +info+=("${c1}${user_host}${c0}") +info+=("---------------------------------------") + +for i in "${!labels[@]}"; do + lbl=$(printf "%-13s" "${labels[$i]}") + info+=("${c1}${lbl}${c0} ${c2}${values[$i]}${c0}") +done + +target_width=72 +max_lines=$((${#logo[@]} > ${#info[@]} ? ${#logo[@]} : ${#info[@]})) + +for ((i=0; i