overengineeringstudio / overengineeringstudio/effect-utils
feat(mkPnpmCli): built-in shell-completion install with a build-time parse gate
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 82
- Forks
- 2
- Avg merge
- 1d 8h
- Merged PRs (30d)
- 121
Description
Summary
Several @effect/cli-based CLIs built with mkPnpmCli want shell completions installed into the standard share/ layout. Today each consumer hand-rolls the same postInstall block:
mkdir -p $out/share/fish/vendor_completions.d $out/share/bash-completion/completions $out/share/zsh/site-functions
$out/bin/<cli> --completions fish > $out/share/fish/vendor_completions.d/<cli>.fish
$out/bin/<cli> --completions bash > $out/share/bash-completion/completions/<cli>
$out/bin/<cli> --completions zsh > $out/share/zsh/site-functions/_<cli>
Proposal: add an opt-in installShellCompletions ? false option to mkPnpmCli that does this once, so a consumer gets completions with one flag instead of duplicated Nix. Default-off keeps it derivation-neutral for existing consumers.
A build-time parse gate is required (not optional)
@effect/cli's fish (and zsh) completion generator does not escape shell-special characters in command/flag descriptions. A description containing an apostrophe, e.g.
"Copy a published version's source back into the tmp dir"
emits an invalid fish script:
complete -c foo ... -d 'Copy a published version's source back into the tmp dir'
fish only honors \' / \\ inside single quotes, so the unescaped ' closes the string early and the entire file fails to parse — the CLI then errors on every <tab>. zsh's '…[desc]…' format has the same hazard. bash is unaffected (word-list based, no descriptions embedded).
Because "emits a script" ≠ "valid script", the shared option MUST validate the generated files at build time and fail the build rather than ship a broken completion:
fish --no-execute $out/share/fish/vendor_completions.d/<cli>.fish
zsh -n $out/share/zsh/site-functions/_<cli>
bash -n $out/share/bash-completion/completions/<cli>
(fish/zsh added as build-time-only nativeBuildInputs, not in the runtime closure.)
Root cause / upstream
The escaping defect is in @effect/cli's completion generation (fish/zsh description quoting). The ideal fix is upstream escaping of description text; the parse gate is the defense-in-depth that keeps consumer completions safe regardless, and turns "a future apostrophe silently breaks fish" into "the build fails loudly". Worth a separate upstream report to @effect/cli.
Notes
- Consumers that hand-roll this block today would collapse onto the shared option.
- The reference implementation lives in a downstream consumer's builder override; happy to upstream it here.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by locating the mkPnpmCli entry point and compare it with the downstream consumer's builder override mentioned in the issue. Add the opt-in completion installation while preserving the default, then verify generated fish, zsh, and bash files with the specified parse commands and confirm fish and zsh are build-time-only inputs.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- bash, fish, shell, typescript, zsh
- Domain
- build-system, cli, tooling
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100