Imported from jiito/dotfiles (
AGENTS.md). Install upstream withnpx skills add jiito/dotfiles. Copyright stays with the author.
Dotfiles & Zsh Configuration
This document explains the dotfiles setup, zsh configuration, and how to set up new machines.
Overview
This repository uses a bare git repository approach for managing dotfiles. Instead of symlinking files from a cloned repo, the dotfiles are tracked directly in your home directory using a special config alias.
Architecture
Bare Git Repository Structure
$HOME/.cfg/ # Bare git repository
$HOME/.zshrc # Actual files tracked in repo (not symlinks)
$HOME/.zsh/ # Directory of aliases
$HOME/.zshfn/ # Directory of shell functions
$HOME/scripts/ # Setup and utility scripts
The config alias is used instead of git to manage dotfiles:
config status
config add .zshrc
config commit -m "Update zsh config"
config push
This approach avoids the need for symlinks and keeps your home directory clean.
Zsh Configuration
Dual-Prompt System
The .zshrc uses a dual-prompt system with intelligent fallback:
-
Primary: Powerlevel10k (p10k)
- Rich, feature-complete prompt with icons and git integration
- Used on local development machines
- Configuration:
~/.p10k.zsh
-
Fallback: Custom Prompt
- Lightweight, portable prompt for SSH sessions and containers
- Activated when
CURSOR_AGENTenvironment variable is set - Shows:
[hostname]when SSH'd in (yellow)- Current directory (cyan)
- Git branch and status (green)
- Directory status indicator (clean/dirty)
- Dotfiles repo status indicator
Example prompts:
Local machine with p10k:
~/projects/myrepo main 10:30:45
❯
SSH session with custom prompt:
[container-abc123] ~/projects/myrepo main *>
Local machine with custom prompt (no SSH):
~/projects/myrepo main *>
Prompt Status Indicators
The custom prompt shows git and dotfiles status:
Git repository status (dir_status):
*(green) - Clean working directory*(yellow) - Uncommitted changes*(red) - Staged changes
Dotfiles repository status (config_dir_status):
(green) - Clean dotfiles#(yellow) - Uncommitted dotfiles changes#(red) - Staged dotfiles changes#↑(yellow) - Unpushed commits in dotfiles
Oh-My-Zsh Plugins
Required plugins (installed by setup_machine.sh):
git- Git aliases and completions (built-in)zsh-syntax-highlighting- Command syntax highlightingzsh-autosuggestions- Fish-like autosuggestions
Functions and Aliases
Functions (~/.zshfn/):
- Loaded automatically from all files in
~/.zshfn/ - Each file can contain one or more shell functions
- Example:
gclonefor cloning repos
Aliases (~/.zsh/aliases):
- Common command shortcuts
config- Git alias for managing dotfiles
Setup Scripts
scripts/setup_machine.sh
Main setup script for new machines. Runs in order:
-
Install Zsh + Oh-My-Zsh
- Installs zsh if not present
- Installs Oh-My-Zsh framework
- Backs up any existing
.zshrcto.zshrc.backup-pre-setup
-
Install Powerlevel10k theme
- Clones p10k into
~/.oh-my-zsh/custom/themes/powerlevel10k - Skipped if already installed
- Clones p10k into
-
Install Oh-My-Zsh plugins
zsh-syntax-highlightingzsh-autosuggestions- Cloned into
~/.oh-my-zsh/custom/plugins/
-
Install Dotfiles
- Calls
scripts/install_dotfiles - Clones bare repo to
~/.cfg/ - Checks out dotfiles to
$HOME - Verifies critical files exist
- Calls
-
Verify Installation
- Checks that
.zshrcwas properly checked out - Restores backup if dotfiles checkout failed
- Checks that
scripts/install_dotfiles
Handles dotfiles installation with robust error handling:
- Clones bare repository from GitHub to
~/.cfg/ - Handles file conflicts by moving them to
~/.dotfiles-backup/ - Checks out all tracked files to
$HOME - Verifies critical files exist:
.zshrc.zsh/aliases.zshfn/directory with functions
- Configures git to not show untracked files
Color-coded output:
- 🟢 Green: Success
- 🟡 Yellow: Warning (skipped, already exists)
- 🔴 Red: Error
Setting Up a New Machine
Prerequisites
- Git installed
- SSH key configured for GitHub access
- Zsh installed (or script will install it)
Quick Setup
# 1. Clone this repo temporarily to get the setup script
git clone git@github.com:jiito/dotfiles.git ~/dotfiles-temp
cd ~/dotfiles-temp
# 2. Copy scripts to home directory
mkdir -p ~/scripts
cp scripts/* ~/scripts/
chmod +x ~/scripts/*
# 3. Run setup script
bash ~/scripts/setup_machine.sh
# 4. Clean up temporary clone
cd ~
rm -rf ~/dotfiles-temp
# 5. Restart shell
exec zsh
For Containers/SSH Environments
If you only need the dotfiles without the full setup:
# Clone bare repo
git clone --bare git@github.com:jiito/dotfiles.git $HOME/.cfg
# Define config alias temporarily
alias config='/usr/bin/git --git-dir=$HOME/.cfg/ --work-tree=$HOME'
# Checkout dotfiles (backup conflicts if needed)
mkdir -p .dotfiles-backup
config checkout 2>&1 | grep -E "^\s+\." | awk '{print $1}' | \
xargs -I{} sh -c 'mkdir -p $(dirname .dotfiles-backup/{}) && mv {} .dotfiles-backup/{}'
config checkout
# Configure repo
config config status.showUntrackedFiles no
# Reload shell
exec zsh
Environment Variables
CURSOR_AGENT
When set, disables Powerlevel10k and uses the custom lightweight prompt.
Set this in CI/CD environments, containers, or SSH sessions where you want a simpler prompt:
export CURSOR_AGENT=1
SSH_CONNECTION
Automatically set by SSH. Used to detect SSH sessions and show hostname in prompt.
No manual configuration needed.
File Organization
Tracked Files
Files tracked in the dotfiles repo:
.zshrc- Main zsh configuration.zsh/aliases- Command aliases.zshfn/*- Shell functions.p10k.zsh- Powerlevel10k configurationscripts/*- Setup and utility scripts.gitconfig- Git configuration (if tracked).tmux.conf- Tmux configuration (if tracked)
Untracked Files
Files NOT tracked (stay local to each machine):
.local/bin/env- Local environment variables and PATH setup.ssh/- SSH keys and config.gnupg/- GPG keys- Any machine-specific configuration
Managing Dotfiles
Common Operations
Check status:
config status
Add a new dotfile:
config add ~/.zshrc
config commit -m "Update zsh config"
config push
View changes:
config diff
Pull updates:
config pull
See what's tracked:
config ls-files
Best Practices
- Test changes locally first - Changes affect your shell immediately
- Keep it portable - Don't hardcode paths or assume files exist
- Use conditional sourcing - Check if files exist before sourcing them
- Document changes - Update this file when adding new features
- Commit .p10k.zsh - Ensure p10k config is tracked for consistency
Troubleshooting
"zsh-syntax-highlighting not found"
The plugin isn't installed. Run:
git clone https://github.com/zsh-users/zsh-syntax-highlighting.git \
~/.oh-my-zsh/custom/plugins/zsh-syntax-highlighting
"zsh-autosuggestions not found"
The plugin isn't installed. Run:
git clone https://github.com/zsh-users/zsh-autosuggestions.git \
~/.oh-my-zsh/custom/plugins/zsh-autosuggestions
"no such file or directory: ~/.local/bin/env"
This file is optional and machine-specific. The error is harmless, but if you want to silence it, create an empty file:
mkdir -p ~/.local/bin
touch ~/.local/bin/env
Or ensure your .zshrc has the conditional check:
[ -f "$HOME/.local/bin/env" ] && . "$HOME/.local/bin/env"
Aliases/functions not loading
The dotfiles weren't properly checked out. Run:
config checkout --force
exec zsh
Prompt doesn't show git info
Ensure you're in a git repository and vcs_info is loaded:
cd ~/projects/some-git-repo
echo $vcs_info_msg_0_ # Should show branch name
Config alias doesn't work
Define it manually:
alias config='/usr/bin/git --git-dir=$HOME/.cfg/ --work-tree=$HOME'
Then reload:
exec zsh
Technical Details
How the Custom Prompt Works
The precmd() function runs before each prompt display:
- Load git info -
vcs_infofetches current branch - Check git status - Determine if repo is clean/dirty/staged
- Check dotfiles status - Query
.cfgbare repo for uncommitted changes - Set hostname - Show hostname only if
SSH_CONNECTIONis set - Build prompt - Assemble all components with color codes
Prompt String Expansion
Zsh prompt uses special sequences:
%F{color}- Start color%f- End color%~- Current directory (with ~ for home)${var}- Variable expansion${var:+text}- Show text only if var is non-empty
Example:
PROMPT='${hostname_display:+[%F{yellow}${hostname_display}%f] }%F{cyan}%~%f> '
Expands to:
- With SSH:
[hostname] /path/to/dir> - Without SSH:
/path/to/dir>
Repository
- GitHub: github.com/jiito/dotfiles
- Branch:
master - Clone URL:
git@github.com:jiito/dotfiles.git
Version History
- 2025-02: Complete rewrite of setup scripts with error handling
- 2025-02: Added SSH hostname detection in prompt
- 2025-02: Made ~/.local/bin/env conditional
- 2025-02: Added Oh-My-Zsh plugin installation to setup script
- 2024: Initial dotfiles setup with bare repo approach
Neovim Configuration
~/.config/nvim/ is tracked by the dotfiles repo. Migrated from a hand-rolled jiito/* config to LazyVim (15.x) on 2026-05-16.
Layout
.config/nvim/
├── init.lua # one-liner: require("config.lazy")
├── lazy-lock.json # plugin version lockfile (always commit)
├── lua/
│ ├── config/
│ │ ├── lazy.lua # LazyVim setup + enabled extras
│ │ ├── keymaps.lua # custom keymaps (incl. leap fork workaround)
│ │ ├── options.lua, autocmds.lua # LazyVim defaults
│ │ └── worktree.lua # snacks-picker worktree switcher logic
│ └── plugins/
│ ├── claudecode.lua # coder/claudecode.nvim (Claude in nvim)
│ ├── diffview.lua # sindrets/diffview.nvim (PR-style diffs)
│ ├── lualine.lua # statusline override: worktree dir
│ └── worktree.lua # <leader>gw* keybindings
LazyVim extras enabled in lua/config/lazy.lua: editor.leap. Add more with :LazyExtras.
Leap workaround (codeberg fork bug)
The editor.leap extra pulls from codeberg.org/andyg/leap.nvim. That fork has an internal inconsistency: plugin/init.lua defines <Plug>(leap-forward) but add_default_mappings() still binds s/S to the now-dead <Plug>(leap-forward-to) name. Compounded by lazy-load timing — the first s press resolves the mapping before leap has loaded, falling through to vim's default substitute.
Fix in lua/config/keymaps.lua: eagerly Lazy load leap.nvim during VeryLazy, bind s/S to the correct <Plug> names with remap = true, and re-apply on User LazyLoad for safety. Worth reporting upstream.
Detailed notes (workflow, keymaps, migration history): ~/notes/dev/tooling/nvim-setup.md and ~/notes/dev/tooling/claude-multi-session.md (in the Obsidian vault, not tracked by the dotfiles repo).