Skip to content

ivankristianto/zsh

Repository files navigation

zsh Config

Personal zsh setup with:

  • a single entrypoint (init.zsh)
  • local secret loading from .env
  • Spaceship prompt customization
  • optional productivity plugins and CLI integrations

Table of Contents

Overview

This repo manages shell behavior through one entrypoint:

source ~/.zsh/init.zsh

init.zsh then loads settings, keys, prompt, functions, and plugins in a predictable order.

Prerequisites

  • macOS or Linux with zsh
  • git
  • Homebrew (recommended on macOS for tool installation)

Setup (Fresh Machine)

  1. Clone repo:
git clone git@github.com:ivankristianto/zsh.git ~/.zsh
cd ~/.zsh
  1. Initialize submodules (required for Spaceship prompt):
git submodule update --init --recursive
  1. Create your local secrets file:
cp .env.example .env
  1. Add entrypoint to ~/.zshrc:
source ~/.zsh/init.zsh
  1. Reload shell:
exec zsh

Update (Existing Install)

From ~/.zsh:

git pull
git submodule update --init --recursive --remote
exec zsh

Configuration Load Order

init.zsh loads files in this order:

  1. settings.zsh
  2. keys.zsh
  3. themes/.zsh_theme
  4. functions/ai_functions.zsh
  5. functions/functions.zsh
  6. plugins/plugins.zsh

This order is intentional:

  • secrets are available before function/theme usage
  • prompt is configured before interactive usage
  • syntax-highlighting plugin is loaded near the end

Repository Layout

  • init.zsh: single entrypoint
  • settings.zsh: shell history and zsh options
  • keys.zsh: loads variables from .env and exports compatibility vars
  • .env.example: tracked template for required env variable names
  • functions/: custom shell functions
  • themes/.zsh_theme: Spaceship prompt config
  • themes/spaceship-prompt/: Spaceship git submodule
  • plugins/plugins.zsh: optional plugin/tool loader (safe guards if missing)

Functions Reference

Both files are auto-loaded from init.zsh:

  • functions/ai_functions.zsh
  • functions/functions.zsh

AI Functions (functions/ai_functions.zsh)

Primary command:

ai [command] [args...]

Implementation layout:

  • Entry loader: functions/ai_functions.zsh
  • Modular files: functions/ai/*.zsh
  • Provider domains: functions/ai/providers/{claude,ollama,llamacpp,codex,gemini,copilot,opencode}.zsh
Command Alias Purpose Example
ai - Open interactive fzf provider picker ai
sonnet s Claude Code with Claude Sonnet ai sonnet "review this diff"
haiku h Claude Code with Claude Haiku ai haiku "summarize this log"
opus o Claude Code with Claude Opus ai opus "deep architecture analysis"
glm g Claude Code via GLM-5.1 (Z.ai) ai glm "plan rollout steps"
kimi k Claude Code via Kimi K2.5 (Moonshot) ai k "draft migration plan"
mini m Claude Code via MiniMax M2.1 ai mini "quick fix proposal"
openrouter or Claude Code via OpenRouter (--model supported) ai openrouter --model anthropic/claude-opus-4 "check this service design"
ollama ol Claude Code via local Ollama (--model supported) ai ollama --model qwen2.5-coder:14b "write unit tests"
llama.cpp ll Claude Code via local llama.cpp (--model supported) ai llama.cpp --model qwen2.5-coder:14b "write unit tests"
custom cu Claude Code via custom Anthropic-compatible endpoint ai custom --model gpt-4o --endpoint https://... --apikey ... "debug error"
codex c OpenAI Codex CLI ai codex "refactor this function"
gemini ge Gemini CLI in yolo mode ai gemini "summarize changes"
copilot cp GitHub Copilot CLI ai copilot "generate release notes"
opencode oc OpenCode build agent (--model, --review) ai opencode --review
install i Install a supported coding agent CLI via npm global ai install codex
bench b Run one prompt across Claude-backed providers ai bench "review this diff" glm kimi or
context ctx Dump project context as markdown ai context --copy
last l Re-run last selected provider ai last
help -h Show built-in help and status (shows only ready cmds) ai help
<cmd> ship - Interactive git assistant (commit/push/PR) ai g ship

Required tooling/env depends on command:

  • Claude Code backends (sonnet/haiku/opus/glm/kimi/mini/openrouter/ollama/llama.cpp/custom) require claude
  • ai glm also requires GLM_API_KEY
  • ai k (ai kimi) also requires KIMI_API_KEY
  • ai mini also requires MINIMAX_API_KEY
  • ai openrouter (ai or) also requires OPENROUTER_API_KEY
  • ai llama.cpp (ai ll) uses hardcoded local Anthropic-compatible values (http://localhost:8001, sk-no-key-required)
  • ai codex requires codex + OPENAI_API_KEY
  • ai gemini requires gemini + GEMINI_API_KEY
  • ai copilot requires copilot
  • ai opencode (ai oc) requires opencode
  • Interactive picker (ai) requires fzf

Examples (long + shorthand):

# Claude Code backends
ai sonnet "review this diff for bugs"
ai s "review this diff for bugs"
ai openrouter --model anthropic/claude-opus-4 "analyze this architecture"
ai or --model anthropic/claude-opus-4 "analyze this architecture"
ai llama.cpp --model qwen2.5-coder:14b "write unit tests"
ai ll --model qwen2.5-coder:14b "write unit tests"
ai custom --model gpt-4o --endpoint https://api.example.com --apikey sk-... "explain this stack trace"
ai cu --model gpt-4o --endpoint https://api.example.com --apikey sk-... "explain this stack trace"

# Standalone CLIs
ai codex "refactor this function safely"
ai c "refactor this function safely"
ai copilot "create release notes from commits"
ai cp "create release notes from commits"
ai opencode --review
ai oc --review

# Utility
ai last
ai l
ai install claude
ai install codex --dry-run
ai bench "compare rollback plans" glm kimi openrouter
ai context
ai context --copy

AI Helper Notes

Git Workflow (ai ship)

Launch interactive git assistant with any provider:

# Default (Haiku)
ai ship

# With specific providers
ai s ship      # Claude Sonnet
ai g ship      # GLM
ai k ship      # Kimi
ai or ship     # OpenRouter

The AI will:

  1. Review your changes
  2. Help craft commit messages
  3. Commit and push
  4. Create a PR via gh

General Functions (functions/functions.zsh)

Function Purpose Example
tt Send Telegram message using TELEGRAM_BOT_TOKEN and TELEGRAM_CHAT_ID tt -m "deploy done"
k2-dev Shortcut SSH/orb connect helper for k2-dev k2-dev
switchphp Switch linked Homebrew PHP version switchphp 8.3
up Run daily software refresh (~/.zsh, current repo, Homebrew, npm globals, Node LTS, skills) up
zload Profile interactive zsh startup with zprof zload 10
tmexclude Recursively exclude folders from Time Machine backups tmexclude ~/projects node_modules

Daily update command details:

up

up executes:

  • git -C ~/.zsh pull --ff-only
  • git pull --ff-only (when inside a git repo and tracking branch exists)
  • brew upgrade
  • brew cleanup
  • npm install -g <all currently installed global npm packages except npm>
  • nvm install --lts (when nvm is available)
  • npx skills update

Startup profiling:

zload 10

zload launches an interactive shell with zprof preloaded and prints the top startup contributors.

Time Machine exclusions:

tmexclude ~/projects node_modules    # Exclude all node_modules folders
tmexclude -d ~ "Caches"              # Dry-run: preview what would be excluded

Secrets Management

Rules:

  • store real tokens only in .env
  • never commit .env
  • commit only .env.example

.env is ignored by git via .gitignore.

Minimal example:

OPENAI_API_KEY="your-openai-api-key"
OPENROUTER_API_KEY="your-openrouter-api-key"
KIMI_API_KEY="your-kimi-api-key"

DevX Bootstrap

Install core tools:

brew install fzf zoxide eza bat fd ripgrep
$(brew --prefix)/opt/fzf/install --key-bindings --completion --no-update-rc

CLI Tools

Tool Purpose Repo Install
fzf Fuzzy finder for files/history/processes https://github.com/junegunn/fzf brew install fzf
zoxide Smarter cd that learns frequent paths https://github.com/ajeetdsouza/zoxide brew install zoxide
eza Modern ls replacement with icons and git metadata https://github.com/eza-community/eza brew install eza
bat Syntax-highlighted cat with pager integration https://github.com/sharkdp/bat brew install bat
fd Fast and simple alternative to find https://github.com/sharkdp/fd brew install fd
ripgrep (rg) Fast recursive text search https://github.com/BurntSushi/ripgrep brew install ripgrep

Usage examples:

# fzf: fuzzy-find files under current directory
fzf

# zoxide: jump to a frequently visited directory (configured as `cd`)
cd .zsh

# eza: long list with icons and git status
eza -la --icons --git

# bat: preview file with syntax highlighting
bat ~/.zsh/README.md

# fd: find zsh files quickly
fd '\.zsh$' ~/.zsh

# ripgrep: search text recursively
rg "SPACESHIP_HOST_SHOW" ~/.zsh

Note: this config initializes zoxide with --cmd cd in plugins/plugins.zsh, so use cd (not z).

Install zsh plugins used by this repo:

git clone --depth=1 https://github.com/zsh-users/zsh-autosuggestions.git ~/.zsh/plugins/zsh-autosuggestions
git clone --depth=1 https://github.com/zsh-users/zsh-syntax-highlighting.git ~/.zsh/plugins/zsh-syntax-highlighting
git clone --depth=1 https://github.com/zsh-users/zsh-completions.git ~/.zsh/plugins/zsh-completions

zsh Plugins

Plugin Purpose Repo Install Path
zsh-autosuggestions Suggests commands based on shell history https://github.com/zsh-users/zsh-autosuggestions ~/.zsh/plugins/zsh-autosuggestions
zsh-syntax-highlighting Highlights valid/invalid commands as you type https://github.com/zsh-users/zsh-syntax-highlighting ~/.zsh/plugins/zsh-syntax-highlighting
zsh-completions Adds many extra command completions https://github.com/zsh-users/zsh-completions ~/.zsh/plugins/zsh-completions

Usage examples:

  • zsh-autosuggestions: type git st (after git status exists in history), then press Right Arrow to accept suggestion.
  • zsh-syntax-highlighting: compare typing ls (valid) vs lss (invalid) to see different highlighting.
  • zsh-completions: type git ch then press Tab to expand completion candidates.

Optional aliases:

alias ls='eza --group-directories-first'
alias ll='eza -la --icons --git --group-directories-first'
alias cat='bat'

Spaceship Prompt Notes

Configured in themes/.zsh_theme.

Current default prompt order:

  • dir
  • git
  • node
  • php
  • exec_time
  • time
  • line_sep
  • jobs
  • exit_code
  • char

Important behavior:

  • host section is disabled (SPACESHIP_HOST_SHOW=false)
  • time uses SPACESHIP_TIME_FORMAT="%D{%H:%M}"
    This avoids %M hostname expansion side effects.

Customization Examples

Hide Node and PHP sections:

SPACESHIP_NODE_SHOW=false
SPACESHIP_PHP_SHOW=false

Remove at before time:

SPACESHIP_TIME_PREFIX=""

Disable time completely:

SPACESHIP_TIME_SHOW=false

Show username always:

SPACESHIP_USER_SHOW=always

Verification Commands

Validate zsh syntax:

zsh -n ~/.zsh/init.zsh ~/.zsh/settings.zsh ~/.zsh/keys.zsh ~/.zsh/themes/.zsh_theme ~/.zsh/plugins/plugins.zsh ~/.zsh/functions/ai_functions.zsh ~/.zsh/functions/ai/*.zsh ~/.zsh/functions/ai/providers/*.zsh

Verify secrets load:

zsh -lc 'source ~/.zsh/keys.zsh; [[ -n "$OPENAI_API_KEY" ]] && echo OK || echo MISSING'

Check current Spaceship values:

zsh -lic 'print -r -- "HOST_SHOW=$SPACESHIP_HOST_SHOW TIME_FORMAT=$SPACESHIP_TIME_FORMAT"'

Run AI function tests:

zsh ~/.zsh/tests/ai_functions_test.zsh

Troubleshooting

Prompt still shows hostname-like output at the end:

  • check SPACESHIP_TIME_FORMAT first; %M inside prompt context can render hostname
  • recommended value: SPACESHIP_TIME_FORMAT="%D{%H:%M}"
  • reload shell: exec zsh

Plugins not loading:

  • ensure plugin dirs exist under ~/.zsh/plugins
  • plugin loader is guarded; missing plugins do not crash startup

Submodule missing after clone:

  • run git submodule update --init --recursive

Secrets not available in commands:

  • confirm .env exists and contains valid KEY="value" lines
  • run source ~/.zsh/keys.zsh
  • verify with printenv | rg 'OPENAI_API_KEY|OPENROUTER_API_KEY|KIMI_API_KEY'

About

Opinionated ZSH Settings

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages