Refactor dotfiles for cross-platform support and add fzf utilities#1
Refactor dotfiles for cross-platform support and add fzf utilities#1
Conversation
- Replace all hardcoded /Users/jackson/ paths with $HOME - Add OS detection (DOTFILES_OS) in shell/common/env - Platform-conditional config for pnpm, powerlevel10k, clipboard, Hyprland - Remove orphaned aliases (watson, lynx, howdoi, vifm, brewup) - Remove deprecated packages from Brewfile (spotify-tui, skype, etc.) - Fix undefined $GLOBALINSTALLDIR in vim plugins - Remove osxkeychain credential helper from gitconfig - Add fzf helper functions from arch branch (fe, fcd, fcb, fbr, etc.) - Add atuin shell history support - Add Wayland env vars to tmux.conf - Add Claude Code config (notify hook) - Add .gitignore for state files and secrets https://claude.ai/code/session_01RtJ89RVipBb4fp1XBbo4Wm
Source ~/.shell/secrets early in env if it exists. The file is created by dotbot install but gitignored, so API keys and tokens stay local to each machine and never touch git. https://claude.ai/code/session_01RtJ89RVipBb4fp1XBbo4Wm
There was a problem hiding this comment.
Pull request overview
Refactors the dotfiles repo toward cross-platform (macOS/Linux) support by removing user-specific paths, adding OS-aware config blocks, and introducing fzf-based shell utilities plus Claude Code notification hooks.
Changes:
- Add OS detection (
DOTFILES_OS) and move platform-specific PATH/config into macOS/Linux conditionals. - Replace hardcoded
/Users/...paths with$HOMEand normalize~/Projects→~/projects. - Add fzf-based navigation/git/tmux helper functions and integrate Atuin history + Claude Code hooks.
Reviewed changes
Copilot reviewed 14 out of 15 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
vim/plugins.vim |
Uses exepath('python3') and updates Startify bookmarks to lowercase ~/projects. |
tmux.conf |
Tweaks prefix handling, simplifies status-right, and adds Wayland env propagation. |
shell/zsh/zshrc |
Removes hardcoded oh-my-zsh path; adds OS-aware powerlevel10k sourcing and Atuin init. |
shell/common/env |
Adds OS detection and splits platform-specific Android/pnpm/bash config by OS. |
shell/common/aliases |
Makes clipboard aliases OS-aware; updates paths and prunes old aliases. |
shell/bash/bashrc |
Adds multiple fzf-based helper functions (files/dirs/git/tmux). |
shell/bash/bash_profile |
Improves structure; adds Atuin env and optional Hyprland autostart on TTY1. |
install.conf.yaml |
Adds Claude config symlinks and directory creation; removes Brewfile linking. |
git/gitconfig |
Removes hardcoded global gitignore path. |
fzf/fzf.zsh |
Replaces hardcoded fzf paths with $HOME. |
fzf/fzf.bash |
Replaces hardcoded fzf paths with $HOME. |
claude/settings.json |
Adds Claude hook configuration to run a notification script. |
claude/hooks/notify.sh |
Adds Linux notification hook implementation. |
brew/Brewfile |
Cleans up taps/packages; keeps a smaller core toolset. |
.gitignore |
Adds ignores for state files and common secret/env files. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
shell/bash/bashrc
Outdated
| dir=$(fd . "${1:-.}" --type=d | fzf --no-multi --layout=reverse --height=40%) && | ||
| cd "$dir" | ||
| } | ||
|
|
||
| # fcda - including hidden directories | ||
| function fcda { | ||
| local dir | ||
| dir=$(fd . "${1:-.}" --hidden --type=d | fzf --no-multi --layout=reverse --height=40%) && | ||
| cd "$dir" |
There was a problem hiding this comment.
fcd relies on the external fd command, but the macOS Brewfile in this repo doesn’t install fd. To keep this helper usable after install, either add fd to brew/Brewfile (and document the Linux package) or provide a fallback using find when fd isn’t available.
| dir=$(fd . "${1:-.}" --type=d | fzf --no-multi --layout=reverse --height=40%) && | |
| cd "$dir" | |
| } | |
| # fcda - including hidden directories | |
| function fcda { | |
| local dir | |
| dir=$(fd . "${1:-.}" --hidden --type=d | fzf --no-multi --layout=reverse --height=40%) && | |
| cd "$dir" | |
| if command -v fd >/dev/null 2>&1; then | |
| dir=$(fd . "${1:-.}" --type=d | fzf --no-multi --layout=reverse --height=40%) | |
| else | |
| dir=$(find "${1:-.}" -type d 2>/dev/null | fzf --no-multi --layout=reverse --height=40%) | |
| fi | |
| [ -n "$dir" ] && cd "$dir" | |
| } | |
| # fcda - including hidden directories | |
| function fcda { | |
| local dir | |
| if command -v fd >/dev/null 2>&1; then | |
| dir=$(fd . "${1:-.}" --hidden --type=d | fzf --no-multi --layout=reverse --height=40%) | |
| else | |
| dir=$(find "${1:-.}" -type d 2>/dev/null | fzf --no-multi --layout=reverse --height=40%) | |
| fi | |
| [ -n "$dir" ] && cd "$dir" |
shell/common/aliases
Outdated
| # List contents with colors for file types, (A)lmost all hidden files (without . and ..), in (C)olumns, with class indicators (F) | ||
| alias ls='ls -ACFG' | ||
| alias ls='ls -ACF' | ||
| # List contents with colors for file types, (a)ll hidden entries (including . and ..), use (l)ong listing format, with class indicators (F) | ||
| alias ll='ls -alFG' | ||
| alias ll='ls -alF' |
There was a problem hiding this comment.
The ls/ll alias comments say they list contents “with colors”, but the updated flags (-ACF / -alF) no longer enable colored output on either macOS (-G) or GNU (--color=auto). Update the comment or add a platform-aware color flag so behavior matches the description.
install.conf.yaml
Outdated
| - [touch ~/.shell/secrets, Creating local secrets file (not tracked by git)] | ||
| - [mkdir -p ~/.claude/hooks, Creating Claude Code config directory] | ||
| # If you haven't already, run prefix-I with tmux open after doing this to reload tmux and install the plugins | ||
| - [ if test -d "~/.tmux/plugins/tpm"; then git clone https://github.com/tmux-plugins/tpm ~/.tmux/plugins/tpm; fi ] |
There was a problem hiding this comment.
The TPM install command won’t work on a fresh setup: it uses test -d "~/.tmux/plugins/tpm" (quoted ~ won’t expand, so the test is always false) and it only runs git clone when the directory exists. Remove the quotes around ~ (or use $HOME) and invert the condition so cloning happens only when TPM is missing.
| - [ if test -d "~/.tmux/plugins/tpm"; then git clone https://github.com/tmux-plugins/tpm ~/.tmux/plugins/tpm; fi ] | |
| - [ if [ ! -d "$HOME/.tmux/plugins/tpm" ]; then git clone https://github.com/tmux-plugins/tpm "$HOME/.tmux/plugins/tpm"; fi ] |
| @@ -7,9 +7,6 @@ | |||
| - link: | |||
| ~/.dotfiles: '' | |||
|
|
|||
There was a problem hiding this comment.
Removing the ~/Brewfile link changes the default brew bundle workflow (it looks for ~/Brewfile unless --file is provided). If the intended setup still expects brew bundle to work without extra flags, consider keeping the symlink or documenting the new --file brew/Brewfile usage.
| # Homebrew | |
| ~/Brewfile: brew/Brewfile |
shell/bash/bashrc
Outdated
| local branches branch | ||
| branches=$(git branch --all | grep -v HEAD) && | ||
| branch=$(echo "$branches" | | ||
| fzf --delimiter=$(( 2 + $(wc -l <<< "$branches") )) --no-multi --layout=reverse --height=40%) && |
There was a problem hiding this comment.
fbr passes a numeric expression to fzf --delimiter, but --delimiter expects a delimiter pattern/string, not a column index. This can cause fzf field-splitting to behave unpredictably; drop --delimiter here or set it to an actual delimiter that matches the branch output format.
| fzf --delimiter=$(( 2 + $(wc -l <<< "$branches") )) --no-multi --layout=reverse --height=40%) && | |
| fzf --no-multi --layout=reverse --height=40%) && |
shell/common/aliases
Outdated
|
|
||
| # Config | ||
| export DOTFILES="~/Projects/dotfiles" | ||
| export DOTFILES="$HOME/projects/dotfiles" |
There was a problem hiding this comment.
DOTFILES is exported as $HOME/projects/dotfiles, but the installer links the repo to ~/.dotfiles (and alias dotfiles also points there). This makes the editor aliases (vimrc, bashrc, etc.) location-dependent and likely broken unless the repo is cloned to exactly ~/projects/dotfiles; consider pointing DOTFILES at ~/.dotfiles (or deriving it from the symlink) to match the install layout.
| export DOTFILES="$HOME/projects/dotfiles" | |
| export DOTFILES="$HOME/.dotfiles" |
shell/common/aliases
Outdated
|
|
||
| # Miscellaneous Shortcuts | ||
| alias c="clear" | ||
| alias cdl="cd $1 && ls" |
There was a problem hiding this comment.
alias cdl="cd $1 && ls" won’t work as intended because shell aliases don’t take positional parameters; $1 will typically expand to empty, causing cd to run with no target. Use a shell function (or a script) so the target directory argument is actually passed at invocation time.
| alias cdl="cd $1 && ls" | |
| cdl() { | |
| cd "$1" && ls | |
| } |
shell/bash/bashrc
Outdated
| local out q k sha | ||
| while out=$( | ||
| git stash list --pretty="%C(yellow)%h %>(14)%Cgreen%cr %C(blue)%gs" | | ||
| fzf --ansi --no-sort --query="$q" --print-query \ | ||
| --expect=ctrl-d,ctrl-b); | ||
| do | ||
| mapfile -t out <<< "$out" | ||
| q="${out[0]}" | ||
| k="${out[1]}" | ||
| sha="${out[-1]}" | ||
| sha="${sha%% *}" |
There was a problem hiding this comment.
fgst uses mapfile, which is not available in the default macOS /bin/bash (3.2). Since this repo targets macOS + Linux, consider rewriting this parsing to avoid mapfile (e.g., using a while IFS= read -r loop) or gating these helpers behind a Bash version check.
| local out q k sha | |
| while out=$( | |
| git stash list --pretty="%C(yellow)%h %>(14)%Cgreen%cr %C(blue)%gs" | | |
| fzf --ansi --no-sort --query="$q" --print-query \ | |
| --expect=ctrl-d,ctrl-b); | |
| do | |
| mapfile -t out <<< "$out" | |
| q="${out[0]}" | |
| k="${out[1]}" | |
| sha="${out[-1]}" | |
| sha="${sha%% *}" | |
| local out q k sha sha_line | |
| while out=$( | |
| git stash list --pretty="%C(yellow)%h %>(14)%Cgreen%cr %C(blue)%gs" | | |
| fzf --ansi --no-sort --query="$q" --print-query \ | |
| --expect=ctrl-d,ctrl-b); | |
| do | |
| IFS=$'\n' read -r q k sha_line <<< "$out" | |
| sha="${sha_line%% *}" |
shell/bash/bashrc
Outdated
| fzf --layout=reverse --height=20% --query="$1" --select-1 --exit-0) && | ||
| tmux -CC attach -d -t "$session" |
There was a problem hiding this comment.
fta uses tmux -CC attach ..., which enables tmux control mode intended for iTerm2 integration and will behave poorly in most terminals (and on Linux). Consider using a normal tmux attach by default and only using -CC when iTerm2 is detected (or via an explicit opt-in env var/flag).
| fzf --layout=reverse --height=20% --query="$1" --select-1 --exit-0) && | |
| tmux -CC attach -d -t "$session" | |
| fzf --layout=reverse --height=20% --query="$1" --select-1 --exit-0) || return | |
| # Use tmux control mode (-CC) only when appropriate: | |
| # - TERM_PROGRAM=iTerm.app (iTerm2 integration), or | |
| # - explicit opt-in via FTA_TMUX_CC environment variable. | |
| if [[ "$TERM_PROGRAM" == "iTerm.app" || -n "$FTA_TMUX_CC" ]]; then | |
| tmux -CC attach -d -t "$session" | |
| else | |
| tmux attach -d -t "$session" | |
| fi |
| INPUT=$(cat) | ||
| TITLE=$(printf '%s' "$INPUT" | jq -r '.title // "Claude Code"') | ||
| MESSAGE=$(printf '%s' "$INPUT" | jq -r '.message // "Needs attention"') | ||
| TYPE=$(printf '%s' "$INPUT" | jq -r '.notification_type // "unknown"') | ||
|
|
There was a problem hiding this comment.
notify.sh hard-depends on jq, notify-send, and pw-play, but none of these are ensured by the macOS Brewfile (and notify-send/pw-play are Linux-specific). Add dependency installation docs or make the script degrade gracefully (e.g., check command -v and no-op / choose a macOS notifier when unavailable) to avoid hook failures.
Fix bugs: notify.sh no-op case branches, tmux C-j `&` vs `&&`, tpm clone inverted condition, cdl alias $1 expansion. Fix issues: restore ls colors per-platform, expand tmux PATH for Linux, add fd to Brewfile, quote $1 in take(), add atuin init for bash, prevent p10k double-load, fix gitconfig mixed indent, remove extra space in FZF config. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Quote $HOME in fzf PATH glob checks to handle spaces - Use readarray instead of unquoted array assignment in fe() - Quote $sha and command substitutions in fgst, fbr, fcoc - Remove -CC (iTerm2 control mode) from fta for cross-platform compat - Use dotbot create directive for directories instead of shell mkdir - Normalize ~ to $HOME in PATH entries for consistency Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Guard tmux auto-attach to interactive shells only, add PATH dedup helpers to prevent duplicates in nested shells, use bat explicitly in FZF preview with fallback, add fd guards to fcd/fcda, create zprofile for shell-agnostic Hyprland auto-start, remove hardcoded tmux PATH override, and add gitconfig local include for platform-specific config like credential helpers. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move fzf helpers to shell/common/functions for both bash and zsh, extract login tasks (atuin env, Hyprland) to shell/common/login, move tmux auto-attach to end of env, add p10k fallback warning, move gitconfig [include] to EOF for proper override semantics, fix commit hash grep pattern, and disown background pw-play. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Summary
This PR refactors the dotfiles configuration to support both macOS and Linux systems, adds a collection of fzf-based utility functions, and removes hardcoded paths in favor of environment variables. It also includes cleanup of unused tools and configuration.
Key Changes
Cross-Platform Support
shell/common/envto setDOTFILES_OSvariable (linux/macos)shell/zsh/zshrcto handle powerlevel10k theme installation paths for both macOS (Homebrew) and Linux (Arch)pbcopy/pbpaste) conditional for Linux onlyPath Hardcoding Fixes
/Users/jacksonpaths with$HOMEthroughout:shell/common/env: SCM Breeze, Deno, gitconfigshell/zsh/zshrc: oh-my-zsh installation pathfzf/fzf.bashandfzf/fzf.zsh: FZF binary pathsgit/gitconfig: global gitignore path~/Projectsto~/projects(lowercase)New fzf Utility Functions
Added several interactive fzf-based helper functions to
shell/bash/bashrc:fe: Open files with default editor via fuzzy finderfcd/fcda: Change directory with fuzzy finder (with/without hidden dirs)cds: Change to directory of selected filefcb: Git commit browser with previewfgst: Interactive git stash manager with diff/branch checkoutfbr: Git branch checkout with fuzzy finderfcoc: Git commit checkoutfta: Tmux session attach with fuzzy finderConfiguration Cleanup
.gitignorefor state files and secretsNew Features
shell/common/envMinor Improvements
exepath()instead of hardcoded path)https://claude.ai/code/session_01RtJ89RVipBb4fp1XBbo4Wm