List GitHub repositories with gh repo list
You will use GitHub CLI's gh repo list to inspect repositories owned by your account or an organisation, then narrow the result by fork status, archive state, language, topic or visibility. You will also produce machine-readable JSON without accidentally limiting a large organisation to the first 30 repositories. Allow about ten minutes. You need the gh package, a working GitHub CLI authentication session, and permission to see the repositories you want to list.
The route
Jump straight to the step you need, or tick off Done means at the end.
1. Confirm the installed command
This guide was checked with GitHub CLI 2.87.3, installed on 23 September 2026. The local manual describes gh repo list [<owner>] [flags]; gh repo ls is an alias shown by the command help. Check your own binary before relying on an option in a script because package versions can differ.
$ gh --version
gh version 2.87.3 (2026-02-23)
$ gh repo list --help
Checkpoint: the version is printed and the help lists the flags you plan to use. If gh is missing, install GitHub CLI through your normal package-management process. Do not add sudo to the listing command merely because a repository is private.
2. List repositories for the current account
With no owner argument, gh repo list lists repositories owned by the authenticated user. The default maximum is 30, so this is a preview rather than necessarily a complete inventory.
$ gh repo list --limit 10
NAME DESCRIPTION VISIBILITY UPDATED
example/project Example project public about 2 hours ago
example/internal-tool Internal tooling private about 1 day ago
The columns and relative time depend on the installed version and the repositories returned. Treat the names above as illustrative output, not values to copy. To inspect a particular organisation or user, put its exact login in the owner position:
$ gh repo list EXAMPLE_ORG --limit 100
The owner boundary matters. The command lists repositories owned by the supplied argument. It does not search member accounts for repositories that happen to be forks of organisation repositories.
3. Choose the repository set explicitly
Use --limit when completeness matters. It accepts an integer and defaults to 30. A value such as 1000 is a request for up to that many repositories, not a guarantee that the account contains that number or that your permissions expose all of them.
$ gh repo list EXAMPLE_ORG --limit 1000 --no-archived
--no-archived omits archived repositories. If you need only archived repositories, use --archived instead. The fork filters are similarly explicit: --fork keeps only forks, while --source keeps only non-forks.
$ gh repo list EXAMPLE_ORG --limit 100 --source --no-archived
$ gh repo list EXAMPLE_ORG --limit 100 --fork --archived
You can add --language Python, --topic security or --visibility private. Visibility accepts public, private or internal. These filters describe the repositories' metadata; they do not change a repository, its topics or its archive state.
4. Request stable fields for scripts
Human-oriented columns are convenient at a terminal but are a poor interface for automation. Ask for named JSON fields instead. The installed command lists fields such as nameWithOwner, description, isArchived, isFork, primaryLanguage, updatedAt, url and visibility.
$ gh repo list EXAMPLE_ORG --limit 100 --no-archived \
--json nameWithOwner,visibility,isFork,updatedAt
[
{
"isFork": false,
"nameWithOwner": "EXAMPLE_ORG/project",
"updatedAt": "2026-09-22T14:30:00Z",
"visibility": "PUBLIC"
}
]
JSON output is suitable for saving to a new file, but avoid overwriting an existing inventory until the command succeeds and the content has been checked:
$ gh repo list EXAMPLE_ORG --limit 1000 --json nameWithOwner,visibility \
> repositories.json.new
$ jq 'length' repositories.json.new
1
$ mv repositories.json.new repositories.json
The final mv replaces the old inventory. If the command fails, remove repositories.json.new and the original file is still available. Do not run rm repositories.json as part of recovery: that deletion is unnecessary and irreversible.
5. Select a small result with jq
The --jq flag applies a jq expression to JSON output. For a simple report containing one repository per line, request the field and select it:
$ gh repo list EXAMPLE_ORG --limit 1000 \
--json nameWithOwner,visibility \
--jq '.[] | [.nameWithOwner, .visibility] | @tsv'
EXAMPLE_ORG/project PUBLIC
The expression is evaluated by gh; a separate jq process is not needed for this example. If you need more elaborate shaping, keep the raw JSON in a temporary file and validate it before handing it to another program. A typo in a field name or jq expression should stop the pipeline rather than silently produce a misleading report.
6. Diagnose empty or incomplete results
First check the owner spelling and the limit. Then compare a human listing with a JSON listing using the same filters. An empty result can be correct when the visibility, topic, language or fork state does not match. An organisation listing also cannot cross the ownership boundary described by the manual.
$ gh repo list EXAMPLE_ORG --limit 5 --json nameWithOwner
$ gh repo list EXAMPLE_ORG --limit 5 --visibility private --json nameWithOwner
If the command reports an authentication or permission error, fix the GitHub CLI session and access rights before changing filters. Do not put a token in the command line, shell history or an output file. Repository descriptions can contain arbitrary text, so quote values when passing them to another shell command and prefer JSON parsing over whitespace splitting.
Done means
- You confirmed the installed
ghversion and read the matching help. - You supplied an owner and an explicit limit when a complete inventory mattered.
- You chose archive and fork filters deliberately instead of assuming their defaults.
- You used
--jsonand, where useful,--jqfor automation. - You staged a replacement inventory through a new file and kept the previous file recoverable until verification.