Skip to content

feat: add repo read-file and repo read-dir#13580

Merged
BagToad merged 22 commits into
trunkfrom
babakks/feature-repo-read
Jun 17, 2026
Merged

feat: add repo read-file and repo read-dir#13580
BagToad merged 22 commits into
trunkfrom
babakks/feature-repo-read

Conversation

@babakks

@babakks babakks commented Jun 3, 2026

Copy link
Copy Markdown
Member

Summary

This PR adds two new (preview) commands for reading repository contents without cloning.

gh repo read-file

gh repo read-file <path> [--ref <ref>] [--output <path>] [--clobber] [--unsafe] [--json <fields>] [--jq <expression>] [--template <string>] [--repo <owner/repo>]

Reads a single file from a repository and writes it to stdout (or to a file with --output).

gh repo read-dir

gh repo read-dir [<path>] [--ref <ref>] [--json <fields>] [--jq <expression>] [--template <string>] [--repo <owner/repo>]

Lists the entries of a directory in a repository, showing each entry's type, name, and size.

Both commands are marked preview, default to the current repository's default branch (overridable with --ref), and support --json/--jq/--template for scripting.

Test plan

You can verify the command behaviour via acceptance tests and the following examples.

The commands below target public repositories so they can be run as-is.

gh repo read-file

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

# Read from a specific tag/branch/commit
gh repo read-file README.md --ref v2.0.0 --repo cli/cli

# Write to a file, then confirm --clobber is required to overwrite
gh repo read-file README.md --output /tmp/readme.md --repo cli/cli
gh repo read-file README.md --output /tmp/readme.md --repo cli/cli            # should error: already exists
gh repo read-file README.md --output /tmp/readme.md --clobber --repo cli/cli  # should succeed

# JSON output, with jq and template
gh repo read-file README.md --json path,size,type --repo cli/cli
gh repo read-file README.md --json path,size --jq '.size' --repo cli/cli
gh repo read-file README.md --template '{{.path}} ({{.size}} bytes){{"\n"}}' --repo cli/cli

# Error: path does not exist
gh repo read-file does/not/exist.md --repo cli/cli

gh repo read-dir

# List the repository root
gh repo read-dir --repo cli/cli

# List a subdirectory (note executables render as `file*`)
gh repo read-dir script --repo cli/cli

# Mixed entry types in one listing: regular files, a symlink (RelNotes),
# and a submodule (sha1collisiondetection)
gh repo read-dir --repo git/git

# List from a specific tag/branch/commit
gh repo read-dir docs --ref v2.0.0 --repo cli/cli

# Non-TTY / scriptable output (tab separated)
gh repo read-dir script --repo cli/cli | cat

# JSON output, with jq and template
gh repo read-dir script --json name,type,mode,modeOctal --repo cli/cli
gh repo read-dir script --json name,type --jq '.entries[] | select(.type=="file") | .name' --repo cli/cli
gh repo read-dir --template '{{range .entries}}{{.type}}: {{.name}}{{"\n"}}{{end}}' --repo cli/cli

# Error: path points to a file, not a directory
gh repo read-dir README.md --repo cli/cli

# Error: path or ref does not exist
gh repo read-dir nope/nope --repo cli/cli

@babakks
babakks marked this pull request as ready for review June 3, 2026 22:29
@babakks
babakks requested a review from a team as a code owner June 3, 2026 22:29
@babakks
babakks requested review from BagToad and Copilot June 3, 2026 22:29

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

This PR introduces two new preview gh repo subcommands—read-file and read-dir—to fetch repository file and directory contents over the GitHub API without cloning, with support for scriptable output (--json/--jq/--template) and acceptance coverage.

Changes:

  • Add gh repo read-file for fetching a single file’s metadata/content and optionally writing it to disk.
  • Add gh repo read-dir for listing a repository directory (TTY table / non-TTY TSV / JSON).
  • Add a shared internal/text.FormatSize helper and acceptance fixtures for both commands.
Show a summary per file
File Description
pkg/cmd/repo/repo.go Registers the new read-file/read-dir commands under gh repo.
pkg/cmd/repo/read-file/read_file.go Implements command parsing and output modes for reading a single file.
pkg/cmd/repo/read-file/http.go Adds REST Contents API fetching and decoding logic for read-file.
pkg/cmd/repo/read-file/read_file_test.go Unit tests for read-file behaviors (TTY/non-TTY, JSON, output writing, etc.).
pkg/cmd/repo/read-dir/read_dir.go Implements command parsing and output modes for listing a directory.
pkg/cmd/repo/read-dir/http.go Adds GraphQL-backed directory listing and entry modeling for read-dir.
pkg/cmd/repo/read-dir/read_dir_test.go Unit tests for read-dir behaviors (TTY/non-TTY, JSON, errors, etc.).
internal/text/text.go Adds FormatSize helper for human-friendly byte formatting.
internal/text/text_test.go Adds tests for FormatSize.
acceptance/testdata/repo/repo-read-file.txtar Adds acceptance coverage for repo read-file.
acceptance/testdata/repo/repo-read-dir.txtar Adds acceptance coverage for repo read-dir.

Copilot's findings

Tip

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

  • Files reviewed: 11/11 changed files
  • Comments generated: 10

Comment thread pkg/cmd/repo/read-file/read_file.go Outdated
Comment thread pkg/cmd/repo/read-file/read_file.go
Comment thread pkg/cmd/repo/read-file/read_file.go
Comment thread pkg/cmd/repo/read-file/http.go
Comment thread pkg/cmd/repo/read-file/read_file.go Outdated
Comment thread pkg/cmd/repo/read-dir/http.go
Comment thread pkg/cmd/repo/read-dir/http.go
Comment thread internal/text/text.go Outdated
Comment thread internal/text/text.go Outdated
Comment thread internal/text/text_test.go
@babakks

babakks commented Jun 16, 2026

Copy link
Copy Markdown
Member Author

I just pushed a commit to add the new commands in gh's skill file.

{1572864, "1.5 MB"},
{5242880, "5.0 MB"},
{1073741824, "1.0 GB"},
{1610612736, "1.5 GB"},

This comment was marked as spam.

Avoids an out-of-range panic for byte counts at or above one exabyte, which
fit within int64, and lets the function accept the full int64 range.

Co-authored-by: Copilot <[email protected]>

@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.

Looks pretty good! 🔥 🚀

Comment thread pkg/cmd/repo/read-file/read_file.go
Comment thread skills/gh/SKILL.md Outdated
Comment thread pkg/cmd/repo/read-file/read_file.go Outdated
Comment thread pkg/cmd/repo/read-file/read_file.go
Comment thread pkg/cmd/repo/read-file/read_file.go
@BagToad
BagToad merged commit 733e35c into trunk Jun 17, 2026
11 checks passed
@BagToad
BagToad deleted the babakks/feature-repo-read branch June 17, 2026 16:59

@26060092 26060092 left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

babakks/feature-repo-read

2038.html

type repoFile struct {
Name string
Path string
SHA string

This comment was marked as spam.

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.

5 participants