Skip to content

feat: add native copilot command to shim copilot cli#12444

Merged
BagToad merged 6 commits intocli:trunkfrom
devm33:ghcopilot
Jan 19, 2026
Merged

feat: add native copilot command to shim copilot cli#12444
BagToad merged 6 commits intocli:trunkfrom
devm33:ghcopilot

Conversation

@devm33
Copy link
Contributor

@devm33 devm33 commented Jan 7, 2026

Fixes #12427

Introduces gh copilot as a core command.

Key behavior

  • gh copilot will prompt to install Copilot CLI when run for the first time.
  • gh copilot <args> will execute the Copilot CLI, forwarding any args and flags provided except those that gh supports.
  • Support the stop parse (--) character for bypassing flag conflicts between gh and Copilot CLI, e.g. gh copilot -- --help
  • Extensions that conflict with core commands are no longer registered. Previously, both extensions and core commands were registered in a non-deterministic race.
  • If gh copilot is run in GitHub Actions, install without confirmation prompt.

Copy link
Contributor

@andyfeller andyfeller left a comment

Choose a reason for hiding this comment

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

Congrats on joining the ranks of gh contribution, @devm33!

Not meant to be a full review but wanted to offer some feedback to help shape this 🙇

@devm33 devm33 marked this pull request as ready for review January 9, 2026 20:02
@devm33 devm33 requested a review from a team as a code owner January 9, 2026 20:02
@devm33 devm33 requested review from BagToad and Copilot January 9, 2026 20:02
@devm33 devm33 temporarily deployed to cli-automation January 9, 2026 20:02 — with GitHub Actions Inactive
@cliAutomation cliAutomation added the external pull request originating outside of the CLI core team label Jan 9, 2026
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR introduces a native gh copilot command that shims the Copilot CLI, addressing issues where the deprecated gh copilot extension no longer works and LLMs incorrectly suggest using gh copilot to invoke the Copilot CLI. The implementation automatically downloads and manages the copilot binary if it's not already in the user's PATH.

Key changes:

  • Adds a new native copilot command that checks for the copilot binary in PATH, then in gh's data directory, and downloads it if not found
  • Implements archive extraction for both tar.gz (Linux/macOS) and zip (Windows) formats with path traversal protection
  • Provides a --remove flag to uninstall the downloaded binary

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 15 comments.

File Description
pkg/cmd/root/root.go Registers the new copilot command in the root command structure
pkg/cmd/copilot/copilot.go Implements the copilot command with download, extraction, and execution logic
pkg/cmd/copilot/copilot_test.go Adds basic tests for command structure and removal functionality
Comments suppressed due to low confidence (2)

pkg/cmd/copilot/copilot.go:169

  • The function does not have a doc comment. Public or exported helper functions should include documentation describing their purpose, parameters, and return values.
func extractTarGz(r io.Reader, destDir string) error {

pkg/cmd/copilot/copilot.go:282

  • Using file mode directly from the zip archive could preserve dangerous permissions or special bits. Consider masking the mode to only preserve standard file permissions (e.g., mode & 0777) to prevent potential security issues.
		if err := extractZipFile(target, f.Mode(), rc); err != nil {

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

Copy link
Member

@babakks babakks left a comment

Choose a reason for hiding this comment

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

Thanks for the PR again, @devm33! 🙏

I haven't yet gone through the tests, but noticed some points that will improve the impl and help with future maintenance.

Regarding the comment on structuring the code to be like other gh commands, I can push a commit to fix that, but I won't do it now in case you have uncommitted/unpushed changes. Let me know please.

Comment on lines 303 to 313
func removeCopilotFromDir(io *iostreams.IOStreams, installDir string) error {
if _, err := os.Stat(installDir); os.IsNotExist(err) {
fmt.Fprintln(io.ErrOut, "Copilot CLI is not installed")
return nil
}
if err := os.RemoveAll(installDir); err != nil {
return fmt.Errorf("failed to remove Copilot CLI: %w", err)
}
fmt.Fprintln(io.ErrOut, "Copilot CLI removed successfully")
return nil
}
Copy link
Member

Choose a reason for hiding this comment

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

I think it's better to handle messaging on stdio at the command level. This way, we won't need to pass IOStreams down.

@babakks
Copy link
Member

babakks commented Jan 14, 2026

I just fixed conflicts between the branches and pushed. When the CI passes, I'll rebase the branch and rewrite the commits as there are lots of repeated/overlapping changes. After that, I'll push a few more to fix issues I've discovered while fixing the conflicts.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 7 out of 8 changed files in this pull request and generated 4 comments.


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

Copy link
Member

@babakks babakks left a comment

Choose a reason for hiding this comment

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

LGTM! 🙏 Just a few quick ones.

Copy link
Member

@BagToad BagToad left a comment

Choose a reason for hiding this comment

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

LGTM

Copy link
Contributor

@andyfeller andyfeller left a comment

Choose a reason for hiding this comment

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

This looks really good, @BagToad @babakks! Ship it!

Comment on lines +136 to +138
if opts.IO.IsStdoutTTY() {
fmt.Fprintln(opts.IO.ErrOut, "Copilot CLI removed successfully")
}
Copy link
Contributor

Choose a reason for hiding this comment

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

thought: I wonder if this conditional should be checking IsStderrTTY since the output is writing to stderr instead of stdout 🤔

This isn't blocking by any means but something I noticed here and in other places of the code base:

cli/pkg/cmd/label/list.go

Lines 98 to 100 in 559e729

if opts.IO.IsStdoutTTY() {
fmt.Fprintf(opts.IO.ErrOut, "Opening %s in your browser.\n", text.DisplayURL(labelListURL))
}

if io.IsStdoutTTY() {
fmt.Fprintf(io.ErrOut, "Opening %s in your browser.\n", text.DisplayURL(url))
}

cli/internal/ghcmd/cmd.go

Lines 132 to 134 in 559e729

if cmdFactory.IOStreams.IsStdoutTTY() {
fmt.Fprintln(stderr, noResultsError.Error())
}

Copy link
Member

Choose a reason for hiding this comment

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

I think it might be nice to unify some of these conditionals to something shared anyway 🤔

babakks and others added 2 commits January 19, 2026 10:38
…ackage

Signed-off-by: Babak K. Shandiz <babakks@github.com>

Co-authored-by: Kynan Ware <bagtoad@github.com>
Co-authored-by: Devraj Mehta <devm33@github.com>
Signed-off-by: Babak K. Shandiz <babakks@github.com>

Co-authored-by: Kynan Ware <bagtoad@github.com>
Co-authored-by: Devraj Mehta <devm33@github.com>
babakks and others added 2 commits January 19, 2026 10:38
Signed-off-by: Babak K. Shandiz <babakks@github.com>

Co-authored-by: Kynan Ware <bagtoad@github.com>
Co-authored-by: Devraj Mehta <devm33@github.com>
Signed-off-by: Babak K. Shandiz <babakks@github.com>

Co-authored-by: Kynan Ware <bagtoad@github.com>
Co-authored-by: Devraj Mehta <devm33@github.com>
Signed-off-by: Babak K. Shandiz <babakks@github.com>
@BagToad BagToad enabled auto-merge January 19, 2026 18:05
@babakks
Copy link
Member

babakks commented Jan 19, 2026

@BagToad and I verified the changes work on Windows. For that to work we had to fix the download URL.

Replaces runtime.GOOS with 'win32' in the test archive filename within TestDownloadCopilot. This ensures the test uses the expected archive name for Windows.
@BagToad BagToad merged commit 2728635 into cli:trunk Jan 19, 2026
11 checks passed
tmeijn pushed a commit to tmeijn/dotfiles that referenced this pull request Jan 22, 2026
This MR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [cli/cli](https://github.com/cli/cli) | minor | `v2.85.0` → `v2.86.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.86.0`](https://github.com/cli/cli/releases/tag/v2.86.0): GitHub CLI 2.86.0

[Compare Source](cli/cli@v2.85.0...v2.86.0)

#### :copilot:  Install and run GitHub Copilot CLI directly from `gh`

Since we deprecated the [GitHub Copilot in the CLI](https://github.blog/changelog/2025-09-25-upcoming-deprecation-of-gh-copilot-cli-extension/) extension in favor of the new agentic [GitHub Copilot CLI](https://github.com/github/copilot-cli), we want to give developers using `gh` a simple way to get started using our most powerful terminal assistant.

- `gh copilot` will prompt to install, then run Copilot CLI
- `gh copilot <args>` will execute the Copilot CLI, forwarding any arguments and flags

For more information and usage options, run `gh copilot --help`.

#### What's Changed

##### ✨ Features

- `gh copilot`: add native `copilot` command to execute/install copilot cli by [@&#8203;devm33](https://github.com/devm33) in [#&#8203;12444](cli/cli#12444)
- `gh cache delete`: allow for delete all caches for a ref by [@&#8203;davidspek](https://github.com/davidspek) in [#&#8203;12101](cli/cli#12101)
- `gh pr create`: error when head and base refs are identical in pr create by [@&#8203;majiayu000](https://github.com/majiayu000) in [#&#8203;12376](cli/cli#12376)

##### 📚 Docs & Chores

- Fix Windows asset URL in `copilot` command tests by [@&#8203;babakks](https://github.com/babakks) in [#&#8203;12500](cli/cli#12500)
- Update contributing guidelines for clarity by [@&#8203;BagToad](https://github.com/BagToad) in [#&#8203;12505](cli/cli#12505)

#### New Contributors

- [@&#8203;devm33](https://github.com/devm33) made their first contribution in [#&#8203;12444](cli/cli#12444)
- [@&#8203;davidspek](https://github.com/davidspek) made their first contribution in [#&#8203;12101](cli/cli#12101)

**Full Changelog**: <cli/cli@v2.85.0...v2.86.0>

</details>

---

### Configuration

📅 **Schedule**: 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 [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0Mi44Ni4xIiwidXBkYXRlZEluVmVyIjoiNDIuODYuMSIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiUmVub3ZhdGUgQm90IiwiYXV0b21hdGlvbjpib3QtYXV0aG9yZWQiLCJkZXBlbmRlbmN5LXR5cGU6Om1pbm9yIl19-->
@azan453

This comment was marked as spam.

@minthuraaung24245-hash

This comment was marked as spam.

@minthuraaung24245-hash

This comment was marked as spam.

asd585140-glitch

This comment was marked as spam.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

external pull request originating outside of the CLI core team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

gh copilot should shim the copilot CLI

9 participants