Skip to content

Conversation

@lukebarousse
Copy link

@lukebarousse lukebarousse commented Dec 13, 2025

Problem

On fresh macOS installations with zsh, users encounter the following error when opening a new terminal:

(eval):2: command not found: compdef

This occurs because the zsh completion system hasn't been initialized before the duckman completion zsh command runs, which requires the compdef function. On fresh installations, compdef is only available after compinit has been called.

Solution

This PR adds an initialization step that ensures compinit runs before loading the duckman completion script. This guarantees that the completion system is properly initialized when compdef is called.

Changes:

  • Added autoload -Uz compinit 2>/dev/null && compinit 2>/dev/null line before the completion eval
  • The 2>/dev/null suppresses any warnings if compinit has already been called (making it safe to run multiple times)

Testing

I've tested this fix on a fresh macOS installation. After adding the new line, opening a new terminal no longer produces the command not found: compdef error, and duckman completion works correctly. I also verified it works correctly with oh-my-zsh installed, where compinit is already called by the framework.

Ensure compinit is called before using compdef to prevent
'command not found: compdef' error on fresh zsh setups
@NiclasHaderer
Copy link
Owner

Hey, thanks for the PR.
I think I would be more comfortable with a warning message that you (might) have to add autoload -U compinit && compinit to your script if you are running zsh rather than just adding it.
Alternatively we would also detect if the autoload command is normally called during their zsh init and then either add it or not...

@lukebarousse
Copy link
Author

lukebarousse commented Dec 17, 2025

Thanks for the feedback!

The fix

I’ve updated the installer to avoid auto-running or adding compinit and instead:

  • guard zsh completion on compdef being available, so it becomes a no-op if completion isn’t initialized
  • print a one-time note during setup (only when configuring zsh) explaining that autoload -Uz compinit && compinit may be required for autocomplete on fresh zsh installs

Why single quotes are used

I switched the zsh completion line to single quotes so duckman completion zsh is written literally to .zshrc rather than being executed during install. This prevents the completion script from being expanded at install time and avoids errors on clean environments.

appendIfNotPresent "$HOME/.zshrc" '(( $+functions[compdef] )) && eval "$(duckman completion zsh)"'

Thoughts on auto-detecting compinit

I intentionally didn’t add logic to inspect .zshrc (or other zsh init files) for compinit, since completion can be initialized indirectly (e.g. via frameworks or sourced scripts). That makes install-time detection brittle and potentially misleading. The runtime compdef guard reflects the actual completion state more reliably without mutating user config.

Testing

I tested this on a fresh Mac install with zsh and also on a Mac with oh-my-zsh. No issues noted.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants