overengineeringstudio / overengineeringstudio/effect-utils

feat(mkPnpmCli): built-in shell-completion install with a build-time parse gate

Open
#907 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

area:nix origin:agent type:feature
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

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.