This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Personal Zsh configuration repository: shell environment, dotfiles, aliases, functions, and utility scripts. Designed to bootstrap a consistent dev environment on new machines via ./install.sh.
~/.zshrcsourcesload.zsh(added byinstall.sh)load.zshorchestrates everything:- Locale, zsh options,
path-ethicplugin, theme (synchronous — needed at startup) - Sources all
include/files: exports, aliases, functions, keybindings, completions, history, prompt - Deferred plugins (via
zsh-defer, interactive sessions only):zsh-history-substring-search,zsh-autosuggestions,zsh-syntax-highlighting— these load after the prompt appears - Non-interactive fallback: deferred plugins load synchronously when
[[ ! -o interactive ]](e.g., tests) zsh-syntax-highlightingMUST be loaded LAST (after all other plugins and keybindings, even when deferred)fpathmust includezsh-completions/srcBEFOREautoload- History-substring-search keybindings are deferred in
load.zsh(not ininclude/keybindings) because they depend on the deferred plugin
- Locale, zsh options,
include/— Modular shell config files sourced byload.zshscripts/— Executable tools, added to$PATHviainclude/exports. Any file here is a CLI command.lib.zsh— Shared library (logging, tree search) sourced by functions and install script
dotfiles/— Symlinked to$HOMEduring install (not copied — changes are live)claude/— Global Claude Code instructions (CLAUDE.md).install.shsymlinks~/.claude/CLAUDE.mdto this file. If~/.claude/CLAUDE.mdalready exists, install prompts[n/Y]before replacing it (default Yes); an existing correct link is left untouchedzsh-plugins/,zsh-theme/— Git submodulestests/— Test suite usingzsh-scriptestsubmodule
./install.sh # Full setup: submodules, symlinks, dirs, .zshrc, neovim, zwc compilation
make test # Run tests (also: ./tests/run_tests.sh)
make update_submodules # Update all git submodules
make compile # Compile zsh files to .zwc bytecode
make clean_zwc # Remove all .zwc bytecode files
reload! # Alias: recompiles .zwc files, then re-sources ~/.zshrc
zsh_bench # Benchmark shell startup time (see scripts/zsh_bench)
zsh_bench -n 20 -o # 20 iterations, save results to .benchmarks/To run a single test file directly: zsh tests/my_test.test.sh (but prefer make test — the runner sets up the sandbox environment via zsh-scriptest).
Tests use the zsh-scriptest framework (submodule in tests/). Test files must be named *.test.sh and placed in tests/.
- Tests run in a sandboxed
$HOME(temporary empty dir). Each test file must:- Verify
$HOMEis empty at start (guard against running outside sandbox) - Write a fingerprint file to
$HOMEand assert it exists in cleanup (proves sandbox isolation) rm -rf "$HOME"in cleanup
- Verify
- Available matchers from
matchers.sh:assert_contains,assert_not_empty,assert_file_exists,assert_dir_exists, etc. - Use
test_case_title/test_setup_title/test_teardown_titlefor structured output. - Test functions are called sequentially at the bottom of the file (not auto-discovered).
- See
tests/sanity.test.shfor the canonical pattern.
CI runs on ubuntu-latest and macos-latest (GitHub Actions, .github/workflows/ci.yml).
- Logging:
__profile_log_{error,warn,info,success}fromscripts/lib.zsh - Tree search:
__profile_search_ancestor_tree <filename>walks up from$PWDto/looking for a file - Private functions: Prefix with
__profile_to indicate internal use - Public functions in
include/functionsare user-facing shell commands (e.g.,start,jest,alias_last)
The start function searches ancestor directories for a .start file and sources it. This is a convention for project-specific environment setup.
When modifying include/aliases:
- Group by category (comment headers indicate sections)
- Git aliases evaluate current branch dynamically:
$(git branch --show-current) alias_last <name>creates an alias from the last command and appends it to the aliases file
$SHA1N_PROFILE_HOME— This repo's directory path (set inload.zsh, used everywhere)$CODE—$HOME/code(defined ininclude/exports)- Other env vars:
include/exports
Files in scripts/ are on $PATH and act as standalone commands. Notable: y and n (yarn/npm wrappers), docker_cleanup, git_config_hook, zsh_bench (startup benchmarking). New scripts placed here are automatically available as commands.
- Startup time: Optimized via
compinitcaching,.zwcbytecode compilation, andzsh-deferplugin deferral. Usezsh_benchto measure impact of changes. - compinit caching (
include/completions): The.zcompdumpfile is only regenerated when stale (>24h) or missing.compinit -Cis used otherwise. .zwcbytecode: Zsh auto-prefersfile.zwcoverfilewhen sourcing (if.zwcis newer). Stale.zwcfiles are harmless — zsh falls back to the source.reload!andinstall.shrecompile automatically. Some files (aliases, exports, functions) failzcompilesilently — this is expected.zsh-defer: Only used in interactive sessions. Keybindings that depend on deferred plugins must also be deferred — seeload.zshfor the pattern.
Changes must work on both macOS and Linux. Use platform checks ($OSTYPE) when behavior differs (see __profile_git_file_timestamp for an example).