Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ The actual config lives under `~/.config/zsh/`.

### Shared files

- `configs/shared/tools.zsh`: external tool initialization, including cached init scripts
- `configs/shared/tools.zsh`: thin orchestrator that sources `shared/tools/_loader.zsh` and calls `_load_tool_config` for each tool module
- `configs/shared/tools/_loader.zsh`: `_load_tool_config()` helper and `_source_cached_tool_init()` with version-based cache invalidation
- `configs/shared/tools/{tool}.zsh`: per-tool module files (fzf, runtime, atuin, bun), loaded on demand by `_load_tool_config`
- `configs/shared/prompt.zsh`: prompt/theme loading

### Local files
Expand Down
19 changes: 12 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Named after Barney's catchphrase from [How I Met Your Mother](https://www.themov
- **Verify mode** — check your installation integrity
- **Clean mode** — remove suitup config files
- `--help` output for quick command discovery
- Backs up existing zsh startup files to `~/.config/suitup/backups/` before changing shell startup config
- Backs up existing zsh startup files to `~/.config/zsh/backups/` before changing shell startup config
- Powerlevel10k is optional; recommended because its async git status stays responsive in large repositories
- Idempotent — safe to run multiple times
- No private/company-specific content — clean, generic configs
Expand Down Expand Up @@ -111,7 +111,7 @@ Interactive step-by-step setup with selectable steps:
10. **Vim Config** — basic vim setup
11. **Dock Cleanup** — clean macOS Dock

Before suitup updates shell startup config, it backs up existing zsh startup files such as `.zshrc`, `.zprofile`, `.zshenv`, and `.zlogin` to `~/.config/suitup/backups/`.
Before suitup updates shell startup config, it backs up existing zsh startup files such as `.zshrc`, `.zprofile`, `.zshenv`, and `.zlogin` to `~/.config/zsh/backups/`.

If you choose Powerlevel10k, suitup keeps prompt loading non-interactive during setup. When `~/.p10k.zsh` is missing, it falls back to a basic prompt until you run `p10k configure` yourself.

Expand Down Expand Up @@ -162,7 +162,7 @@ This command:

- extracts detected PATH-related lines from `.zshrc`
- appends them to `~/.config/zsh/core/paths.zsh`
- creates a backup in `~/.config/suitup/backups/`
- creates a backup in `~/.config/zsh/backups/`
- runs a post-migration Zsh syntax check
- rolls back automatically if validation fails

Expand All @@ -175,7 +175,7 @@ node src/cli.js clean
Attempts a safe uninstall of suitup-managed config:

- restores the latest non-suitup backup of `~/.zshrc` / `~/.zshenv` when available
- removes suitup-generated `~/.config/zsh/` and `~/.config/suitup/` files when they still match shipped templates
- removes suitup-generated `~/.config/zsh/` files when they still match shipped templates
- strips `# >>> suitup/... >>>` blocks from an existing `~/.zshrc` if you used `append`
- preserves user-modified files instead of deleting them blindly

Expand Down Expand Up @@ -231,17 +231,22 @@ After setup, your shell config looks like:
paths.zsh # PATH + tool bootstrap entries
options.zsh # Zsh shell options
shared/
tools.zsh # Tool init (fzf, atuin, zoxide, fnm)
tools.zsh # Tool init orchestrator
tools/
_loader.zsh # _load_tool_config() + version-based cache
fzf.zsh # FZF env, init, Ctrl-T widget
runtime.zsh # zoxide + fnm
atuin.zsh # Atuin history (owns Ctrl-R)
bun.zsh # Bun async completion
plugins.zsh # zinit plugin declarations
highlighting.zsh # zsh-syntax-highlighting styles
aliases.zsh # Shared aliases
completion.zsh # Native completion setup
prompt.zsh # Prompt/theme (p10k)
local/
machine.zsh # Machine-specific overrides
config.vim # Vim config
secrets.zsh # API keys (create manually, gitignored)
~/.config/suitup/
config.vim # Vim config
```

## Testing
Expand Down
14 changes: 9 additions & 5 deletions configs/core/perf.zsh
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@ _print_duration_row() {
if (( rounded_ms > 1000 )); then
local sec=$(( rounded_ms / 1000 ))
local rem=$(( rounded_ms % 1000 ))
printf '│ %-8s %12d.%01ds │\n' "$name" "$sec" "$(( rem / 100 ))"
printf '│ %-10s %12d.%01ds │\n' "$name" "$sec" "$(( rem / 100 ))"
else
printf '│ %-8s %13dms │\n' "$name" "$rounded_ms"
printf '│ %-10s %13dms │\n' "$name" "$rounded_ms"
fi
}

Expand All @@ -66,13 +66,17 @@ _zsh_report() {
local i

echo ''
echo '┌──────────────────────────┐'
echo '┌────────────────────────────┐'

for i in {1..${#_zsh_stage_names}}; do
_print_duration_row "${_zsh_stage_names[$i]}" "${_zsh_stage_durations[$i]}"
done

echo '├──────────────────────────┤'
echo '├────────────────────────────┤'
_print_duration_row 'total' "$total_ms"
echo '└──────────────────────────┘'
echo '└────────────────────────────┘'

if [[ "${_zsh_completion_cache_mode:-}" == 'cache-hit' && -n "${_zsh_compdump_file:-}" ]]; then
printf 'completion cache hit; remove %s to rebuild\n' "$_zsh_compdump_file"
fi
}
2 changes: 1 addition & 1 deletion configs/shared/aliases.zsh
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ alias cat="bat"
# git
alias gco="git checkout"
alias gph="git push"
alias gphu='local b; b=$(git rev-parse --abbrev-ref HEAD 2>/dev/null); [[ $b != HEAD ]] && gph -u origin "$b"'
alias gphu='local b; b=$(git branch --show-current 2>/dev/null); [[ -n $b ]] && gph -u origin "$b"'
alias gcol="git checkout --no-guess"
alias gpl="git pull --rebase"
alias gcz="git-cz"
Expand Down
33 changes: 0 additions & 33 deletions configs/shared/fzf.zsh

This file was deleted.

54 changes: 22 additions & 32 deletions configs/shared/tools.zsh
Original file line number Diff line number Diff line change
@@ -1,37 +1,27 @@
# ============================================================================
# External tool configuration and initialization
# Shared tool entry point
# ============================================================================
#
# This file is the only tool entry point sourced by `~/.zshrc`.
#
# Maintenance rules:
# - Keep this file orchestration-only. Do not add tool-specific logic here.
# - Add shared helper functions to `shared/tools/_loader.zsh`.
# - Add each tool to its own file under `shared/tools/`.
# - Keep the load order explicit. Do not auto-discover files from the directory,
# because keyboard bindings and tool init order matter.
# - If two tools compete for the same binding, document the winner here.

# FZF configuration (env vars for fd-based search and preview bindings)
[[ -f "${ZDOTDIR:-$HOME/.config/zsh}/shared/fzf.zsh" ]] && source "${ZDOTDIR:-$HOME/.config/zsh}/shared/fzf.zsh"
_zsh_tools_dir="${ZSH_CONFIG:-$HOME/.config/zsh}/shared/tools"

_zsh_tools_cache_dir="${XDG_CACHE_HOME:-$HOME/.cache}/zsh"
[[ -d "$_zsh_tools_cache_dir" ]] || mkdir -p "$_zsh_tools_cache_dir"
source "$_zsh_tools_dir/_loader.zsh"

_source_cached_tool_init() {
local cache_name="$1"
local binary_name="$2"
local init_command="$3"
local binary_path
local cache_file="$_zsh_tools_cache_dir/${cache_name}.zsh"
local tmp_file="${cache_file}.tmp"

binary_path=$(command -v "$binary_name") || return 0

if [[ ! -s "$cache_file" || "$binary_path" -nt "$cache_file" ]]; then
if eval "$init_command" >| "$tmp_file" 2>/dev/null; then
mv "$tmp_file" "$cache_file"
else
rm -f "$tmp_file"
eval "$init_command"
return
fi
fi

source "$cache_file"
}

_source_cached_tool_init fzf-init fzf 'fzf --zsh'
_source_cached_tool_init atuin-init atuin 'atuin init zsh'
_source_cached_tool_init zoxide-init zoxide 'zoxide init zsh'
_source_cached_tool_init fnm-init fnm 'fnm env --use-on-cd --version-file-strategy=recursive --shell zsh'
# Load order matters:
# 1. fzf defines Ctrl-T and shared picker behavior.
# 2. runtime tools initialize common navigation/node helpers.
# 3. atuin loads after fzf so it can own Ctrl-R.
# 4. bun completion is deferred because it is non-essential at startup.
_load_tool_config fzf
_load_tool_config runtime
_load_tool_config atuin
_load_tool_config bun
57 changes: 57 additions & 0 deletions configs/shared/tools/_loader.zsh
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# ============================================================================
# Shared tool loader and cached init helpers
# ============================================================================
#
# This file contains common helpers used by multiple tool modules.
#
# Maintenance rules:
# - Put reusable helper functions here only when at least two tool modules need
# them, or when the helper exists purely to support module loading.
# - Keep tool-specific env vars, aliases, bindings, and wrapper functions in the
# tool's own file.
# - `_source_cached_tool_init` is the preferred way to source expensive shell
# init output from CLIs such as `fzf`, `zoxide`, `fnm`, and `atuin`.

_zsh_tools_cache_dir="${XDG_CACHE_HOME:-$HOME/.cache}/zsh"
[[ -d "$_zsh_tools_cache_dir" ]] || mkdir -p "$_zsh_tools_cache_dir"

_load_tool_config() {
local tool_name="$1"
local tool_file="$_zsh_tools_dir/${tool_name}.zsh"

[[ -f "$tool_file" ]] && source "$tool_file"
}

_source_cached_tool_init() {
local cache_name="$1"
local binary_name="$2"
local init_command="$3"
local binary_path
local cache_file="$_zsh_tools_cache_dir/${cache_name}.zsh"
local tmp_file="${cache_file}.tmp"
local version_file="$_zsh_tools_cache_dir/${cache_name}.version"
local current_version

binary_path=$(command -v "$binary_name") || return 0
current_version=$("$binary_path" --version 2>/dev/null | head -1) || current_version="unknown"

if [[ -s "$cache_file" && -s "$version_file" ]]; then
local cached_version
cached_version=$(<"$version_file")
if [[ "$current_version" == "$cached_version" ]]; then
source "$cache_file"
return
fi
fi

if eval "$init_command" >| "$tmp_file" 2>/dev/null; then
mv "$tmp_file" "$cache_file"
echo -n "$current_version" > "$version_file"
else
rm -f "$tmp_file"
eval "$init_command"
return
fi

source "$cache_file"
}
14 changes: 14 additions & 0 deletions configs/shared/tools/atuin.zsh
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# ============================================================================
# atuin history integration
# ============================================================================
#
# This module owns shell initialization for atuin.
#
# Maintenance rules:
# - Load atuin after fzf so atuin can override Ctrl-R with its history widget.
# - Do not place completion or Tab behavior here; keep atuin focused on history.
# - If atuin init ever conflicts with another history tool, document the final
# binding winner in `shared/tools.zsh`.

# Atuin - load after fzf to override ctrl-r binding.
_source_cached_tool_init atuin-init atuin 'atuin init zsh'
16 changes: 16 additions & 0 deletions configs/shared/tools/bun.zsh
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# ============================================================================
# bun completion
# ============================================================================
#
# This module keeps bun completion isolated because it is optional and can be
# loaded slightly later without hurting the main interactive shell experience.
#
# Maintenance rules:
# - Keep this async unless there is a strong reason to make bun completion part
# of the synchronous startup path.
# - Only source the completion file when it exists on the current machine.

{
sleep 0.5
[[ -s "$HOME/.bun/_bun" ]] && source "$HOME/.bun/_bun"
} &!
Loading
Loading