Skip to content

feat(skills): list available skills when install runs non-interactively#13548

Merged
BagToad merged 1 commit into
trunkfrom
sammorrowdrums/skill-install-nontty-listing
Jun 17, 2026
Merged

feat(skills): list available skills when install runs non-interactively#13548
BagToad merged 1 commit into
trunkfrom
sammorrowdrums/skill-install-nontty-listing

Conversation

@SamMorrowDrums

Copy link
Copy Markdown
Contributor

Summary

Running gh skill install <repo> (or --from-local <dir>) without a skill name in a non-interactive context previously errored with must specify a skill name when not running interactively. That made discovery awkward when piping or scripting — users had to switch to an interactive shell just to see what skills a repo offered.

This PR changes that behavior so the discovered skills are printed instead, mirroring (approximately) what the interactive picker shows. The list is rendered through tableprinter, so it auto-switches between a friendly TTY table and tab-separated SKILL\tDESCRIPTION rows when piped — making it easy to grep / fzf / awk.

Before

$ gh skill install github/awesome-copilot | grep review
must specify a skill name when not running interactively

After

$ gh skill install github/awesome-copilot | grep review
code-review     Reviews pull requests

Re-running with a specific skill name installs as before. Same behavior for --from-local.

Context

Came out of a Slack thread where this was identified as a UX gap: interactive mode supports browsing-then-installing, and non-interactive mode should provide the same discoverability so it composes with standard Unix tooling.

Changes

  • selectSkillsWithSelector now prints discovered skills via a new listAvailableSkills helper instead of erroring when !canPrompt.
  • Sentinel errSkillsListed lets installRun / runLocalInstall bail cleanly without going into the install path.
  • Descriptions are pre-fetched (same fetchDescriptions callback the picker uses) so the listed output is useful, not bare.
  • Help text + an example for piping into grep updated.
  • Tests: replaced the old "errors" case with a remote listing assertion and added an equivalent local install case.

Verification

  • go test ./pkg/cmd/skills/...
  • make lint

Copilot AI review requested due to automatic review settings May 29, 2026 16:28
@SamMorrowDrums
SamMorrowDrums requested review from a team as code owners May 29, 2026 16:28
@SamMorrowDrums
SamMorrowDrums requested a review from BagToad May 29, 2026 16:28

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Changes gh skill install <repo> behavior so that running it non-interactively without a skill name now lists the discovered skills (via tableprinter, falling back to tab-separated output when piped) instead of erroring out. This improves discoverability and composes with Unix tools.

Changes:

  • Replace the non-interactive "must specify a skill name" error with a new listAvailableSkills helper that prints skills using tableprinter; a sentinel errSkillsListed lets installRun/runLocalInstall exit cleanly.
  • Update long help text and add a piping example to reflect the new behavior.
  • Replace the old "errors" test with a remote listing assertion and add an equivalent local-install listing test.
Show a summary per file
File Description
pkg/cmd/skills/install/install.go Adds listAvailableSkills + errSkillsListed sentinel, swaps the non-interactive error path for listing, updates help text/example.
pkg/cmd/skills/install/install_test.go Updates non-interactive remote test to verify listed output and adds an analogous local-install listing test.

Copilot's findings

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 2/2 changed files
  • Comments generated: 0

Previously, running 'gh skill install <repo>' without a skill name in a
non-interactive context returned an error. This made discovery awkward
when piping or scripting: callers had to first run the command
interactively to see what skills were available.

Now, when no skill name is given and stdin/stdout is not a TTY, the
discovered skills are printed as tab-separated 'SKILL\tDESCRIPTION' rows
to stdout (matching the interactive picker contents) so they can be
piped into grep, awk, fzf, etc. Re-running with a specific skill name
performs the install as before. The same behavior applies to
--from-local installs.

Co-authored-by: Copilot <[email protected]>
@BagToad
BagToad force-pushed the sammorrowdrums/skill-install-nontty-listing branch from aa28bca to 5af799f Compare June 17, 2026 19:14
Comment on lines +773 to +776
if opts.IO.IsStdoutTTY() {
fmt.Fprintf(opts.IO.ErrOut, "Showing %s from %s. Re-run with a skill name to install.\n\n",
text.Pluralize(len(skills), "skill"), sel.sourceHint)
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤔 I don't think this could ever fire in practice because we check if we can prompt before calling listAvailableSkills

Comment on lines 713 to 718
if !canPrompt {
return nil, cmdutil.FlagErrorf("must specify a skill name when not running interactively")
if err := listAvailableSkills(opts, skills, sel); err != nil {
return nil, err
}
return nil, errSkillsListed
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I were being nit-picky, I'd say this decision should be one level higher up the stack - that's not really something we're causing here, but we are deepening it by making a longer branch in the noninteractive case. I think the noninteractive branch is different enough that it would be more natural to see it diverge before entering a function whose name suggests that we're selecting stuff. It also would eliminate the need for a sentinel error; we'd just do a print and early return without falling into this function instead.

@BagToad BagToad left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, nothing blocking.

If we could clean some of my comments up in a follow up eventually, I think that'd help tear down a bit of tech debt for editing these flows in the future 🙌

@BagToad
BagToad merged commit 70bb306 into trunk Jun 17, 2026
11 checks passed
@BagToad
BagToad deleted the sammorrowdrums/skill-install-nontty-listing branch June 17, 2026 19:28
@kittiyuththkakkx40-afk

This comment has been minimized.

tmeijn pushed a commit to tmeijn/dotfiles that referenced this pull request Jul 9, 2026
This MR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [cli/cli](https://github.com/cli/cli) | minor | `v2.94.0` → `v2.96.0` |

MR created with the help of [el-capitano/tools/renovate-bot](https://gitlab.com/el-capitano/tools/renovate-bot).

**Proposed changes to behavior should be submitted there as MRs.**

---

### Release Notes

<details>
<summary>cli/cli (cli/cli)</summary>

### [`v2.96.0`](https://github.com/cli/cli/releases/tag/v2.96.0): GitHub CLI 2.96.0

[Compare Source](cli/cli@v2.95.0...v2.96.0)

#### Security

A security vulnerability has been identified, and fixed, that could allow command execution on a user's computer when connecting to a malicious Codespace via `gh codespace jupyter`.

Users of `gh codespace jupyter` are advised to update gh to version v2.96.0 as soon as possible.

For more information see: <GHSA-8cg3-r6g9-fpg2>

#### Download release assets without authentication

`gh release download` now works against public repositories without authentication, matching `gh extension install`. A token is still used when one is present:

```shell

# Download assets from a public repository, no login required
gh release download v2.96.0 --repo cli/cli
```

#### What's Changed

##### ✨ Features

- Allow `gh release download` without authentication on public repositories by [@&#8203;BagToad](https://github.com/BagToad) in [#&#8203;13723](cli/cli#13723)
- Detect additional third-party coding agents by [@&#8203;BagToad](https://github.com/BagToad) in [#&#8203;13722](cli/cli#13722)
- Support `antigravity-cli` and `antigravity2.0` in `gh skill` by [@&#8203;BagToad](https://github.com/BagToad) in [#&#8203;13784](cli/cli#13784)

##### 🐛 Fixes

- fix: show checks summary when all checks were cancelled by [@&#8203;s3onghyun](https://github.com/s3onghyun) in [#&#8203;13679](cli/cli#13679)
- fix(skills): install universal agent to `~/.agents/skills` by [@&#8203;toller892](https://github.com/toller892) in [#&#8203;13681](cli/cli#13681)
- fix(skills): honor `--dir` without agent prompt by [@&#8203;happysnaker](https://github.com/happysnaker) in [#&#8203;13766](cli/cli#13766)
- Fix concurrent map writes in codespace port forwarding by [@&#8203;williammartin](https://github.com/williammartin) in [#&#8203;13313](cli/cli#13313)
- Use `int64` for GitHub database IDs by [@&#8203;williammartin](https://github.com/williammartin) in [#&#8203;13403](cli/cli#13403)

##### 📚 Docs & Chores

- Pin reusable triage workflows to a commit SHA by [@&#8203;BagToad](https://github.com/BagToad) in [#&#8203;13705](cli/cli#13705)
- Add security disclosure guidance to `AGENTS.md` by [@&#8203;BagToad](https://github.com/BagToad) in [#&#8203;13720](cli/cli#13720)
- Clarify `--clone` boolean flag behaviour in `gh repo fork` help by [@&#8203;BagToad](https://github.com/BagToad) in [#&#8203;13786](cli/cli#13786)
- Fix flaky `TestHuhPrompterMultiSelectWithSearchPersistence` on slow architectures by [@&#8203;pdostal](https://github.com/pdostal) in [#&#8203;13675](cli/cli#13675)
- docs(search): add examples for multiple qualifiers by [@&#8203;happysnaker](https://github.com/happysnaker) in [#&#8203;13756](cli/cli#13756)
- docs: fix broken anchor link in release-process-deep-dive by [@&#8203;patrickwehbe](https://github.com/patrickwehbe) in [#&#8203;13688](cli/cli#13688)
- docs: fix broken install command and link/grammar errors by [@&#8203;patrickwehbe](https://github.com/patrickwehbe) in [#&#8203;13690](cli/cli#13690)
- docs: fix duplicated word in primer README by [@&#8203;s3onghyun](https://github.com/s3onghyun) in [#&#8203;13677](cli/cli#13677)

##### :dependabot: Dependencies

- chore(deps): bump github.com/microsoft/dev-tunnels from 0.1.19 to 0.1.27 by [@&#8203;dependabot](https://github.com/dependabot) in [#&#8203;13708](cli/cli#13708)
- chore(deps): bump actions/checkout from 6.0.3 to 7.0.0 by [@&#8203;dependabot](https://github.com/dependabot) in [#&#8203;13703](cli/cli#13703)
- chore(deps): bump github.com/google/go-containerregistry from 0.21.6 to 0.21.7 by [@&#8203;dependabot](https://github.com/dependabot) in [#&#8203;13702](cli/cli#13702)
- chore(deps): bump actions/setup-go from 6.4.0 to 6.5.0 by [@&#8203;dependabot](https://github.com/dependabot) in [#&#8203;13740](cli/cli#13740)
- chore(deps): bump actions/attest from 4.1.0 to 4.1.1 by [@&#8203;dependabot](https://github.com/dependabot) in [#&#8203;13754](cli/cli#13754)
- chore(deps): bump goreleaser/goreleaser-action from 7.2.2 to 7.2.3 by [@&#8203;dependabot](https://github.com/dependabot) in [#&#8203;13759](cli/cli#13759)
- chore(deps): bump golangci/golangci-lint-action from 9.2.1 to 9.3.0 by [@&#8203;dependabot](https://github.com/dependabot) in [#&#8203;13779](cli/cli#13779)

#### New Contributors

- [@&#8203;patrickwehbe](https://github.com/patrickwehbe) made their first contribution in [#&#8203;13688](cli/cli#13688)
- [@&#8203;s3onghyun](https://github.com/s3onghyun) made their first contribution in [#&#8203;13679](cli/cli#13679)
- [@&#8203;toller892](https://github.com/toller892) made their first contribution in [#&#8203;13681](cli/cli#13681)
- [@&#8203;happysnaker](https://github.com/happysnaker) made their first contribution in [#&#8203;13756](cli/cli#13756)

**Full Changelog**: <cli/cli@v2.95.0...v2.96.0>

### [`v2.95.0`](https://github.com/cli/cli/releases/tag/v2.95.0): GitHub CLI 2.95.0

[Compare Source](cli/cli@v2.94.0...v2.95.0)

#### Read repository files and directories with `gh repo read-file` and `gh repo read-dir`

Two new preview commands read repository contents without cloning:

```shell

# Read a single file to stdout
gh repo read-file README.md --repo cli/cli

# Read from a specific branch, tag, or commit
gh repo read-file go.mod --ref v2.94.0 --repo cli/cli

# Write a file to disk (use --clobber to overwrite)
gh repo read-file README.md --output ./README.md --repo cli/cli

# List the entries in a directory
gh repo read-dir script --repo cli/cli
```

Both commands default to the repository's default branch, accept `--ref` to target any branch, tag, or commit, and support `--json`, `--jq`, and `--template` for scripting. This makes it easy for agents and automation to inspect a repo without a full checkout.

> \[!NOTE]
> `gh repo read-file` and `gh repo read-dir` are in preview and subject to change without notice.

#### What's Changed

##### ✨ Features

- feat: add `repo read-file` and `repo read-dir` by [@&#8203;babakks](https://github.com/babakks) in [#&#8203;13580](cli/cli#13580)
- feat(skills): list available skills when install runs non-interactively by [@&#8203;SamMorrowDrums](https://github.com/SamMorrowDrums) in [#&#8203;13548](cli/cli#13548)
- Support custom CLAUDE\_CONFIG\_DIR in install by [@&#8203;tommaso-moro](https://github.com/tommaso-moro) in [#&#8203;13523](cli/cli#13523)

##### 🐛 Fixes

- fix(skills): stage updates in a temp dir and swap in-place by [@&#8203;SamMorrowDrums](https://github.com/SamMorrowDrums) in [#&#8203;13449](cli/cli#13449)

##### 📚 Docs & Chores

- Make filtering by bot authors more discoverable by [@&#8203;BagToad](https://github.com/BagToad) in [#&#8203;13642](cli/cli#13642)
- docs(discussion): polish help docs by [@&#8203;babakks](https://github.com/babakks) in [#&#8203;13632](cli/cli#13632)
- Bump Go in devcontainer by [@&#8203;spenserblack](https://github.com/spenserblack) in [#&#8203;13674](cli/cli#13674)

##### :dependabot: Dependencies

- chore(deps): bump golang.org/x/text from 0.37.0 to 0.38.0 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;13640](cli/cli#13640)
- chore(deps): bump charm.land/lipgloss/v2 from 2.0.3 to 2.0.4 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;13663](cli/cli#13663)
- chore(deps): bump golang.org/x/term from 0.43.0 to 0.44.0 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;13661](cli/cli#13661)
- chore(deps): bump github/codeql-action from 4.36.1 to 4.36.2 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;13619](cli/cli#13619)
- chore(deps): bump github.com/sigstore/sigstore-go from 1.1.4 to 1.2.1 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;13662](cli/cli#13662)
- chore(deps): bump golang.org/x/crypto from 0.52.0 to 0.53.0 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;13641](cli/cli#13641)

**Full Changelog**: <cli/cli@v2.94.0...v2.95.0>

</details>

---

### Configuration

📅 **Schedule**: (UTC)

- Branch creation
  - At any time (no schedule defined)
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever MR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this MR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this MR, check this box

---

This MR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yMjcuMSIsInVwZGF0ZWRJblZlciI6IjQzLjIzMi4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJSZW5vdmF0ZSBCb3QiLCJhdXRvbWF0aW9uOmJvdC1hdXRob3JlZCIsImRlcGVuZGVuY3ktdHlwZTo6bWlub3IiXX0=-->
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.

4 participants