func listRun(opts *ListOptions) error {
	httpClient, err := opts.HttpClient()
	if err != nil {
		return err
	}

	baseRepo, err := opts.BaseRepo()
	if err != nil {
		return err
	}

	issueState := strings.ToLower(opts.State)
	if issueState == "open" && prShared.QueryHasStateClause(opts.Search) {
		issueState = ""
	}

	if opts.Detector == nil {
		cachedClient := api.NewCachedHTTPClient(httpClient, time.Hour*12)
		opts.Detector = fd.NewDetector(cachedClient, baseRepo.RepoHost())
	}
	features, err := opts.Detector.IssueFeatures()
	if err != nil {
		return err
	}
	fields := defaultFields
	if features.StateReason {
		fields = append(defaultFields, "stateReason")
	}

	filterOptions := prShared.FilterOptions{
		Entity:    "issue",
		State:     issueState,
		Assignee:  opts.Assignee,
		Labels:    opts.Labels,
		Author:    opts.Author,
		Mention:   opts.Mention,
		Milestone: opts.Milestone,
		Search:    opts.Search,
		Fields:    fields,
	}

	isTerminal := opts.IO.IsStdoutTTY()

	if opts.WebMode {
		issueListURL := ghrepo.GenerateRepoURL(baseRepo, "issues")
		openURL, err := prShared.ListURLWithQuery(issueListURL, filterOptions)
		if err != nil {
			return err
		}

		if isTerminal {
			fmt.Fprintf(opts.IO.ErrOut, "Opening %s in your browser.\n", text.DisplayURL(openURL))
		}
		return opts.Browser.Browse(openURL)
	}

	if opts.Exporter != nil {
		filterOptions.Fields = opts.Exporter.Fields()
	}

	listResult, err := issueList(httpClient, baseRepo, filterOptions, opts.LimitResults)
	if err != nil {
		return err
	}
	if len(listResult.Issues) == 0 && opts.Exporter == nil {
		return prShared.ListNoResults(ghrepo.FullName(baseRepo), "issue", !filterOptions.IsDefault())
	}

	if err := opts.IO.StartPager(); err == nil {
		defer opts.IO.StopPager()
	} else {
		fmt.Fprintf(opts.IO.ErrOut, "failed to start pager: %v\n", err)
	}

	if opts.Exporter != nil {
		return opts.Exporter.Write(opts.IO, listResult.Issues)
	}

	if listResult.SearchCapped {
		fmt.Fprintln(opts.IO.ErrOut, "warning: this query uses the Search API which is capped at 1000 results maximum")
	}
	if isTerminal {
		title := prShared.ListHeader(ghrepo.FullName(baseRepo), "issue", len(listResult.Issues), listResult.TotalCount, !filterOptions.IsDefault())
		fmt.Fprintf(opts.IO.Out, "\n%s\n\n", title)
	}

	issueShared.PrintIssues(opts.IO, opts.Now(), "", len(listResult.Issues), listResult.Issues)

	return nil
}