fix(cli): defer zsh compdef registration until compinit is available#56555
Conversation
Greptile SummaryThis PR fixes a long-standing What changed:
One minor test-coverage gap: the integration test directly invokes Confidence Score: 5/5Safe to merge — the deferred registration logic is correct and no runtime regressions were identified. All findings are P2 (test coverage suggestion). The production zsh script change is logically sound: immediate registration when compdef is available, correct deferred precmd hook with deduplication and self-cleanup when it is not. No P0 or P1 issues found. src/cli/completion-cli.test.ts — the integration test could be extended to assert hook queuing and self-removal, but this does not block merge.
|
| Filename | Overview |
|---|---|
| src/cli/completion-cli.ts | Replaces bare compdef at source-time with a deferred _register_completion pattern. Logic is correct: checks $+functions[compdef], registers immediately if available, otherwise queues a self-removing precmd hook with deduplication guard. No issues found. |
| src/cli/completion-cli.test.ts | Adds a zsh integration test with proper platform/binary guards and temp-dir cleanup. Core invariants are verified, but the test bypasses the precmd_functions hook mechanism and never asserts the hook is queued or self-cleans. |
Prompt To Fix All With AI
This is a comment left during a code review.
Path: src/cli/completion-cli.test.ts
Line: 52-76
Comment:
**Test bypasses the precmd hook path**
The test manually calls `_openclaw_register_completion` after `compinit -C` rather than letting the `precmd_functions` hook fire naturally. This means the test validates that the function *itself* works correctly, but never verifies:
1. That `_openclaw_register_completion` was actually added to `precmd_functions` after sourcing (when compdef isn't yet available).
2. That the hook self-removes from `precmd_functions` after it fires.
A more complete test could add assertions like:
```zsh
source ${scriptPath}
# Verify hook is queued
[[ "${precmd_functions[(r)_openclaw_register_completion]}" = "_openclaw_register_completion" ]] || exit 11
autoload -Uz compinit
compinit -C
_openclaw_register_completion
# Verify hook was removed after firing
[[ -z "${precmd_functions[(r)_openclaw_register_completion]}" ]] || exit 12
[[ "${_comps[openclaw]-}" = "_openclaw_root_completion" ]]
```
This won't affect production behavior, but the current test would pass even if the `precmd_functions` registration block were accidentally deleted.
How can I resolve this? If you propose a fix, please make it concise.Reviews (1): Last reviewed commit: "fix(cli): defer zsh compdef registration..." | Re-trigger Greptile
The generated zsh completion script called compdef at source time, which fails with 'command not found: compdef' when loaded before compinit. Replace with a deferred registration that tries immediately, and if compdef is not yet available, queues a self-removing precmd hook that retries on first prompt. Handles repeated sourcing (deduped hook entry) and shells that never run compinit (completion simply never registers, matching zsh model). Add real zsh integration test verifying no compdef error on source and successful registration after compinit. Fixes openclaw#14289
54e7576 to
e85ada9
Compare
Add missing changelog entries for PRs openclaw#56500, openclaw#56540, openclaw#56555, openclaw#56567, openclaw#56573, openclaw#56587, openclaw#56595, openclaw#56612, openclaw#56620.
…penclaw#56555) The generated zsh completion script called compdef at source time, which fails with 'command not found: compdef' when loaded before compinit. Replace with a deferred registration that tries immediately, and if compdef is not yet available, queues a self-removing precmd hook that retries on first prompt. Handles repeated sourcing (deduped hook entry) and shells that never run compinit (completion simply never registers, matching zsh model). Add real zsh integration test verifying no compdef error on source and successful registration after compinit. Fixes openclaw#14289
Add missing changelog entries for PRs openclaw#56500, openclaw#56540, openclaw#56555, openclaw#56567, openclaw#56573, openclaw#56587, openclaw#56595, openclaw#56612, openclaw#56620.
…penclaw#56555) The generated zsh completion script called compdef at source time, which fails with 'command not found: compdef' when loaded before compinit. Replace with a deferred registration that tries immediately, and if compdef is not yet available, queues a self-removing precmd hook that retries on first prompt. Handles repeated sourcing (deduped hook entry) and shells that never run compinit (completion simply never registers, matching zsh model). Add real zsh integration test verifying no compdef error on source and successful registration after compinit. Fixes openclaw#14289
Add missing changelog entries for PRs openclaw#56500, openclaw#56540, openclaw#56555, openclaw#56567, openclaw#56573, openclaw#56587, openclaw#56595, openclaw#56612, openclaw#56620.
…penclaw#56555) The generated zsh completion script called compdef at source time, which fails with 'command not found: compdef' when loaded before compinit. Replace with a deferred registration that tries immediately, and if compdef is not yet available, queues a self-removing precmd hook that retries on first prompt. Handles repeated sourcing (deduped hook entry) and shells that never run compinit (completion simply never registers, matching zsh model). Add real zsh integration test verifying no compdef error on source and successful registration after compinit. Fixes openclaw#14289
Add missing changelog entries for PRs openclaw#56500, openclaw#56540, openclaw#56555, openclaw#56567, openclaw#56573, openclaw#56587, openclaw#56595, openclaw#56612, openclaw#56620.
…penclaw#56555) The generated zsh completion script called compdef at source time, which fails with 'command not found: compdef' when loaded before compinit. Replace with a deferred registration that tries immediately, and if compdef is not yet available, queues a self-removing precmd hook that retries on first prompt. Handles repeated sourcing (deduped hook entry) and shells that never run compinit (completion simply never registers, matching zsh model). Add real zsh integration test verifying no compdef error on source and successful registration after compinit. Fixes openclaw#14289
Add missing changelog entries for PRs openclaw#56500, openclaw#56540, openclaw#56555, openclaw#56567, openclaw#56573, openclaw#56587, openclaw#56595, openclaw#56612, openclaw#56620.
…penclaw#56555) The generated zsh completion script called compdef at source time, which fails with 'command not found: compdef' when loaded before compinit. Replace with a deferred registration that tries immediately, and if compdef is not yet available, queues a self-removing precmd hook that retries on first prompt. Handles repeated sourcing (deduped hook entry) and shells that never run compinit (completion simply never registers, matching zsh model). Add real zsh integration test verifying no compdef error on source and successful registration after compinit. Fixes openclaw#14289
Add missing changelog entries for PRs openclaw#56500, openclaw#56540, openclaw#56555, openclaw#56567, openclaw#56573, openclaw#56587, openclaw#56595, openclaw#56612, openclaw#56620.
…penclaw#56555) The generated zsh completion script called compdef at source time, which fails with 'command not found: compdef' when loaded before compinit. Replace with a deferred registration that tries immediately, and if compdef is not yet available, queues a self-removing precmd hook that retries on first prompt. Handles repeated sourcing (deduped hook entry) and shells that never run compinit (completion simply never registers, matching zsh model). Add real zsh integration test verifying no compdef error on source and successful registration after compinit. Fixes openclaw#14289
Add missing changelog entries for PRs openclaw#56500, openclaw#56540, openclaw#56555, openclaw#56567, openclaw#56573, openclaw#56587, openclaw#56595, openclaw#56612, openclaw#56620.
…penclaw#56555) The generated zsh completion script called compdef at source time, which fails with 'command not found: compdef' when loaded before compinit. Replace with a deferred registration that tries immediately, and if compdef is not yet available, queues a self-removing precmd hook that retries on first prompt. Handles repeated sourcing (deduped hook entry) and shells that never run compinit (completion simply never registers, matching zsh model). Add real zsh integration test verifying no compdef error on source and successful registration after compinit. Fixes openclaw#14289
Add missing changelog entries for PRs openclaw#56500, openclaw#56540, openclaw#56555, openclaw#56567, openclaw#56573, openclaw#56587, openclaw#56595, openclaw#56612, openclaw#56620.
Summary
compdefat source time, which fails withcommand not found: compdefwhen loaded beforecompinitcompdefnot available queues a self-removingprecmdhook that retries on first promptcompinitRoot Cause
getCompletionScript('zsh')insrc/cli/completion-cli.tsemitted barecompdef _openclaw_root_completion openclawat the top level. This runs at source time, beforecompinitin most plugin manager and manual setups.Reference
ghandkubectlboth document "runcompinitfirst". We go one step further: defer registration so it works regardless of load order.Change Type
Testing
4/4 tests pass including new zsh integration test that:
compdeferrorFixes #14289