Files
dotfiles/install.sh
kappa f9126603f5 fish 플러그인을 fisher 관리로 분리, ensure 함수 경로 탐색 개선
- fish completions/conf.d/functions를 dotfiles에서 제거 (fisher가 관리)
- config.fish + fish_plugins만 stow로 관리
- ensure 함수가 go/cargo/kitty 등 비표준 경로도 탐색
- install.sh에서 fisher 실행 전 stow 심링크 정리

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 23:08:15 +09:00

313 lines
12 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
OS="$(uname)"
ARCH="$(uname -m)"
echo "==> OS: $OS / ARCH: $ARCH"
# ──────────────────────────────────────────────────────────────────
# 헬퍼 함수
# ──────────────────────────────────────────────────────────────────
ensure() {
# PATH 및 알려진 경로에서 검색
if command -v "$1" &>/dev/null \
|| [ -x "/usr/local/go/bin/$1" ] \
|| [ -x "$HOME/.cargo/bin/$1" ] \
|| [ -x "$HOME/go/bin/$1" ] \
|| [ -x "$HOME/.local/bin/$1" ] \
|| [ -x "$HOME/.local/kitty.app/bin/$1" ]; then
echo "$1 이미 설치됨"
return 1
fi
echo "$1 설치 중..."
return 0
}
# ──────────────────────────────────────────────────────────────────
# macOS
# ──────────────────────────────────────────────────────────────────
install_macos() {
echo "==> macOS 환경 설치 시작"
# Homebrew
if ! command -v brew &>/dev/null; then
echo "==> Homebrew 설치 중..."
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
fi
brew update
BREW_PACKAGES=(
# 기본 도구
git curl wget unzip make stow
# 셸 & 터미널
fish tmux
# 에디터
neovim
# 검색 & 탐색
fzf ripgrep fd bat eza tree
# Git 도구
gh git-delta lazygit
# 데이터 처리
jq yq
# 인프라
kubectl helm vault
# 개발 런타임
node uv go rust
# SSH
trzsz-ssh
# 모니터링
htop
)
for pkg in "${BREW_PACKAGES[@]}"; do
brew list "$pkg" &>/dev/null || brew install "$pkg"
done
# cask 앱
brew list kitty &>/dev/null || brew install --cask kitty
# Claude Code
if ! command -v claude &>/dev/null; then
npm install -g @anthropic-ai/claude-code
fi
# fish를 기본 셸로 등록
FISH_PATH="$(brew --prefix)/bin/fish"
if ! grep -q "$FISH_PATH" /etc/shells; then
echo "$FISH_PATH" | sudo tee -a /etc/shells
fi
echo "==> macOS 설치 완료"
}
# ──────────────────────────────────────────────────────────────────
# Linux (Debian/Ubuntu)
# ──────────────────────────────────────────────────────────────────
install_linux() {
echo "==> Linux 환경 설치 시작"
sudo apt-get update
# ── apt 일괄 설치 ──
APT_PACKAGES=(
# 기본 도구
git curl wget unzip make gcc stow
# 셸 & 터미널
fish tmux
# 검색 & 탐색
fzf ripgrep fd-find tree
# Git 도구
gh git-delta
# 데이터 처리
jq
# 모니터링
htop
# 클립보드
xclip
# Python 기본
python3 python3-pip python3-venv
)
sudo apt-get install -y "${APT_PACKAGES[@]}"
# ── fd 심링크 (Debian은 fdfind) ──
if command -v fdfind &>/dev/null && ! command -v fd &>/dev/null; then
sudo ln -sf "$(which fdfind)" /usr/local/bin/fd
fi
# ── bat (Debian은 batcat) ──
if ! command -v bat &>/dev/null; then
sudo apt-get install -y bat 2>/dev/null || sudo apt-get install -y batcat
if command -v batcat &>/dev/null && ! command -v bat &>/dev/null; then
sudo ln -sf "$(which batcat)" /usr/local/bin/bat
fi
fi
# ── eza ──
if ensure eza; then
sudo apt-get install -y eza 2>/dev/null || {
sudo mkdir -p /etc/apt/keyrings
wget -qO- https://raw.githubusercontent.com/eza-community/eza/main/deb.asc | sudo gpg --dearmor -o /etc/apt/keyrings/gierens.gpg
echo "deb [signed-by=/etc/apt/keyrings/gierens.gpg] http://deb.gierens.de stable main" | sudo tee /etc/apt/sources.list.d/gierens.list
sudo apt-get update && sudo apt-get install -y eza
}
fi
# ── neovim (최신) ──
if ensure nvim; then
curl -Lo /tmp/nvim.tar.gz https://github.com/neovim/neovim/releases/latest/download/nvim-linux-x86_64.tar.gz
sudo tar -C /usr/local --strip-components=1 -xzf /tmp/nvim.tar.gz
rm -f /tmp/nvim.tar.gz
fi
# ── kitty ──
if ! command -v kitty &>/dev/null && [ ! -x "$HOME/.local/kitty.app/bin/kitty" ]; then
echo " → kitty 설치 중..."
curl -L https://sw.kovidgoyal.net/kitty/installer.sh | sh /dev/stdin
fi
# ── yq ──
if ensure yq; then
local yq_arch="amd64"
[ "$ARCH" = "aarch64" ] && yq_arch="arm64"
curl -Lo /tmp/yq "https://github.com/mikefarah/yq/releases/latest/download/yq_linux_${yq_arch}"
sudo install /tmp/yq /usr/local/bin/yq
rm -f /tmp/yq
fi
# ── lazygit ──
if ensure lazygit; then
LAZYGIT_VERSION=$(curl -s "https://api.github.com/repos/jesseduffield/lazygit/releases/latest" | jq -r '.tag_name' | sed 's/^v//')
local lg_arch="x86_64"
[ "$ARCH" = "aarch64" ] && lg_arch="arm64"
curl -Lo /tmp/lazygit.tar.gz "https://github.com/jesseduffield/lazygit/releases/download/v${LAZYGIT_VERSION}/lazygit_${LAZYGIT_VERSION}_Linux_${lg_arch}.tar.gz"
tar -xzf /tmp/lazygit.tar.gz -C /tmp lazygit
sudo install /tmp/lazygit /usr/local/bin/lazygit
rm -f /tmp/lazygit.tar.gz /tmp/lazygit
fi
# ── Node.js (이미 없으면) ──
if ensure node; then
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
sudo apt-get install -y nodejs
fi
# ── uv (Python 패키지 매니저) ──
if ensure uv; then
curl -LsSf https://astral.sh/uv/install.sh | sh
fi
# ── Go ──
if ensure go; then
local go_arch="amd64"
[ "$ARCH" = "aarch64" ] && go_arch="arm64"
GO_VERSION=$(curl -s 'https://go.dev/VERSION?m=text' | head -1)
curl -Lo /tmp/go.tar.gz "https://go.dev/dl/${GO_VERSION}.linux-${go_arch}.tar.gz"
sudo rm -rf /usr/local/go
sudo tar -C /usr/local -xzf /tmp/go.tar.gz
rm -f /tmp/go.tar.gz
fi
# ── Rust ──
if ensure cargo; then
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
fi
# ── HashiCorp Vault CLI ──
if ensure vault; then
wget -qO- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt-get update && sudo apt-get install -y vault
fi
# ── tssh (trzsz-ssh) ──
if ensure tssh; then
curl -Ls https://raw.githubusercontent.com/trzsz/trzsz-ssh/main/install.sh | sudo bash
fi
# ── Claude Code ──
if ensure claude; then
npm install -g @anthropic-ai/claude-code
fi
echo "==> Linux 설치 완료"
}
# ──────────────────────────────────────────────────────────────────
# fisher & fish 플러그인
# ──────────────────────────────────────────────────────────────────
install_fish_plugins() {
echo "==> Fisher 및 fish 플러그인 설치 중..."
if command -v fish &>/dev/null; then
FISH_BIN=fish
elif [ -x /opt/homebrew/bin/fish ]; then
FISH_BIN=/opt/homebrew/bin/fish
else
echo " !! fish를 찾을 수 없습니다. 스킵."
return
fi
# stow된 플러그인 파일은 fisher와 충돌하므로,
# fish 플러그인은 stow가 아닌 fisher로 관리한다.
# fish_plugins 파일만 dotfiles에서 가져오고, 실제 설치는 fisher가 처리.
FISH_PLUGIN_DIRS=(completions conf.d functions)
for dir in "${FISH_PLUGIN_DIRS[@]}"; do
find "$HOME/.config/fish/$dir" -maxdepth 1 -type l -delete 2>/dev/null || true
done
$FISH_BIN -c '
if not functions -q fisher
curl -sL https://raw.githubusercontent.com/jorgebucaran/fisher/main/functions/fisher.fish | source
fisher install jorgebucaran/fisher
end
fisher update
'
echo "==> fish 플러그인 설치 완료"
}
# ──────────────────────────────────────────────────────────────────
# stow 적용
# ──────────────────────────────────────────────────────────────────
apply_dotfiles() {
echo "==> dotfiles 심링크 적용 중..."
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
cd "$SCRIPT_DIR"
# fish 플러그인 파일은 fisher가 관리하므로 stow 충돌 방지
mkdir -p "$HOME/.config/fish"
stow -v --adopt -t "$HOME" fish git kitty nvim tmux
git checkout -- .
echo "==> dotfiles 적용 완료"
}
# ──────────────────────────────────────────────────────────────────
# OS별 gitconfig.local
# ──────────────────────────────────────────────────────────────────
setup_gitconfig_local() {
if [ ! -f "$HOME/.gitconfig.local" ]; then
echo "==> .gitconfig.local 생성 중..."
if [ "$OS" = "Darwin" ]; then
cat > "$HOME/.gitconfig.local" <<'EOF'
[credential]
helper = osxkeychain
EOF
else
cat > "$HOME/.gitconfig.local" <<'EOF'
[credential]
helper = store
EOF
fi
fi
}
# ──────────────────────────────────────────────────────────────────
# 메인
# ──────────────────────────────────────────────────────────────────
case "$OS" in
Darwin) install_macos ;;
Linux) install_linux ;;
*) echo "지원하지 않는 OS: $OS"; exit 1 ;;
esac
apply_dotfiles
install_fish_plugins
setup_gitconfig_local
echo ""
echo "========================================"
echo " 설치 완료! 설치된 도구 목록:"
echo "========================================"
echo ""
echo " 셸/터미널 : fish, tmux, kitty"
echo " 에디터 : neovim"
echo " 검색/탐색 : fzf, ripgrep, fd, bat, eza, tree"
echo " Git : git, gh, delta, lazygit"
echo " 데이터 : jq, yq"
echo " 런타임 : node, python3, uv, go, rust"
echo " 인프라 : kubectl, helm, vault"
echo " AI : claude (Claude Code)"
echo " 기타 : tssh, htop, stow"
echo ""
echo " 새 셸을 열거나 'source ~/.config/fish/config.fish' 를 실행하세요."