Остання активність 1 week ago

Cross-platform Zsh setup scripts and managed dotfiles with Oh My Zsh framework, Starship prompt, aliases, functions, and path configuration.

Версія d5c3c35f8b63c5cff0585cafc4ceb97ad571a54b

README.md Неформатований

Bash Script Installer for Zsh

The "Bash Script Installer" simplifies the setup of Zsh.

Zsh

Ubuntu

bash -c "$(curl -fsSL https://tinyurl.com/y6fhb594)"

WSL

bash -c "$(curl -fsSL https://tinyurl.com/ycyct6wp)"

MacOS

bash -c "$(curl -fsSL https://tinyurl.com/yptybtpa)"

Configuration

bash -c "$(curl -fsSL https://tinyurl.com/y8vf753j)"

Shell framework and prompt

The installers use Oh My Zsh for framework features and plugins, with the OMZ theme disabled:

ZSH_THEME=""
source "$ZSH/oh-my-zsh.sh"
eval "$(starship init zsh)"

Starship owns the prompt and loads after Oh My Zsh. The managed Starship config is installed at ~/.config/starship.toml. A Nerd Font is required for the Powerline symbols.

Plan-build workflow

plan_build launches Claude Code as the implementation orchestrator, with Codex and CodeRabbit as independent reviewers. The configuration installer also installs its workflow at ~/.claude/skills/plan-build/SKILL.md.

plan_build                                      # Standard plan and build
plan_build --prompt                             # Enhance the payload with Auggie first
plan_build --writing-plan                       # Superpowers implementation plan, Codex review, then build
plan_build --prompt --brainstorm                # Auggie, Superpowers design and plan, Codex review, then build
plan_build --yolo --writing-plan                # Pass --yolo through to Claude Code

--brainstorm and --writing-plan are mutually exclusive. They require the enabled superpowers@claude-plugins-official Claude Code plugin; plan_build reports the install or enable command and exits before Auggie when the requirement is not met.

alias Неформатований
1# =============================================================================
2# OS-SPECIFIC ALIASES
3# =============================================================================
4if [[ "$OSTYPE" == "linux-gnu"* ]] && command -v apt-get >/dev/null 2>&1; then
5 # Linux Only System update & cleanup
6 alias uu='sudo apt-get update && \
7 sudo apt-get upgrade -y && \
8 sudo apt-get full-upgrade -y && \
9 sudo apt-get autoremove -y && \
10 sudo apt-get autoclean -y && \
11 sudo apt-get clean'
12elif [[ "$OSTYPE" == "darwin"* ]]; then
13 # macOS Only
14 alias flushdns='sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder'
15fi
16
17# =============================================================================
18# UNIVERSAL GIT ALIASES (Fixed: Removed broken "$@" from aliases)
19# =============================================================================
20alias gph='git push'
21alias gco='git checkout'
22alias gbh='git branch'
23alias gmt='git commit'
24alias gpl='git pull'
25alias grb='git rebase'
26alias grt='git reset'
27alias gst='git status'
28alias grmrf='git checkout -- . && git clean -fd'
config.sh Неформатований
1#!/bin/bash
2set -euo pipefail
3
4# Configuration
5GIST_RAW_BASE="https://opengist.resetrix.work/weehong/f0d940c3c1214bf5b7996195199fdc09/raw/HEAD"
6CONFIG_FILES=(
7 ".alias"
8 ".func"
9 ".pathrc"
10 ".sourcerc"
11 ".vimrc"
12 ".zshrc"
13 ".config/starship.toml"
14)
15PLAN_BUILD_SKILL_TARGET="$HOME/.claude/skills/plan-build/SKILL.md"
16
17echo "Starting configuration download..."
18download_failed=0
19
20for f in "${CONFIG_FILES[@]}"; do
21 # Remove the leading dot for the URL path
22 remote_name="${f#.}"
23 [[ "$f" == ".config/starship.toml" ]] && remote_name="starship.toml"
24 url="$GIST_RAW_BASE/$remote_name"
25 target="$HOME/$f"
26 tmp="${target}.tmp.$$"
27
28 echo "Downloading $f..."
29 mkdir -p "$(dirname "$target")"
30
31 # Use -f to fail silently on server errors, -s for silent, -L to follow redirects
32 if curl -fsSL "$url" -o "$tmp" && mv "$tmp" "$target"; then
33 echo "Successfully updated $target"
34 else
35 rm -f "$tmp"
36 echo "Error: Failed to download $f from $url" >&2
37 download_failed=1
38 fi
39done
40
41echo "Downloading Claude Code plan-build workflow..."
42mkdir -p "$(dirname "$PLAN_BUILD_SKILL_TARGET")"
43skill_tmp="${PLAN_BUILD_SKILL_TARGET}.tmp.$$"
44if curl -fsSL "$GIST_RAW_BASE/orchestrate-loop.md" -o "$skill_tmp" && mv "$skill_tmp" "$PLAN_BUILD_SKILL_TARGET"; then
45 echo "Successfully updated $PLAN_BUILD_SKILL_TARGET"
46else
47 rm -f "$skill_tmp"
48 echo "Error: Failed to download the plan-build workflow" >&2
49 download_failed=1
50fi
51
52if [ "$download_failed" -ne 0 ]; then
53 echo "Configuration download completed with errors." >&2
54 exit 1
55fi
56
57echo "Done! All configuration files have been replaced."
58
func Неформатований
1# =============================================================================
2# CUSTOM FUNCTIONS
3# =============================================================================
4
5# -----------------------------------------------------------------------------
6# Function: funcs (List available .func functions)
7# -----------------------------------------------------------------------------
8funcs() {
9 local func_file="${1:-$HOME/.func}"
10
11 if [ ! -f "$func_file" ]; then
12 printf "Error: Function file '%s' not found.\n" "$func_file" >&2
13 return 1
14 fi
15
16 printf "Available functions in %s:\n" "$func_file"
17 awk '
18 /^# Function: / {
19 line = $0
20 sub(/^# Function: /, "", line)
21
22 name = line
23 sub(/ .*/, "", name)
24
25 desc = ""
26 if (line ~ / \(.+\)$/) {
27 desc = line
28 sub(/^[^ ]+ \(/, "", desc)
29 sub(/\)$/, "", desc)
30 }
31
32 if (desc != "") {
33 printf " %-22s %s\n", name, desc
34 } else {
35 printf " %s\n", name
36 }
37 }
38 ' "$func_file"
39}
40
41# -----------------------------------------------------------------------------
42# Function: clip (Cross-platform clipboard)
43# -----------------------------------------------------------------------------
44clip() {
45 local cmd
46 local args=()
47
48 if command -v pbcopy >/dev/null 2>&1; then
49 cmd="pbcopy" # macOS
50 elif grep -qi "microsoft" /proc/version 2>/dev/null && command -v clip.exe >/dev/null 2>&1; then
51 cmd="clip.exe" # WSL
52 elif [ "$XDG_SESSION_TYPE" = "wayland" ] && command -v wl-copy >/dev/null 2>&1; then
53 cmd="wl-copy" # Linux Wayland
54 elif command -v xclip >/dev/null 2>&1; then
55 cmd="xclip" # Linux X11 (Fallback 1)
56 args=("-selection" "clipboard")
57 elif command -v xsel >/dev/null 2>&1; then
58 cmd="xsel" # Linux X11 (Fallback 2)
59 args=("--clipboard" "--input")
60 else
61 printf "Error: No supported clipboard utility found.\n" >&2
62 return 1
63 fi
64
65 if [ $# -gt 0 ]; then
66 if [ -f "$1" ]; then
67 "$cmd" "${args[@]}" < "$1"
68 echo "Copied contents of '$1' to clipboard."
69 else
70 printf "Error: File '%s' not found.\n" "$1" >&2
71 return 1
72 fi
73 else
74 "$cmd" "${args[@]}"
75 fi
76}
77
78# -----------------------------------------------------------------------------
79# Function: open_file (Cross-platform file/directory opener)
80# -----------------------------------------------------------------------------
81open_file() {
82 local target="${1:-.}"
83
84 if [[ "$OSTYPE" == "darwin"* ]]; then
85 command open "$target"
86 elif grep -qi "microsoft" /proc/version 2>/dev/null; then
87 if command -v wslpath >/dev/null 2>&1 && command -v explorer.exe >/dev/null 2>&1; then
88 explorer.exe "$(wslpath -w "$target")"
89 else
90 printf "Error: 'wslpath' or 'explorer.exe' not found.\n" >&2
91 return 1
92 fi
93 elif [[ "$OSTYPE" == "linux-gnu"* ]]; then
94 if command -v xdg-open >/dev/null 2>&1; then
95 xdg-open "$target"
96 else
97 printf "Error: 'xdg-open' not found.\n" >&2
98 return 1
99 fi
100 fi
101}
102alias open='open_file'
103
104# -----------------------------------------------------------------------------
105# Function: clear_history (Supports shell, Claude, Codex, and OpenCode)
106# -----------------------------------------------------------------------------
107clear_history() {
108 case "${1:-}" in
109 claude)
110 if [ -d "$HOME/.claude/projects" ]; then
111 # Use 'yes' to skip prompts and -f to ignore non-existent files
112 yes | rm -rf "$HOME/.claude/projects"/*
113 echo "Claude project history/cache cleared."
114 fi
115 ;;
116
117 codex)
118 local codex_home="${CODEX_HOME:-$HOME/.codex}"
119 local codex_session_file
120 local codex_session_id
121
122 mkdir -p "$codex_home"
123 : > "$codex_home/history.jsonl"
124
125 if command -v codex >/dev/null 2>&1; then
126 find "$codex_home/sessions" "$codex_home/archived_sessions" -type f -name '*.jsonl' -print 2>/dev/null | while IFS= read -r codex_session_file; do
127 codex_session_id="$(sed -n 's/.*"session_id":"\([^"]*\)".*/\1/p; q' "$codex_session_file")"
128 if [ -n "$codex_session_id" ]; then
129 codex delete --force "$codex_session_id" >/dev/null 2>&1 || true
130 fi
131 done
132 fi
133
134 rm -rf "$codex_home/sessions" "$codex_home/archived_sessions" "$codex_home/shell_snapshots"
135 mkdir -p "$codex_home/sessions" "$codex_home/archived_sessions" "$codex_home/shell_snapshots"
136
137 echo "Codex history cleared."
138 ;;
139
140 opencode)
141 local opencode_state_home="${XDG_STATE_HOME:-$HOME/.local/state}/opencode"
142 local opencode_data_home="${XDG_DATA_HOME:-$HOME/.local/share}/opencode"
143
144 mkdir -p "$opencode_state_home" "$opencode_data_home"
145 : > "$opencode_state_home/prompt-history.jsonl"
146 rm -f \
147 "$opencode_data_home/opencode.db" \
148 "$opencode_data_home/opencode.db-shm" \
149 "$opencode_data_home/opencode.db-wal"
150 rm -rf "$opencode_data_home/repos" "$opencode_data_home/log"
151 mkdir -p "$opencode_data_home/repos" "$opencode_data_home/log"
152
153 echo "OpenCode history cleared."
154 ;;
155
156 *)
157 # 1. Truncate the file
158 : > "$HISTFILE"
159
160 # 2. Clear RAM by briefly setting history size to 0
161 local old_histsize=$HISTSIZE
162 HISTSIZE=0
163 HISTSIZE=$old_histsize
164
165 echo "Shell history cleared."
166 ;;
167 esac
168}
169
170# -----------------------------------------------------------------------------
171# Function: require_cli (Check external CLI availability)
172# -----------------------------------------------------------------------------
173require_cli() {
174 local binary="$1"
175 local label="$2"
176 local resolved
177
178 if command -v whence >/dev/null 2>&1; then
179 if whence -p "$binary" >/dev/null 2>&1; then
180 return 0
181 fi
182 else
183 resolved="$(command -v "$binary" 2>/dev/null)" || resolved=""
184 if [ -n "$resolved" ] && [ -x "$resolved" ]; then
185 return 0
186 fi
187 fi
188
189 printf "Error: %s ('%s') is not installed or not in your PATH.\n" "$label" "$binary" >&2
190 return 1
191}
192
193# -----------------------------------------------------------------------------
194# Function: claude (Includes --yolo and clear shortcuts)
195# -----------------------------------------------------------------------------
196claude() {
197 # Shortcut for clearing cache
198 if [[ "$1" == "clear" ]]; then
199 clear_history claude
200 return 0
201 fi
202
203 # Check if binary exists
204 require_cli claude "Claude Code CLI" || return 1
205
206 # Handle --yolo mode
207 if [[ "$1" == "--yolo" ]]; then
208 shift
209 command claude --dangerously-skip-permissions "$@"
210 return $?
211 fi
212
213 command claude "$@"
214}
215
216# -----------------------------------------------------------------------------
217# Internal: _prompt_confirm_indexing (Confirm project indexing via the terminal)
218# -----------------------------------------------------------------------------
219_prompt_confirm_indexing() {
220 local project_root="$1"
221 local reply
222
223 if ! (: </dev/tty) 2>/dev/null; then
224 printf "Notice: No interactive terminal available; enhancing without project indexing.\n" >&2
225 return 1
226 fi
227
228 printf "Allow Auggie to index and use project context from '%s'? (y/N) " "$project_root" >/dev/tty
229 if ! IFS= read -r reply </dev/tty; then
230 printf "\nNotice: Unable to read confirmation; enhancing without project indexing.\n" >&2
231 return 1
232 fi
233
234 case "$reply" in
235 y|Y|yes|YES|Yes)
236 return 0
237 ;;
238 *)
239 return 1
240 ;;
241 esac
242}
243
244# -----------------------------------------------------------------------------
245# Internal: _enhance_prompt (Run Auggie and write only the enhanced prompt)
246# -----------------------------------------------------------------------------
247_enhance_prompt() {
248 local prompt="$1"
249 local output_file="$2"
250 local run_dir
251 local prompt_file
252 local workspace
253 local cache_dir
254 local auth_file
255 local log_file
256 local parsed_file
257 local project_root
258 local use_project_context
259 local script_pid
260 local waited
261 local timeout_seconds
262 local monitor_status
263
264 if [ -z "$prompt" ]; then
265 printf "Error: Prompt was empty.\n" >&2
266 return 1
267 fi
268
269 if [ ! -s "$HOME/.augment/session.json" ]; then
270 printf "Error: Auggie session file not found. Run 'auggie login' first.\n" >&2
271 return 1
272 fi
273
274 run_dir="$(mktemp -d "${TMPDIR:-/tmp}/auggie-enhance.XXXXXX")" || return 1
275 prompt_file="$run_dir/prompt.txt"
276 workspace="$run_dir/workspace"
277 cache_dir="$run_dir/cache"
278 auth_file="$HOME/.augment/session.json"
279 log_file="$run_dir/auggie.log"
280 parsed_file="$run_dir/enhanced.txt"
281 mkdir -p "$workspace" "$cache_dir"
282 printf "%s\n" "$prompt" > "$prompt_file"
283
284 project_root="$(git rev-parse --show-toplevel 2>/dev/null)" || project_root="$PWD"
285 use_project_context=0
286 timeout_seconds=90
287
288 if _prompt_confirm_indexing "$project_root"; then
289 use_project_context=1
290 timeout_seconds=300
291 workspace="$project_root"
292 cache_dir="$HOME/.augment"
293 printf "Indexing approved; enhancing with project context from '%s'.\n" "$project_root" >&2
294 else
295 printf "Enhancing without project indexing.\n" >&2
296 fi
297
298 (
299 if [ "$use_project_context" -eq 1 ]; then
300 AUGGIE_PROMPT_FILE="$prompt_file" \
301 AUGGIE_WORKSPACE="$workspace" \
302 AUGGIE_CACHE_DIR="$cache_dir" \
303 AUGGIE_AUTH_FILE="$auth_file" \
304 script -q -f -O "$log_file" -c 'auggie --print --enhance-prompt --workspace-root "$AUGGIE_WORKSPACE" --augment-cache-dir "$AUGGIE_CACHE_DIR" --augment-session-json "$AUGGIE_AUTH_FILE" --allow-indexing --wait-for-indexing --dont-save-session --instruction-file "$AUGGIE_PROMPT_FILE"' </dev/null >/dev/null 2>&1 &
305 else
306 AUGGIE_PROMPT_FILE="$prompt_file" \
307 AUGGIE_WORKSPACE="$workspace" \
308 AUGGIE_CACHE_DIR="$cache_dir" \
309 AUGGIE_AUTH_FILE="$auth_file" \
310 script -q -f -O "$log_file" -c 'auggie --print --enhance-prompt --no-discover-workspaces --workspace-root "$AUGGIE_WORKSPACE" --augment-cache-dir "$AUGGIE_CACHE_DIR" --augment-session-json "$AUGGIE_AUTH_FILE" --dont-save-session --instruction-file "$AUGGIE_PROMPT_FILE"' </dev/null >/dev/null 2>&1 &
311 fi
312
313 script_pid=$!
314 waited=0
315
316 while kill -0 "$script_pid" >/dev/null 2>&1; do
317 if grep -aq "🤖" "$log_file" 2>/dev/null || grep -aq "Tool call:" "$log_file" 2>/dev/null; then
318 kill "$script_pid" >/dev/null 2>&1 || true
319 wait "$script_pid" >/dev/null 2>&1 || true
320 exit 0
321 fi
322
323 if [ "$waited" -ge "$timeout_seconds" ]; then
324 kill "$script_pid" >/dev/null 2>&1 || true
325 wait "$script_pid" >/dev/null 2>&1 || true
326 exit 124
327 fi
328
329 sleep 1
330 waited=$((waited + 1))
331 done
332
333 wait "$script_pid" >/dev/null 2>&1 || true
334 exit 0
335 )
336 monitor_status=$?
337
338 if [ "$monitor_status" -eq 124 ]; then
339 printf "Error: Timed out waiting for Auggie to enhance the prompt.\n" >&2
340 rm -rf "$run_dir"
341 return 124
342 fi
343
344 perl -ne '
345 # Auggie redraws streamed terminal lines with carriage returns. Keep only
346 # the final rendered segment so stale text cannot corrupt the prompt.
347 s/\r$//;
348 s/.*\r//;
349 1 while s/[^\x08]\x08//g;
350 s/\x08//g;
351 s/\e\][^\a]*(?:\a|\e\\)//g;
352 s/\e\[[0-?]*[ -\/]*[@-~]//g;
353 next if /Script started on/ || /Script done on/;
354 if (/^(?:✨\s*)?Enhanced prompt:\s*(.*)$/) {
355 $capturing = 1;
356 $output .= "$1\n" if length $1;
357 next;
358 }
359 next unless $capturing;
360 exit if /^🤖/ || /Tool call:/ || /Session terminated/;
361 $output .= $_;
362 END {
363 $output =~ s/^\s*\n//;
364 $output =~ s/\s+\z//;
365 print "$output\n" if length $output;
366 }
367 ' "$log_file" > "$parsed_file"
368
369 if [ ! -s "$parsed_file" ]; then
370 printf "Error: Auggie did not return an enhanced prompt.\n" >&2
371 rm -rf "$run_dir"
372 return 1
373 fi
374
375 if ! command cp "$parsed_file" "$output_file"; then
376 printf "Error: Unable to save the enhanced prompt.\n" >&2
377 rm -rf "$run_dir"
378 return 1
379 fi
380 rm -rf "$run_dir"
381}
382
383# -----------------------------------------------------------------------------
384# Function: prompt (Enhance a prompt with Auggie and optional project context)
385# -----------------------------------------------------------------------------
386prompt() {
387 local prompt
388 local line
389 local output_file
390
391 require_cli auggie "Auggie CLI" || return 1
392 require_cli script "script utility" || return 1
393
394 if [ $# -gt 0 ]; then
395 prompt="$*"
396 elif [ ! -t 0 ]; then
397 prompt="$(cat)"
398 else
399 echo "Reading prompt... Type 'EOF' on a new line and press Enter when finished."
400 prompt=""
401
402 while IFS= read -r line; do
403 [ "$line" = "EOF" ] && break
404 if [ -z "$prompt" ]; then
405 prompt="$line"
406 else
407 prompt="${prompt}"$'\n'"${line}"
408 fi
409 done
410 fi
411
412 if [ -z "$prompt" ]; then
413 printf "Error: Prompt was empty.\n" >&2
414 return 1
415 fi
416
417 output_file="$(mktemp "${TMPDIR:-/tmp}/auggie-enhanced-prompt.XXXXXX")" || return 1
418 if ! _enhance_prompt "$prompt" "$output_file"; then
419 rm -f "$output_file"
420 return 1
421 fi
422
423 printf "Enhanced prompt:\n"
424 command cat "$output_file"
425 rm -f "$output_file"
426
427 command auggie account status
428}
429
430# -----------------------------------------------------------------------------
431# Function: plan_build (Claude Code multi-agent workflow orchestrator)
432# -----------------------------------------------------------------------------
433_plan_build_superpowers_state() {
434 awk '
435 BEGIN {
436 RS = "}"
437 state = "missing"
438 printed = 0
439 }
440 /"id"[[:space:]]*:[[:space:]]*"superpowers@claude-plugins-official"/ {
441 state = "installed"
442 if ($0 ~ /"enabled"[[:space:]]*:[[:space:]]*true/) {
443 state = "enabled"
444 } else if ($0 ~ /"enabled"[[:space:]]*:[[:space:]]*false/) {
445 state = "disabled"
446 }
447 print state
448 printed = 1
449 exit
450 }
451 END {
452 if (!printed) {
453 print state
454 }
455 }
456 '
457}
458
459_plan_build_superpowers_preflight() {
460 local plugin_json
461 local plugin_state
462
463 case "${CLAUDE_CODE_SAFE_MODE:-}" in
464 1|true|TRUE|yes|YES|on|ON)
465 echo "❌ Error: Claude Code safe mode disables Superpowers."
466 echo "Unset CLAUDE_CODE_SAFE_MODE before using --brainstorm or --writing-plan."
467 return 1
468 ;;
469 esac
470
471 if ! plugin_json="$(command claude plugin list --json 2>/dev/null)"; then
472 echo "❌ Error: Unable to inspect Claude Code plugins."
473 echo "Run 'claude plugin list' to diagnose the problem."
474 return 1
475 fi
476
477 plugin_state="$(printf '%s\n' "$plugin_json" | _plan_build_superpowers_state)"
478
479 case "$plugin_state" in
480 enabled)
481 return 0
482 ;;
483 disabled)
484 echo "❌ Error: Claude Code Superpowers is installed but disabled."
485 echo "Enable it with: claude plugin enable superpowers@claude-plugins-official"
486 ;;
487 missing)
488 echo "❌ Error: Claude Code Superpowers is required for --brainstorm and --writing-plan."
489 echo "Install it in Claude Code with: /plugin install superpowers@claude-plugins-official"
490 ;;
491 *)
492 echo "❌ Error: Unable to determine Claude Code Superpowers status."
493 echo "Run 'claude plugin list' to diagnose the problem."
494 ;;
495 esac
496
497 return 1
498}
499
500plan_build() {
501 local claude_args=()
502 local use_yolo=0
503 local enhance_payload=0
504 local planning_mode="standard"
505 local usage="Usage: plan_build [--yolo] [--prompt] [--brainstorm | --writing-plan]"
506
507 while [ $# -gt 0 ]; do
508 case "$1" in
509 --yolo)
510 if [ "$use_yolo" -eq 1 ]; then
511 echo "Error: Duplicate argument: --yolo"
512 echo "$usage"
513 return 1
514 fi
515 use_yolo=1
516 claude_args=(--yolo)
517 ;;
518 --prompt)
519 if [ "$enhance_payload" -eq 1 ]; then
520 echo "Error: Duplicate argument: --prompt"
521 echo "$usage"
522 return 1
523 fi
524 enhance_payload=1
525 ;;
526 --brainstorm)
527 if [ "$planning_mode" = "brainstorm" ]; then
528 echo "Error: Duplicate argument: --brainstorm"
529 echo "$usage"
530 return 1
531 fi
532 if [ "$planning_mode" != "standard" ]; then
533 echo "Error: --brainstorm and --writing-plan are mutually exclusive."
534 echo "$usage"
535 return 1
536 fi
537 planning_mode="brainstorm"
538 ;;
539 --writing-plan)
540 if [ "$planning_mode" = "writing-plan" ]; then
541 echo "Error: Duplicate argument: --writing-plan"
542 echo "$usage"
543 return 1
544 fi
545 if [ "$planning_mode" != "standard" ]; then
546 echo "Error: --brainstorm and --writing-plan are mutually exclusive."
547 echo "$usage"
548 return 1
549 fi
550 planning_mode="writing-plan"
551 ;;
552 *)
553 echo "Error: Unknown argument: $1"
554 echo "$usage"
555 return 1
556 ;;
557 esac
558 shift
559 done
560
561 require_cli claude "Claude Code CLI" || return 1
562 if [ "$planning_mode" != "standard" ]; then
563 _plan_build_superpowers_preflight || return 1
564 fi
565 require_cli codex "Codex CLI" || return 1
566 require_cli coderabbit "CodeRabbit CLI" || return 1
567 if [ "$enhance_payload" -eq 1 ]; then
568 require_cli auggie "Auggie CLI" || return 1
569 require_cli script "script utility" || return 1
570 fi
571
572 echo "📥 Reading payload... Type 'EOF' on a new line and press Enter when finished."
573
574 local payload
575 local line
576 payload=""
577
578 while IFS= read -r line; do
579 [ "$line" = "EOF" ] && break
580 if [ -z "$payload" ]; then
581 payload="$line"
582 else
583 payload="${payload}"$'\n'"${line}"
584 fi
585 done
586
587 if [ -z "$payload" ]; then
588 echo "❌ Error: Payload was empty."
589 return 1
590 fi
591
592 if [ "$enhance_payload" -eq 1 ]; then
593 local enhanced_file
594 local review_reply
595 enhanced_file="$(mktemp "${TMPDIR:-/tmp}/plan-build-enhanced.XXXXXX")" || return 1
596
597 echo "✨ Enhancing payload with Auggie..."
598 if ! _enhance_prompt "$payload" "$enhanced_file"; then
599 rm -f "$enhanced_file"
600 echo "❌ Error: Prompt enhancement failed; Claude was not launched."
601 return 1
602 fi
603
604 payload="$(cat "$enhanced_file")"
605 rm -f "$enhanced_file"
606
607 if [ -z "$payload" ]; then
608 echo "❌ Error: Enhanced payload was empty; Claude was not launched."
609 return 1
610 fi
611
612 printf '\n%s\n' "━━━━━━━━━━━━━━━━ Auggie enhanced prompt ━━━━━━━━━━━━━━━━"
613 printf '%s\n' "$payload"
614 printf '%s\n\n' "━━━━━━━━━━━━━━━━ End enhanced prompt ━━━━━━━━━━━━━━━━━"
615
616 if ! (: </dev/tty) 2>/dev/null; then
617 echo "❌ Error: Cannot review the enhanced prompt without an interactive terminal; Claude was not launched."
618 return 1
619 fi
620
621 printf "Proceed with this enhanced prompt? (y/N) " >/dev/tty
622 if ! IFS= read -r review_reply </dev/tty; then
623 printf '\n' >/dev/tty
624 echo "🛑 Review cancelled; Claude was not launched."
625 return 1
626 fi
627
628 case "$review_reply" in
629 y|Y|yes|YES|Yes)
630 echo "✅ Enhanced prompt approved."
631 ;;
632 *)
633 echo "🛑 Enhanced prompt not approved; Claude was not launched."
634 return 0
635 ;;
636 esac
637 fi
638
639 local planning_instruction
640 case "$planning_mode" in
641 brainstorm)
642 planning_instruction="Planning mode: brainstorm. Use the superpowers:brainstorming skill, including its approval gates and transition to superpowers:writing-plans. After the implementation plan is saved, return to the plan-build workflow for Codex plan review before implementation."
643 ;;
644 writing-plan)
645 planning_instruction="Planning mode: writing-plan. Use the superpowers:writing-plans skill with the payload as the requirements. After the implementation plan is saved, return to the plan-build workflow for Codex plan review before implementation."
646 ;;
647 *)
648 planning_instruction="Planning mode: standard. Create the workflow's normal short implementation plan."
649 ;;
650 esac
651
652 echo "🚀 Launching Claude Code with your multi-agent workflow ($planning_mode planning)..."
653
654 claude "${claude_args[@]}" "Please read \`~/.claude/skills/plan-build/SKILL.md\` and strictly follow the 8-step multi-agent workflow to implement the following task.
655
656$planning_instruction
657
658$payload"
659}
660
661# -----------------------------------------------------------------------------
662# Function: aicommit (Automated Conventional Commit Engine Wrapper)
663# -----------------------------------------------------------------------------
664aicommit() {
665 local diff engine prompt
666
667 # 1. Get diff safely: exclude lock files/minified files and cap at ~100k characters to prevent CLI crashes
668 diff=$(git diff --cached -- . ":(exclude)*.lock" ":(exclude)*-lock.json" ":(exclude)*.min.js" | head -c 100000)
669
670 if [ -z "$diff" ]; then
671 printf "❌ Error: Nothing staged to commit.\n" >&2
672 return 1
673 fi
674
675 if [ ! -f "$HOME/.config/ai-commit-prompt.txt" ]; then
676 printf "❌ Error: Configuration file not found at ~/.config/ai-commit-prompt.txt\n" >&2
677 printf "Please create it and paste your system prompt inside.\n" >&2
678 return 1
679 fi
680
681 engine=${1:-claude}
682 prompt=$(cat "$HOME/.config/ai-commit-prompt.txt")
683
684 case "$engine" in
685 claude)
686 echo "🤖 Claude is analyzing staged changes..."
687 cat "$HOME/.config/ai-commit-prompt.txt" <(echo -e "\n\nHere is the git diff:\n$diff") \
688 | command claude --allowedTools 'Bash(git commit *)' --permission-mode dontAsk -p \
689 "Read the provided instructions and diff, then generate and execute the commit."
690 ;;
691
692 codex)
693 echo "🤖 Codex is analyzing staged changes..."
694 cat "$HOME/.config/ai-commit-prompt.txt" <(echo -e "\n\nHere is the git diff:\n$diff") \
695 | command codex --ask-for-approval never exec --sandbox workspace-write --ephemeral \
696 "Read the provided instructions and diff, then generate and execute the commit."
697 ;;
698
699 copilot)
700 echo "🤖 Copilot is analyzing staged changes..."
701 copilot -p "$prompt
702
703Here is the git diff:
704$diff" -s --no-ask-user --allow-tool='shell(git:*)'
705 ;;
706
707 opencode)
708 echo "🤖 OpenCode is analyzing staged changes..."
709 cat "$HOME/.config/ai-commit-prompt.txt" <(echo -e "\n\nHere is the git diff:\n$diff") | opencode run
710 ;;
711
712 *)
713 printf "❌ Error: Invalid engine '%s'\n" "$engine" >&2
714 printf "Usage: aicommit [claude | codex | copilot | opencode]\n" >&2
715 return 1
716 ;;
717 esac
718}
719
720# -----------------------------------------------------------------------------
721# Function: create (Efficiently create file + parent dirs)
722# -----------------------------------------------------------------------------
723create() {
724 if ! command -v install >/dev/null 2>&1; then
725 printf "Error: 'install' coreutil is not available.\n" >&2
726 return 1
727 fi
728
729 if [ $# -eq 0 ]; then
730 printf "Usage: create <file> [file ...]\n" >&2
731 return 2
732 fi
733
734 for p in "$@"; do
735 # Expand tilde manually if shell doesn't
736 [[ "$p" == "~/"* ]] && p="${HOME}/${p#\~/}"
737
738 if [ -z "$p" ] || [ "$p" = "/" ]; then
739 printf "create: refusing to operate on '%s'\n" "$p" >&2
740 continue
741 fi
742
743 if [ -e "$p" ]; then
744 printf "create: '%s' already exists. Skipping.\n" "$p" >&2
745 continue
746 fi
747
748 if install -D /dev/null "$p"; then
749 echo "Created '$p'"
750 fi
751 done
752}
753
754# -----------------------------------------------------------------------------
755# Function: kill_port (Kill or check the process using a port)
756# -----------------------------------------------------------------------------
757kill_port() {
758 local action="kill"
759 local signal="TERM"
760 local port
761 local pids
762 local pid
763
764 case "${1:-}" in
765 -c|--check)
766 action="check"
767 shift
768 ;;
769 -k|--kill)
770 action="kill"
771 shift
772 ;;
773 -f|--force)
774 action="kill"
775 signal="KILL"
776 shift
777 ;;
778 -h|--help|"")
779 printf "Usage: kill_port [--check|-c|--kill|-k|--force|-f] <port_number>\n" >&2
780 return 1
781 ;;
782 esac
783
784 port="${1:-}"
785 if [[ ! "$port" =~ ^[0-9]+$ ]] || [ "$port" -lt 1 ] || [ "$port" -gt 65535 ]; then
786 printf "Error: port must be a number between 1 and 65535.\n" >&2
787 printf "Usage: kill_port [--check|-c|--kill|-k|--force|-f] <port_number>\n" >&2
788 return 1
789 fi
790
791 if [[ "$OSTYPE" == "darwin"* ]]; then
792 pids="$(
793 {
794 lsof -nP -tiTCP:"$port" -sTCP:LISTEN 2>/dev/null
795 lsof -nP -tiUDP:"$port" 2>/dev/null
796 } | sort -u
797 )"
798
799 if [ -z "$pids" ]; then
800 printf "Port %s is FREE\n" "$port"
801 return 0
802 fi
803
804 printf "Port %s is in use:\n" "$port"
805 lsof -nP -iTCP:"$port" -sTCP:LISTEN -iUDP:"$port" 2>/dev/null
806 else
807 local port_hex
808 local inodes
809
810 port_hex="$(printf "%04X" "$port")"
811 inodes="$(
812 awk -v port="$port_hex" '
813 NR > 1 {
814 split($2, local_addr, ":")
815 if (toupper(local_addr[length(local_addr)]) == port && ($4 == "0A" || FILENAME ~ /udp/)) {
816 print $10
817 }
818 }
819 ' /proc/net/tcp /proc/net/tcp6 /proc/net/udp /proc/net/udp6 2>/dev/null | sort -u
820 )"
821
822 if [ -z "$inodes" ]; then
823 printf "Port %s is FREE\n" "$port"
824 return 0
825 fi
826
827 pids=""
828 pids="$(
829 find /proc/[0-9]*/fd -maxdepth 1 -type l -printf "%p %l\n" 2>/dev/null |
830 awk -v inodes="$inodes" '
831 BEGIN {
832 split(inodes, inode_list, " ")
833 for (i in inode_list) {
834 wanted["socket:[" inode_list[i] "]"] = 1
835 }
836 }
837 $2 in wanted {
838 split($1, path, "/")
839 print path[3]
840 }
841 ' | sort -u
842 )"
843
844 if [ -z "$pids" ]; then
845 printf "Port %s is in use, but no readable process owner was found.\n" "$port" >&2
846 return 1
847 fi
848
849 printf "Port %s is in use:\n" "$port"
850 for pid in $pids; do
851 if [ -r "/proc/$pid/cmdline" ]; then
852 printf " PID %-8s %s\n" "$pid" "$(tr '\0' ' ' < "/proc/$pid/cmdline")"
853 else
854 printf " PID %s\n" "$pid"
855 fi
856 done
857 fi
858
859 if [ "$action" = "kill" ]; then
860 for pid in $pids; do
861 if kill "-$signal" "$pid" 2>/dev/null; then
862 printf "Killed PID %s with SIG%s.\n" "$pid" "$signal"
863 else
864 printf "Error: failed to kill PID %s. Try with sudo or --force.\n" "$pid" >&2
865 return 1
866 fi
867 done
868 fi
869}
870
871# -----------------------------------------------------------------------------
872# Function: append_path (Adds to session PATH if exists)
873# -----------------------------------------------------------------------------
874append_path() {
875 local dir="$1"
876 if [ -d "$dir" ]; then
877 case ":$PATH:" in
878 *":$dir:"*) ;;
879 *) PATH="$PATH:$dir" ;;
880 esac
881 elif [ "${SUPPRESS_WARNINGS:-0}" -ne 1 ]; then
882 echo "Warning: $dir does not exist." >&2
883 fi
884}
885
886# -----------------------------------------------------------------------------
887# Function: add_path_to_config (Fixed awk/sed injection)
888# -----------------------------------------------------------------------------
889add_path_to_config() {
890 local new_path="$1"
891 local config_file="$HOME/.bashrc"
892 [[ "$SHELL" == *"zsh"* ]] && config_file="$HOME/.zshrc"
893
894 if [ -z "$new_path" ]; then
895 printf "Usage: add_path_to_config <directory>\n" >&2
896 return 1
897 fi
898
899 new_path="${new_path/#\~/$HOME}"
900
901 if [ ! -d "$new_path" ]; then
902 printf "Warning: '%s' does not exist. Add anyway? (y/N) " "$new_path"
903 read -r REPLY
904 [[ ! $REPLY =~ ^[Yy]$ ]] && return 1
905 fi
906
907 # Check if already exists in file
908 if grep -Fq "append_path \"$new_path\"" "$config_file"; then
909 printf "Notice: Already in %s.\n" "$config_file"
910 return 0
911 fi
912
913 # Robust Injection: Use sed to insert before export PATH or just append
914 if grep -q "^export PATH" "$config_file"; then
915 sed -i.bak "/^export PATH/i append_path \"$new_path\"" "$config_file"
916 else
917 echo "append_path \"$new_path\"" >> "$config_file"
918 echo "export PATH" >> "$config_file"
919 fi
920
921 printf "✅ Success: Added to %s\n" "$config_file"
922 append_path "$new_path" && export PATH
923}
924
orchestrate-loop.md Неформатований

Plan-Build Orchestrate Loop

Use this workflow when plan_build hands Claude Code an implementation task. The goal is to keep Claude as the orchestrator while using Codex and CodeRabbit as independent review and validation agents.

Operating Rules

  • Run from the project root. Treat the current working directory as the project to modify.
  • Preserve user work. Check git status before edits and do not revert unrelated changes.
  • Keep implementation scoped to the payload unless repository context proves a wider change is required.
  • Prefer existing project conventions, scripts, test commands, and dependency managers.
  • Do not call the task complete until validation has run or the reason it cannot run is documented.
  • If any agent reports a plausible correctness, security, data-loss, migration, or test risk, resolve it or explicitly document why it is not applicable.

The 8-Step Workflow

1. Intake

Read the user payload fully. Identify:

  • Objective and expected user-visible behavior.
  • Files, modules, commands, and frameworks likely involved.
  • Constraints from repository docs, package scripts, CI config, and existing patterns.
  • Any ambiguity that blocks safe execution.

Only ask the user a question when no reasonable project-local assumption is safe.

2. Baseline

Inspect the repository before changing files:

git status --short
rg --files

Then read the smallest useful set of files. Prefer rg, package manifests, tests, routing files, and nearby implementations over broad file dumps.

3. Plan

Follow the planning mode supplied by plan_build:

  • standard: Create a short implementation plan with concrete steps and validation commands.
  • brainstorm: Invoke superpowers:brainstorming, honor its design and written-spec approval gates, and let it transition to superpowers:writing-plans after approval.
  • writing-plan: Invoke superpowers:writing-plans directly, treating the payload as the requirements or specification.

For either Superpowers mode, save the artifacts at the paths selected by the skills. When writing-plans reaches its execution handoff, return to this workflow instead of starting implementation: Codex must review the plan first. If the user rejects or cancels a required approval, stop cleanly without modifying implementation files.

If the task touches behavior, data, auth, payments, destructive actions, or shared infrastructure, include a rollback or compatibility note.

4. Codex Plan Review

Run this step only for brainstorm and writing-plan modes. Ask Codex for an independent, read-only review of the approved spec, when present, and the implementation plan before touching implementation files. Provide the original payload and artifact paths. Ask it to focus on requirement coverage, incorrect assumptions, unsafe migrations, missing edge cases, inadequate tests, and steps that are too vague to execute.

Recommended prompt shape:

Review these planning artifacts before implementation. Check requirement coverage, technical correctness, repository fit, edge cases, migration or rollback risk, test coverage, and whether every step is executable. Report concrete findings only; do not modify files.

Task:
<payload>

Spec:
<spec path, if present>

Implementation plan:
<plan path>

Use a read-only, ephemeral Codex invocation. Resolve every valid finding in the artifacts and repeat the review if revisions are substantial. If an artifact is missing or empty, or Codex cannot complete the review, stop before implementation and report the failure.

In standard mode, skip this step and continue directly to implementation.

5. Implement

Make the change in small, reviewable edits:

  • Follow existing style and abstractions.
  • Add or update tests when behavior changes.
  • Update docs only when user-facing usage changes.
  • Avoid unrelated refactors and formatting churn.

After each meaningful edit group, re-check the diff for accidental changes.

6. Codex Code Review Pass

Ask Codex for an independent review of the local diff before finalizing. Provide the task, constraints, and current diff. Ask it to focus on bugs, edge cases, missing tests, regressions, and simpler project-native alternatives.

Recommended prompt shape:

Review this change for correctness and risk. Prioritize bugs, regressions, missing tests, and mismatches with existing project patterns. Do not rewrite the whole solution unless a specific issue requires it.

Task:
<payload>

Diff:
<git diff>

Apply fixes for valid findings, then repeat this review pass if the fixes are non-trivial.

7. CodeRabbit Review Pass

Run CodeRabbit on the branch or diff when available. Treat its output as advisory but investigate every concrete finding.

If CodeRabbit cannot run locally, record the command attempted and the failure. Continue with manual validation rather than blocking indefinitely.

8. Validate And Close

Run the planned validation commands, such as:

npm test
npm run lint
pytest
cargo test
go test ./...

Use the commands that actually exist in the project. If validation fails, fix the issue and rerun the relevant command. If a failure is unrelated or environmental, capture the evidence.

Before final response:

  • Confirm git diff contains only intended changes.
  • Summarize what changed.
  • Report validation run and result.
  • Note any remaining risks or commands that could not run.
pathrc Неформатований
1# =============================================================================
2# ENVIRONMENT & PATH CONFIGURATION
3# =============================================================================
4
5# 1. Source functions first
6if [[ -f "$HOME/.func" && -r "$HOME/.func" ]]; then
7 source "$HOME/.func"
8fi
9
10# 2. Define Root Variables
11export DOTNET_ROOT="$HOME/.dotnet"
12
13# 3. PATH INITIALIZATION
14# -----------------------------------------------------------------------------
15append_path "$HOME/.local/bin"
16append_path "$DOTNET_ROOT"
17append_path "$DOTNET_ROOT/tools"
18append_path "$HOME/.opencode/bin"
19append_path "$HOME/Flutter/bin"
20
21# macOS specific paths
22if [[ "$OSTYPE" == "darwin"* ]]; then
23 append_path "/Applications/Espanso.app/Contents/MacOS"
24fi
25
26# Finalize PATH
27export PATH
sourcerc Неформатований
1# =============================================================================
2# FILE: ~/.sourcerc
3# Description: Initializes third-party package managers and external tools.
4# =============================================================================
5
6# =============================================================================
7# GENERAL ENV
8# =============================================================================
9if [[ -f "$HOME/.local/bin/env" && -r "$HOME/.local/bin/env" ]]; then
10 source "$HOME/.local/bin/env"
11fi
12
13# =============================================================================
14# CLAUDE CODE / AI GATEWAY
15# =============================================================================
16export ANTHROPIC_BASE_URL="https://gateway.ai.cloudflare.com/v1/9a71825e3842e918e0dff9ad84f50484/claude-code-gateway/anthropic"
17
18# =============================================================================
19# SDKMAN (Java/Kotlin/Scala Version Manager)
20# =============================================================================
21export SDKMAN_DIR="$HOME/.sdkman"
22if [[ -f "$SDKMAN_DIR/bin/sdkman-init.sh" && -r "$SDKMAN_DIR/bin/sdkman-init.sh" ]]; then
23 source "$SDKMAN_DIR/bin/sdkman-init.sh"
24fi
25
26# =============================================================================
27# NVM (Node Version Manager)
28# =============================================================================
29export NVM_DIR="$HOME/.nvm"
30if [[ -f "$NVM_DIR/nvm.sh" && -r "$NVM_DIR/nvm.sh" ]]; then
31 source "$NVM_DIR/nvm.sh"
32fi
33if [[ -f "$NVM_DIR/bash_completion" && -r "$NVM_DIR/bash_completion" ]]; then
34 source "$NVM_DIR/bash_completion"
35fi
36
37# =============================================================================
38# GOOGLE CLOUD SDK
39# =============================================================================
40if [[ -f "/opt/google-cloud-sdk/path.zsh.inc" ]]; then
41 source "/opt/google-cloud-sdk/path.zsh.inc"
42fi
43
44if [[ -f "/opt/google-cloud-sdk/completion.zsh.inc" ]]; then
45 source "/opt/google-cloud-sdk/completion.zsh.inc"
46fi
47
starship.toml Неформатований
1"$schema" = 'https://starship.rs/config-schema.json'
2
3format = """
4[](red)\
5$os\
6$username\
7[](bg:peach fg:red)\
8$directory\
9[](bg:yellow fg:peach)\
10$git_branch\
11$git_status\
12[](fg:yellow bg:green)\
13$c\
14$rust\
15$golang\
16$nodejs\
17$bun\
18$php\
19$java\
20$kotlin\
21$haskell\
22$python\
23[](fg:green bg:sapphire)\
24$conda\
25[](fg:sapphire bg:lavender)\
26$time\
27[ ](fg:lavender)\
28$cmd_duration\
29$line_break\
30$character"""
31
32palette = 'catppuccin_mocha'
33
34[os]
35disabled = false
36style = "bg:red fg:crust"
37
38[os.symbols]
39Windows = ""
40Ubuntu = "󰕈"
41SUSE = ""
42Raspbian = "󰐿"
43Mint = "󰣭"
44Macos = "󰀵"
45Manjaro = ""
46Linux = "󰌽"
47Gentoo = "󰣨"
48Fedora = "󰣛"
49Alpine = ""
50Amazon = ""
51Android = ""
52AOSC = ""
53Arch = "󰣇"
54Artix = "󰣇"
55CentOS = ""
56Debian = "󰣚"
57Redhat = "󱄛"
58RedHatEnterprise = "󱄛"
59
60[username]
61show_always = true
62style_user = "bg:red fg:crust"
63style_root = "bg:red fg:crust"
64format = '[ $user]($style)'
65
66[directory]
67style = "bg:peach fg:crust"
68format = "[ $path ]($style)"
69truncation_length = 3
70truncation_symbol = "…/"
71
72[directory.substitutions]
73"Documents" = "󰈙 "
74"Downloads" = " "
75"Music" = "󰝚 "
76"Pictures" = " "
77"Developer" = "󰲋 "
78
79[git_branch]
80symbol = ""
81style = "bg:yellow"
82format = '[[ $symbol $branch ](fg:crust bg:yellow)]($style)'
83
84[git_status]
85style = "bg:yellow"
86format = '[[($all_status$ahead_behind )](fg:crust bg:yellow)]($style)'
87
88[nodejs]
89symbol = ""
90style = "bg:green"
91format = '[[ $symbol( $version) ](fg:crust bg:green)]($style)'
92
93[bun]
94symbol = ""
95style = "bg:green"
96format = '[[ $symbol( $version) ](fg:crust bg:green)]($style)'
97
98[c]
99symbol = " "
100style = "bg:green"
101format = '[[ $symbol( $version) ](fg:crust bg:green)]($style)'
102
103[rust]
104symbol = ""
105style = "bg:green"
106format = '[[ $symbol( $version) ](fg:crust bg:green)]($style)'
107
108[golang]
109symbol = ""
110style = "bg:green"
111format = '[[ $symbol( $version) ](fg:crust bg:green)]($style)'
112
113[php]
114symbol = ""
115style = "bg:green"
116format = '[[ $symbol( $version) ](fg:crust bg:green)]($style)'
117
118[java]
119symbol = " "
120style = "bg:green"
121format = '[[ $symbol( $version) ](fg:crust bg:green)]($style)'
122
123[kotlin]
124symbol = ""
125style = "bg:green"
126format = '[[ $symbol( $version) ](fg:crust bg:green)]($style)'
127
128[haskell]
129symbol = ""
130style = "bg:green"
131format = '[[ $symbol( $version) ](fg:crust bg:green)]($style)'
132
133[python]
134symbol = ""
135style = "bg:green"
136format = '[[ $symbol( $version)(\(#$virtualenv\)) ](fg:crust bg:green)]($style)'
137
138[docker_context]
139symbol = ""
140style = "bg:sapphire"
141format = '[[ $symbol( $context) ](fg:crust bg:sapphire)]($style)'
142
143[conda]
144symbol = "  "
145style = "fg:crust bg:sapphire"
146format = '[$symbol$environment ]($style)'
147ignore_base = false
148
149[time]
150disabled = false
151time_format = "%R"
152style = "bg:lavender"
153format = '[[  $time ](fg:crust bg:lavender)]($style)'
154
155[line_break]
156disabled = false
157
158[character]
159disabled = false
160success_symbol = '[❯](bold fg:green)'
161error_symbol = '[❯](bold fg:red)'
162vimcmd_symbol = '[❮](bold fg:green)'
163vimcmd_replace_one_symbol = '[❮](bold fg:lavender)'
164vimcmd_replace_symbol = '[❮](bold fg:lavender)'
165vimcmd_visual_symbol = '[❮](bold fg:yellow)'
166
167[cmd_duration]
168show_milliseconds = true
169format = " in $duration "
170style = "bg:lavender"
171disabled = false
172show_notifications = true
173min_time_to_notify = 45000
174
175[palettes.catppuccin_mocha]
176rosewater = "#f5e0dc"
177flamingo = "#f2cdcd"
178pink = "#f5c2e7"
179mauve = "#cba6f7"
180red = "#f38ba8"
181maroon = "#eba0ac"
182peach = "#fab387"
183yellow = "#f9e2af"
184green = "#a6e3a1"
185teal = "#94e2d5"
186sky = "#89dceb"
187sapphire = "#74c7ec"
188blue = "#89b4fa"
189lavender = "#b4befe"
190text = "#cdd6f4"
191subtext1 = "#bac2de"
192subtext0 = "#a6adc8"
193overlay2 = "#9399b2"
194overlay1 = "#7f849c"
195overlay0 = "#6c7086"
196surface2 = "#585b70"
197surface1 = "#45475a"
198surface0 = "#313244"
199base = "#1e1e2e"
200mantle = "#181825"
201crust = "#11111b"
202
203[palettes.catppuccin_frappe]
204rosewater = "#f2d5cf"
205flamingo = "#eebebe"
206pink = "#f4b8e4"
207mauve = "#ca9ee6"
208red = "#e78284"
209maroon = "#ea999c"
210peach = "#ef9f76"
211yellow = "#e5c890"
212green = "#a6d189"
213teal = "#81c8be"
214sky = "#99d1db"
215sapphire = "#85c1dc"
216blue = "#8caaee"
217lavender = "#babbf1"
218text = "#c6d0f5"
219subtext1 = "#b5bfe2"
220subtext0 = "#a5adce"
221overlay2 = "#949cbb"
222overlay1 = "#838ba7"
223overlay0 = "#737994"
224surface2 = "#626880"
225surface1 = "#51576d"
226surface0 = "#414559"
227base = "#303446"
228mantle = "#292c3c"
229crust = "#232634"
230
231[palettes.catppuccin_latte]
232rosewater = "#dc8a78"
233flamingo = "#dd7878"
234pink = "#ea76cb"
235mauve = "#8839ef"
236red = "#d20f39"
237maroon = "#e64553"
238peach = "#fe640b"
239yellow = "#df8e1d"
240green = "#40a02b"
241teal = "#179299"
242sky = "#04a5e5"
243sapphire = "#209fb5"
244blue = "#1e66f5"
245lavender = "#7287fd"
246text = "#4c4f69"
247subtext1 = "#5c5f77"
248subtext0 = "#6c6f85"
249overlay2 = "#7c7f93"
250overlay1 = "#8c8fa1"
251overlay0 = "#9ca0b0"
252surface2 = "#acb0be"
253surface1 = "#bcc0cc"
254surface0 = "#ccd0da"
255base = "#eff1f5"
256mantle = "#e6e9ef"
257crust = "#dce0e8"
258
259[palettes.catppuccin_macchiato]
260rosewater = "#f4dbd6"
261flamingo = "#f0c6c6"
262pink = "#f5bde6"
263mauve = "#c6a0f6"
264red = "#ed8796"
265maroon = "#ee99a0"
266peach = "#f5a97f"
267yellow = "#eed49f"
268green = "#a6da95"
269teal = "#8bd5ca"
270sky = "#91d7e3"
271sapphire = "#7dc4e4"
272blue = "#8aadf4"
273lavender = "#b7bdf8"
274text = "#cad3f5"
275subtext1 = "#b8c0e0"
276subtext0 = "#a5adcb"
277overlay2 = "#939ab7"
278overlay1 = "#8087a2"
279overlay0 = "#6e738d"
280surface2 = "#5b6078"
281surface1 = "#494d64"
282surface0 = "#363a4f"
283base = "#24273a"
284mantle = "#1e2030"
285crust = "#181926"
286
test_plan_build.zsh Неформатований
1#!/usr/bin/env zsh
2
3set -eu
4
5repo_dir="${0:A:h}"
6source "$repo_dir/func"
7
8failures=0
9
10assert_equal() {
11 local expected="$1"
12 local actual="$2"
13 local label="$3"
14
15 if [ "$actual" != "$expected" ]; then
16 print -u2 -- "FAIL: $label (expected '$expected', got '$actual')"
17 failures=$((failures + 1))
18 fi
19}
20
21assert_contains() {
22 local output="$1"
23 local expected="$2"
24 local label="$3"
25
26 if [[ "$output" != *"$expected"* ]]; then
27 print -u2 -- "FAIL: $label (missing '$expected')"
28 failures=$((failures + 1))
29 fi
30}
31
32plugin_state() {
33 printf '%s\n' "$1" | _plan_build_superpowers_state
34}
35
36assert_equal "enabled" "$(plugin_state '[{"id":"superpowers@claude-plugins-official","enabled":true}]')" "compact enabled JSON"
37assert_equal "disabled" "$(plugin_state $'[\n {\n "enabled": false,\n "id": "superpowers@claude-plugins-official"\n }\n]')" "reordered disabled JSON"
38assert_equal "enabled" "$(plugin_state $'[\n {"enabled": false, "id": "other@market"},\n {"enabled": true, "id": "superpowers@claude-plugins-official"}\n]')" "multiple plugin JSON"
39assert_equal "missing" "$(plugin_state '[{"id":"coderabbit@claude-plugins-official","enabled":true}]')" "missing plugin JSON"
40assert_equal "installed" "$(plugin_state '[{"id":"superpowers@claude-plugins-official"}]')" "malformed plugin JSON"
41
42output="$(plan_build --brainstorm --writing-plan 2>&1)" && rc=0 || rc=$?
43assert_equal "1" "$rc" "mutually exclusive flags status"
44assert_contains "$output" "mutually exclusive" "mutually exclusive flags message"
45
46output="$(plan_build --brainstorm --brainstorm 2>&1)" && rc=0 || rc=$?
47assert_equal "1" "$rc" "duplicate brainstorm status"
48assert_contains "$output" "Duplicate argument: --brainstorm" "duplicate brainstorm message"
49
50output="$(plan_build --writing-plan --writing-plan 2>&1)" && rc=0 || rc=$?
51assert_equal "1" "$rc" "duplicate writing-plan status"
52assert_contains "$output" "Duplicate argument: --writing-plan" "duplicate writing-plan message"
53
54export CLAUDE_CODE_SAFE_MODE=1
55output="$(_plan_build_superpowers_preflight 2>&1)" && rc=0 || rc=$?
56unset CLAUDE_CODE_SAFE_MODE
57assert_equal "1" "$rc" "safe mode status"
58assert_contains "$output" "safe mode disables Superpowers" "safe mode message"
59
60require_cli() { return 0; }
61_plan_build_superpowers_preflight() { return 0; }
62claude() {
63 printf 'CLAUDE_ARGS:'
64 printf ' <%s>' "$@"
65 printf '\n'
66}
67
68output="$(printf 'build feature\nEOF\n' | plan_build --writing-plan --yolo 2>&1)" && rc=0 || rc=$?
69assert_equal "0" "$rc" "writing-plan launch status"
70assert_contains "$output" "Planning mode: writing-plan" "writing-plan prompt"
71assert_contains "$output" "<--yolo>" "yolo forwarding"
72
73output="$(printf 'build feature\nEOF\n' | plan_build --brainstorm 2>&1)" && rc=0 || rc=$?
74assert_equal "0" "$rc" "brainstorm launch status"
75assert_contains "$output" "Planning mode: brainstorm" "brainstorm prompt"
76
77output="$(printf 'build feature\nEOF\n' | plan_build 2>&1)" && rc=0 || rc=$?
78assert_equal "0" "$rc" "standard launch status"
79assert_contains "$output" "Planning mode: standard" "standard prompt"
80
81if [ "$failures" -ne 0 ]; then
82 exit 1
83fi
84
85print -- "PASS: plan_build tests"
86
vimrc Неформатований
1" Enable line numbers
2set number
3
4" Enable relative line numbers
5set relativenumber
6
7" Enable syntax highlighting
8syntax on
9
10" Set colorscheme
11colorscheme slate
12
13" Enable file type detection and plugins
14filetype plugin indent on
15
16" Set the tab width to 4 spaces
17set tabstop=4
18set shiftwidth=4
19set expandtab
20
21" Enable auto-indentation
22set autoindent
23set smartindent
24
25" Highlight current line
26set cursorline
27
28" Show matching parentheses
29set showmatch
30
31" Enable line wrapping
32set wrap
33
34" Enable mouse support
35set mouse=a
36
37" Enable clipboard access
38set clipboard=unnamedplus
39
40" Disable swap file
41set noswapfile
42
43" Enable incremental search
44set incsearch
45
46" Ignore case in search
47set ignorecase
48
49" Override ignorecase if search contains capital letters
50set smartcase
51
52" Display line and column number of the cursor position
53set ruler
54
55" Set the status line at the bottom
56set laststatus=2
57
58" Show command in bottom bar
59set showcmd
60
61" Set command height
62set cmdheight=2
63
64" Set history lines
65set history=1000
66
67" Disable backup file
68set nobackup
69
70" Enable persistent undo
71set undofile
72
73" Set maximum number of undo levels
74set undolevels=1000
75
76" Set undo directory
77if has("persistent_undo")
78 silent !mkdir ~/.vim/undodir > /dev/null 2>&1
79 set undodir=~/.vim/undodir
80endif
81
82" Set search highlighting
83set hlsearch
84
85" Enable visual bell
86set visualbell
87
88" Set default file encoding
89set encoding=utf-8
90
91" Set the leader key to space
92let mapleader = " "
93
94" Map <Leader>w to save the file
95nnoremap <Leader>w :w<CR>
96
97" Map <Leader>q to quit
98nnoremap <Leader>q :q<CR>
99
100" Map <Leader>x to save and quit
101nnoremap <Leader>x :wq<CR>
102
103" Enable folding
104set foldmethod=syntax
105set foldlevelstart=99
106
107" Enable line wrapping at 80 characters
108set textwidth=80
109set colorcolumn=80
110
111" Add some basic key mappings
112" Map jj to escape insert mode
113inoremap jj <Esc>
114
115" Map <Leader>n to toggle line numbers
116nnoremap <Leader>n :set number!<CR>
117
118" Map <Leader>r to toggle relative line numbers
119nnoremap <Leader>r :set relativenumber!<CR>
120
121" Configure plugins (if you use a plugin manager like vim-plug)
122" Example with vim-plug:
123" call plug#begin('~/.vim/plugged')
124" Plug 'tpope/vim-sensible'
125" Plug 'preservim/nerdtree'
126" Plug 'junegunn/fzf', { 'do': { -> fzf#install() } }
127" Plug 'airblade/vim-gitgutter'
128" call plug#end()
129
130" NERDTree key mappings
131" nnoremap <C-n> :NERDTreeToggle<CR>
132
133" Enable automatic hard wrapping at textwidth (80 chars)
134set formatoptions+=t " Auto-wrap text using textwidth
135set formatoptions+=c " Auto-wrap comments using textwidth
136set formatoptions+=r " Continue comments when pressing Enter
137set formatoptions+=o " Continue comments when using 'o' or 'O'
138set formatoptions+=q " Allow formatting of comments with 'gq'
139set formatoptions+=n " Recognize numbered lists
140set formatoptions+=l " Don't break lines that were already long
141
142" Enable syntax highlighting
143syntax on
144
145" Increase memory limit for complex syntax parsing (Prevents E363)
146set maxmempattern=20000
zsh_macos.sh Неформатований
1#!/bin/bash
2set -euo pipefail
3
4# =============================
5# COLORS & LOGGING
6# =============================
7RED='\033[0;31m'
8GREEN='\033[0;32m'
9YELLOW='\033[1;33m'
10BLUE='\033[0;34m'
11NC='\033[0m'
12
13log() { echo -e "${BLUE}[INFO]${NC} $*"; }
14ok() { echo -e "${GREEN}[OK]${NC} $*"; }
15warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
16err() { echo -e "${RED}[ERROR]${NC} $*" >&2; }
17
18# =============================
19# CONFIG
20# =============================
21GIST_RAW_BASE="https://opengist.resetrix.work/weehong/f0d940c3c1214bf5b7996195199fdc09/raw/HEAD"
22
23CONFIG_FILES=(
24 ".alias"
25 ".func"
26 ".pathrc"
27 ".sourcerc"
28 ".vimrc"
29 ".zshrc"
30 ".config/starship.toml"
31)
32
33# =============================
34# REQUIREMENTS
35# =============================
36check_requirements() {
37 if [[ $EUID -eq 0 ]]; then
38 err "Do not run as root on macOS"
39 exit 1
40 fi
41}
42
43# =============================
44# INSTALLATION FUNCTIONS
45# =============================
46install_oh_my_zsh() {
47 log "Installing Oh My Zsh and plugins..."
48 export RUNZSH=no
49 export CHSH=no
50 export KEEP_ZSHRC=yes
51
52 if [[ ! -d "$HOME/.oh-my-zsh" ]]; then
53 sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" --unattended
54 else
55 ok "Oh My Zsh already installed"
56 fi
57
58 local custom="${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}"
59 local plugin_dir="$custom/plugins"
60 mkdir -p "$plugin_dir"
61
62 [[ -d "$plugin_dir/zsh-autosuggestions" ]] || \
63 git clone https://github.com/zsh-users/zsh-autosuggestions "$plugin_dir/zsh-autosuggestions"
64
65 [[ -d "$plugin_dir/zsh-syntax-highlighting" ]] || \
66 git clone https://github.com/zsh-users/zsh-syntax-highlighting "$plugin_dir/zsh-syntax-highlighting"
67
68 ok "Oh My Zsh plugins installed to $plugin_dir"
69}
70
71install_starship() {
72 if command -v starship >/dev/null 2>&1 || [[ -f "$HOME/.local/bin/starship" ]]; then
73 ok "Starship already installed"
74 elif command -v brew >/dev/null 2>&1; then
75 log "Installing Starship with Homebrew..."
76 brew install starship
77 ok "Starship installed"
78 else
79 log "Installing Starship..."
80 mkdir -p "$HOME/.local/bin"
81 curl -fsSL https://starship.rs/install.sh | sh -s -- -y -b "$HOME/.local/bin"
82 ok "Starship installed"
83 fi
84}
85
86download_configs() {
87 log "Downloading custom config files..."
88 local backup="$HOME/.config_backup_$(date +%Y%m%d_%H%M%S)"
89 mkdir -p "$backup"
90
91 for f in "${CONFIG_FILES[@]}"; do
92 # Strip the leading dot for the download URL
93 local remote_file="${f#.}"
94 [[ "$f" == ".config/starship.toml" ]] && remote_file="starship.toml"
95 local url="$GIST_RAW_BASE/$remote_file"
96 local target="$HOME/$f"
97 local tmp="${target}.tmp.$$"
98
99 mkdir -p "$(dirname "$target")"
100
101 if [[ -f "$target" ]]; then
102 cp "$target" "$backup/"
103 fi
104
105 log "Fetching $remote_file -> $f ..."
106 if curl -fsSL "$url" -o "$tmp"; then
107 mv "$tmp" "$target"
108 else
109 rm -f "$tmp"
110 warn "Failed to download $remote_file"
111 fi
112 done
113
114 local skill_target="$HOME/.claude/skills/plan-build/SKILL.md"
115 local skill_tmp="${skill_target}.tmp.$$"
116 mkdir -p "$(dirname "$skill_target")"
117 log "Fetching orchestrate-loop.md -> .claude/skills/plan-build/SKILL.md ..."
118 if curl -fsSL "$GIST_RAW_BASE/orchestrate-loop.md" -o "$skill_tmp"; then
119 mv "$skill_tmp" "$skill_target"
120 else
121 rm -f "$skill_tmp"
122 warn "Failed to download orchestrate-loop.md"
123 fi
124
125 ok "Configs downloaded (Backup at $backup)"
126}
127
128configure_zshrc() {
129 local zshrc="$HOME/.zshrc"
130 log "Configuring .zshrc for Oh My Zsh and Starship..."
131
132 touch "$zshrc"
133 cp "$zshrc" "$HOME/.zshrc.backup_$(date +%Y%m%d_%H%M%S)"
134
135 cat > "$zshrc" <<'EOF'
136# =============================================================================
137# 1. HELPER FUNCTIONS & PATH
138# =============================================================================
139source_if_readable() {
140 local file="$1"
141 if [[ -f "$file" && -r "$file" ]]; then
142 source "$file"
143 fi
144}
145
146export PATH="$HOME/.local/bin:$PATH"
147
148# =============================================================================
149# 2. OH MY ZSH FRAMEWORK
150# =============================================================================
151export ZSH="${ZSH:-$HOME/.oh-my-zsh}"
152ZSH_THEME=""
153
154plugins=(
155 git
156 zsh-autosuggestions
157 zsh-syntax-highlighting
158)
159
160source_if_readable "$ZSH/oh-my-zsh.sh"
161
162# =============================================================================
163# 3. THIRD-PARTY INITIALIZATION & CUSTOM CONFIGS
164# =============================================================================
165source_if_readable "$HOME/.sourcerc"
166source_if_readable "$HOME/.func"
167source_if_readable "$HOME/.pathrc"
168source_if_readable "$HOME/.alias"
169
170# =============================================================================
171# 4. STARSHIP PROMPT
172# =============================================================================
173if [[ -z "${STARSHIP_CONFIG:-}" && -f "$HOME/.config/starship.toml" ]]; then
174 export STARSHIP_CONFIG="$HOME/.config/starship.toml"
175fi
176
177if command -v starship >/dev/null 2>&1; then
178 eval "$(starship init zsh)"
179elif [[ -x "$HOME/.local/bin/starship" ]]; then
180 eval "$("$HOME/.local/bin/starship" init zsh)"
181fi
182EOF
183
184 ok ".zshrc configured for Oh My Zsh framework with Starship prompt"
185}
186
187switch_shell() {
188 log "Starting Zsh session..."
189 echo -e "${YELLOW}Type 'exit' to return to this installer menu.${NC}"
190 echo "----------------------------------------"
191 zsh -l
192 echo "----------------------------------------"
193 ok "Returned from Zsh session"
194}
195
196# =============================
197# INTERACTIVE MENU
198# =============================
199show_menu() {
200 echo "==========================================="
201 echo "macOS Minimal Zsh Setup - Choose what to do"
202 echo "==========================================="
203 echo " 0) Run ALL steps (1-5)"
204 echo " 1) Install Oh My Zsh + plugins"
205 echo " 2) Install Starship prompt"
206 echo " 3) Download custom configs (~/.alias, .func, .vimrc, etc.)"
207 echo " 4) Configure ~/.zshrc (Oh My Zsh + Starship)"
208 echo " 5) Switch to Zsh (Temporary Sub-shell)"
209 echo " 6) Quit"
210 echo "==========================================="
211}
212
213run_choices() {
214 local input
215 read -p "Select: " input
216 input="${input//,/ }"
217
218 local -a to_run=()
219 local -a to_exclude=()
220
221 for item in $input; do
222 if [[ "$item" == !* ]]; then
223 to_exclude+=("${item:1}")
224 elif [[ "$item" == "0" ]]; then
225 to_run+=(1 2 3 4 5)
226 else
227 to_run+=("$item")
228 fi
229 done
230
231 if [[ ${#to_run[@]} -gt 0 ]]; then
232 for choice in "${to_run[@]}"; do
233 local skip=false
234
235 if [[ ${#to_exclude[@]} -gt 0 ]]; then
236 for ex in "${to_exclude[@]}"; do
237 if [[ "$choice" == "$ex" ]]; then
238 skip=true
239 break
240 fi
241 done
242 fi
243
244 $skip && continue
245
246 case "$choice" in
247 1) install_oh_my_zsh ;;
248 2) install_starship ;;
249 3) download_configs ;;
250 4) configure_zshrc ;;
251 5) switch_shell ;;
252 6) exit 0 ;;
253 *) warn "Skipping invalid option: $choice" ;;
254 esac
255 echo
256 done
257 fi
258}
259
260# =============================
261# MAIN
262# =============================
263main() {
264 check_requirements
265 while true; do
266 show_menu
267 run_choices
268 read -p "Do you want to run more options? (y/n): " again
269 [[ "$again" =~ ^[Yy]$ ]] || break
270 done
271 ok "macOS minimal Zsh configuration complete!"
272}
273
274main "$@"
275
zsh_ubuntu.sh Неформатований
1#!/bin/bash
2set -euo pipefail
3
4# =============================
5# COLORS & LOGGING
6# =============================
7RED='\033[0;31m'
8GREEN='\033[0;32m'
9YELLOW='\033[1;33m'
10BLUE='\033[0;34m'
11NC='\033[0m'
12
13log() { echo -e "${BLUE}[INFO]${NC} $*"; }
14ok() { echo -e "${GREEN}[OK]${NC} $*"; }
15warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
16err() { echo -e "${RED}[ERROR]${NC} $*" >&2; }
17
18# =============================
19# FLAGS & CONFIG
20# =============================
21SKIP_PACKAGES=false
22SKIP_SHELL_CHANGE=false
23INSTALL_HOMEBREW=false
24
25GIST_RAW_BASE="https://opengist.resetrix.work/weehong/f0d940c3c1214bf5b7996195199fdc09/raw/HEAD"
26CONFIG_FILES=(
27 ".alias"
28 ".func"
29 ".pathrc"
30 ".sourcerc"
31 ".vimrc"
32 ".zshrc"
33 ".config/starship.toml"
34)
35
36# =============================
37# OS DETECTION
38# =============================
39detect_os() {
40 if [[ "$OSTYPE" == "darwin"* ]]; then
41 echo "macos"
42 elif [ -f /etc/os-release ]; then
43 . /etc/os-release
44 echo "$ID"
45 else
46 echo "unknown"
47 fi
48}
49
50# =============================
51# REQUIREMENTS
52# =============================
53check_requirements() {
54 if [[ $EUID -eq 0 ]]; then
55 err "Do not run as root. The script will request sudo when necessary."
56 exit 1
57 fi
58 if [[ "$(detect_os)" != "macos" ]] && ! command -v sudo >/dev/null 2>&1; then
59 err "sudo required on Linux"
60 exit 1
61 fi
62}
63
64# =============================
65# INSTALLATION FUNCTIONS
66# =============================
67update_system() {
68 $SKIP_PACKAGES && return
69 log "Updating system..."
70 local os=$(detect_os)
71
72 case "$os" in
73 macos)
74 brew update || warn "Homebrew update failed; continuing installer"
75 ;;
76 ubuntu|debian)
77 sudo apt-get update -y
78 if ! sudo apt-get upgrade -y; then
79 warn "System upgrade did not complete. This can happen when apt wants to downgrade a package."
80 warn "Continuing because the Zsh setup does not require OS package upgrades to finish."
81 fi
82 ;;
83 fedora)
84 sudo dnf upgrade -y || warn "System upgrade failed; continuing installer"
85 ;;
86 arch)
87 sudo pacman -Syu --noconfirm || warn "System upgrade failed; continuing installer"
88 ;;
89 *) warn "Auto-update not supported for OS: $os" ;;
90 esac
91 ok "System update step finished"
92}
93
94install_packages() {
95 $SKIP_PACKAGES && return
96 log "Installing core packages..."
97 local os=$(detect_os)
98
99 case "$os" in
100 macos) brew install zsh git vim curl wget unzip xz ;;
101 ubuntu|debian) sudo apt-get install -y zsh git vim curl wget unzip zip build-essential xz-utils ;;
102 fedora) sudo dnf install -y zsh git vim curl wget unzip zip @development-tools xz ;;
103 arch) sudo pacman -S --noconfirm zsh git vim curl wget unzip zip base-devel xz ;;
104 *) warn "Auto-install not supported for OS: $os. Please install zsh, git, vim, curl manually." ;;
105 esac
106 ok "Packages installed"
107}
108
109set_timezone() {
110 log "Setting timezone to Asia/Singapore..."
111 local os=$(detect_os)
112 if [[ "$os" == "macos" ]]; then
113 sudo systemsetup -settimezone Asia/Singapore >/dev/null
114 else
115 sudo timedatectl set-timezone Asia/Singapore
116 fi
117 ok "Timezone set to Asia/Singapore"
118}
119
120install_homebrew() {
121 ! $INSTALL_HOMEBREW && return
122 command -v brew >/dev/null 2>&1 && ok "Homebrew already installed" && return
123 log "Installing Homebrew..."
124 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
125 ok "Homebrew installed"
126}
127
128configure_shell() {
129 $SKIP_SHELL_CHANGE && return
130 log "Changing default shell to zsh..."
131 local zsh_path
132 zsh_path="$(command -v zsh)"
133
134 if ! grep -qx "$zsh_path" /etc/shells; then
135 echo "$zsh_path" | sudo tee -a /etc/shells >/dev/null
136 fi
137 chsh -s "$zsh_path"
138 ok "Shell changed (requires logout/login to take effect)"
139}
140
141install_oh_my_zsh() {
142 log "Installing Oh My Zsh and plugins..."
143 export RUNZSH=no
144 export CHSH=no
145 export KEEP_ZSHRC=yes
146
147 if [[ ! -d "$HOME/.oh-my-zsh" ]]; then
148 sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" --unattended
149 else
150 ok "Oh My Zsh already installed"
151 fi
152
153 local custom="${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}"
154 local plugin_dir="$custom/plugins"
155 mkdir -p "$plugin_dir"
156
157 [[ -d "$plugin_dir/zsh-autosuggestions" ]] || git clone https://github.com/zsh-users/zsh-autosuggestions "$plugin_dir/zsh-autosuggestions"
158 [[ -d "$plugin_dir/zsh-syntax-highlighting" ]] || git clone https://github.com/zsh-users/zsh-syntax-highlighting "$plugin_dir/zsh-syntax-highlighting"
159
160 ok "Oh My Zsh plugins installed to $plugin_dir"
161}
162
163install_starship() {
164 if command -v starship >/dev/null 2>&1 || [[ -f "$HOME/.local/bin/starship" ]]; then
165 ok "Starship already installed"
166 else
167 log "Installing Starship prompt..."
168 if command -v brew >/dev/null 2>&1; then
169 brew install starship
170 else
171 mkdir -p "$HOME/.local/bin"
172 curl -fsSL https://starship.rs/install.sh | sh -s -- -y -b "$HOME/.local/bin"
173 fi
174 ok "Starship installed"
175 fi
176}
177
178download_configs() {
179 log "Downloading custom config files from OpenGist..."
180 local backup="$HOME/.config_backup_$(date +%Y%m%d_%H%M%S)"
181 mkdir -p "$backup"
182
183 for f in "${CONFIG_FILES[@]}"; do
184 local remote_file="${f#.}"
185 [[ "$f" == ".config/starship.toml" ]] && remote_file="starship.toml"
186 local url="$GIST_RAW_BASE/$remote_file"
187 local target="$HOME/$f"
188 local tmp="${target}.tmp.$$"
189
190 mkdir -p "$(dirname "$target")"
191
192 if [[ -f "$target" ]]; then
193 cp "$target" "$backup/"
194 fi
195
196 log "Fetching $remote_file -> $f ..."
197 if curl -fsSL "$url" -o "$tmp"; then
198 mv "$tmp" "$target"
199 else
200 rm -f "$tmp"
201 warn "Failed to download $remote_file"
202 fi
203 done
204
205 local skill_target="$HOME/.claude/skills/plan-build/SKILL.md"
206 local skill_tmp="${skill_target}.tmp.$$"
207 mkdir -p "$(dirname "$skill_target")"
208 log "Fetching orchestrate-loop.md -> .claude/skills/plan-build/SKILL.md ..."
209 if curl -fsSL "$GIST_RAW_BASE/orchestrate-loop.md" -o "$skill_tmp"; then
210 mv "$skill_tmp" "$skill_target"
211 else
212 rm -f "$skill_tmp"
213 warn "Failed to download orchestrate-loop.md"
214 fi
215
216 ok "Configs downloaded (Backup at $backup)"
217}
218
219configure_zshrc() {
220 local zshrc="$HOME/.zshrc"
221 log "Configuring .zshrc for Oh My Zsh and Starship..."
222
223 touch "$zshrc"
224 cp "$zshrc" "$HOME/.zshrc.backup_$(date +%Y%m%d_%H%M%S)"
225
226 cat > "$zshrc" <<'EOF'
227# =============================================================================
228# 1. HELPER FUNCTIONS & PATH
229# =============================================================================
230source_if_readable() {
231 local file="$1"
232 if [[ -f "$file" && -r "$file" ]]; then
233 source "$file"
234 fi
235}
236
237export PATH="$HOME/.local/bin:$PATH"
238
239# =============================================================================
240# 2. OH MY ZSH FRAMEWORK
241# =============================================================================
242export ZSH="${ZSH:-$HOME/.oh-my-zsh}"
243ZSH_THEME=""
244
245plugins=(
246 git
247 zsh-autosuggestions
248 zsh-syntax-highlighting
249)
250
251source_if_readable "$ZSH/oh-my-zsh.sh"
252
253# =============================================================================
254# 3. THIRD-PARTY INITIALIZATION & CUSTOM CONFIGS
255# =============================================================================
256source_if_readable "$HOME/.sourcerc"
257source_if_readable "$HOME/.func"
258source_if_readable "$HOME/.pathrc"
259source_if_readable "$HOME/.alias"
260
261# =============================================================================
262# 4. STARSHIP PROMPT
263# =============================================================================
264if [[ -z "${STARSHIP_CONFIG:-}" && -f "$HOME/.config/starship.toml" ]]; then
265 export STARSHIP_CONFIG="$HOME/.config/starship.toml"
266fi
267
268if command -v starship >/dev/null 2>&1; then
269 eval "$(starship init zsh)"
270elif [[ -x "$HOME/.local/bin/starship" ]]; then
271 eval "$("$HOME/.local/bin/starship" init zsh)"
272fi
273EOF
274
275 ok ".zshrc configured for Oh My Zsh framework with Starship prompt"
276}
277
278switch_shell() {
279 log "Starting Zsh session..."
280 echo -e "${YELLOW}Type 'exit' to return to this installer menu.${NC}"
281 echo "----------------------------------------"
282 zsh -l
283 echo "----------------------------------------"
284 ok "Returned from Zsh session"
285}
286
287# =============================
288# INTERACTIVE MENU
289# =============================
290show_menu() {
291 echo "==========================================="
292 echo "Minimal Zsh Installer - Choose what to do"
293 echo "==========================================="
294 echo " 0) Run ALL steps (1-10)"
295 echo " 1) Update system packages"
296 echo " 2) Install core packages (zsh, git, vim, etc.)"
297 echo " 3) Set Timezone (Asia/Singapore)"
298 echo " 4) Install Homebrew"
299 echo " 5) Configure shell (chsh - sets default shell)"
300 echo " 6) Install Oh My Zsh + plugins"
301 echo " 7) Install Starship prompt"
302 echo " 8) Download custom configs (from OpenGist)"
303 echo " 9) Configure ~/.zshrc (Oh My Zsh + Starship)"
304 echo "10) Switch to Zsh (Temporary Sub-shell)"
305 echo "11) Quit"
306 echo "==========================================="
307}
308
309run_choices() {
310 local input
311 read -p "Select: " input
312 input="${input//,/ }"
313
314 local -a to_run=()
315 local -a to_exclude=()
316
317 for item in $input; do
318 if [[ "$item" == !* ]]; then
319 to_exclude+=("${item:1}")
320 elif [[ "$item" == "0" ]]; then
321 to_run+=(1 2 3 4 5 6 7 8 9 10)
322 else
323 to_run+=("$item")
324 fi
325 done
326
327 for choice in "${to_run[@]}"; do
328 local skip=false
329
330 for ex in "${to_exclude[@]}"; do
331 if [[ "$choice" == "$ex" ]]; then
332 skip=true
333 break
334 fi
335 done
336
337 $skip && continue
338
339 case "$choice" in
340 1) update_system ;;
341 2) install_packages ;;
342 3) set_timezone ;;
343 4) install_homebrew ;;
344 5) configure_shell ;;
345 6) install_oh_my_zsh ;;
346 7) install_starship ;;
347 8) download_configs ;;
348 9) configure_zshrc ;;
349 10) switch_shell ;;
350 11) log "Exiting..."; exit 0 ;;
351 *) warn "Skipping invalid option: $choice" ;;
352 esac
353 echo
354 done
355}
356
357# =============================
358# MAIN
359# =============================
360main() {
361 check_requirements
362 while true; do
363 show_menu
364 run_choices
365 read -p "Do you want to run more options? (y/n): " again
366 [[ "$again" =~ ^[Yy]$ ]] || break
367 done
368 ok "Zsh installation/configuration complete!"
369}
370
371main "$@"
372
zsh_wsl.sh Неформатований
1#!/bin/bash
2set -euo pipefail
3
4# =============================
5# COLORS & LOGGING
6# =============================
7RED='\033[0;31m'
8GREEN='\033[0;32m'
9YELLOW='\033[1;33m'
10BLUE='\033[0;34m'
11NC='\033[0m'
12
13log() { echo -e "${BLUE}[INFO]${NC} $*"; }
14ok() { echo -e "${GREEN}[OK]${NC} $*"; }
15warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
16err() { echo -e "${RED}[ERROR]${NC} $*" >&2; }
17
18# =============================
19# FLAGS & CONFIG
20# =============================
21SKIP_PACKAGES=false
22SKIP_SHELL_CHANGE=false
23INSTALL_HOMEBREW=false
24
25GIST_RAW_BASE="https://opengist.resetrix.work/weehong/f0d940c3c1214bf5b7996195199fdc09/raw/HEAD"
26CONFIG_FILES=(
27 ".alias"
28 ".func"
29 ".pathrc"
30 ".sourcerc"
31 ".vimrc"
32 ".zshrc"
33 ".config/starship.toml"
34)
35
36# =============================
37# PLATFORM DETECTION
38# =============================
39detect_os() {
40 if [ -f /etc/os-release ]; then
41 . /etc/os-release
42 echo "$ID"
43 else
44 echo "unknown"
45 fi
46}
47
48is_wsl() {
49 grep -qi "microsoft" /proc/version 2>/dev/null
50}
51
52# =============================
53# REQUIREMENTS
54# =============================
55check_requirements() {
56 if [[ $EUID -eq 0 ]]; then
57 err "Do not run as root. The script will request sudo when necessary."
58 exit 1
59 fi
60 if ! command -v sudo >/dev/null 2>&1; then
61 err "sudo required"
62 exit 1
63 fi
64 if ! is_wsl; then
65 err "This installer is intended for WSL"
66 exit 1
67 fi
68}
69
70# =============================
71# INSTALLATION FUNCTIONS
72# =============================
73update_system() {
74 $SKIP_PACKAGES && return
75 log "Updating system..."
76 local os=$(detect_os)
77
78 case "$os" in
79 ubuntu|debian)
80 sudo apt-get update -y
81 if ! sudo apt-get upgrade -y; then
82 warn "System upgrade did not complete. This can happen when apt wants to downgrade a package."
83 warn "Continuing because the Zsh setup does not require OS package upgrades to finish."
84 fi
85 ;;
86 fedora)
87 sudo dnf upgrade -y || warn "System upgrade failed; continuing installer"
88 ;;
89 arch)
90 sudo pacman -Syu --noconfirm || warn "System upgrade failed; continuing installer"
91 ;;
92 *) warn "Auto-update not supported for OS: $os" ;;
93 esac
94 ok "System update step finished"
95}
96
97install_packages() {
98 $SKIP_PACKAGES && return
99 log "Installing core packages..."
100 local os=$(detect_os)
101
102 case "$os" in
103 ubuntu|debian) sudo apt-get install -y zsh git vim curl wget unzip zip build-essential xz-utils ;;
104 fedora) sudo dnf install -y zsh git vim curl wget unzip zip @development-tools xz ;;
105 arch) sudo pacman -S --noconfirm zsh git vim curl wget unzip zip base-devel xz ;;
106 *) warn "Auto-install not supported for OS: $os. Please install zsh, git, vim, curl manually." ;;
107 esac
108 ok "Packages installed"
109}
110
111set_timezone() {
112 log "Checking timezone configuration..."
113 if command -v timedatectl >/dev/null 2>&1 && timedatectl status >/dev/null 2>&1; then
114 sudo timedatectl set-timezone Asia/Singapore
115 ok "Timezone set to Asia/Singapore"
116 return
117 fi
118
119 warn "Skipping timezone change: timedatectl is not available in this WSL environment"
120}
121
122install_homebrew() {
123 ! $INSTALL_HOMEBREW && return
124 command -v brew >/dev/null 2>&1 && ok "Homebrew already installed" && return
125 log "Installing Homebrew..."
126 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
127 ok "Homebrew installed"
128}
129
130configure_shell() {
131 $SKIP_SHELL_CHANGE && return
132 log "Changing default shell to zsh..."
133 local zsh_path
134 zsh_path="$(command -v zsh)"
135
136 if ! grep -qx "$zsh_path" /etc/shells; then
137 echo "$zsh_path" | sudo tee -a /etc/shells >/dev/null
138 fi
139 chsh -s "$zsh_path"
140 ok "Shell changed (open a new WSL session for it to take effect)"
141}
142
143install_oh_my_zsh() {
144 log "Installing Oh My Zsh and plugins..."
145 export RUNZSH=no
146 export CHSH=no
147 export KEEP_ZSHRC=yes
148
149 if [[ ! -d "$HOME/.oh-my-zsh" ]]; then
150 sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" --unattended
151 else
152 ok "Oh My Zsh already installed"
153 fi
154
155 local custom="${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}"
156 local plugin_dir="$custom/plugins"
157 mkdir -p "$plugin_dir"
158
159 [[ -d "$plugin_dir/zsh-autosuggestions" ]] || git clone https://github.com/zsh-users/zsh-autosuggestions "$plugin_dir/zsh-autosuggestions"
160 [[ -d "$plugin_dir/zsh-syntax-highlighting" ]] || git clone https://github.com/zsh-users/zsh-syntax-highlighting "$plugin_dir/zsh-syntax-highlighting"
161
162 ok "Oh My Zsh plugins installed to $plugin_dir"
163}
164
165install_starship() {
166 if command -v starship >/dev/null 2>&1 || [[ -f "$HOME/.local/bin/starship" ]]; then
167 ok "Starship already installed"
168 else
169 log "Installing Starship prompt..."
170 if command -v brew >/dev/null 2>&1; then
171 brew install starship
172 else
173 mkdir -p "$HOME/.local/bin"
174 curl -fsSL https://starship.rs/install.sh | sh -s -- -y -b "$HOME/.local/bin"
175 fi
176 ok "Starship installed"
177 fi
178}
179
180download_configs() {
181 log "Downloading custom config files from OpenGist..."
182 local backup="$HOME/.config_backup_$(date +%Y%m%d_%H%M%S)"
183 mkdir -p "$backup"
184
185 for f in "${CONFIG_FILES[@]}"; do
186 local remote_file="${f#.}"
187 [[ "$f" == ".config/starship.toml" ]] && remote_file="starship.toml"
188 local url="$GIST_RAW_BASE/$remote_file"
189 local target="$HOME/$f"
190 local tmp="${target}.tmp.$$"
191
192 mkdir -p "$(dirname "$target")"
193
194 if [[ -f "$target" ]]; then
195 cp "$target" "$backup/"
196 fi
197
198 log "Fetching $remote_file -> $f ..."
199 if curl -fsSL "$url" -o "$tmp"; then
200 mv "$tmp" "$target"
201 else
202 rm -f "$tmp"
203 warn "Failed to download $remote_file"
204 fi
205 done
206
207 local skill_target="$HOME/.claude/skills/plan-build/SKILL.md"
208 local skill_tmp="${skill_target}.tmp.$$"
209 mkdir -p "$(dirname "$skill_target")"
210 log "Fetching orchestrate-loop.md -> .claude/skills/plan-build/SKILL.md ..."
211 if curl -fsSL "$GIST_RAW_BASE/orchestrate-loop.md" -o "$skill_tmp"; then
212 mv "$skill_tmp" "$skill_target"
213 else
214 rm -f "$skill_tmp"
215 warn "Failed to download orchestrate-loop.md"
216 fi
217
218 ok "Configs downloaded (Backup at $backup)"
219}
220
221configure_zshrc() {
222 local zshrc="$HOME/.zshrc"
223 log "Configuring .zshrc for Oh My Zsh and Starship..."
224
225 touch "$zshrc"
226 cp "$zshrc" "$HOME/.zshrc.backup_$(date +%Y%m%d_%H%M%S)"
227
228 cat > "$zshrc" <<'EOF'
229# =============================================================================
230# 1. HELPER FUNCTIONS & PATH
231# =============================================================================
232source_if_readable() {
233 local file="$1"
234 if [[ -f "$file" && -r "$file" ]]; then
235 source "$file"
236 fi
237}
238
239export PATH="$HOME/.local/bin:$PATH"
240
241# =============================================================================
242# 2. OH MY ZSH FRAMEWORK
243# =============================================================================
244export ZSH="${ZSH:-$HOME/.oh-my-zsh}"
245ZSH_THEME=""
246
247plugins=(
248 git
249 zsh-autosuggestions
250 zsh-syntax-highlighting
251)
252
253source_if_readable "$ZSH/oh-my-zsh.sh"
254
255# =============================================================================
256# 3. THIRD-PARTY INITIALIZATION & CUSTOM CONFIGS
257# =============================================================================
258source_if_readable "$HOME/.sourcerc"
259source_if_readable "$HOME/.func"
260source_if_readable "$HOME/.pathrc"
261source_if_readable "$HOME/.alias"
262
263# =============================================================================
264# 4. STARSHIP PROMPT
265# =============================================================================
266if [[ -z "${STARSHIP_CONFIG:-}" && -f "$HOME/.config/starship.toml" ]]; then
267 export STARSHIP_CONFIG="$HOME/.config/starship.toml"
268fi
269
270if command -v starship >/dev/null 2>&1; then
271 eval "$(starship init zsh)"
272elif [[ -x "$HOME/.local/bin/starship" ]]; then
273 eval "$("$HOME/.local/bin/starship" init zsh)"
274fi
275EOF
276
277 ok ".zshrc configured for Oh My Zsh framework with Starship prompt"
278}
279
280switch_shell() {
281 log "Starting Zsh session..."
282 echo -e "${YELLOW}Type 'exit' to return to this installer menu.${NC}"
283 echo "----------------------------------------"
284 zsh -l
285 echo "----------------------------------------"
286 ok "Returned from Zsh session"
287}
288
289# =============================
290# INTERACTIVE MENU
291# =============================
292show_menu() {
293 echo "==========================================="
294 echo "WSL Minimal Zsh Installer - Choose what to do"
295 echo "==========================================="
296 echo " 0) Run ALL steps (1-10)"
297 echo " 1) Update system packages"
298 echo " 2) Install core packages (zsh, git, vim, etc.)"
299 echo " 3) Set Timezone (best effort)"
300 echo " 4) Install Homebrew"
301 echo " 5) Configure shell (chsh - sets default shell)"
302 echo " 6) Install Oh My Zsh + plugins"
303 echo " 7) Install Starship prompt"
304 echo " 8) Download custom configs (from OpenGist)"
305 echo " 9) Configure ~/.zshrc (Oh My Zsh + Starship)"
306 echo "10) Switch to Zsh (Temporary Sub-shell)"
307 echo "11) Quit"
308 echo "==========================================="
309}
310
311run_choices() {
312 local input
313 read -p "Select: " input
314 input="${input//,/ }"
315
316 local -a to_run=()
317 local -a to_exclude=()
318
319 for item in $input; do
320 if [[ "$item" == !* ]]; then
321 to_exclude+=("${item:1}")
322 elif [[ "$item" == "0" ]]; then
323 to_run+=(1 2 3 4 5 6 7 8 9 10)
324 else
325 to_run+=("$item")
326 fi
327 done
328
329 for choice in "${to_run[@]}"; do
330 local skip=false
331
332 for ex in "${to_exclude[@]}"; do
333 if [[ "$choice" == "$ex" ]]; then
334 skip=true
335 break
336 fi
337 done
338
339 $skip && continue
340
341 case "$choice" in
342 1) update_system ;;
343 2) install_packages ;;
344 3) set_timezone ;;
345 4) install_homebrew ;;
346 5) configure_shell ;;
347 6) install_oh_my_zsh ;;
348 7) install_starship ;;
349 8) download_configs ;;
350 9) configure_zshrc ;;
351 10) switch_shell ;;
352 11) log "Exiting..."; exit 0 ;;
353 *) warn "Skipping invalid option: $choice" ;;
354 esac
355 echo
356 done
357}
358
359# =============================
360# MAIN
361# =============================
362main() {
363 check_requirements
364 while true; do
365 show_menu
366 run_choices
367 read -p "Do you want to run more options? (y/n): " again
368 [[ "$again" =~ ^[Yy]$ ]] || break
369 done
370 ok "WSL Zsh installation/configuration complete!"
371}
372
373main "$@"
374
zshrc Неформатований
1# =============================================================================
2# 1. HELPER FUNCTIONS & PATH
3# =============================================================================
4source_if_readable() {
5 local file="$1"
6 if [[ -f "$file" && -r "$file" ]]; then
7 source "$file"
8 fi
9}
10
11# Ensure local bin is in PATH early (catches manual Starship installations)
12export PATH="$HOME/.local/bin:$PATH"
13
14# =============================================================================
15# 2. OH MY ZSH FRAMEWORK
16# =============================================================================
17export ZSH="${ZSH:-$HOME/.oh-my-zsh}"
18ZSH_THEME=""
19
20plugins=(
21 git
22 zsh-autosuggestions
23 zsh-syntax-highlighting
24)
25
26source_if_readable "$ZSH/oh-my-zsh.sh"
27
28# =============================================================================
29# 3. THIRD-PARTY INITIALIZATION & CUSTOM CONFIGS
30# =============================================================================
31# Load external initializers (SDKMAN, NVM, etc.)
32source_if_readable "$HOME/.sourcerc"
33
34# Custom Functions (must load before Path Management)
35source_if_readable "$HOME/.func"
36
37# Path Management (Relies on append_path from .func)
38source_if_readable "$HOME/.pathrc"
39
40# Aliases (Loaded late so they override framework/system defaults)
41source_if_readable "$HOME/.alias"
42
43# =============================================================================
44# 4. STARSHIP PROMPT
45# =============================================================================
46if [[ -z "${STARSHIP_CONFIG:-}" && -f "$HOME/.config/starship.toml" ]]; then
47 export STARSHIP_CONFIG="$HOME/.config/starship.toml"
48fi
49
50# Starship owns the prompt. It must initialize after Oh My Zsh.
51if command -v starship >/dev/null 2>&1; then
52 eval "$(starship init zsh)"
53elif [[ -x "$HOME/.local/bin/starship" ]]; then
54 eval "$("$HOME/.local/bin/starship" init zsh)"
55fi
56