feat(packslip): shell completions from a tool's packslip - #12779
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository YAML (base), Central YAML (inherited), Organization UI (inherited) Review profile: CHILL Plan: Team Run ID: 📒 Files selected for processing (11)
Included review availability: Your plan provides up to 10 included reviews per hour; 2 remain after this review. 📝 WalkthroughWalkthroughChangesThe Packslip resource acquisition
Completion resolution
CLI integration and supporting updates
Estimated code review effort: 4 (Complex) | ~45 minutes Merge Risk: ⚪ Minimal · up to No actionable merge-blocking risk is established at the current head. Sequence Diagram(s)sequenceDiagram
participant Shell
participant MiseCompletion
participant Packslip
participant Tool
Shell->>MiseCompletion: request completion for installed tool
MiseCompletion->>Packslip: resolve active statement and sources
Packslip->>Tool: run derivation command when packslip.exec is enabled
Tool-->>Packslip: return completion script
Packslip-->>MiseCompletion: provide selected script
MiseCompletion-->>Shell: print or load completion
Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Greptile SummaryThis PR adds packslip-provided, active-version-aware tool completions and install-time fetching of completion resources.
Confidence Score: 5/5The PR appears safe to merge. No blocking failure remains. Important Files Changed
Reviews (20): Last reviewed commit: "fix(packslip): say when a completion was..." | Re-trigger Greptile |
77168be to
5dfd6d4
Compare
72f539d to
476f317
Compare
| functions[_{tool}]="$__mise_stub" | ||
| compdef _{tool} '{tool}' | ||
| return $__mise_ret | ||
| "# |
There was a problem hiding this comment.
Zsh stub double-runs vendor scripts
Medium Severity
The zsh stub evals the vendor script inside _{tool}, so usage-style scripts whose funcstack[1] check self-invokes already complete once. The stub then sees the redefined body and calls that function again, producing duplicate candidates and a second generator run on every tab.
Reviewed by Cursor Bugbot for commit 476f317. Configure here.
There was a problem hiding this comment.
Fixed: the stub reads compstate[nmatches] before and after the eval. A script that completes on its own, as a usage or clap script does when it finds itself inside _tool, changes it, and the stub then does not call the function again.
| } else { | ||
| Ok(HeaderMap::new()) | ||
| } | ||
| } |
There was a problem hiding this comment.
Asset fetch omits GitHub API headers
Medium Severity
headers_for only treats github.com and raw.githubusercontent.com as GitHub, so a resource url on api.github.com (or GHE) is downloaded with no bearer token and no Accept: application/octet-stream. The artifact installer already uses is_github_api_url for those URLs; without it the response is metadata JSON, the signed digest does not match, and the whole install is aborted.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 476f317. Configure here.
There was a problem hiding this comment.
Fixed: headers_for treats api.github.com like the backend does, so an asset URL on the API host is fetched with the bearer token and the octet-stream media type.
6254d61 to
5bb4f90
Compare
22048ae to
76e38ab
Compare
76e38ab to
a533620
Compare
a533620 to
126dc89
Compare
7b54d2f to
b56ad8f
Compare
c173151 to
0be41a6
Compare
A packslip may list what a release ships besides its executables. For tools installed with the `packslip:` backend, `mise completion <shell> --tool <name>` prints the tool's completion script for whichever of its versions is active here, from the most verifiable source the vendor offered, in the order the specification gives: a file inside the artifact or a separate signed asset, a file from the source repository at the release's commit, a script derived from the tool's usage spec with the `usage` command, and only then a command of the tool's own. That last kind runs a freshly installed binary before the user has run it, so it is refused unless the new `packslip.exec` setting is on. Completions are global shell state while the active version depends on the directory, so `--install` writes a stub, not the script: it asks mise for the script when the shell first completes the tool, and needs no rewrite on a version switch. The stub goes where the shell loads completions by name, through usage's resolver, like mise's own. Files a vendor keeps outside the artifact are fetched at install time: a separate release asset must match the digest the packslip signed, and a repository file is pinned by the release's commit. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…e the install - The zsh and bash stubs let the vendor's script take over for one completion and then put themselves back (function and compdef binding in zsh, the `complete -F` registration in bash), so the next tab asks mise again and a version switch in another directory is followed. fish and PowerShell load the script once per session, which the docs now say. - An asset name must be a plain file name and a repository path a safe relative one before either is joined onto the install directory, both when fetching and when reading back, so a statement on disk cannot point mise outside the install. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
A vendor script may register with complete -C or -W rather than -F. The stub now only invokes a function when one is registered; otherwise it leaves the vendor's registration in place and returns 124, which makes bash retry the completion with it. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…g after a spec exec fails - Repository files are fetched through the contents API with the raw media type, so a token applies to a private repository and a missing file is an error, not a login page mistaken for a script. - A failing spec-generating command is one more skipped source, not the end of the search. - The PowerShell stub joins the script's lines itself instead of going through Out-String, which wraps long lines at the buffer width. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…eter When the vendor registers with complete -C, -W or -A, the stub hands that completion over by returning 124 and reinstalls itself from PROMPT_COMMAND at the next prompt (string or array form), so later completions ask mise again and a version switch is still followed. The PowerShell stub forces an array before joining, so a one-line script is not split into characters. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… now requires Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…y paths in URLs - A completion derived from a spec the tool generated names the spec file at completion time, so the spec now lives under the install's .mise-packslip/specs instead of a temp dir that is gone by then, and the bin and format names are checked before they form a file name. - Repository paths are percent-encoded per segment before they go into a URL, so a name with ? or # cannot rewrite the query or fragment and reach past the pinned commit. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Calling the vendor's function directly dropped the options its own complete call carried (-o nospace and the like). The stub now hands every completion to the vendor's registration by returning 124 and puts itself back at the next prompt, so options apply and version switches are still followed. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
A resource may carry os, arch, or libc when layouts differ by platform. Completion lookup keeps the entries that apply to the artifact this host installed, and the most specific of them, before the source order. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ers; --install takes a plain name Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…sh script runs in its own function; the spec for the completed executable wins Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…xe too; rustfmt Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
A declared completion file that is not in the install drops out of the source list, and an empty list was reported as "the packslip declares no completion" — which is the vendor's doing, not what happened. What happened is that the resource fetch failed or was skipped, and saying the other thing hides it. Ask the statement whether it offers this shell anything at all, and report the two cases apart. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
0be41a6 to
c098baf
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
There are 3 total unresolved issues (including 2 from previous reviews).
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit c098baf. Configure here.
| spec_entries.into_iter().filter(|r| describes(r)).collect() | ||
| } else { | ||
| spec_entries | ||
| }; |
There was a problem hiding this comment.
Multi-bin completions pick wrong source
Medium Severity
completion_sources selects among every completion and cli-spec together instead of isolating the executable being completed. Entries for other bins stay in play, and applicable can drop another executable's only entry when one bin is more specifically scoped. Completing a second binary can then load the first binary's script or spec.
Reviewed by Cursor Bugbot for commit c098baf. Configure here.
c098baf to
9c7f00a
Compare
9c7f00a to
c098baf
Compare
## Summary Stacked on #12779. A packslip may declare an agent skill: a directory holding `SKILL.md` and whatever it references, in the Agent Skills format. This PR fetches them and hands them to agents at the version a project pins. - **Fetched at install**, like completions: from inside the artifact, from a separate signed asset (verified against the statement, then unpacked), or from the source repository at the release's commit through the GitHub contents API. A skill offered only as a command of the tool's own is generated at install when `packslip.exec` is on. - **`mise skills ls`** lists the skills of the tools active in the current directory, with the version each belongs to and its path (`--json` for agents and scripts). - **`mise skills sync`** writes one symlink per skill into the project's `.claude/skills` (`--dir` for another agent's location, `--global` for `~/.claude/skills`), pointing at the installed version's directory. Since the project pins its tool versions, an agent working there sees the skill for exactly that version; running sync again after `mise use` moves the links. Only links mise made, which point into its installs directory, are ever replaced or, with `--prune`, removed. A real directory or a link of your own at a skill's name is left alone and reported, as is a name two tools both claim. ## Settings Four settings under `skills` shape what the commands do, all with `MISE_SKILLS_*` env forms: - **`skills.dir`** (`.claude/skills`): where `mise skills sync` links, relative to the project root, or to the home directory with `--global`; an absolute path is used as is. `--dir` still overrides it for one run. Set `.agents/skills` for agents that look there. - **`skills.auto_sync`** (off): after every `mise install` and `mise use`, link the active tools' skills into `skills.dir`, so the links never lag `mise.toml`. Nothing is written outside a project root, and a problem is reported without failing the install. - **`skills.prune`** (off): remove links mise made for skills that are no longer active, as the default for the command and for auto sync. - **`skills.fetch`** (on): turned off, tools install without their skills. ## Test plan - [x] clippy, fmt, hk; CLI docs and sidebar regenerated - [x] Unit tests: skill discovery per source (including a stripped top-level directory and an ungenerated exec skill), and sync semantics: link, unchanged, version switch, foreign directory and link left alone, duplicate name skipped, prune of a stale mise-made link, nothing created when there is nothing to link - [x] e2e: `mise skills ls` and `sync` on a tool whose packslip declares no skill 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > New symlink writes under project dirs and install-time fetching/exec of tool binaries; sync logic is careful about not touching user paths, but filesystem side effects and `packslip.exec` semantics changed for completions. > > **Overview** > Adds **`mise skills`** so packslip-installed tools can expose **Agent Skills** (`SKILL.md` directories) at the versions pinned in the project. > > **`mise skills ls`** lists skills for active tools (table or `--json`). **`mise skills sync`** symlinks them into `skills.dir` (default `.claude/skills`), with `--dir`, `--global`, and `--prune`. Sync only replaces or removes links mise recorded in `.mise-skills.json` that point into the installs tree; user dirs or foreign links are skipped. > > Skills are **fetched at install** (archive, signed asset + unpack, GitHub repo tree at release commit, or tool `exec` when `packslip.exec` is on). New **`skills.*`** settings control fetch, link target, auto-sync after `mise install` / `mise use`, and default pruning. > > **`packslip.exec` is narrowed**: it applies to install-time exec resources (e.g. generated skills), not shell completions. **Exec completions** run on first tab, cache under `.mise-packslip/completions/`, and no longer require `packslip.exec`. > > Docs, CLI usage/man output, schema, unit tests for discovery/sync, and packslip e2e for tools with no skills are updated. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 3ad64ce. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Added `mise skills` support for discovering agent skills provided by installed tools. - Use `mise skills ls` to view available skills, including JSON output. - Use `mise skills sync` to link skills into project or global agent directories, with custom directory and pruning options. - Skills can be fetched during installation and synchronized automatically after installs or tool changes. - **Documentation** - Added CLI, configuration, man-page, and packslip documentation for agent skills and related settings. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Instruction countsThe comparison never ran — an earlier step failed.
|


Summary
Stacked on #12778. A packslip may list what a release ships besides its executables. This PR reads its
completionandcli-specresources for tools installed with thepackslip:backend.mise completion <shell> --tool <name>prints the tool's completion script for whichever of its versions is active in the current directory.<name>is the tool or one of its executables. Sources are tried in the order the specification gives, most verifiable first: a file inside the artifact or a separate signed asset, a file from the source repository at the release's commit, a script derived from the tool's usage spec with theusagecommand, and only then a command of the tool's own.packslip.execsetting (default off). Anexecentry runs a freshly installed binary when the shell first asks for a completion, before the user has run the tool, so it is refused unless this is on; the error says what would have run and how to allow it.--installwrites a stub, not the script. Completions are global shell state while the active version depends on the directory, so the stub asks mise for the script at completion time and follows version switches without being rewritten. It goes where the shell loads completions by name, through usage's resolver, the same placemise completion zsh --installputs mise's own, and carries the marker that resolver looks for so re-installing replaces it. The zsh stub only calls the loaded function if the script actually redefined it, so an autoload-style vendor script cannot recurse into the stub.Test plan
mise completion zsh --tool packslipreports that the 0.2.0 packslip declares no completion; an unknown tool is refused🤖 Generated with Claude Code
Note
Medium Risk
New install-time network fetches and completion-time tool execution (when
packslip.execis enabled) touch shell integration and verified packslip data, though paths and digests are constrained and exec is opt-in.Overview
Adds
mise completion <shell> --tool <name>so packslip-installed tools can expose shell completions from their signed manifestresources(completion/cli-spec), using the active version in the current directory. Sources are tried in spec order (shipped files → signed assets → repo files at the release commit → usage-derived scripts → toolexeccommands).Introduces
packslip.exec(default off) because exec-based completions run a freshly installed binary at tab time.--installnow writes a version-aware stub (via usage’s installer) that calls mise at completion time instead of baking in one script; zsh/bash restore the stub after each completion so directory-based version switches stay correct.On install, the packslip backend fetches out-of-artifact resources into
.mise-packslip/(digest-checked assets, GitHub/GitLab repo files). Docs, schema, and e2e cover missing completions and unknown tools.Reviewed by Cursor Bugbot for commit 9c7f00a. Bugbot is set up for automated code reviews on this repo. Configure here.
Summary by CodeRabbit
New Features
--tool <TOOL>tomise completionto generate shell completions for installed tools.--installsupport for version-aware completion stubs that update automatically when tool versions change.[packslip] execconfiguration, disabled by default, for command-based completion generation.Documentation
Bug Fixes