Full Code of dlvhdr/gh-dash for AI

main 129bf09618cb cached
294 files
3.9 MB
1.0M tokens
1381 symbols
1 requests
Download .txt
Showing preview only (4,171K chars total). Download the full file or copy to clipboard to get everything.
Repository: dlvhdr/gh-dash
Branch: main
Commit: 129bf09618cb
Files: 294
Total size: 3.9 MB

Directory structure:
gitextract_yckel_xs/

├── .envrc
├── .gh-dash.yml
├── .github/
│   ├── FUNDING.yml
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.md
│   │   └── feature_request.md
│   ├── pull_request_template.md
│   └── workflows/
│       ├── build-and-test.yaml
│       ├── build-docs.yaml
│       ├── dependabot-sync.yml
│       ├── go-release.yml
│       ├── lint.yml
│       └── publish-docs.yaml
├── .gitignore
├── .golangci.yml
├── .goreleaser.yaml
├── AI_POLICY.md
├── CONTRIBUTING.md
├── LICENSE.txt
├── README.md
├── Taskfile.yaml
├── cmd/
│   ├── root.go
│   └── sponsors.go
├── devbox.json
├── docs/
│   ├── .dockerignore
│   ├── .envrc
│   ├── .eslint.config.js
│   ├── .gitignore
│   ├── .prettierrc.mjs
│   ├── Dockerfile
│   ├── README.mdx
│   ├── astro.config.mjs
│   ├── devbox.json
│   ├── package.json
│   ├── public/
│   │   ├── custom-commands.webm
│   │   ├── enhance-demo.webm
│   │   ├── overview.webm
│   │   ├── rerun.webm
│   │   ├── sections.webm
│   │   └── watch.webm
│   ├── src/
│   │   ├── assets/
│   │   │   ├── custom-commands.tape
│   │   │   ├── custom-commands.yml
│   │   │   ├── demo.yml
│   │   │   ├── overview.tape
│   │   │   ├── sections.tape
│   │   │   ├── sections.yml
│   │   │   ├── theme-catpuccin.yml
│   │   │   ├── theme-gruvbox.yml
│   │   │   └── theme-tokyonight.yml
│   │   ├── components/
│   │   │   ├── Box.astro
│   │   │   ├── DashHeroLogo.astro
│   │   │   ├── DecorationBottom.astro
│   │   │   ├── DecorationSeparator.astro
│   │   │   ├── DecorationTop.astro
│   │   │   ├── DiffnavCard.astro
│   │   │   ├── DiffnavMiniLogo.astro
│   │   │   ├── Discord.astro
│   │   │   ├── EnhanceCard.astro
│   │   │   ├── EnhanceLogo.astro
│   │   │   ├── EnhanceMiniLogo.astro
│   │   │   ├── EnhanceOneLineLogo.astro
│   │   │   ├── FadeImages.astro
│   │   │   ├── FeatureCard.astro
│   │   │   ├── FeatureSponsorshipGoal.astro
│   │   │   ├── Footer.astro
│   │   │   ├── Header.astro
│   │   │   ├── Hero.astro
│   │   │   ├── Logo.astro
│   │   │   ├── NerdFontIcon.astro
│   │   │   ├── PillLink.astro
│   │   │   ├── ReleaseVersionButton.astro
│   │   │   ├── Showcase.astro
│   │   │   ├── Sponsorship.astro
│   │   │   ├── SponsorshipGoal.astro
│   │   │   ├── StargazersCount.astro
│   │   │   ├── StargazersFallback.astro
│   │   │   ├── SupportSection.astro
│   │   │   ├── Terminal.astro
│   │   │   └── ThemeSelect.astro
│   │   ├── content/
│   │   │   └── docs/
│   │   │       ├── companions/
│   │   │       │   ├── enhance/
│   │   │       │   │   ├── dash-integration.mdx
│   │   │       │   │   ├── getting-started.mdx
│   │   │       │   │   ├── index.mdx
│   │   │       │   │   ├── keybindings.mdx
│   │   │       │   │   ├── theme.mdx
│   │   │       │   │   └── usage.mdx
│   │   │       │   └── index.mdx
│   │   │       ├── configuration/
│   │   │       │   ├── defaults.mdx
│   │   │       │   ├── examples.mdx
│   │   │       │   ├── index.mdx
│   │   │       │   ├── issue-section.mdx
│   │   │       │   ├── keybindings/
│   │   │       │   │   ├── index.mdx
│   │   │       │   │   ├── issues.mdx
│   │   │       │   │   └── prs.mdx
│   │   │       │   ├── layout/
│   │   │       │   │   ├── issue.mdx
│   │   │       │   │   ├── options.mdx
│   │   │       │   │   └── pr.mdx
│   │   │       │   ├── notification-section.mdx
│   │   │       │   ├── pr-section.mdx
│   │   │       │   ├── repo-paths.mdx
│   │   │       │   ├── reusing.mdx
│   │   │       │   ├── schema.mdx
│   │   │       │   ├── searching.mdx
│   │   │       │   └── theme.mdx
│   │   │       ├── contributing/
│   │   │       │   └── index.mdx
│   │   │       ├── donating/
│   │   │       │   └── index.mdx
│   │   │       ├── getting-started/
│   │   │       │   ├── index.mdx
│   │   │       │   ├── keybindings/
│   │   │       │   │   ├── global.mdx
│   │   │       │   │   ├── index.mdx
│   │   │       │   │   ├── navigation.mdx
│   │   │       │   │   ├── preview.mdx
│   │   │       │   │   ├── selected-issue.mdx
│   │   │       │   │   ├── selected-item.mdx
│   │   │       │   │   ├── selected-notification.mdx
│   │   │       │   │   └── selected-pr.mdx
│   │   │       │   ├── updating.mdx
│   │   │       │   └── usage.mdx
│   │   │       └── insiders/
│   │   │           └── index.mdx
│   │   ├── content.config.ts
│   │   ├── data/
│   │   │   ├── latestVersion.ts
│   │   │   ├── schemas/
│   │   │   │   ├── defaults.yaml
│   │   │   │   ├── definitions/
│   │   │   │   │   ├── grow.yaml
│   │   │   │   │   └── hexcolor.yaml
│   │   │   │   ├── gh-dash.yaml
│   │   │   │   ├── issue-section.yaml
│   │   │   │   ├── keybindings/
│   │   │   │   │   ├── entry.yaml
│   │   │   │   │   ├── issues.yaml
│   │   │   │   │   └── prs.yaml
│   │   │   │   ├── layout/
│   │   │   │   │   ├── issue.yaml
│   │   │   │   │   ├── options.yaml
│   │   │   │   │   └── pr.yaml
│   │   │   │   ├── pr-section.yaml
│   │   │   │   └── theme.yaml
│   │   │   ├── sponsorshipGoal.ts
│   │   │   └── stars.ts
│   │   ├── fonts/
│   │   │   ├── CommitMono-400-Regular.otf
│   │   │   ├── CommitMonoNerdFontMono-Regular.otf
│   │   │   └── font-face.css
│   │   ├── pages/
│   │   │   ├── enhance.astro
│   │   │   ├── index.astro
│   │   │   ├── robots.txt.ts
│   │   │   ├── schema/
│   │   │   │   ├── defaults.json.ts
│   │   │   │   ├── definitions/
│   │   │   │   │   ├── grow.json.ts
│   │   │   │   │   └── hexcolor.json.ts
│   │   │   │   ├── issue-section.json.ts
│   │   │   │   ├── keybindings/
│   │   │   │   │   ├── entry.json.ts
│   │   │   │   │   ├── issues.json.ts
│   │   │   │   │   └── prs.json.ts
│   │   │   │   ├── layout/
│   │   │   │   │   ├── issue.json.ts
│   │   │   │   │   ├── options.json.ts
│   │   │   │   │   └── pr.json.ts
│   │   │   │   ├── pr-section.json.ts
│   │   │   │   └── theme.json.ts
│   │   │   └── schema.json.ts
│   │   └── styles/
│   │       ├── custom.css
│   │       ├── fade-images.css
│   │       ├── index.css
│   │       ├── nerd-font.css
│   │       └── terminal.css
│   └── tsconfig.json
├── gh-dash.go
├── go.mod
├── go.sum
├── internal/
│   ├── config/
│   │   ├── feature_flags.go
│   │   ├── parser.go
│   │   ├── parser_test.go
│   │   ├── testdata/
│   │   │   ├── .gh-dash.yml
│   │   │   ├── ansi-color-config.yml
│   │   │   ├── gh-dash/
│   │   │   │   └── config.yml
│   │   │   ├── global-config.golden.yml
│   │   │   ├── merged-config.golden.yml
│   │   │   ├── other-test-config.yml
│   │   │   └── test-config.yml
│   │   └── utils.go
│   ├── data/
│   │   ├── assignee.go
│   │   ├── bookmarks.go
│   │   ├── bookmarks_test.go
│   │   ├── cache.go
│   │   ├── commonapi.go
│   │   ├── donestore.go
│   │   ├── donestore_test.go
│   │   ├── donestore_testing.go
│   │   ├── issueapi.go
│   │   ├── labelapi.go
│   │   ├── notificationapi.go
│   │   ├── notificationapi_test.go
│   │   ├── prapi.go
│   │   ├── prapi_test.go
│   │   ├── repository.go
│   │   ├── user.go
│   │   └── utils.go
│   ├── git/
│   │   └── git.go
│   ├── tui/
│   │   ├── common/
│   │   │   ├── diff.go
│   │   │   ├── diff_test.go
│   │   │   ├── labels.go
│   │   │   ├── labels_test.go
│   │   │   ├── repopath.go
│   │   │   ├── repopath_test.go
│   │   │   └── styles.go
│   │   ├── components/
│   │   │   ├── autocomplete/
│   │   │   │   └── autocomplete.go
│   │   │   ├── branch/
│   │   │   │   ├── branch.go
│   │   │   │   ├── data.go
│   │   │   │   ├── data_test.go
│   │   │   │   └── utils.go
│   │   │   ├── branchsidebar/
│   │   │   │   ├── branchsidebar.go
│   │   │   │   └── branchsidebar_test.go
│   │   │   ├── carousel/
│   │   │   │   └── carousel.go
│   │   │   ├── common/
│   │   │   │   └── interface.go
│   │   │   ├── footer/
│   │   │   │   └── footer.go
│   │   │   ├── inputbox/
│   │   │   │   └── inputbox.go
│   │   │   ├── issuerow/
│   │   │   │   └── issuerow.go
│   │   │   ├── issuessection/
│   │   │   │   ├── constants.go
│   │   │   │   └── issuessection.go
│   │   │   ├── issueview/
│   │   │   │   ├── action.go
│   │   │   │   ├── action_test.go
│   │   │   │   ├── activity.go
│   │   │   │   ├── issueview.go
│   │   │   │   └── labels.go
│   │   │   ├── listviewport/
│   │   │   │   └── listviewport.go
│   │   │   ├── notificationrow/
│   │   │   │   ├── data.go
│   │   │   │   ├── data_test.go
│   │   │   │   ├── notificationrow.go
│   │   │   │   └── notificationrow_test.go
│   │   │   ├── notificationssection/
│   │   │   │   ├── DESIGN.md
│   │   │   │   ├── commands.go
│   │   │   │   ├── commands_test.go
│   │   │   │   ├── filters_test.go
│   │   │   │   └── notificationssection.go
│   │   │   ├── notificationview/
│   │   │   │   ├── notificationview.go
│   │   │   │   └── notificationview_test.go
│   │   │   ├── prompt/
│   │   │   │   └── prompt.go
│   │   │   ├── prrow/
│   │   │   │   ├── data.go
│   │   │   │   ├── prrow.go
│   │   │   │   └── prrow_test.go
│   │   │   ├── prssection/
│   │   │   │   ├── checkout.go
│   │   │   │   ├── diff.go
│   │   │   │   ├── prssection.go
│   │   │   │   ├── prssection_test.go
│   │   │   │   └── watchChecks.go
│   │   │   ├── prview/
│   │   │   │   ├── action.go
│   │   │   │   ├── action_test.go
│   │   │   │   ├── activity.go
│   │   │   │   ├── checks.go
│   │   │   │   ├── checks_test.go
│   │   │   │   ├── commits.go
│   │   │   │   ├── files.go
│   │   │   │   ├── prview.go
│   │   │   │   └── reviewers_test.go
│   │   │   ├── reposection/
│   │   │   │   ├── commands.go
│   │   │   │   └── reposection.go
│   │   │   ├── search/
│   │   │   │   └── search.go
│   │   │   ├── section/
│   │   │   │   ├── section.go
│   │   │   │   └── section_test.go
│   │   │   ├── sidebar/
│   │   │   │   └── sidebar.go
│   │   │   ├── table/
│   │   │   │   └── table.go
│   │   │   ├── tabs/
│   │   │   │   ├── tabs.go
│   │   │   │   ├── tabs_test.go
│   │   │   │   └── testdata/
│   │   │   │       ├── TestTabs/
│   │   │   │       │   ├── Should_allow_setting_new_tabs.golden
│   │   │   │       │   ├── Should_display_loading_tabs.golden
│   │   │   │       │   ├── Should_display_tab_counts.golden
│   │   │   │       │   └── Should_show_overflow_symbol.golden
│   │   │   │       └── test_section.go
│   │   │   ├── tasks/
│   │   │   │   ├── issue.go
│   │   │   │   ├── issue_test.go
│   │   │   │   ├── pr.go
│   │   │   │   └── pr_test.go
│   │   │   └── utils.go
│   │   ├── constants/
│   │   │   ├── constants.go
│   │   │   ├── errMsg.go
│   │   │   ├── initMsg.go
│   │   │   └── progressMsg.go
│   │   ├── context/
│   │   │   ├── context.go
│   │   │   └── styles.go
│   │   ├── keys/
│   │   │   ├── branchKeys.go
│   │   │   ├── issueKeys.go
│   │   │   ├── keys.go
│   │   │   ├── keys_test.go
│   │   │   ├── notificationKeys.go
│   │   │   └── prKeys.go
│   │   ├── markdown/
│   │   │   ├── markdownRenderer.go
│   │   │   └── theme.go
│   │   ├── modelUtils.go
│   │   ├── tasks.go
│   │   ├── testdata/
│   │   │   ├── searchIssues.json
│   │   │   └── searchPullRequests.json
│   │   ├── testutils/
│   │   │   └── utils.go
│   │   ├── theme/
│   │   │   ├── theme.go
│   │   │   └── theme_test.go
│   │   ├── ui.go
│   │   └── ui_test.go
│   └── utils/
│       ├── templateHandler.go
│       ├── utils.go
│       └── utils_test.go
└── testdata/
    ├── api.github.com.graphql-schema.json
    ├── gh-dash/
    │   └── config.yml
    └── graphql.http

================================================
FILE CONTENTS
================================================

================================================
FILE: .envrc
================================================
#!/bin/bash

# Automatically sets up your devbox environment whenever you cd into this
# directory via our direnv integration:

eval "$(devbox generate direnv --print-envrc)"

# check out https://www.jetify.com/docs/devbox/ide_configuration/direnv/
# for more details


================================================
FILE: .gh-dash.yml
================================================
# yaml-language-server: $schema=https://gh-dash.dev/schema.json
prSections:
  - title: Mine
    filters: is:open author:@me repo:dlvhdr/gh-dash updated:>={{ nowModify "-3w" }} sort:updated-desc
    layout:
      author:
        hidden: true
      repoName:
        hidden: true
  - title: Review
    filters: repo:dlvhdr/gh-dash -author:@me is:open updated:>={{ nowModify "-2.5w" }}
    layout:
      repoName:
        hidden: true
  - title: All
    filters: repo:dlvhdr/gh-dash
issuesSections:
  - title: Open
    filters: repo:dlvhdr/gh-dash is:open sort:reactions
  - title: Bugs
    filters: repo:dlvhdr/gh-dash is:open sort:reactions label:bug
  - title: Features
    filters: repo:dlvhdr/gh-dash is:open sort:reactions label:feat
  - title: High
    filters: repo:dlvhdr/gh-dash is:open sort:reactions label:high-pri
  - title: Mid
    filters: repo:dlvhdr/gh-dash is:open sort:reactions label:mid-pri
  - title: Low
    filters: repo:dlvhdr/gh-dash is:open sort:reactions label:low-pri
  - title: Unlabeled
    filters: repo:dlvhdr/gh-dash is:open sort:reactions -label:bug -label:feat
  - title: All
    filters: repo:dlvhdr/gh-dash sort:reactions

defaults:
  view: prs
  refetchIntervalMinutes: 5
  layout:
    prs:
      repoName:
        hidden: true
      base:
        hidden: true

  preview:
    open: true
  prsLimit: 20
  issuesLimit: 20


================================================
FILE: .github/FUNDING.yml
================================================
github: [dlvhdr]


================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: Bug report
about: Create a report to help us improve
title: "[BUG]"
labels: bug
assignees: ""
---

**Describe the bug**
A clear and concise description of what the bug is.

**To Reproduce**
Steps to reproduce the behavior:

1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error

**Expected behavior**
A clear and concise description of what you expected to happen.

**Screenshots**
If applicable, add screenshots to help explain your problem.

**Desktop (please complete the following information):**

- OS: [e.g. Mac]
- Terminal Emulator
- Using tmux?


================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.md
================================================
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''

---

**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

**Describe the solution you'd like**
A clear and concise description of what you want to happen.

**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.

**Additional context**
Add any other context or screenshots about the feature request here.


================================================
FILE: .github/pull_request_template.md
================================================
# Summary

- [] Closes issue #...
- [] I have read the [CONTIBUTING.md](../CONTRIBUTING.md) and [AI_POLICY.md](../AI_POLICY.md) guides

## How Did You Test this Change?

## Images/Videos

<!-- if relevant, please include any relevant images that show off how your feature is
working -->


================================================
FILE: .github/workflows/build-and-test.yaml
================================================
name: build and test

on:
  pull_request:
    paths-ignore:
      - "docs/**"

permissions:
  contents: read

jobs:
  build-and-test:
    name: Build and test
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v5
      - name: Install Go
        uses: actions/setup-go@v6
        with:
          go-version-file: ./go.mod
      - name: Download Go modules
        run: go mod download
      - name: Build
        run: go build ./...
      - name: Test
        run: go test ./...

  dependabot:
    needs: [build-and-test]
    runs-on: ubuntu-latest
    permissions:
      pull-requests: write
      contents: write
    if: ${{ github.actor == 'dependabot[bot]' && github.event_name == 'pull_request'}}
    steps:
      - id: metadata
        uses: dependabot/fetch-metadata@08eff52bf64351f401fb50d4972fa95b9f2c2d1b # v2.4.0
        with:
          github-token: "${{ secrets.GITHUB_TOKEN }}"
      - run: |
          gh pr review --approve "$PR_URL"
          gh pr merge --squash --auto "$PR_URL"
        env:
          PR_URL: ${{github.event.pull_request.html_url}}
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}


================================================
FILE: .github/workflows/build-docs.yaml
================================================
name: Build Docs

on:
  pull_request:
    paths:
      - "docs/**"
  workflow_dispatch:

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout your repository using git
        uses: actions/checkout@v6
      - name: Install, build, and upload your site output
        uses: withastro/action@v5
        with:
          path: ./docs


================================================
FILE: .github/workflows/dependabot-sync.yml
================================================
name: dependabot-sync
on:
  schedule:
    - cron: "0 0 * * 0" # every Sunday at midnight
  workflow_dispatch: # allows manual triggering

permissions:
  contents: write
  pull-requests: write

jobs:
  dependabot-sync:
    uses: charmbracelet/meta/.github/workflows/dependabot-sync.yml@main
    with:
      repo_name: ${{ github.event.repository.name }}
    secrets:
      gh_token: ${{ secrets.PERSONAL_ACCESS_TOKEN }}


================================================
FILE: .github/workflows/go-release.yml
================================================
name: goreleaser

on:
  push:
    tags:
      - "*"

permissions:
  contents: write

jobs:
  goreleaser:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - name: Set up Go
        uses: actions/setup-go@v5
        with:
          go-version: ">=1.21.0"
          cache: true
      - name: Run GoReleaser
        uses: goreleaser/goreleaser-action@v6
        with:
          distribution: goreleaser
          version: "~> v2"
          args: release --clean --draft
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          DISCORD_WEBHOOK_ID: ${{ secrets.DISCORD_WEBHOOK_ID }}
          DISCORD_WEBHOOK_TOKEN: ${{ secrets.DISCORD_WEBHOOK_TOKEN }}
          BLUESKY_APP_PASSWORD: ${{ secrets.BLUESKY_APP_PASSWORD }}


================================================
FILE: .github/workflows/lint.yml
================================================
name: lint
on:
  pull_request:

permissions:
  contents: read

jobs:
  golangci:
    name: lint
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-go@v5
        with:
          go-version: stable
      - name: golangci-lint
        uses: golangci/golangci-lint-action@v9


================================================
FILE: .github/workflows/publish-docs.yaml
================================================
name: Build and Push Docs Docker image

on:
  push:
    branches: ["main"]
    paths:
      - "docs/**"

jobs:
  build-and-push-dockerfile-image:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout repository
        uses: actions/checkout@v3

      - name: Log in to Docker Hub
        uses: docker/login-action@v2
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

      - name: Build and push Docker image
        uses: docker/build-push-action@v4
        with:
          context: "{{defaultContext}}:docs"
          secrets: |
            gh_token=${{ secrets.GH_TOKEN }}
          file: ./Dockerfile
          push: ${{ github.event_name == 'push' }}
          # Make sure to replace with your own namespace and repository
          tags: |
            dlvhdr/gh-dash-docs:latest
          platforms: linux/amd64


================================================
FILE: .gitignore
================================================
debug.log
dist
gh-prs
/gh-dash
.direnv/
/result*
.DS_Store
.killgrave.log
docs/broken-links.log
.devbox
__debug*
testdata/gh-schema.graphql


================================================
FILE: .golangci.yml
================================================
version: "2"
linters:
  enable:
    - bodyclose
    # - exhaustive
    # - goconst
    # - godot
    # - godox
    # - gomoddirectives
    - goprintffuncname
    # - gosec
    - misspell
    # - nakedret
    # - nestif
    # - nilerr
    # - noctx
    - nolintlint
    # - prealloc
    # - revive
    - rowserrcheck
    - sqlclosecheck
    - staticcheck
    - tparallel
    # - unconvert
    # - unparam
    - whitespace
    # - wrapcheck
  disable:
    - errcheck
    - ineffassign
    - unused
  exclusions:
    generated: lax
    presets:
      - common-false-positives
    rules:
      - text: '(slog|log)\.\w+'
        linters:
          - noctx
issues:
  max-issues-per-linter: 0
  max-same-issues: 0
formatters:
  enable:
    - gofumpt
    - goimports
    - golines
  settings:
    golines:
      chain-split-dots: true
  exclusions:
    generated: lax


================================================
FILE: .goreleaser.yaml
================================================
version: 2

before:
  hooks:
    - go mod tidy

gomod:
  proxy: true
  env:
    - GOPROXY=https://proxy.golang.org,direct
    - GOSUMDB=sum.golang.org
    - GOPRIVATE=github.com/dlvhdr/gh-dash
  mod: mod

builds:
  - env:
      - CGO_ENABLED=0
    flags:
      - -tags=nodbus
    goos:
      - android
      - freebsd
      - linux
      - windows
      - darwin
    goarch:
      - amd64
      - arm64
      - arm
      - "386"
    goarm:
      - "7"
    ldflags:
      - -s -w
      - -X github.com/dlvhdr/gh-dash/cmd.Version={{.Version}}
      - -X github.com/dlvhdr/gh-dash/cmd.Commit={{.Commit}}
      - -X github.com/dlvhdr/gh-dash/cmd.Date={{.CommitDate}}
      - -X github.com/dlvhdr/gh-dash/cmd.BuiltBy=goreleaser
    # Skipping builds for Android non-ARM64 architectures as they need CGO enabled
    # https://goreleaser.com/limitations/cgo/
    ignore:
      - goos: android
        goarch: amd64
      - goos: android
        goarch: arm
      - goos: android
        goarch: "386"
      - goos: windows
        goarch: arm

archives:
  - formats:
      - binary
    name_template: "gh-dash_{{ .Tag }}_{{ .Os }}-{{ .Arch }}{{if .Arm}}_{{.Arm}}{{end}}"
checksum:
  name_template: "checksums.txt"
snapshot:
  version_template: "{{ incpatch .Version }}-next"

release:
  header: |
    # {{ .Version }}

    <!-- what's new in this version? -->

    To update run:
    ```bash
    gh extension upgrade dash
    ```

  footer: |
    ---

    If you enjoy `dash`, consider [making a donation](https://www.gh-dash.dev/donating) ❤️

    Have questions? Join our [Discord community](https://discord.gg/SXNXp9NctV)!

    <br />

    <a  class="underline: none;" href="https://gh-dash.dev">
      <picture>
        <source media="(prefers-color-scheme: dark)" srcset="https://gh-dash.dev/logo.png">
        <img alt="DASH Logo" width="600" src="https://gh-dash.dev/logo-light.png">
      </picture>
    </a>

announce:
  bluesky:
    enabled: true
    username: "dlvhdr.me"
    # message_template: (Default) '{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}'.

  discord:
    enabled: true
    color: "8037112"
    icon_url: "https://www.gh-dash.dev/favicon.png"
    # message_template: (Default) '{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}'.

changelog:
  sort: asc
  use: github
  filters:
    exclude:
      - "^test:"
      - "^chore"
      - "merge conflict"
      - Merge pull request
      - Merge remote-tracking branch
      - Merge branch
      - go mod tidy
  groups:
    - title: Dependency updates
      regexp: "^.*\\(deps\\)*:+.*$"
      order: 300
    - title: "New Features"
      regexp: "^.*feat[(\\w)]*:+.*$"
      order: 100
    - title: "Bug fixes"
      regexp: "^.*fix[(\\w)]*:+.*$"
      order: 200
    - title: "Documentation updates"
      regexp: "^.*docs[(\\w)]*:+.*$"
      order: 400
    - title: Other work
      order: 9999


================================================
FILE: AI_POLICY.md
================================================
# AI Usage Policy

This project has strict rules for AI usage:

- **All AI usage in any form must be disclosed.** You must state
  the tool you used (e.g. Claude Code, Cursor, Amp) along with
  the extent that the work was AI-assisted.

- **The human-in-the-loop must fully understand all code.** If you
  can't explain what your changes do and how they interact with the
  greater system without the aid of AI tools, do not contribute
  to this project.

- **Issues and discussions can use AI assistance but must have a full
  human-in-the-loop.** This means that any content generated with AI
  must have been reviewed _and edited_ by a human before submission.
  AI is excellent at being overly verbose and including noise that
  distracts from the main point. Humans must do their research and
  trim this down.

- **No AI-generated media is allowed (art, images, videos, audio, etc.).**
  Text and code are the only acceptable AI-generated content, per the
  other rules in this policy.

These rules apply only to outside contributions. Maintainers
are exempt from these rules and may use AI tools at their discretion;
they've proven themselves trustworthy to apply good judgment.

## There Are Humans Here

Please remember that this project is maintained by humans.

Every discussion, issue, and pull request is read and reviewed by
humans (and sometimes machines, too). It is a boundary point at which
people interact with each other and the work done. It is rude and
disrespectful to approach this boundary with low-effort, unqualified
work, since it puts the burden of validation on the maintainer.

In a perfect world, AI would produce high-quality, accurate work
every time. But today, that reality depends on the driver of the AI.
And today, most drivers of AI are just not good enough. So, until either
the people get better, the AI gets better, or both, we have to have
strict rules to protect maintainers.


================================================
FILE: CONTRIBUTING.md
================================================
# Contributing To `gh-dash`

Thank you for investing your time in contributing to our project!

In this guide you will get an overview of the contribution workflow from opening an issue, creating a PR, reviewing, and merging the PR.

## The Critical Rule

- The most important rule: you must understand your code. If you can't explain what your changes do and how they interact with the greater system without the aid of AI tools, do not contribute to this project.
- The second most important rule: when you submit a PR you must be willing to address comments and maintain this code. Dot not submit drive-by PRs that solve your own issue without the willingness to iterate on it. Keep these in your own fork.
- Using AI to write code is fine. You can gain understanding by interrogating an agent with access to the codebase until you grasp all edge cases and effects of your changes. What's not fine is submitting agent-generated slop without that understanding. Be sure to read the [AI Usage Policy](AI_POLICY.md).

## AI Usage

The project has strict rules for AI usage. Please see the [AI Usage Policy](AI_POLICY.md). This is very important.

## Quick Guide

### I Have an Idea for a Feature

Like bug reports, first search through both issues and discussions and try to find if your feature has already been requested. Otherwise, open a discussion in the ["Feature Requests, Ideas"](https://github.com/dlvhdr/gh-dash/issues/new?template=feature_request.md) category.

### I've Implemented a Feature

- If there is an issue for the feature, open a pull request straight away.
- If there is no issue, open a discussion and link to your branch.
- If you want to live dangerously, open a pull request and hope for the best.

### I Have a Question Which Is Neither a Bug Report nor a Feature Request

Open a [Q&A discussion](https://github.com/dlvhdr/gh-dash/discussions/categories/q-a), or join our [Discord Server](https://discord.gg/SXNXp9NctV) and ask away in the #help forum channel.

## Working on the Code

### Installing Required Tooling

Our project uses [Devbox](https://github.com/jetpack-io/devbox) to manage its development environment.

Using Devbox will get your dev environment up and running easily and make sure we're all using the same tools with the same versions.

- Clone this repo

```sh
git clone git@github.com:dlvhdr/gh-dash.git && cd gh-dash
```

- Install `devbox`

```sh
curl -fsSL https://get.jetpack.io/devbox | bash
```

- Start the `devbox` shell and run the setup (will take a while on first time)

```sh
devbox shell
```

_This will create a shell where all required tools are installed._

- _(Optional)_ Set up `direnv` so `devbox shell` runs automatically
  - [direnv](https://www.jetify.com/devbox/docs/ide_configuration/direnv/) is a tool that allows setting unique environment variables per directory in your filesystem.
    - Install `direnv` with: `brew install direnv`
    - Add the following line at the end of the `~/.bashrc` file: `eval "$(direnv hook bash)"`
      - See [direnv's installation instructions](https://direnv.net/docs/hook.html) for other shells.
    - Enable `direnv` by running `direnv allow`
- _(Optional)_ Install the VSCode Extension
  - Follow [this guide](https://www.jetify.com/devbox/docs/ide_configuration/vscode/) to set up VSCode to automatically run `devbox shell`.

#### Troubleshooting

- delete the `.devbox` directory at the project's root

### Navigating the Codebase

To navigate our codebase with confidence, familiarize yourself with:

- [Bubbletea](https://github.com/charmbracelet/bubbletea) - the TUI framework we're using
- [The Elm architecture](https://guide.elm-lang.org/architecture/)
- [charmbracelet/glow](https://github.com/charmbracelet/glow) - for parsing and presenting Markdown

#### Code Structure

- `ui/` - this is the code that's responsible for rendering the different parts of the TUI
- `data/` - the code that fetches data from GitHub's GraphQL API
- `config/` - code to parse the user's `config.yml` file
- `utils/` - various utilities

### Debugging

- Write to the log by using Charm's `log` package
- Tail the log by running `task logs`
- Run `dash` in debug mode with `task debug` in another terminal window / pane

```go
import "charm.land/log/v2"

// more code...

log.Debug("some message", "someVariable", someVariable)
```

### Running the Docs Locally

- Run the docs site by running `task docs`

* Go to `localhost:4321` to view them


================================================
FILE: LICENSE.txt
================================================
MIT License

Copyright (c) 2025 Dolev Hadar

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.md
================================================
<br />
<p align="center">
  <a  class="underline: none;" href="https://gh-dash.dev">
    <picture>
      <source media="(prefers-color-scheme: dark)" srcset="./docs/public/logo.png">
      <img alt="Text changing depending on mode. Light: 'So light!' Dark: 'So dark!'" width="600" src="./docs/public/logo-light.png">
    </picture>
  </a>
</p>

<p align="center">
    <a href="https://gh-dash.dev" target="_blank">→ https://gh-dash.dev ←</a>
</p>
<p align="center">
  A rich terminal UI for GitHub that doesn't break your flow.
  <br />
  <br />
  <a href="https://github.com/dlvhdr/gh-dash/releases"><img src="https://img.shields.io/github/release/dlvhdr/gh-dash.svg" alt="Latest Release"></a>
  <a href="https://discord.gg/SXNXp9NctV"><img src="https://img.shields.io/discord/1413193703476035755?label=discord" alt="Discord"/></a>
  <a href="https://github.com/sponsors/dlvhdr"><img src=https://img.shields.io/github/sponsors/dlvhdr?logo=githubsponsors&color=EA4AAA /></a>
  <a href="https://www.jetify.com/devbox/docs/contributor-quickstart/" alt="Built with Devbox"><img src="https://www.jetify.com/img/devbox/shield_galaxy.svg" /></a>
</p>

<br />

<img src="./docs/src/assets/overview.gif" />

## 🌟 Features

> [!NOTE]
> If you like quickly navigating with your keyboard, seeing the PRs and issues you need and you <strong>love the terminal</strong> - <code>DASH</code> is for you! 🫵🏽

- User-defined, per-repo, PRs & issues sections
- Overridable vim-style keyboard hotkeys
- Custom actions to perform your specific workflow needs
- Everything you can do on GitHub - diff, comment, checkout, push, update etc.
- Control every setting with a YAML config file

## 📃 Docs

`DASH` has an extensive docs site at [gh-dash.dev/getting-started](https://gh-dash.dev/getting-started).

## ❤️ Donating

If you enjoy `DASH` and want to help, consider supporting the project with a
donation at the [sponsors page](https://github.com/sponsors/dlvhdr).

## 👥 Discord

Have questions? Join our [Discord community](https://discord.gg/SXNXp9NctV)!

## 🙏 Contributing

See the contribution guide at [https://www.gh-dash.dev/contributing](https://www.gh-dash.dev/contributing/).

## 🛞 Under the hood

`DASH` uses:

- [bubbletea](https://github.com/charmbracelet/bubbletea) for the TUI
- [lipgloss](https://github.com/charmbracelet/lipgloss) for the styling
- [glamour](https://github.com/charmbracelet/glamour) for rendering markdown
- [vhs](https://github.com/charmbracelet/vhs) for generating the GIF
- [cobra](https://github.com/spf13/cobra) for the CLI
- [gh](https://github.com/cli/cli) for the GitHub functionality
- [delta](https://github.com/dandavison/delta) for viewing PR diffs

## Author

Dolev Hadar [@dlvhdr](https://github.com/dlvhdr).


================================================
FILE: Taskfile.yaml
================================================
# https://taskfile.dev

version: "3"
silent: true

tasks:
  default:
    cmds:
      - go run . {{.CLI_ARGS}}
    interactive: true
    desc: Run

  build:
    - go build .

  uninstall:
    cmds:
      - gh ext remove dash

  install:
    cmds:
      - task: build
      - task: uninstall
      - echo "🕐 Installing local build..." && gh ext install .
      - gh dash --version

  install:prod:
    cmds:
      - task: uninstall
      - echo "🕐 Installing latest version..." && gh ext install dlvhdr/gh-dash
      - gh dash --version

  debug:
    cmds:
      - printf "~\n~\n~\n~\n~\n~\n~\n~\n~\n~\n~\n~\n~\n~\n~\n―――――――――――――――――――――――――――――――――――――――――――――――\n" > ./debug.log
      - DEBUG=true go run . --debug {{.CLI_ARGS}}
    interactive: true
    desc: Run in debug mode. Run `task logs` to watch the logs.

  debug:warn:
    cmds:
      - printf "~\n~\n~\n~\n~\n~\n~\n~\n~\n~\n~\n~\n~\n~\n~\n―――――――――――――――――――――――――――――――――――――――――――――――\n" > ./debug.log
      - LOG_LEVEL=warn DEBUG=true go run . --debug {{.CLI_ARGS}}
    interactive: true
    desc: Run in debug mode, only log warning. Run `task logs` to watch the logs.

  dlv:
    cmds:
      - dlv debug --headless --api-version=2 --listen=127.0.0.1:43000 .
    desc: Debug with dlv

  logs:
    cmds:
      - rm -f ./debug.log
      - touch ./debug.log
      - tail -f ./debug.log
    interactive: true
    desc: Tail the debug logs

  lint:
    desc: Run base linters
    cmds:
      - golangci-lint run --path-mode=abs --config=".golangci.yml" --timeout=5m
    env:
      GOEXPERIMENT: null

  lint:fix:
    desc: Run base linters and fix issues
    cmds:
      - golangci-lint run --path-mode=abs --config=".golangci.yml" --timeout=5m --fix
    env:
      GOEXPERIMENT: null

  test:one:
    cmds:
      - gotip
    desc: Run a test

  test:rerun:
    cmds:
      - gotip --rerun
    desc: Rerun the last test

  test:
    cmds:
      - prism test {{.CLI_ARGS}} ./...
    desc: Run tests

  fmt:
    desc: Run gofumpt
    cmds:
      - gofumpt -w $(git ls-files '*.go')

  check-nerd-font:
    cmds:
      - nerdfix check $(fd --extension go)
    desc: Find broken nerdfont characters

  fix-nerd-font:
    cmds:
      - nerdfix fix --format=json $(fd --extension go)
    desc: Fix broken nerdfont icons

  docs-prepare:
    cmds:
      - cd docs && pnpm i

  docs:
    cmds:
      - cd docs && pnpm dev
    desc: Start docs server

  docs-build:
    cmds:
      - task: docs-prepare
      - cd docs && pnpm build
    desc: Run docs production build

  docs-preview:
    cmds:
      - task: docs-build
      - cd docs && pnpm preview
    desc: Preview docs production build


================================================
FILE: cmd/root.go
================================================
/*
Copyright © 2022 NAME HERE <EMAIL ADDRESS>
*/
package cmd

import (
	"context"
	"fmt"
	slog "log"
	"os"
	"runtime"
	"runtime/debug"
	"runtime/pprof"
	"time"

	tea "charm.land/bubbletea/v2"
	"charm.land/lipgloss/v2"
	"charm.land/log/v2"
	"github.com/charmbracelet/fang"
	zone "github.com/lrstanley/bubblezone/v2"
	"github.com/spf13/cobra"

	"github.com/dlvhdr/gh-dash/v4/internal/config"
	"github.com/dlvhdr/gh-dash/v4/internal/git"
	"github.com/dlvhdr/gh-dash/v4/internal/tui"
	"github.com/dlvhdr/gh-dash/v4/internal/tui/constants"
	dctx "github.com/dlvhdr/gh-dash/v4/internal/tui/context"
)

var (
	Version = "dev"
	Commit  = ""
	Date    = ""
	BuiltBy = ""
)

var (
	cfgFlag string

	logo = lipgloss.NewStyle().Foreground(dctx.LogoColor).MarginBottom(1).SetString(constants.Logo)

	rootCmd = &cobra.Command{
		Use: "gh dash",
		Long: lipgloss.JoinVertical(lipgloss.Left, logo.Render(),
			"A rich terminal UI for GitHub that doesn't break your flow.",
			"Visit https://gh-dash.dev for the docs."),
		Short:   "A rich terminal UI for GitHub that doesn't break your flow.",
		Version: "",
		Example: `
# Running without arguments will either:
#   - Use the global configuration file
#   - Use a local .gh-dash.yml file if in a git repo
gh dash

# Run with a specific configuration file
gh dash --config /path/to/configuration/file.yml

# Run with debug logging to debug.log
gh dash --debug

# Print version
gh dash -v
	`,
		Args: cobra.MaximumNArgs(1),
	}
)

func Execute() {
	if err := fang.Execute(
		context.Background(),
		rootCmd,
		fang.WithVersion(rootCmd.Version),
		fang.WithoutCompletions(),
		fang.WithoutManpage(),
	); err != nil {
		os.Exit(1)
	}
}

func setDebugLogLevel() {
	switch os.Getenv("LOG_LEVEL") {
	case "debug", "":
		log.SetLevel(log.DebugLevel)
	case "info":
		log.SetLevel(log.InfoLevel)
	case "warn":
		log.SetLevel(log.WarnLevel)
	case "error":
		log.SetLevel(log.ErrorLevel)
	}
}

func createModel(location config.Location, debug bool) (tui.Model, *os.File) {
	var loggerFile *os.File

	if debug {
		var fileErr error
		loggerFile, fileErr = os.OpenFile("debug.log",
			os.O_RDWR|os.O_CREATE|os.O_APPEND, 0o666)
		if fileErr == nil {
			log.SetOutput(loggerFile)
			log.SetTimeFormat(time.Kitchen)
			log.SetReportCaller(true)
			setDebugLogLevel()
			log.Info("Logging to debug.log")
			if location.RepoPath != "" {
				log.Info("Running in repo", "repo", location.RepoPath)
			}
		} else {
			loggerFile, _ = tea.LogToFile("debug.log", "debug")
			slog.Print("Failed setting up logging", fileErr)
		}
	} else {
		log.SetOutput(os.Stderr)
		log.SetLevel(log.FatalLevel)
	}

	return tui.NewModel(location), loggerFile
}

func buildVersion(version, commit, date, builtBy string) string {
	result := version
	if commit != "" {
		result = fmt.Sprintf("%s\ncommit: %s", result, commit)
	}
	if date != "" {
		result = fmt.Sprintf("%s\nbuilt at: %s", result, date)
	}
	if builtBy != "" {
		result = fmt.Sprintf("%s\nbuilt by: %s", result, builtBy)
	}
	result = fmt.Sprintf("%s\ngoos: %s\ngoarch: %s", result, runtime.GOOS, runtime.GOARCH)
	if info, ok := debug.ReadBuildInfo(); ok && info.Main.Sum != "" {
		result = fmt.Sprintf(
			"%s\nmodule version: %s, checksum: %s",
			result,
			info.Main.Version,
			info.Main.Sum,
		)
	}

	return result
}

func init() {
	rootCmd.PersistentFlags().StringVarP(
		&cfgFlag,
		"config",
		"c",
		"",
		`use this configuration file
(default lookup:
  1. a .gh-dash.yml file if inside a git repo
  2. $GH_DASH_CONFIG env var
  3. $XDG_CONFIG_HOME/gh-dash/config.yml
)`,
	)
	err := rootCmd.MarkPersistentFlagFilename("config", "yaml", "yml")
	if err != nil {
		log.Fatal("Cannot mark config flag as filename", err)
	}

	rootCmd.Version = buildVersion(Version, Commit, Date, BuiltBy)
	rootCmd.SetVersionTemplate(`gh-dash {{printf "version %s\n" .Version}}`)

	rootCmd.Flags().Bool(
		"debug",
		false,
		"passing this flag will allow writing debug output to debug.log",
	)

	rootCmd.Flags().String(
		"cpuprofile",
		"",
		"write cpu profile to file",
	)

	rootCmd.Flags().BoolP(
		"help",
		"h",
		false,
		"help for gh-dash",
	)

	rootCmd.Run = func(_ *cobra.Command, args []string) {
		var repo string
		repos := config.IsFeatureEnabled(config.FF_REPO_VIEW)
		if repos && len(args) > 0 {
			repo = args[0]
		}

		if repo == "" {
			r, err := git.GetRepoInPwd()
			if err == nil && r != nil {
				repo = r.Path()
			}
		}
		debug, err := rootCmd.Flags().GetBool("debug")
		if err != nil {
			log.Fatal("Cannot parse debug flag", err)
		}

		zone.NewGlobal()

		model, logger := createModel(config.Location{RepoPath: repo, ConfigFlag: cfgFlag}, debug)
		if logger != nil {
			defer logger.Close()
		}

		cpuprofile, err := rootCmd.Flags().GetString("cpuprofile")
		if err != nil {
			log.Fatal("Cannot parse cpuprofile flag", err)
		}
		if cpuprofile != "" {
			f, err := os.Create(cpuprofile)
			if err != nil {
				log.Fatal(err)
			}
			_ = pprof.StartCPUProfile(f)
			defer pprof.StopCPUProfile()
		}

		p := tea.NewProgram(model)
		if _, err := p.Run(); err != nil {
			log.Fatal("Failed starting the TUI", err)
		}
	}
}


================================================
FILE: cmd/sponsors.go
================================================
/*
Copyright © 2025 NAME HERE <EMAIL ADDRESS>
*/
package cmd

import (
	"fmt"

	"charm.land/lipgloss/v2"
	"charm.land/log/v2"
	"github.com/spf13/cobra"

	"github.com/dlvhdr/gh-dash/v4/internal/data"
)

// sponsorsCmd represents the sponsors command
var sponsorsCmd = &cobra.Command{
	Use:   "sponsors",
	Short: "Show the list of current sponsors for gh-dash",
	Long: `Show the list of current sponsors for gh-dash from GitHub Sponsors under https://github.com/sponsors/dlvhdr.
If you enjoy dash and want to help, consider supporting the project with a donation!`,
	RunE: func(cmd *cobra.Command, args []string) error {
		log.SetLevel(log.ErrorLevel)
		sponsors, err := data.FetchSponsors()
		if err != nil {
			return err
		}

		fmt.Print("\n")
		fmt.Print(
			lipgloss.JoinHorizontal(
				lipgloss.Top,
				lipgloss.NewStyle().
					Foreground(lipgloss.Color("1")).
					Bold(true).
					Render("Thank you ❤️ "),
				lipgloss.NewStyle().Foreground(lipgloss.Color("255")).Render(
					"to all the current (and past!) sponsors - you rock! 🤘🏽"),
			))
		fmt.Print("\n")
		fmt.Print("To help this project with a donation go to https://github.com/sponsors/dlvhdr\n")
		fmt.Print("\n")
		for _, sponsor := range sponsors.User.Sponsors.Nodes {
			if sponsor.Typename == "User" {
				fmt.Printf("  • %s (%s)\n", lipgloss.NewStyle().Bold(true).Render(
					fmt.Sprintf("@%s", sponsor.User.Login)), sponsor.User.Url)
			} else {
				fmt.Printf("  • %s (%s)\n", lipgloss.NewStyle().Bold(true).Render(
					sponsor.Organization.Name), sponsor.Organization.Url)
			}
		}

		return nil
	},
}

func init() {
	rootCmd.AddCommand(sponsorsCmd)
}


================================================
FILE: devbox.json
================================================
{
  "$schema": "https://raw.githubusercontent.com/jetify-com/devbox/0.16.0/.schema/devbox.schema.json",
  "env": {
    "GOPATH": "$PWD/.devbox/go",
    "GOBIN": "$PWD/.devbox/go/bin",
    "PATH": "$PATH:$PWD/.devbox/go/bin"
  },
  "packages": {
    "git": "latest",
    "gh": "latest",
    "go": "1.23",
    "golangci-lint": "2.10.1",
    "gofumpt": "0.8.0",
    "go-task": "3.44.1",
    "nerdfix": "0.4.2",
    "fd": "10.2.0"
  },
  "shell": {
    "init_hook": [
      "echo \"Creating devbox shell...\"",
      "[[ $(command -v prism) != \"$GOBIN/prism\" ]] && go install go.dalton.dog/prism@latest",
      "[[ $(command -v gotip) != \"$GOBIN/gotip\" ]] && go install github.com/lusingander/gotip/cmd/gotip@latest"
    ]
  }
}


================================================
FILE: docs/.dockerignore
================================================
.DS_Store
node_modules
dist


================================================
FILE: docs/.envrc
================================================
#!/bin/bash

# Automatically sets up your devbox environment whenever you cd into this
# directory via our direnv integration:

eval "$(devbox generate direnv --print-envrc)"

# check out https://www.jetify.com/docs/devbox/ide_configuration/direnv/
# for more details


================================================
FILE: docs/.eslint.config.js
================================================
import eslintPluginAstro from "eslint-plugin-astro";
export default [
  js.configs.recommended,
  ...eslintPluginAstro.configs.recommended,
];


================================================
FILE: docs/.gitignore
================================================
# build output
dist/
# generated types
.astro/

# dependencies
node_modules/

# logs
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*


# environment variables
.env
.env.production

# macOS-specific files
.DS_Store


================================================
FILE: docs/.prettierrc.mjs
================================================
// .prettierrc.mjs
/** @type {import("prettier").Config} */
export default {
  plugins: ["prettier-plugin-astro", "prettier-plugin-tailwindcss"],
  overrides: [
    {
      files: "*.astro",
      options: {
        parser: "astro",
      },
    },
  ],
};


================================================
FILE: docs/Dockerfile
================================================
FROM node:20-slim AS base
ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
RUN corepack enable

COPY . /app
WORKDIR /app

FROM base AS prod-deps
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --prod --frozen-lockfile

FROM base AS build
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile
RUN --mount=type=secret,id=gh_token,env=GH_TOKEN pnpm run build

FROM base
COPY --from=prod-deps /app/node_modules /app/node_modules
COPY --from=build /app/dist /app/dist

ENV HOST=0.0.0.0
ENV PORT=4321
EXPOSE 4321
CMD node ./dist/server/entry.mjs


================================================
FILE: docs/README.mdx
================================================
# Docs Site

[![Built with Starlight](https://astro.badg.es/v2/built-with-starlight/tiny.svg)](https://starlight.astro.build)

Live at [https://gh-dash.dev](https://gh-dash.dev).

## 🚀 Project Structure

In this project you'll see the following folders and files:

```
.
├── public/
├── src/
│   ├── assets/
│   ├── content/
│   │   └── docs/
│   └── content.config.ts
├── astro.config.mjs
├── package.json
└── tsconfig.json
```

Starlight looks for `.md` or `.mdx` files in the `src/content/docs/` directory. Each file is exposed as a route based on its file name.

Images can be added to `src/assets/` and embedded in Markdown with a relative link.

Static assets, like favicons, can be placed in the `public/` directory.

## 🧞 Commands

All commands are run from the root of the project, from a terminal:

| Command                | Action                                           |
| :--------------------- | :----------------------------------------------- |
| `pnpm install`         | Installs dependencies                            |
| `pnpm dev`             | Starts local dev server at `localhost:4321`      |
| `pnpm build`           | Build your production site to `./dist/`          |
| `pnpm preview`         | Preview your build locally, before deploying     |
| `pnpm astro ...`       | Run CLI commands like `astro add`, `astro check` |
| `pnpm astro -- --help` | Get help using the Astro CLI                     |


================================================
FILE: docs/astro.config.mjs
================================================
// @ts-check
import { defineConfig } from "astro/config";
import starlight from "@astrojs/starlight";
import tailwindcss from "@tailwindcss/vite";
import astroBrokenLinksChecker from "astro-broken-links-checker";

import node from "@astrojs/node";

const ogUrl = new URL("og.png", "https://gh-dash.dev/").href;
const ogImageAlt = "DASH Through Your GitHub";

// https://astro.build/config
export default defineConfig({
  site: "https://gh-dash.dev",
  integrations: [
    astroBrokenLinksChecker({
      logFilePath: "broken-links.log",
      checkExternalLinks: false,
    }),
    starlight({
      title: "DASH",
      favicon: "/favicon.png",
      customCss: ["./src/styles/custom.css", "./src/fonts/font-face.css"],
      head: [
        {
          tag: "meta",
          attrs: { property: "og:image", content: ogUrl },
        },
        {
          tag: "meta",
          attrs: { property: "og:image:alt", content: ogImageAlt },
        },
        {
          tag: "meta",
          attrs: {
            name: "description",
            content:
              "DASH - a rich terminal UI for GitHub that doesn't break your flow",
          },
        },
      ],
      components: {
        Header: "./src/components/Header.astro",
      },
      social: [
        {
          icon: "github",
          label: "GitHub",
          href: "https://github.com/dlvhdr/gh-dash",
        },
      ],
      sidebar: [
        {
          label: "Getting Started",
          items: [
            "getting-started",
            "getting-started/usage",
            "getting-started/updating",
          ],
        },
        {
          label: "Keybindings",
          collapsed: true,
          autogenerate: { directory: "getting-started/keybindings" },
        },
        {
          label: "Configuration",
          collapsed: true,
          items: [
            "configuration",
            "configuration/schema",
            "configuration/defaults",
            "configuration/searching",
            "configuration/pr-section",
            "configuration/issue-section",
            "configuration/notification-section",
            "configuration/repo-paths",
            "configuration/keybindings",
            "configuration/theme",
            "configuration/reusing",
            "configuration/examples",
            {
              label: "Layout",
              items: [
                "configuration/layout/options",
                "configuration/layout/pr",
                "configuration/layout/issue",
              ],
            },
          ],
        },
        {
          label: "Companion Apps",
          items: [
            {
              label: "ENHANCE",
              collapsed: true,
              items: [
                "companions/enhance/getting-started",
                "companions/enhance/usage",
                "companions/enhance/keybindings",
                "companions/enhance/dash-integration",
                "companions/enhance/theme",
              ],
            },
          ],
        },
        {
          label: "Insiders 🌟",
          items: ["insiders"],
        },
        { slug: "contributing" },
        { slug: "donating" },
      ],
    }),
  ],

  vite: {
    plugins: [tailwindcss()],
  },
  adapter: node({
    mode: "standalone",
  }),
});


================================================
FILE: docs/devbox.json
================================================
{
  "$schema": "https://raw.githubusercontent.com/jetify-com/devbox/0.16.0/.schema/devbox.schema.json",
  "env": {
    "DEVBOX_COREPACK_ENABLED": "true"
  },
  "packages": {
    "nodejs": "22.14.0"
  },
  "shell": {
    "init_hook": ["echo \"Creating devbox shell for docs site...\""]
  }
}


================================================
FILE: docs/package.json
================================================
{
  "name": "docs",
  "type": "module",
  "version": "0.0.1",
  "scripts": {
    "dev": "astro dev",
    "start": "astro dev",
    "build": "astro build",
    "preview": "astro preview",
    "astro": "astro"
  },
  "dependencies": {
    "@astrojs/node": "^9.4.3",
    "@astrojs/starlight": "^0.35.2",
    "@astrojs/starlight-tailwind": "^4.0.1",
    "@tailwindcss/vite": "^4.1.12",
    "astro": "^5.6.1",
    "astro-broken-links-checker": "github:imazen/astro-broken-link-checker",
    "sharp": "^0.34.2",
    "tailwindcss": "^4.1.12"
  },
  "devDependencies": {
    "@typescript-eslint/parser": "^8.41.0",
    "eslint": "^9.34.0",
    "eslint-plugin-astro": "^1.3.1",
    "eslint-plugin-jsx-a11y": "^6.10.2",
    "prettier": "^3.6.2",
    "prettier-plugin-astro": "^0.14.1",
    "prettier-plugin-tailwindcss": "^0.6.14"
  },
  "packageManager": "pnpm@10.14.0"
}


================================================
FILE: docs/src/assets/custom-commands.tape
================================================
Output custom-commands.webm
Output custom-commands.mp4
Output custom-commands.gif

Set Theme TokyoNight
Set Padding 0
Set FontSize 24
Set FontFamily "CommitMono Nerd Font"
Set Width 1400
Set Height 600

Hide
Type "gh dash --config custom-commands.yml"

Enter
Sleep 8s
Show

Sleep 1000ms

Type "g"
Sleep 1000ms
Type@200ms "jjjjjjjjjj"
Sleep 1000ms
Type "q"



================================================
FILE: docs/src/assets/custom-commands.yml
================================================
prSections:
  - title: My Pull Requests
    filters: is:open author:@me owner:dlvhdr
  - title: Needs My Review
    filters: review-requested:@me owner:dlvhdr
issuesSections:
  - title: Ghostty
    filters: is:open ghostty-org/ghostty
  - title: Neovim
    filters: is:open neovim/neovim

defaults:
  preview:
    open: false
    width: 40
  prsLimit: 20
  issuesLimit: 20
  view: repo
keybindings:
  universal:
    - key: g
      name: lazygit
      command: >
        cd {{.RepoPath}} && lazygit
    - key: C
      name: code review
      command: >
        tmux new-window -c {{.RepoPath}} '
        nvim -c ":silent Octo pr edit {{.PrNumber}}"
        '
repoPaths:
  dlvhdr/*: ~/code/personal/*
pager:
  diff: diffnav
theme:
  colors:
    text:
      primary: "#E2E1ED"
      secondary: "#666CA6"
      inverted: "#242347"
      faint: "#b0b3bf"
      warning: "#F23D5C"
      success: "#3DF294"
    background:
      selected: "#1b1b33"
    border:
      primary: "#383B5B"
      secondary: "#39386B"
      faint: "#2B2B40"
smartFilteringAtLaunch: false


================================================
FILE: docs/src/assets/demo.yml
================================================
prSections:
  - title: My Pull Requests
    filters: is:open author:@me owner:charmbracelet
  - title: Review Requested
    filters: review-requested:@me owner:charmbraclet
  - title: My Team
    filters: is:open owner:neovim author:gpanders author:tjdevries
  - title: Open Source
    filters: is:open repo:ghostty-org/ghostty repo:neovim/neovim
issuesSections:
  - title: Ghostty
    filters: is:open ghostty-org/ghostty
  - title: Neovim
    filters: is:open neovim/neovim
  - title: Bubbletea
    filters: repo:charmbracelet/bubbletea

defaults:
  preview:
    open: true
    width: 40
  prsLimit: 20
  issuesLimit: 20
  view: repo
keybindings:
  prs: []
repoPaths: {}
pager:
  diff: diffnav
theme:
  colors:
    text:
      primary: "#E2E1ED"
      secondary: "#666CA6"
      inverted: "#242347"
      faint: "#b0b3bf"
      warning: "#F23D5C"
      success: "#3DF294"
    background:
      selected: "#1b1b33"
    border:
      primary: "#383B5B"
      secondary: "#39386B"
      faint: "#2B2B40"
smartFilteringAtLaunch: false


================================================
FILE: docs/src/assets/overview.tape
================================================
Output overview.webm
Output overview.mp4
Output overview.gif

Set PlaybackSpeed 1.3
Set Theme TokyoNight
Set Padding 0
Set FontSize 24
Set FontFamily "CommitMono Nerd Font"
Set Width 1600
Set Height 800

Hide
Type "gh dash --config demo.yml"

Enter
Sleep 8s
Show

Set TypingSpeed 600ms
Sleep 500ms

Type "j"
Type "j"
Type "]"
Type "]"

Type "?"
Sleep 1s
Type "?"

Hide
Type "d"
Sleep 1s
Type "jjjjjjjjj"
Show
Ctrl+D
Sleep 500ms
Ctrl+D
Sleep 500ms
Ctrl+D
Sleep 300ms
Type j
Sleep 200ms
Type j
Sleep 200ms
Type "q"
Sleep 500ms

Type "c"

Type@60ms "Looks good to me! 🚀"
Sleep 500ms

Hide
Ctrl+c
Type y
Sleep 500ms
Show

Hide
Sleep 2s
Show
Sleep 500ms

Type "l"
Type "l"
Type "l"
Sleep 500ms

Type "s"
Hide
Sleep 7s
Type "j"
Sleep 100ms
Show
Sleep 1500ms


================================================
FILE: docs/src/assets/sections.tape
================================================
Output sections.webm
Output sections.mp4
Output sections.gif

Set Theme TokyoNight
Set Padding 0
Set FontSize 24
Set FontFamily "CommitMono Nerd Font"
Set Width 1200
Set Height 600

Hide
Type "gh dash --config sections.yml"

Enter
Sleep 8s
Show

Sleep 1500ms

Type "l"
Sleep 1000ms

Hide
Type "s"
Sleep 8s
Type "l"
Type "h"
Show

Sleep 1500ms

Type "l"
Sleep 1000ms


================================================
FILE: docs/src/assets/sections.yml
================================================
prSections:
  - title: My Pull Requests
    filters: is:open author:@me owner:dlvhdr
  - title: Needs My Review
    filters: review-requested:@me owner:dlvhdr
issuesSections:
  - title: Ghostty
    filters: is:open ghostty-org/ghostty
  - title: Neovim
    filters: is:open neovim/neovim

defaults:
  preview:
    open: false
    width: 40
  prsLimit: 20
  issuesLimit: 20
  view: repo
keybindings:
  prs: []
repoPaths: {}
pager:
  diff: diffnav
theme:
  colors:
    text:
      primary: "#E2E1ED"
      secondary: "#666CA6"
      inverted: "#242347"
      faint: "#b0b3bf"
      warning: "#F23D5C"
      success: "#3DF294"
    background:
      selected: "#1b1b33"
    border:
      primary: "#383B5B"
      secondary: "#39386B"
      faint: "#2B2B40"
smartFilteringAtLaunch: false


================================================
FILE: docs/src/assets/theme-catpuccin.yml
================================================
prSections:
  - title: My Pull Requests
    filters: is:open author:@me owner:dlvhdr
  - title: Needs My Review
    filters: review-requested:@me owner:dlvhdr
issuesSections:
  - title: Ghostty
    filters: is:open ghostty-org/ghostty
  - title: Neovim
    filters: is:open neovim/neovim

defaults:
  preview:
    open: true
    width: 50
  prsLimit: 20
  issuesLimit: 20
  view: repo
keybindings:
  prs: []
repoPaths: {}
pager:
  diff: diffnav
theme:
  colors:
    text:
      primary: "#89b4fa"
      secondary: "#b4befe"
      inverted: "#181825"
      faint: "#7f849c"
      warning: "#f9e2af"
      success: "#a6e3a1"
    background:
      selected: "#313244"
    border:
      primary: "#9399b2"
      secondary: "#585b70"
      faint: "#313244"
smartFilteringAtLaunch: false


================================================
FILE: docs/src/assets/theme-gruvbox.yml
================================================
prSections:
  - title: My Pull Requests
    filters: is:open author:@me owner:dlvhdr
  - title: Needs My Review
    filters: review-requested:@me owner:dlvhdr
issuesSections:
  - title: Ghostty
    filters: is:open ghostty-org/ghostty
  - title: Neovim
    filters: is:open neovim/neovim

defaults:
  preview:
    open: true
    width: 50
  prsLimit: 20
  issuesLimit: 20
  view: repo
keybindings:
  prs: []
repoPaths: {}
pager:
  diff: diffnav
theme:
  colors:
    text:
      primary: "#fe8019"
      secondary: "#d65d0e"
      inverted: "#3c3836"
      faint: "#d5c4a1"
      warning: "#fabd2f"
      success: "#98971a"
    background:
      selected: "#282828"
    border:
      primary: "#665c54"
      secondary: "#3c3836"
      faint: "#1d2021"
smartFilteringAtLaunch: false


================================================
FILE: docs/src/assets/theme-tokyonight.yml
================================================
prSections:
  - title: My Pull Requests
    filters: is:open author:@me owner:dlvhdr
  - title: Needs My Review
    filters: review-requested:@me owner:dlvhdr
issuesSections:
  - title: Ghostty
    filters: is:open ghostty-org/ghostty
  - title: Neovim
    filters: is:open neovim/neovim

defaults:
  preview:
    open: true
    width: 50
  prsLimit: 20
  issuesLimit: 20
  view: repo
keybindings:
  prs: []
repoPaths: {}
pager:
  diff: diffnav
theme:
  colors:
    text:
      primary: "#E2E1ED"
      secondary: "#666CA6"
      inverted: "#242347"
      faint: "#b0b3bf"
      warning: "#F23D5C"
      success: "#3DF294"
    background:
      selected: "#1b1b33"
    border:
      primary: "#383B5B"
      secondary: "#39386B"
      faint: "#2B2B40"
smartFilteringAtLaunch: false


================================================
FILE: docs/src/components/Box.astro
================================================
---
import { Icon } from "@astrojs/starlight/components";

const { header, icon } = Astro.props;
---

<div class="relative flex w-full max-w-full flex-row gap-6 lg:w-auto">
  <div
    class="w-full border border-[var(--sl-color-gray-5)] bg-[var(--sl-color-black)] p-2 py-6 lg:w-lg lg:p-6"
  >
    <div
      class="is-dark:bg-[var(--sl-color-gray-5)] absolute -top-4 right-2 left-2 z-10 max-w-full rounded-2xl bg-[var(--sl-color-gray-6)] px-2 lg:right-auto lg:px-3"
    >
      <h3
        class="flex items-center gap-2 !text-base text-[var(--sl-color-accent)]"
      >
        <Icon class="inline" name={icon} size="20px" />
        {header}
      </h3>
    </div>
    <slot />
  </div>
</div>


================================================
FILE: docs/src/components/DashHeroLogo.astro
================================================
---
import Logo from "./Logo.astro";
---

<style>
  @keyframes dash-in {
    from {
      opacity: 0;
      filter: blur(1rem);
      translate: -50vw 0;
    }

    to {
      opacity: 1;
      filter: blur(0);
      translate: 0 0;
    }
  }

  #title-logo {
    animation: dash-in 400ms ease-out;
    h1 {
      line-height: 1.3;
      background-image: var(--hdr-gradient);
      background-size: 100%;
      background-clip: text;
      -webkit-background-clip: text;
      -webkit-text-fill-color: transparent;
      -moz-background-clip: text;
      -moz-text-fill-color: transparent;
      background-repeat: repeat;
    }
    transform: skew(-20deg);

    & > [aria-label="DASH ASCII Logo"] {
      transform: skew(0);
    }
  }
</style>

<div
  id="title-logo"
  class="relative flex flex-col items-center justify-center gap-[1ch] text-white lg:flex-row lg:items-baseline-last lg:gap-[3ch]"
>
  <div class="relative -left-2 flex flex-row items-center gap-8 md:left-0">
    {/* prettier-ignore */}
    <pre
      class="!bg-transparent p-0 text-[var(--sl-color-gray-4)]">  ·-
·---
  --
</pre>
    <Logo className="inline text-3xl md:left-0 lg:text-4xl" />
  </div>
  <h1
    id="_top"
    aria-label="DASH Through Your GitHub"
    class="mt-0 w-full translate-x-8 text-center -indent-4 text-2xl leading-normal lg:w-auto lg:translate-x-0 lg:text-left lg:indent-0 lg:text-4xl"
  >
    Through <br />
    Your GitHub
  </h1>
</div>


================================================
FILE: docs/src/components/DecorationBottom.astro
================================================
---

---

<pre
  class="!bg-transparent leading-normal text-[var(--sl-color-gray-4)]">
 ────────────────·.   .·──────────────── 
(                  \_/                  )
 ‾                                     ‾ 
</pre>


================================================
FILE: docs/src/components/DecorationSeparator.astro
================================================
---

---

<pre
  class="!bg-transparent leading-normal text-[var(--sl-color-gray-4)]">
  {"<~-----------------◇-----------------~>"}
</pre>


================================================
FILE: docs/src/components/DecorationTop.astro
================================================
---

---

<pre
  class="!bg-transparent leading-normal text-[var(--sl-color-gray-4)]">
 _                  _                  _ 
(                  / \                  )
 ────────────────·´   `·──────────────── 
</pre>


================================================
FILE: docs/src/components/DiffnavCard.astro
================================================
---
import { Icon } from "@astrojs/starlight/components";
import DiffnavMiniLogo from "./DiffnavMiniLogo.astro";
---

<a
  href="https://github.com/dlvhdr/diffnav"
  target="_blank"
  class="no-underline"
>
  <div
    class="flex w-full flex-row items-center gap-8 border border-[var(--sl-color-gray-4)] p-4 no-underline hover:bg-[var(--sl-color-gray-6)]"
  >
    <div class="flex flex-col gap-4">
      <DiffnavMiniLogo />
      <Icon
        name="right-arrow"
        size="24px"
        class="mt-0 animate-pulse self-center rounded-full bg-[var(--sl-color-gray-4)] md:hidden"
      />
    </div>
    <Icon
      name="right-arrow"
      size="24px"
      class="relative -left-4 mt-0 hidden min-w-max animate-pulse justify-self-end rounded-full bg-[var(--sl-color-gray-4)] md:block"
    />
  </div>
</a>


================================================
FILE: docs/src/components/DiffnavMiniLogo.astro
================================================
---
const { class: className } = Astro.props;
---

<style>
  [aria-label="DIFFNAV ASCII Logo"] {
    position: relative;
    background-image: var(--hdr-green-red-gradient);
    background-size: 100%;
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    -moz-background-clip: text;
    -moz-text-fill-color: transparent;
    background-repeat: repeat;
    border: none;
    padding: 0;
  }
</style>

<div class="inline-flex flex-col">
  <pre
    aria-label="DIFFNAV ASCII Logo"
    class:list={[
      "w-fit text-xl leading-none lg:text-lg",
      className,
    ]}>
▜▔▚ ▌▐▔▔▐▔▔▐▚ ▌▐▔▌▐ ▞
▟▁▞ ▌▐▔ ▐▔ ▐ ▚▌▐▔▌▐▞ </pre>
  <p class="mt-4 ml-1 p-0 text-sm text-[var(--sl-color-white)]">
    A git diff pager based on delta but with a file tree, à la GitHub.
  </p>
</div>


================================================
FILE: docs/src/components/Discord.astro
================================================
---
import { Icon } from "@astrojs/starlight/components";

const { class: className } = Astro.props;
---

<div class:list={["text-center text-pretty lg:w-lg", className]}>
  <h2>
    <Icon class="relative -top-0.5 inline align-middle" name="discord" /> Join Our
    Discord Community
  </h2>
  <p>
    If you want to keep up with the TUIs I'm developing or just want to nerd out
    about the terminal - <br /><a
      href="https://discord.gg/SXNXp9NctV"
      target="_blank">come join us!</a
    >
  </p>
</div>


================================================
FILE: docs/src/components/EnhanceCard.astro
================================================
---
import { Icon } from "@astrojs/starlight/components";
import EnhanceMiniLogo from "./EnhanceMiniLogo.astro";
---

<a href="/enhance" class="no-underline">
  <div
    class="flex w-full flex-row items-center gap-8 border border-[var(--sl-color-gray-4)] p-4 no-underline hover:bg-[var(--sl-color-gray-6)]"
  >
    <div class="flex flex-col gap-4">
      <EnhanceMiniLogo />
      <Icon
        name="right-arrow"
        size="24px"
        class="mt-0 animate-pulse self-center rounded-full bg-[var(--sl-color-gray-4)] md:hidden"
      />
    </div>
    <Icon
      name="right-arrow"
      size="24px"
      class="relative -left-4 mt-0 hidden min-w-max animate-pulse justify-self-end rounded-full bg-[var(--sl-color-gray-4)] md:block"
    />
  </div>
</a>


================================================
FILE: docs/src/components/EnhanceLogo.astro
================================================
---
const { className } = Astro.props;
---

<style>
  [aria-label="ENHANCE ASCII Logo"] {
    position: relative;
    background-image: var(--hdr-green-gradient);
    background-size: 100%;
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    -moz-background-clip: text;
    -moz-text-fill-color: transparent;
    background-repeat: repeat;
  }

  [aria-label="Magnifying Glass"] {
    background-image: var(--radial-silver-gradient);
    background-size: 100%;
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    -moz-background-clip: text;
    -moz-text-fill-color: transparent;
    background-repeat: repeat;
  }
</style>

<div class={`relative ${className}`}>
  <pre
    aria-label="Magnifying Glass"
    class="absolute -top-[80%] -z-1 text-lg leading-[1.1] -tracking-[1px] opacity-45 md:-left-1/8">
      _.-·--._      
    .´        `.    
   ╱            \   
  ¡             ▕   
  |        ╱╱   ;|  
  :        ╱╱   ;;  
  :╲          .´/   
   \`-.__..·-´.'    
    `╱╱╱___.-´      
    ╱╱╱             
   ╱╱╱              
  ╱╱╱               
 (_╱                
</pre>
  <pre
    aria-label="ENHANCE ASCII Logo"
    class="text-2xl leading-none lg:text-3xl">
▐▔▔▐▚ ▌▐ ▌▐▔▌▐▚ ▌▐▔▔▐▔▔
▐▛▁▐ ▚▌▐▔▌▐▔▌▐ ▚▌▐▁▁▐▛▁
</pre>
</div>


================================================
FILE: docs/src/components/EnhanceMiniLogo.astro
================================================
---
const { class: className } = Astro.props;
---

<style>
  [aria-label="ENHANCE ASCII Logo"] {
    position: relative;
    background-image: var(--hdr-green-gradient);
    background-size: 100%;
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    -moz-background-clip: text;
    -moz-text-fill-color: transparent;
    background-repeat: repeat;
    border: none;
    padding: 0;
  }
</style>

<div class="inline-flex flex-col">
  <pre
    aria-label="ENHANCE ASCII Logo"
    class:list={[
      "text-xl leading-none lg:text-lg",
      className,
    ]}>
▐▔▔▐▚ ▌▐ ▌▐▔▌▐▚ ▌▐▔▔▐▔▔
▐▛▁▐ ▚▌▐▔▌▐▔▌▐ ▚▌▐▁▁▐▛▁</pre>
  <p class="mt-4 ml-1 p-0 text-sm text-[var(--sl-color-white)]">
    A Blazingly Fast Terminal UI for GitHub Actions
  </p>
</div>


================================================
FILE: docs/src/components/EnhanceOneLineLogo.astro
================================================
---
const { class: className } = Astro.props;
---

<style>
  [aria-label="ENHANCE ASCII Logo"] {
    position: relative;
    background-image: var(--hdr-green-gradient);
    background-size: 100%;
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    -moz-background-clip: text;
    -moz-text-fill-color: transparent;
    background-repeat: repeat;
    border: none;
    padding: 0;
    margin: 0;
  }
</style>

<div>
  <pre
    aria-label="ENHANCE ASCII Logo"
    class:list={[
      "text-xs leading-none",
      className,
    ]}>
▐▔▔▐▚ ▌▐ ▌▐▔▌▐▚ ▌▐▔▔▐▔▔
▐▛▁▐ ▚▌▐▔▌▐▔▌▐ ▚▌▐▁▁▐▛▁</pre>
</div>


================================================
FILE: docs/src/components/FadeImages.astro
================================================
---
import "../styles/fade-images.css";
---

<div class="fadein h-full w-full">
  <slot />
</div>


================================================
FILE: docs/src/components/FeatureCard.astro
================================================
---
import FeatureSponsorshipGoal from "./FeatureSponsorshipGoal.astro";

const PROJECTS = {
  dash: {
    url: "/",
    colorClass: "text-[var(--sl-color-accent-high)]",
  },
  enhance: {
    url: "/enhance",
    colorClass: "text-[#38E796]",
  },
} as const;

interface Props {
  project: keyof typeof PROJECTS;
  feature: string;
  description: string;
  variant?: "mini" | "full";
  future?: boolean;
}

const {
  feature,
  future = false,
  description,
  project,
  variant = "full",
} = Astro.props;
---

<div class="w-full">
  <form action={`${PROJECTS[project].url}`}>
    <button
      type="submit"
      class="w-full border-none bg-transparent text-left hover:no-underline!"
    >
      <div
        class="flex w-full flex-row items-center gap-8 border border-[var(--sl-color-gray-4)] p-4 no-underline hover:bg-[var(--sl-color-gray-6)]"
      >
        <div class="p-2">
          {
            variant === "mini" ? null : (
              <div
                class={`${PROJECTS[project].colorClass} inline w-auto rounded bg-[var(--sl-color-gray-5)] p-1 text-sm tracking-wide`}
              >
                <span class="uppercase">{project}</span> FEATURE
              </div>
            )
          }
          <FeatureSponsorshipGoal
            server:defer
            variant="mini"
            feature={feature}
            description={description}
            future={future}
          >
            <div
              slot="fallback"
              class="h-9 w-full animate-pulse rounded bg-[var(--sl-color-gray-6)]"
            >
            </div>
          </FeatureSponsorshipGoal>
        </div>
      </div>
    </button>
  </form>
</div>


================================================
FILE: docs/src/components/FeatureSponsorshipGoal.astro
================================================
---
import { getSponsorshipGoal } from "../data/sponsorshipGoal";
import { Icon } from "@astrojs/starlight/components";

const { variant, future = false, feature, description } = Astro.props;

const response = await getSponsorshipGoal();
const current = response.data.user.monthlyEstimatedSponsorsIncomeInCents / 100;
const GOAL = 250; // USD
---

<div class={`mt-0 max-w-full md:max-w-[80ch]`}>
  <label
    for="sponsorship-goal"
    class="mt-0 mb-0 text-sm text-pretty text-[var(--sl-color-gray-3)]"
  >
    {
      variant !== "mini" ? (
        <div class="hidden md:block">
          <Icon
            name="information"
            size="16px"
            class="mr-1/2 relative -bottom-[2.5px] inline"
          />
          Get early access through the
          <a
            class="text-[var(--sl-color-gray-2)] no-underline"
            href="/insiders"
          >
            Insiders Program
          </a>
        </div>
      ) : null
    }
  </label>
  <div class="flex flex-col gap-2">
    <h3 class="mt-0 mb-0 text-xl font-bold">{feature}</h3>
    <p class="mt-0 text-base">{description}</p>
  </div>

  {
    future ? null : (
      <div class="relative mt-4 text-center">
        <progress
          id="sponsorship-goal"
          value={current}
          max={GOAL}
          class="h-4 w-full appearance-none [&::-moz-progress-bar]:bg-pink-200 dark:[&::-moz-progress-bar]:bg-pink-300 [&::-webkit-progress-bar]:rounded [&::-webkit-progress-bar]:bg-[var(--sl-color-gray-5)] [&::-webkit-progress-value]:rounded [&::-webkit-progress-value]:bg-pink-400 dark:[&::-webkit-progress-value]:bg-pink-800"
        >
          {Intl.NumberFormat("en-US", {
            style: "currency",
            currency: "USD",
          }).format(current)}{" "}
          /{" "}
          {Intl.NumberFormat("en-US", {
            style: "currency",
            currency: "USD",
          }).format(GOAL)}
        </progress>
        <p class="absolute -top-[0.6rem] right-0 left-0 text-xs text-[var(--sl-color-gray-2)] mix-blend-hard-light dark:mix-blend-lighten">
          {Intl.NumberFormat("en-US", { maximumFractionDigits: 2 }).format(
            (current / GOAL) * 100,
          )}
          % towards ${GOAL} per month goal
        </p>
        <p
          class={`mt-0 text-xs text-pretty text-[var(--sl-color-gray-3)] md:text-sm`}
        >
          Hitting the goal will open source it for everyone
        </p>
      </div>
    )
  }
</div>


================================================
FILE: docs/src/components/Footer.astro
================================================
---
import DecorationTop from "./DecorationTop.astro";
import DecorationBottom from "./DecorationBottom.astro";

const { class: className, isCommunity = true } = Astro.props;
---

<div
  class:list={[
    "flex flex-col items-center p-8 text-center !text-sm",
    className,
  ]}
>
  <DecorationTop />
  <p class="mb-2">
    Created and maintained by <a href="https://github.com/dlvhdr">@dlvhdr</a>{
      isCommunity ? (
        <>
          {" "}
          and the{" "}
          <a href="https://github.com/dlvhdr/gh-dash/graphs/contributors">
            community
          </a>
        </>
      ) : null
    }
  </p>
  <div class="flex gap-3">
    <a
      class={"flex items-center gap-2 text-[var(--sl-color-accent-low)] no-underline hover:underline rounded-lg border border-[var(--sl-color-gray-5)] bg-[var(--sl-color-black)] px-2 py-1 text-xs"}
      href="https://charm.sh"
      target="_blank"
    >
      Built with: <span class="underline">Charm</span>
    </a>
    <a
      class={"flex items-center gap-2 text-[var(--sl-color-accent-low)] no-underline hover:underline rounded-lg border border-[var(--sl-color-gray-5)] bg-[var(--sl-color-black)] px-2 py-1 text-xs"}
      href="https://github.com/tokyo-night/tokyo-night-vscode-theme"
      target="_blank"
    >
      Theme: <span class="underline">Tokyo Night</span>
    </a>
  </div>
  <DecorationBottom />
</div>


================================================
FILE: docs/src/components/Header.astro
================================================
---
import Search from "@astrojs/starlight/components/Search.astro";
import Logo from "./Logo.astro";
import { Icon } from "@astrojs/starlight/components";
import PillLink from "./PillLink.astro";
import ThemeSelect from "./ThemeSelect.astro";
import StargazersCount from "./StargazersCount.astro";
import StargazersFallback from "./StargazersFallback.astro";

const isDashHomepage = Astro.locals.starlightRoute.id === "";
const isEnhanceHomepage = Astro.locals.starlightRoute.id === "enhance";
---

<div class="bg-[var(--sl-color-bg)] px-2 py-2 lg:px-6">
  <div
    class="flex max-w-[100vw] flex-row items-center gap-3 rounded border border-[var(--sl-color-gray-5)] py-2 pr-2 pl-4 lg:gap-3 lg:px-6"
  >
    <div class="flex grow items-end">
      <a href="/" class="no-underline">
        <Logo />
      </a>
      {
        isEnhanceHomepage ? (
          <p class="ml-2 hidden h-min text-sm leading-[18px] text-orange-400 uppercase md:block dark:text-orange-600">
            Companion
          </p>
        ) : null
      }
    </div>
    <form action="/insiders/" class="flex items-center">
      <button
        class="dark:bg-orange-250 relative h-8 rounded border border-orange-200 bg-orange-100 px-1 text-sm text-orange-600 hover:bg-orange-200 hover:text-orange-700 hover:!no-underline md:h-[38px] md:px-3 lg:text-base dark:border-orange-900 dark:bg-orange-950 dark:text-orange-400 dark:hover:bg-orange-900 dark:hover:text-orange-200"
      >
        <span class="hidden md:block">🌟 Join Insiders</span>
        <span class="flex flex-row items-center gap-1 md:hidden">
          <Icon name="heart" size="16px" color="var(--color-red-500)" />
          Donate
        </span>
      </button>
    </form>
    {
      isDashHomepage ? (
        <PillLink href="/getting-started" class="hidden lg:block">
          <>
            <Icon name="document" size="20px" />
            <span class="hidden lg:block"> Docs</span>
          </>
        </PillLink>
      ) : null
    }
    <div class="hidden md:block">
      <StargazersCount server:defer>
        <StargazersFallback slot="fallback" />
      </StargazersCount>
    </div>
    <PillLink class="hidden lg:block" href="/donating">
      <Icon name="heart" size="20px" color="var(--color-red-500)" /><span
        class="hidden lg:block"
      >
        Donate</span
      >
    </PillLink>
    <PillLink
      class="hidden lg:block"
      href="https://discord.gg/SXNXp9NctV"
      target="_blank"
    >
      <Icon name="discord" size="20px" />
    </PillLink>
    <Search />
    <div class="hidden md:block">
      <ThemeSelect />
    </div>
  </div>
</div>


================================================
FILE: docs/src/components/Hero.astro
================================================
---
import Default from "@astrojs/starlight/components/PageTitle.astro";
import Logo from "./Logo.astro";
import EnhanceLogo from "./EnhanceLogo.astro";
import ReleaseVersionButton from "./ReleaseVersionButton.astro";
import Terminal from "./Terminal.astro";
import { Icon } from "@astrojs/starlight/components";

const { tagline, githubUrl, videoUrl, getStartedUrl } = Astro.props;
---

<div class="flex flex-col-reverse items-center gap-16 2xl:flex-row 2xl:gap-6">
  <Terminal>
    <video autoplay loop muted playsinline class="w-[95vw] lg:w-[800px]">
      <source src={`/${videoUrl}.webm`} type="video/webm" />
      <source src={`/${videoUrl}.mp4`} type="video/mp4" />
    </video>
  </Terminal>
  <div class="flex w-full shrink-[5] flex-col items-center">
    <slot />
    <div class="flex flex-row items-center gap-1">
      <form action={`${githubUrl}/releases`}>
        <ReleaseVersionButton server:defer>
          <button
            slot="fallback"
            class="m-0 h-7 w-16 animate-pulse rounded-lg bg-[var(--sl-color-black)] px-2 py-2 text-sm text-[var(--sl-color-gray-3)]"
          ></button>
        </ReleaseVersionButton>
      </form>
      <button
        class="m-0 rounded-lg bg-[var(--sl-color-black)] px-2 py-1 text-sm text-[var(--sl-color-gray-3)]"
      >
        Build: passing
      </button>
    </div>
    <h2
      class="text-center !text-xl font-normal text-pretty lg:w-[30ch] lg:!text-2xl"
    >
      {tagline}
    </h2>
    <div
      id="main-buttons"
      class="mt-8 flex flex-col items-center gap-4 md:flex-row"
    >
      <form action={getStartedUrl}>
        <button
          class="flex items-center justify-center gap-1 bg-[var(--sl-color-accent-high)] font-bold text-[var(--sl-color-black)]"
          >Get started <Icon
            class="inline"
            name="right-arrow"
            size="20px"
          /></button
        >
      </form>
      <form class="m-0" action={githubUrl} target="_blank">
        <button
          class="flex items-center justify-center gap-1 bg-[var(--sl-color-gray-6)] text-[var(--sl-color-white)]"
          >View on GitHub <Icon class="inline" name="external" size="20px" />
        </button>
      </form>
    </div>
  </div>
</div>


================================================
FILE: docs/src/components/Logo.astro
================================================
---
const { className } = Astro.props;
---

<style>
  [aria-label="DASH ASCII Logo"] {
    transform: skew(-20deg);
    width: fit-content;
    background-image: var(--hdr-gradient);
    background-size: 100%;
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    -moz-background-clip: text;
    -moz-text-fill-color: transparent;
    background-repeat: repeat;
  }
</style>

<div
  aria-label="DASH ASCII Logo"
  class={`leading-[1.09] text-blue-300 not-dark:text-blue-500 ${className}`}
>
  ▜▔▚▐▔▌▚▔▐ ▌<br />
  ▟▁▞▐▔▌▁▚▐▔▌
</div>


================================================
FILE: docs/src/components/NerdFontIcon.astro
================================================
---
const { icon } = Astro.props;
import "../styles/nerd-font.css";
---

<code class="rounded bg-blue-950 text-xl text-blue-200"
  ><i class={`nf ${icon}`}></i></code
>


================================================
FILE: docs/src/components/PillLink.astro
================================================
---
const { href, target, class: className } = Astro.props;
---

<a
  class:list={[
    "flex items-center gap-2 text-[var(--sl-color-accent-low)] no-underline hover:underline",
    className,
  ]}
  href={href}
  target={target}
>
  <div
    class="flex h-[38px] items-center gap-2 rounded-lg px-1 text-[var(--sl-color-accent-low)] hover:bg-[var(--sl-color-gray-5)] lg:border lg:border-[var(--sl-color-gray-5)] lg:bg-[var(--sl-color-black)] lg:px-2 lg:py-1"
  >
    <slot />
  </div>
</a>


================================================
FILE: docs/src/components/ReleaseVersionButton.astro
================================================
---
import { getLatestVersion } from "../data/latestVersion";

const response = await getLatestVersion();
---

<form action="https://github.com/dlvhdr/gh-dash/releases">
  <button
    class="m-0 rounded-lg bg-[var(--sl-color-black)] px-2 py-1 text-sm text-[var(--sl-color-gray-3)]"
    >{response?.tag_name}</button
  >
</form>


================================================
FILE: docs/src/components/Showcase.astro
================================================
---
const { reversed } = Astro.props;
---

<div class={`flex flex-col gap-8 w-full lg:w-auto lg:gap-18 items-center`}>
  <div
    class={`flex w-full flex-col gap-0 items-center lg:gap-8 ${reversed ? "lg:flex-row-reverse" : "lg:flex-row"}`}
  >
    <slot />
  </div>
  <div class="mt-0 text-[var(--sl-color-gray-5)]">──◇──</div>
</div>


================================================
FILE: docs/src/components/Sponsorship.astro
================================================
---
import { getSponsorshipGoal } from "../data/sponsorshipGoal";

const response = await getSponsorshipGoal();
const current = response.data.user.monthlyEstimatedSponsorsIncomeInCents / 100;
const GOAL = 250; // USD
---

<div class={`text-center mt-0 max-w-full md:max-w-[80ch]`}>
  <div class="relative mt-1">
    <progress
      id="sponsorship-goal"
      value={current}
      max={GOAL}
      class="h-4 w-full appearance-none [&::-moz-progress-bar]:bg-pink-200 dark:[&::-moz-progress-bar]:bg-pink-300 [&::-webkit-progress-bar]:rounded [&::-webkit-progress-bar]:bg-[var(--sl-color-gray-5)] [&::-webkit-progress-value]:rounded [&::-webkit-progress-value]:bg-pink-400 dark:[&::-webkit-progress-value]:bg-pink-800"
    >
      {
        Intl.NumberFormat("en-US", {
          style: "currency",
          currency: "USD",
        }).format(current)
      } / {
        Intl.NumberFormat("en-US", {
          style: "currency",
          currency: "USD",
        }).format(GOAL)
      }
    </progress>
    <p
      class="absolute -top-[0.6rem] right-0 left-0 text-xs text-[var(--sl-color-gray-2)] mix-blend-hard-light dark:mix-blend-lighten"
    >
      {
        Intl.NumberFormat("en-US", { maximumFractionDigits: 2 }).format(
          (current / GOAL) * 100,
        )
      }% towards ${GOAL} per month goal
    </p>
  </div>
</div>


================================================
FILE: docs/src/components/SponsorshipGoal.astro
================================================
---
import { getSponsorshipGoal } from "../data/sponsorshipGoal";
import { Icon } from "@astrojs/starlight/components";

const { variant } = Astro.props;

const response = await getSponsorshipGoal();
const current = response.data.user.monthlyEstimatedSponsorsIncomeInCents / 100;
const GOAL = 150; // USD
---

<div class={`text-center mt-0 max-w-full md:max-w-[80ch]`}>
  <label
    for="sponsorship-goal"
    class="mt-0 mb-0 text-sm text-pretty text-[var(--sl-color-gray-3)]"
  >
    {
      variant !== "mini" ? (
        <div class="hidden md:block">
          <Icon
            name="information"
            size="16px"
            class="mr-1/2 relative -bottom-[2.5px] inline"
          />
          Get early access through the
          <a
            class="text-[var(--sl-color-gray-2)] no-underline"
            href="/insiders"
          >
            Insiders Program
          </a>
        </div>
      ) : null
    }
  </label>
  <div class="relative mt-1">
    <progress
      id="sponsorship-goal"
      value={current}
      max={GOAL}
      class="h-4 w-full appearance-none [&::-moz-progress-bar]:bg-pink-200 dark:[&::-moz-progress-bar]:bg-pink-300 [&::-webkit-progress-bar]:rounded [&::-webkit-progress-bar]:bg-[var(--sl-color-gray-5)] [&::-webkit-progress-value]:rounded [&::-webkit-progress-value]:bg-pink-400 dark:[&::-webkit-progress-value]:bg-pink-800"
    >
      {
        Intl.NumberFormat("en-US", {
          style: "currency",
          currency: "USD",
        }).format(current)
      } / {
        Intl.NumberFormat("en-US", {
          style: "currency",
          currency: "USD",
        }).format(GOAL)
      }
    </progress>
    <p
      class="absolute -top-[0.6rem] right-0 left-0 text-xs text-[var(--sl-color-gray-2)] mix-blend-hard-light dark:mix-blend-lighten"
    >
      {
        Intl.NumberFormat("en-US", { maximumFractionDigits: 2 }).format(
          (current / GOAL) * 100,
        )
      }% towards ${GOAL} per month goal
    </p>
  </div>
  <p
    class={`flex justify-center items-center gap-2 mt-0 md:mt-0 mb-0 text-xs md:text-sm text-[var(--sl-color-gray-3) text-pretty`}
  >
    <span
      class="hidden text-pink-400 md:inline-block md:align-middle dark:text-pink-600"
    >
      <Icon class="inline align-text-top" name="heart" size="16px" />
    </span> Hitting the goal will open source the app
  </p>
</div>


================================================
FILE: docs/src/components/StargazersCount.astro
================================================
---
import { Icon } from "@astrojs/starlight/components";
import PillLink from "./PillLink.astro";
import { getStars } from "../data/stars";

const response = await getStars();
---

<PillLink href="https://github.com/dlvhdr/gh-dash" target="_blank">
  <Icon name="github" size="20px" /><span class="hidden lg:block"
    >{
      Intl.NumberFormat("en-US", {
        notation: "compact",
        maximumSignificantDigits: 2,
      })
        .format(response.stargazers_count)
        .toLocaleLowerCase()
    }</span
  >
</PillLink>


================================================
FILE: docs/src/components/StargazersFallback.astro
================================================
---
import { Icon } from "@astrojs/starlight/components";
import PillLink from "./PillLink.astro";
---

<PillLink href="https://github.com/dlvhdr/gh-dash" target="_blank">
  <Icon name="github" size="20px" />{" "}
  <span class="animate-pulse">GitHub</span>
</PillLink>


================================================
FILE: docs/src/components/SupportSection.astro
================================================
---
import { Icon } from "@astrojs/starlight/components";
import Sponsorship from "../components/Sponsorship.astro";
---

<h2 class="mt-8 mb-2 text-center !text-3xl">Donate To Support the Project</h2>

<div class="mt-12 flex flex-col gap-2 text-center">
  <p class="text-pretty lg:w-[80ch]">
    I'm always working on new terminal UIs to make my life easier.<br />By
    donating or joining <a href="/insiders">Insiders</a> you can support this and
    any of my other projects.<br />
  </p>
  <div class="m-auto flex max-w-lg flex-col justify-center">
    <p class="mt-4 text-[var(--sl-color-gray-3)]">
      This is my current sponsorship goal
    </p>
    <Sponsorship server:defer />
  </div>
</div>

<form action="/donating" class="flex w-full justify-center pt-8">
  <button
    type="submit"
    class="flex items-center gap-2 bg-[var(--sl-color-accent)] px-4 py-2 font-bold text-black"
  >
    Donate!
    <Icon class="mt-0" name="heart" size="20px" color="var(--color-pink-800)" />
  </button>
</form>


================================================
FILE: docs/src/components/Terminal.astro
================================================
---
import "../styles/terminal.css";
const { className, title = "gh dash" } = Astro.props;
---

<div class={`terminal ${className}`}>
  <div class="top">
    <div class="btns">
      <span class="circle red"></span>
      <span class="circle yellow"></span>
      <span class="circle green"></span>
    </div>
    <div class="terminal-title">{title} -- 70x32</div>
  </div>
  <div class="body">
    <slot />
  </div>
</div>


================================================
FILE: docs/src/components/ThemeSelect.astro
================================================
---
import Select from "@astrojs/starlight/components/Select.astro";
---

<starlight-theme-select>
  {
    /* TODO: Can we give this select a width that works well for each language’s strings? */
  }
  <Select
    icon="laptop"
    label={Astro.locals.t("themeSelect.accessibleLabel")}
    options={[
      {
        label: Astro.locals.t("themeSelect.dark"),
        selected: false,
        value: "dark",
      },
      {
        label: Astro.locals.t("themeSelect.light"),
        selected: false,
        value: "light",
      },
      {
        label: Astro.locals.t("themeSelect.auto"),
        selected: true,
        value: "auto",
      },
    ]}
    width="20px"
  />
</starlight-theme-select>

{/* Inlined to avoid FOUC. Uses global scope from `ThemeProvider.astro` */}
<script is:inline>
  StarlightThemeProvider.updatePickers();
</script>

<script>
  type Theme = "auto" | "dark" | "light";

  /** Key in `localStorage` to store color theme preference at. */
  const storageKey = "starlight-theme";

  /** Get a typesafe theme string from any JS value (unknown values are coerced to `'auto'`). */
  const parseTheme = (theme: unknown): Theme =>
    theme === "auto" || theme === "dark" || theme === "light" ? theme : "auto";

  /** Load the user’s preference from `localStorage`. */
  const loadTheme = (): Theme =>
    parseTheme(
      typeof localStorage !== "undefined" && localStorage.getItem(storageKey),
    );

  /** Store the user’s preference in `localStorage`. */
  function storeTheme(theme: Theme): void {
    if (typeof localStorage !== "undefined") {
      localStorage.setItem(
        storageKey,
        theme === "light" || theme === "dark" ? theme : "",
      );
    }
  }

  /** Get the preferred system color scheme. */
  const getPreferredColorScheme = (): Theme =>
    matchMedia("(prefers-color-scheme: light)").matches ? "light" : "dark";

  /** Update select menu UI, document theme, and local storage state. */
  function onThemeChange(theme: Theme): void {
    StarlightThemeProvider.updatePickers(theme);
    document.documentElement.dataset.theme =
      theme === "auto" ? getPreferredColorScheme() : theme;
    storeTheme(theme);
  }

  // React to changes in system color scheme.
  matchMedia(`(prefers-color-scheme: light)`).addEventListener("change", () => {
    if (loadTheme() === "auto") onThemeChange("auto");
  });

  class StarlightThemeSelect extends HTMLElement {
    constructor() {
      super();
      onThemeChange(loadTheme());
      this.querySelector("select")?.addEventListener("change", (e) => {
        if (e.currentTarget instanceof HTMLSelectElement) {
          onThemeChange(parseTheme(e.currentTarget.value));
        }
      });
    }
  }
  customElements.define("starlight-theme-select", StarlightThemeSelect);
</script>


================================================
FILE: docs/src/content/docs/companions/enhance/dash-integration.mdx
================================================
---
title: DASH Integration
---

In order to launch `ENHANCE` from `DASH` [add a custom keybind](../../../configuration/keybindings) to your
`DASH` config:

```yaml
keybindings:
  prs:
    - key: T
      command: gh enhance -R {{.RepoName}} {{.PrNumber}}
```

_Note: You can change the <kbd>T</kbd> keybind to whatever you want, I just remember it
by the `Test` mnemonic._

## Using `tmux`

If you're working with `tmux`, you can also launch it in a new window:

```yaml
keybindings:
  prs:
    - key: T
      command: >-
        tmux new-window '
          gh enhance -R {{.RepoName}} {{.PrNumber}}
        '
```


================================================
FILE: docs/src/content/docs/companions/enhance/getting-started.mdx
================================================
---
title: Installation
---

import { Aside } from "@astrojs/starlight/components";

Get started using `ENHANCE` to manage your PRs GitHub Actions.

## Recommended Steps

1. Install the `gh` CLI

   ```bash
   brew install gh # e.g. if on macOS
   ```

   Or, see the [installation instructions][01] for other platforms.

2. Install this extension:

   ```sh
   # if you're *not* in the insiders program
   gh extension install dlvhdr/gh-enhance

   # if you are in the insiders program
   gh extension install dlvhdr-insiders/gh-enhance

   ```

3. To get the icons to render properly, you should download and install a [Nerd font][02]. Then,
   select that font as your font for your terminal of choice.

   ```bash
    brew install --cask font-fira-code-nerd-font
   ```

---

<details>
<summary>How do I get these exact colors and font?</summary>
The screenshots in this documentation use [Ghostty][n01] with the
[tokyonight theme][n02] and the [Fira Code][n03] Nerd Font. For the full setup,
see [these dotfiles][n04].

[n01]: https://ghostty.org/
[n02]: https://github.com/folke/tokyonight.nvim
[n03]: https://github.com/ryanoasis/nerd-fonts/tree/master/patched-fonts/FiraCode
[n04]: https://github.com/dlvhdr/dotfiles

</details>

---

## Manual Steps

If you want to install this extension **manually**, follow these steps:

1. Clone the repo

- If you're **not** in the insiders program:

  ```bash
  # Git
  git clone https://github.com/dlvhdr/gh-enhance

  # or with the GitHub CLI
  gh repo clone dlvhdr/gh-enhance
  ```

- If you are in the insiders program:

  ```bash
    # Git
    git clone https://github.com/dlvhdr-insiders/gh-enhance

    # or with the GitHub CLI
    gh repo clone dlvhdr-insiders/gh-enhance
  ```

2. `cd` into it

   ```bash
   cd gh-enhance
   ```

3. Install it locally

   ```bash
   gh extension install .
   ```

[01]: https://github.com/cli/cli#installation
[02]: https://www.nerdfonts.com/


================================================
FILE: docs/src/content/docs/companions/enhance/index.mdx
================================================
---
title: ENHANCE
---


================================================
FILE: docs/src/content/docs/companions/enhance/keybindings.mdx
================================================
---
title: Keybindings
---

`ENHANCE` supports the following keybindings.

## Navigating

| Key            | Action        |
| -------------- | ------------- |
| <kbd>j/↓</kbd> | next row      |
| <kbd>k/↑</kbd> | previous row  |
| <kbd>l</kbd>   | next pane     |
| <kbd>h</kbd>   | previous pane |
| <kbd>g</kbd>   | go to top     |
| <kbd>G</kbd>   | go to bottom  |
| <kbd>→</kbd>   | move right    |
| <kbd>←</kbd>   | move left     |
| <kbd>?</kbd>   | toggle help   |

## Searching

| Key               | Action         |
| ----------------- | -------------- |
| <kbd>/</kbd>      | search in pane |
| <kbd>esc</kbd>    | cancel search  |
| <kbd>enter</kbd>  | apply search   |
| <kbd>ctrl+n</kbd> | next match     |
| <kbd>ctrl+p</kbd> | prev match     |

## Actions

| Key               | Action                           |
| ----------------- | -------------------------------- |
| <kbd>m</kbd>      | switch between flat/grouped mode |
| <kbd>o</kbd>      | open in browser                  |
| <kbd>O</kbd>      | open PR                          |
| <kbd>R</kbd>      | refresh all                      |
| <kbd>ctrl+r</kbd> | rerun                            |


================================================
FILE: docs/src/content/docs/companions/enhance/theme.mdx
================================================
---
title: Theming
---

`ENHANCE` supports all the themes listed in [bubbletint's website](https://lrstanley.github.io/bubbletint/).

The site shows a preview of the themes as well as provide their IDs.

## Get a Theme's ID

Go to [bubbletint's website](https://lrstanley.github.io/bubbletint/) and copy a theme's ID.

## Using a Theme

To use a theme, pass the `ENHANCE_THEME` environment variable with the theme's ID, like so:

```bash
ENHANCE_THEME=dracula gh enhance <PR_URL>
```


================================================
FILE: docs/src/content/docs/companions/enhance/usage.mdx
================================================
---
title: Usage
---

To use `enhance`, follow these steps after you've [installed it][01]:

1. Run

   ```
    gh enhance [<PR URL> | <PR number>] [flags]
   ```

   **Examples:**

   ```bash
    # look up checks via a full URL to a GitHub PR
    gh enhance https://github.com/dlvhdr/gh-dash/pull/767

    # look up checks via a PR number when inside a clone of dlvhdr/gh-dash
    # will look at checks of https://github.com/dlvhdr/gh-dash/pull/767
    gh enhance 767
   ```

2. Press <kbd>?</kbd> for help.

Run `gh enhance --help` for more info:

```
Usage:
  gh enhance [<url> | <number>] [flags]

Flags:
      --debug         passing this flag will allow writing debug output to debug.log
      --flat          passing this flag will present checks as a flat list
  -h, --help          help for gh-enhance
  -R, --repo string   [HOST/]OWNER/REPO   Select another repository using the [HOST/]OWNER/REPO format
  -v, --version       version for gh-enhance
```


================================================
FILE: docs/src/content/docs/companions/index.mdx
================================================
---
title: Companion Apps
---


================================================
FILE: docs/src/content/docs/configuration/defaults.mdx
================================================
---
title: Defaults
---

## Default Options (`defaults`)

These settings define the default behavior for the dashboard. You can override many of these
settings on a per-section basis.

```yaml
defaults:
  issuesLimit: 20
  notificationsLimit: 20
  prApproveComment: LGTM
  preview:
    open: true
    width: 0.45
  prsLimit: 20
  refetchIntervalMinutes: 30
  view: prs
```

By default, the dashboard is configured to:

- Display the preview pane with a width of 45% for all work items.
- Only fetch 20 PRs, issues, and notifications at a time for each section.
- Display the PRs view when the dashboard loads.
- Refetch PRs and issues for each section every 30 minutes.
- Display dates using relative values.

For more details on the default layouts, see the documentation for [PR] and [issue] layout definitions.

[PR]: /configuration/layout/pr/
[issue]: /configuration/layout/issue/

### Layout Options (`layout`)

This setting defines the layout for the work item tables in the dashboard. You can override
these settings in any section you define in the [`prSections`] or [`issueSections`] settings.

They determine which columns are displayed and how.

[`prSections`]: /configuration/pr-section
[`issueSections`]: /configuration/issue-section

#### PR Section Layout

You can define how a PR section displays items in its table by setting options for the
available columns. You can define a column's width, whether it grows to fill available space,
and whether the column should be visible at all.

Note that if the length of a column's text exceeds the defined column [`width`], the view
truncates the column's text to two characters shorter than the column's width. For example, if
the width is `6`, `gh-dash` displays as `gh-d`.

Column headings have their color defined by the [`theme.colors.text.primary`] setting.

For more information, see [PR Section Layout](/configuration/layout/pr).

[`width`]: /configuration/layout/options
[`theme.colors.text.primary`]: /configuration/theme

#### Issue Section Layout (`issues`)

You can define how an issue section displays items in its table by setting options for the
available columns. You can define a column's width, whether it grows to fill available space,
and whether the column should be visible at all.

Note that if the length of a column's text exceeds the defined column [`width`], the view
truncates the column's text to two characters shorter than the column's width. For example, if
the width is `6`, `gh-dash` displays as `gh-d`.

Column headings have their color defined by the [`theme.colors.text.primary`] setting.

For more information, see [Issue Section Layout](/configuration/layout/issue).

[`width`]: layout.options.width
[`theme.colors.text.primary`]: theme.colors.text.primary

### PR Fetch Limit

| Type    | Minimum | Default |
| :------ | :-----: | :-----: |
| Integer |    1    |   20    |

This setting defines how many PRs the dashboard should fetch for each section when:

- The dashboard first loads.
- The [fetch interval] elapses.
- You navigate to the next PR in a table without another fetched PR to display.
- You use the [refresh current section] or [refresh all sections] commands.

[fetch interval]: #refetch-interval-in-minutes-refetchintervalminutes
[refresh current section]: /getting-started/keybindings/global/#r---refresh-current-section
[refresh all sections]: /getting-started/keybindings/global/#r---refresh-all-sections

### Issue Fetch Limit (`issuesLimit`)

| Type    | Minimum | Default |
| :------ | :-----: | :-----: |
| Integer |    1    |   20    |

This setting defines how many issues the dashboard should fetch for each section when:

- The dashboard first loads.
- The [fetch interval] elapses.
- You navigate to the next issue in a table without another fetched issue to display.
- You use the [refresh current section] or [refresh all sections] commands.

[fetch interval]: #refetch-interval-in-minutes-refetchintervalminutes
[refresh current section]: /getting-started/keybindings/global/#r---refresh-current-section
[refresh all sections]: /getting-started/keybindings/global/#r---refresh-all-sections

### Notifications Fetch Limit (`notificationsLimit`)

| Type    | Minimum | Default |
| :------ | :-----: | :-----: |
| Integer |    1    |   20    |

This setting defines how many notifications the dashboard should fetch when:

- The dashboard first loads.
- You navigate to the next notification in a table without another fetched notification to display.
- You use the [refresh current section] or [refresh all sections] commands.

[refresh current section]: /getting-started/keybindings/global/#r---refresh-current-section
[refresh all sections]: /getting-started/keybindings/global/#r---refresh-all-sections

### Preview Pane (`preview`)

These settings define how the preview pane displays in the dashboard. You can specify
whether the preview pane is open by default and how many columns wide it should be when

#### Open on Load (`open`)

| Type    | Default |
| :------ | :-----: |
| Boolean |  true   |

Specifies whether the preview pane should be open by default for the selected work item
when the dashboard loads. You can always use the [toggle preview pane] command to
toggle the preview pane's visibility.

By default, the dashboard displays the preview pane.

[toggle preview pane]: /getting-started/keybindings/preview/#p---toggle-preview-pane

#### Preview Pane Width (`width`)

| Type    | Minimum | Default |
| :------ | :-----: | :-----: |
| Number  |    0    |  0.45   |

Specifies the width of the preview pane. You can set the size to the percentage of the terminal size by using fractions (e.g. 0.4 would be 40%).

By default, the preview pane is 45% wide.

### Refetch Interval in Minutes (`refetchIntervalMinutes`)

| Type    | Minimum | Default |
| :------ | :-----: | :-----: |
| Integer |    0    |   30    |

This setting defines how often the dashboard should fetch issues and PRs from GitHub. The
dashboard fetches work items for every section in the active view when the dashboard loads
and the first time you switch to the inactive view.

After the dashboard fetches the work items for the first time, it waits until this setting's
defined interval elapses before fetching the work items again.

By default, the dashboard refetches work items every 30 minutes.

To disable the refetching interval set it to 0.

You can always use the [refresh current section] or [refresh all sections] command to
refetch work items in the current view. If you change the search query for a view, the
dashboard fetches results for the updated query immediately.

[refresh current section]: /getting-started/keybindings/global/#r---refresh-current-section
[refresh all sections]: /getting-started/keybindings/global/#r---refresh-all-sections

### Date format (`dateFormat`)

| Type   |  Default   |
| :----- | :--------: |
| String | "relative" |

This setting defines how dates are formatted. The format either be "relative" or a [go time format].

By default, the format is "relative" which fits just inside the default column width of
updated at in the issues and pull request layouts.

You may need to adjust the layout column width depending on your format.

[go time format]: https://pkg.go.dev/time#pkg-constants

### Default View (`view`)

| Type   |     Options     | Default |
| :----- | :-------------: | :-----: |
| String | "prs", "issues" |   20    |

This setting defines whether the dashboard should display the PRs or Issues view when it
first loads.

By default, the dashboard displays the PRs view.

### PR Approval (`prApproveComment`)

| Type   | Default |
| :----- | :-----: |
| String | "LGTM"  |

This setting defines the default comment used as a starting point when [approving a PR].
This can be set as an empty string to not prefill a comment.

By default, the comment is "LGTM".

[approving a PR]: /getting-started/keybindings/selected-pr/#v---approve-pr

## Confirm Quit (`confirmQuit`)

| Type    | Default |
| :------ | :-----: |
| Boolean |  false  |

This setting specifies whether the user needs to confirm when quitting `gh-dash`
When this is on, `gh-dash` shows a prompt that requires the user to press <kbd>y</kbd>/<kbd>Enter</kbd> to actually quit.
Pressing any other key dismisses the message.

By default, dash doesn't need a confirmation.

[approving a PR]: /getting-started/keybindings/selected-pr/#v---approve-pr


## Include Read Notifications (`includeReadNotifications`)

| Type    | Default |
| :------ | :-----: |
| Boolean |  true   |

This setting controls whether the default notification view includes read notifications
alongside unread ones, matching GitHub’s default behavior.

When set to `true` (the default), notification sections with no explicit `is:` filter show
both read and unread notifications. When set to `false`, they show only unread notifications
plus any bookmarked items.

Explicit filters like `is:unread` or `is:read` in a section’s `filters` always override
this setting.

```yaml
# Show only unread notifications by default (old behavior)
includeReadNotifications: false
```


================================================
FILE: docs/src/content/docs/configuration/examples.mdx
================================================
---
title: Examples
---

These examples show a few ways you might configure your dashboard.

## Complete Examples

- The config for the `gh-dash` repo under [.gh-dash.yml](https://github.com/dlvhdr/gh-dash/blob/main/.gh-dash.yml)
- My config under my dotfiles repo [dlvhdr/dotfiles](https://github.com/dlvhdr/dotfiles/blob/main/nix/module/gh-dash/configs/config.yml)
- Many other configs found by [searching GitHub](https://github.com/search?q=path%3Agh-dash%2Fconfig.yml&type=code)

## Default Values

<div style="max-height: 500px; overflow-y:scroll;">

```yaml
prSections:
  - title: "My Pull Requests"
    filters: "is:open author:@me"
  - title: "Needs My Review"
    filters: "is:open review-requested:@me"
  - title: "Involved"
    filters: "is:open involves:@me -author:@me"

issuesSections:
  - title: "My Issues"
    filters: "is:open author:@me"
  - title: "Assigned"
    filters: "is:open assignee:@me"
  - title: "Involved"
    filters: "is:open involves:@me -author:@me"

notificationsSections:
  - title: "All"
    filters: ""
  - title: "Created"
    filters: "reason:author"
  - title: "Participating"
    filters: "reason:participating"
  - title: "Mentioned"
    filters: "reason:mention"
  - title: "Review Requested"
    filters: "reason:review-requested"
  - title: "Assigned"
    filters: "reason:assign"
  - title: "Subscribed"
    filters: "reason:subscribed"
  - title: "Team Mentioned"
    filters: "reason:team-mention"

pager:
  diff: less
showAuthorIcons: true
smartFilteringAtLaunch: true

defaults:
  view: prs
  refetchIntervalMinutes: 5
  layout:
    prs:
      repoName:
        grow: true,
        width: 10
        hidden: false
      base:
        hidden: true
  preview:
    open: true
    width: 84
  prsLimit: 20
  issuesLimit: 20
  notificationsLimit: 20

theme:
  ui:
    sectionsShowCount: true
    table:
      compact: false
  colors:
    text:
      primary: "#E2E1ED"
      secondary: "#666CA6"
      inverted: "#242347"
      faint: "#B0B3BF"
      warning: "#E0AF68"
      success: "#3DF294"
    background:
      selected: "#1B1B33"
    border:
      primary: "#383B5B"
      secondary: "#39386B"
      faint: "#2B2B40"
```

</div>

## Theming Example

The color palette in this example is inspired by the [Monokai Pro Spectrum Filter][01] palette.

```yaml
theme:
  colors:
    text:
      primary: "#F7F1FF"
      secondary: "#5AD4E6"
      inverted: "#F7F1FF"
      faint: "#3E4057"
      warning: "#FC618D"
      success: "#7BD88F"
    background:
      selected: "#535155"
    border:
      primary: "#948AE3"
      secondary: "#7BD88F"
      faint: "#3E4057"
```

[01]: https://www.vscolors.com/themes/f5d7ffda-c1d6-4070-ba80-803c705a1ee6-3ed72ace

## Custom Keybindings Example

Utilizing `tmux` we can launch other TUIs:

```yaml
keybindings:
  universal:
    - key: g
      name: lazygit
      command: >
        cd {{.RepoPath}} && lazygit
  prs:
    - key: O
      builtin: checkout
    - key: m
      command: gh pr merge --admin --repo {{.RepoName}} {{.PrNumber}}
    - key: C
      name: code review
      command: >
        tmux new-window -c {{.RepoPath}} '
        nvim -c ":silent Octo pr edit {{.PrNumber}}"
        '
    - key: a
      name: lazygit add
      command: >
        cd {{.RepoPath}} && git add -A && lazygit
    - key: v
      name: approve
      command: >
        gh pr review --repo {{.RepoName}} --approve --body "$(gum input --prompt='Approval Comment: ')" {{.PrNumber}}
```

## Repo Paths Example

Configure [`repoPaths`](/configuration/repo-paths) in order to check out PRs in
the right git directory.

```yaml
repoPaths:
  dlvhdr/*: ~/code/personal/*
  my-work-org/*: ~/code/my-work-org/*
  charmbracelet/*: ~/code/charm/*
  dlvhdr/dotfiles: ~/dotfiles
```


================================================
FILE: docs/src/content/docs/configuration/index.mdx
================================================
---
title: How to Configure
---

import { Aside, LinkCard, CardGrid } from "@astrojs/starlight/components";

`dash` has extensive configuration options.

- Modify the default config which is usually under `$HOME/.config/gh-dash/config.yml`.
- Use the [`--config`][01] flag to specify a different configuration file.
- Create a `.gh-dash.yml` file in a repo for project specific configuration.

<details>
  <summary>Give me more details!</summary>
  Using the following logic:
1. If `$GH_DASH_CONFIG` is a non-empty string, `dash` will use this file for
   its configuration.
2. If `$GH_DASH_CONFIG` isn't set and you're in a git repository, it will look for `.gh-dash.yml` or `.gh-dash.yaml`
   in the repository root.
3. If neither of the above applies, then:
  - If `$XDG_CONFIG_HOME` is a non-empty string, the default path is `$XDG_CONFIG_HOME/gh-dash/config.yml`.
  - If `$XDG_CONFIG_HOME` isn't set, then:
    - On Linux and macOS systems, the default path is `$HOME/.config/gh-dash/config.yml`.
    - On Windows systems, the default path is `%USERPROFILE%\.config\gh-dash\config.yml`.

</details>

---

<br />

<Aside type="tip">
  Just want a few examples for inspiration? Check out the
  [examples](./examples).
</Aside>

[01]: /getting-started/usage/#--config

## Options

The configuration for `dash` is schematized. The pages in this section list the configuration
options, their defaults, and how you can use them.

### Schema

Documentation and schema for the configuration of your GitHub dashboard.

<CardGrid>
  <LinkCard
    title="Schema"
    href="./schema"
    description="Configure your IDE to autocomplete when editing the config file"
  />
  <LinkCard
    title="Defaults"
    href="./defaults"
    description="Documentation for the default setting options for your GitHub dashboard."
  />
  <LinkCard
    title="Searching"
    href="./searching"
    description="How to search and filter issues and prs"
  />
  <LinkCard
    title="PR Section"
    href="./pr-section"
    description="Documentation for configuring the PR sections of your GitHub dashboard."
  />
  <LinkCard
    title="Issue Section"
    href="./issue-section"
    description="Documentation for configuring the issue's sections of your GitHub dashboard."
  />
  <LinkCard
    title="Keybindings"
    href="./keybindings"
    description="Documentation for defining commands for your GitHub dashboard."
  />
  <LinkCard
    title="Layout"
    href="./layout/options"
    description="Documentation for configuring your GitHub dashboard’s layout."
  />
  <LinkCard
    title="Theme"
    href="./theme"
    description="Documentation for configuring your GitHub dashboard’s theme."
  />
  <LinkCard
    title="Reusing Settings"
    href="./reusing.mdx"
    description="Define global settings that will always be applied"
  />
</CardGrid>


================================================
FILE: docs/src/content/docs/configuration/issue-section.mdx
================================================
---
title: Issue Sections
---

# Issues Section Options (`issuesSections`)

Defines a section in the dashboard's issues view.

- Every section must define a [`title`] and [`filters`].
- When you define [`limit`] for a section, that value overrides the
  [`defaults.issuesLimit`] setting.
- When you define [`layout`] for a section, that value overrides the
  [`defaults.layout.issue`] setting.

[`title`]: #issues-title-title
[`filters`]: #issues-filters-filters
[`limit`]: #issues-fetch-limit-limit
[`layout`]: #issues-section-layout-layout
[`defaults.issuesLimit`]: /configuration/defaults/#issue-fetch-limit-issueslimit
[`defaults.layout.issue`]: /configuration/defaults/#layout-options-layout

## Issues Title (`title`)

This setting defines the section's name. The dashboard displays this value in the tabs for
the issues view.

## Issues Filters (`filters`)

This setting defines the [GitHub search filters][01] for the Issues in the section's table.

Don't specify `is:issue` for this setting. The dashboard always adds that filter for Issues
sections. 

Note issues from archived repositories are excluded by default with `archived:false`.

You can define any combination of search filters. To make it easier to read and maintain
your filters, we recommend using the `>-` syntax after the `filter` key and writing one
filter per line.

For example:

```yaml
- # Involved
  filter: >-
    is:open
    involves:@me
    -author:@me
    updated:>={{ nowModify "-2w" }}
```

For more information about writing filters for searching GitHub, see [Searching].

[Searching]: /configuration/searching

## Issues Section Layout (`layout`)

You can define how a Issues section displays items in its table by setting options for the
available columns. You can define a column's width, whether it grows to fill available space,
and whether the column should be visible at all.

Note that if the length of a column's text exceeds the defined column [`width`], the view
truncates the column's text to two characters shorter than the column's width. For example, if
the width is `6`, `gh-dash` displays as `gh-d`.

Column headings have their color defined by the [`theme.colors.text.issueimary`] setting.

[`width`]: /configuration/layout/options#layout-options-width
[`theme.colors.text.issueimary`]: /configuration/theme

## Issues Fetch Limit (`limit`)

| Type    | Minimum | Default |
| :------ | :-----: | :-----: |
| Integer |    1    |   20    |

This setting defines how many Issues the dashboard should fetch for the section when:

- The dashboard first loads.
- The [fetch interval] elapses.
- You navigate to the next issue in a table without another fetched issue to display.
- You use the [refresh current section] or [refresh all sections] commands.

This setting overrides the [`defaults.issuesLimit`] setting.

[01]: https://docs.github.com/en/search-github/searching-on-github/searching-issues-and-pull-requests
[fetch interval]: /configuration/defaults/#refetch-interval-in-minutes-refetchintervalminutes
[refresh current section]: /getting-started/keybindings/global/#r---refresh-current-section
[refresh all sections]: /getting-started/keybindings/global/#r---refresh-all-sections
[`defaults.issuesLimit`]: /configuration/defaults/#issue-fetch-limit


================================================
FILE: docs/src/content/docs/configuration/keybindings/index.mdx
================================================
---
title: Custom Keybindings
---

`dash` allows you to override existing keybindings as well as add custom ones.

Every valid entry for the configuration options must have a `key` and `command`.
When a user presses the key or key combination the dashboard shells out and executes the command.

To help you identify your custom commands, an additional `name` property can be supplied to describe it in the help menu.

There are 3 types of keybindings: `universal`, `prs` and `issues`.

## Universal Keybindings

Define keybindings that will work in any view.

For example:

```yaml
keybindings:
  universal:
    - key: g
      name: lazygit
      command: >
        cd {{.RepoPath}} && lazygit
    - key: s
      builtin: search
```

### Built-in Commands

The following built-in universal commands can be overridden with custom keybinds:

| Command         | Description                                     |
| --------------- | ----------------------------------------------- |
| `up`            | row up                                          |
| `down`          | row down                                        |
| `firstLine`     | go to first row                                 |
| `lastLine`      | go to last row                                  |
| `togglePreview` | toggle the preview pane                         |
| `openGithub`    | open the selection in GitHub                    |
| `refresh`       | refresh the current section                     |
| `refreshAll`    | refresh all sections                            |
| `redraw`        | redraw the screen - in case of visual artifacts |
| `pageDown`      | go one page down in the preview pane            |
| `pageUp`        | go one page up in the preview pane              |
| `nextSection`   | go to next section                              |
| `prevSection`   | go to previous section                          |
| `search`        | focus the search bar                            |
| `copyurl`       | copy the URL of the selected row                |
| `copyNumber`    | copy the number of the selected row             |
| `help`          | toggle the help menu                            |
| `quit`          | quit gh-dash                                    |

See [global keys](../../getting-started/keybindings/global/) and [navigation keys](../../getting-started/keybindings/navigation/) for more details.

## PR Keybindings

Define any number of keybindings for the PRs view or override existing ones.

For example:

```yaml
keybindings:
  prs:
    - key: O
      builtin: checkout
    - key: m
      command: gh pr merge --admin --repo {{.RepoName}} {{.PrNumber}}
    - key: g
      name: lazygit add
      command: >
        cd {{.RepoPath}} && git add -A && lazygit
    - key: v
      name: approve
      command: >
        gh pr review --repo {{.RepoName}} --approve --body "$(gum input --prompt='Approval Comment: ')" {{.PrNumber}}
```

### Available Command Arguments

| Argument      | Description                                                                     |
| ------------- | ------------------------------------------------------------------------------- |
| `RepoName`    | The full name of the repo (e.g. `dlvhdr/gh-dash`)                               |
| `RepoPath`    | The path to the Repo, using the `config.yml` `repoPaths` key to get the mapping |
| `PrNumber`    | The PR number                                                                   |
| `HeadRefName` | The PR's head branch name                                                       |
| `BaseRefName` | The PR's base branch name                                                       |
| `Author`      | The username of the PR author                                                   |

### Built-in Commands

The following built-in PR commands can be overridden with custom keybinds:

| Command            | Description                                 |
| ------------------ | ------------------------------------------- |
| `prevSidebarTab`   | previous sidebar tab                        |
| `nextSidebarTab`   | next sidebar tab                            |
| `approve`          | approve the PR                              |
| `assign`           | assign users to the PR                      |
| `unassign`         | unassign users from the PR                  |
| `comment`          | add a comment to the PR                     |
| `diff`             | show the diff of the PR                     |
| `checkout`         | locally checkout the PR                     |
| `close`            | close the PR                                |
| `ready`            | mark the PR as ready                        |
| `reopen`           | reopen a closed PR                          |
| `merge`            | merge the PR                                |
| `update`           | update the PR to the latest base branch     |
| `watchChecks`      | watch the checks of the PR and get notified |
| `approveWorkflows` | approve the runs of the PR                  |
| `viewIssues`       | switch to the Issues view                   |
| `summaryViewMore`  | expand the truncated PR description         |

See [PR keys](../../getting-started/keybindings/selected-pr/) for more details.

## Issue Keybindings

Define any number of keybindings for the issues view or override existing ones.

For example:

```yaml
keybindings:
  issues:
    key: "P"
    command: >
      gh issue pin {{ .IssueNumber }} --repo {{ .RepoName }}
```

### Available Command Arguments

| Argument      | Description                                                                     |
| ------------- | ------------------------------------------------------------------------------- |
| `RepoName`    | The full name of the repo (e.g. `dlvhdr/gh-dash`)                               |
| `RepoPath`    | The path to the Repo, using the `config.yml` `repoPaths` key to get the mapping |
| `IssueNumber` | The issue number                                                                |
| `Author`      | The username of the issue author                                                |

### Built-in Commands

The following built-in PR commands can be overridden with custom keybinds:

| Command    | Description                          |
| ---------- | ------------------------------------ |
| `label`    | edit the issue's labels              |
| `assign`   | assign users to the issue            |
| `unassign` | remove assigned users from the issue |
| `comment`  | add a comment to the issue           |
| `close`    | close the issue                      |
| `reopen`   | reopen a closed issue                |
| `viewPrs`  | switch to the PRs view               |

See [issue keys](../../getting-started/keybindings/selected-issue/) for more details.

## Notification Keybindings

Define any number of keybindings for the notifications view or override existing ones.

For example:

```yaml
keybindings:
  notifications:
    - key: d
      builtin: markAsDone
    - key: D
      builtin: markAllAsDone
```

### Available Command Arguments

The command template receives different fields depending on whether the sidebar has been opened:

| State            | PR template fields                       |
| ---------------- | ---------------------------------------- |
| Sidebar not open | `RepoName`, `PrNumber`, `RepoPath`       |
| Sidebar open     | + `HeadRefName`, `BaseRefName`, `Author` |

| State            | Issue template fields                 |
| ---------------- | ------------------------------------- |
| Sidebar not open | `RepoName`, `IssueNumber`, `RepoPath` |
| Sidebar open     | + `Author`                            |

If a template references a sidebar-only field (e.g., `{{.HeadRefName}}`) before the sidebar is opened, the template engine’s `missingkey=error` option produces an error message. This is intentional — users should open the notification first to populate the full data.

### Built-in Commands

The following built-in notifications commands can be overridden with custom keybinds:

| Command          | Description                                        |
| ---------------- | -------------------------------------------------- |
| `view`           | view notification (fetches content, marks as read) |
| `markAsDone`     | mark as done (removes from inbox)                  |
| `markAllAsDone`  | mark all as done                                   |
| `markAsRead`     | mark as read                                       |
| `markAllAsRead`  | mark all as read                                   |
| `unsubscribe`    | unsubscribe from thread                            |
| `toggleBookmark` | toggle bookmark                                    |

See [notification keys](../../getting-started/keybindings/selected-notification/) for more details.


================================================
FILE: docs/src/content/docs/configuration/keybindings/issues.mdx
================================================
---
title: Issues
linkTitle: >-
  ![icon:circle-dot](lucide)&nbsp;Issues
weight: 2
summary: >-
  Documentation for defining commands in the Issues view of your GitHub dashboard.
schematize: keybindings.issues
outputs:
  - HTML
  - Schematize
---


================================================
FILE: docs/src/content/docs/configuration/keybindings/prs.mdx
================================================
---
title: PRs
linkTitle: >-
  PRs
---


================================================
FILE: docs/src/content/docs/configuration/layout/issue.mdx
================================================
---
title: Issue Layout
---

import { Aside, Code } from "@astrojs/starlight/components";
import NerdFontIcon from "../../../../components/NerdFontIcon.astro";

# Issues Section Layout

You can define how an Issue section displays items in its table by setting options for the
available columns. You can define a column's width, whether it grows to fill available space,
and whether the column should be visible at all.

Note that if the length of a column's text exceeds the defined column [`width`], the view
truncates the column's text to two characters shorter than the column's width. For example, if
the width is `6`, `gh-dash` displays as `gh-d`.

Column headings have their color defined by the [`theme.colors.text.primary`] setting.

[`width`]: /configuration/layout/options#column-width
[`theme.colors.text.primary`]: /configuration/theme#primary-text-color

By default, Issue views display the following columns in the order they're listed:

1. [`updatedAt`] with a width of 7 columns.
1. [`state`] with a width of 3 columns.
1. [`repo`] with a width of 15 columns.
1. [`title`], set to grow to fill available space.
1. [`creator`] with a width of 10 columns.
1. [`comments`] with a width of 3 columns.
1. [`reactions`] with a width of 3 columns.

<Aside type="caution" title="Watch out!">
  Even though the `state`, `title`, `comments`, and `reactions` settings
  aren't explicitly defined in your configuration file, they're added to
  the table unless you set their [`hidden`] option to `false`.

[`hidden`]: /configuration/layout/options#hide-column

</Aside>
      
[`updatedAt`]:    #issues-updated-at-column
[`state`]:        #issues-state-column
[`repo`]:         #issues-repo-column
[`title`]:        #issues-title-column
[`creator`]:       #issues-creator-column
[`comments`]:           #issues-comments-column
[`reactions`]:        #issues-reactions-column

```yaml
title:
  grow: true
assignees:
  hidden: true
  width: 20
creator:
  width: 10
repo:
  width: 15
updatedAt:
  width: 7
```

## Issue Updated At Column

| Property    | Type | Default                                            |
| :---------- | :--- | :------------------------------------------------- |
| `updatedAt` | yaml | <Code code={`width: 7`} lang="yaml" frame="none"/> |

This column displays how recently the Issue was updated. The entry shows the time elapsed
since the last update, like `1h` or `3d`.

The heading for this column is <NerdFontIcon icon="nf-oct-clock"/>

## Issue State Column

| Property | Type | Default                                            |
| :------- | :--- | :------------------------------------------------- |
| `state`  | yaml | <Code code={`width: 3`} lang="yaml" frame="none"/> |

This column displays the issue's state. When an issue is open, the column displays the icon <NerdFontIcon icon="nf-oct-issue_opened"/>
with the color set to `#42a0fa`. When an issue is closed, the
column displays the icon <NerdFontIcon icon="nf-oct-issue_closed"/> with the color set to
[`theme.colors.text.faint`].

The heading for this column is <NerdFontIcon icon="nf-oct-issue_opened"/>.

[`theme.colors.text.faint`]: /configuration/theme#faint-text-color

## Issue Repo Column

| Property | Type | Default                                             |
| :------- | :--- | :-------------------------------------------------- |
| `repo`   | yaml | <Code code={`width: 15`} lang="yaml" frame="none"/> |

This column displays the name of the repository the Issue is filed in. The entry shows the
name of the repository without the owner, like `gh-dash` for the
`https://github.com/dlvhdr/gh-dash` repository.

The heading for this column is <NerdFontIcon icon="nf-oct-repo"/>

[`width`]: /configuration/layout/options#column-width

## Issue Title Column

| Property | Type | Default                                              |
| :------- | :--- | :--------------------------------------------------- |
| `title`  | yaml | <Code code={`grow: true`} lang="yaml" frame="none"/> |

This column displays the Issue's number followed by its title. This column is always displayed
unless you set [`hidden`] to `false`. By default, it grows to fill the available space
in the terminal after accounting for other column widths.

The heading for this column is `Title`.

The [`theme.colors.text.primary`] setting defines the issue number's color.

[`hidden`]: /configuration/layout/options#hide-column
[`theme.colors.text.primary`]: /configuration/theme#primary-text-color

## Issue Creator Column

| Property  | Type | Default                                             |
| :-------- | :--- | :-------------------------------------------------- |
| `creator` | yaml | <Code code={`width: 10`} lang="yaml" frame="none"/> |

This column displays the username for the person who created the Issue.

The heading for this column is `Creator`.

## Issue Author Role Icon

| Property      | Type | Default                                                |
| :------------ | :--- | :----------------------------------------------------- |
| `creatorIcon` | yaml | <Code code={`hidden: true`} lang="yaml" frame="none"/> |

This setting affects display of the role icon for the person who created the Issue.

## Issue Assignees Column

| Property    | Type | Default                                                           |
| :---------- | :--- | :---------------------------------------------------------------- |
| `assignees` | yaml | <Code code={`width: 20\nhidden: true`} lang="yaml" frame="none"/> |

This column displays the usernames for the people assigned to the Issue.

The heading for this column is `Assignees`.

## Issue Comments Column

| Property   | Type | Default                                            |
| :--------- | :--- | :------------------------------------------------- |
| `comments` | yaml | <Code code={`width: 3`} lang="yaml" frame="none"/> |

This column displays the count of comments on the issue as an integer.

The heading for this column is <NerdFontIcon icon="nf-oct-comment_discussion"/>

## Issue Reactions Column

| Property    | Type | Default                                            |
| :---------- | :--- | :------------------------------------------------- |
| `reactions` | yaml | <Code code={`width: 3`} lang="yaml" frame="none"/> |

This column displays the count of all reactions on the issue as an integer.

The heading for this column is <NerdFontIcon icon="nf-oct-thumbsup"/>


================================================
FILE: docs/src/content/docs/configuration/layout/options.mdx
================================================
---
title: Valid Options
---

## Valid Layout Options

Any column can define the [`align`], [`grow`], [`width`], and [`hidden`] options.

[`align`]: #column-alignment
[`hidden`]: #hide-column
[`grow`]: #grow-column
[`width`]: #column-width

## Grow Column

| Property | Type    | Default |
| :------- | :------ | :------ |
| `grow`   | boolean | false   |

Specify whether the column should grow to fill the available space.

Set this value to `true` and the column's width expands to fill any leftover space in the
terminal after accounting for other columns and the preview pane. Set this value to `false`
to use the value of [`width`] instead.

We recommend only setting this for one column in a given section layout.

[`width`]: #column-width

## Column Width

| Property | Type    | Minimum |
| :------- | :------ | :------ |
| `width`  | integer | 1       |

Specify the column's width by character count. Because the dashboard expects the terminal
font to be monospace, this is a reliable way to ensure a minimum width for readability.

## Hide Column

| Property | Type    | Default |
| :------- | :------ | :------ |
| `hidden` | boolean | false   |

Specify whether the column should be hidden from view. Set this value to `true` to hide the
column or `false` to show it.

## Column Alignment

| Property | Type   | Default |
| :------- | :----- | :------ |
| `align`  | string | `left`  |

Specify the horizontal alignment of the column's content. Valid values are:

- `left` — Align content to the left (default)
- `right` — Align content to the right
- `center` — Center the content

This is useful for numeric columns like comment counts where right-alignment improves readability.

```yaml
prs:
  layout:
    numComments:
      width: 5
      align: right
```


================================================
FILE: docs/src/content/docs/configuration/layout/pr.mdx
================================================
---
title: PR Layout
---

import { Aside, Code } from "@astrojs/starlight/components";
import NerdFontIcon from "../../../../components/NerdFontIcon.astro";

# PR Section Layout

You can define how a PR section displays items in its table by setting options for the
available columns. You can define a column's width, whether it grows to fill available space,
and whether the column should be visible at all.

Note that if the length of a column's text exceeds the defined column [`width`], the view
truncates the column's text to two characters shorter than the column's width. For example, if
the width is `6`, `gh-dash` displays as `gh-d`.

Column headings have their color defined by the [`theme.colors.text.primary`] setting.

[`width`]: /configuration/layout/options/#column-width
[`theme.colors.text.primary`]: /configuration/theme#primary-text-color

By default, PR views display the following columns in the order they're listed:

1. [`updatedAt`] with a width of 7 columns.
1. [`state`] with a width of 3 columns.
1. [`repo`] with a width of 15 columns.
1. [`title`], set to grow to fill available space.
1. [`author`] with a width of 10 columns.
1. [`numComments`] with a width of 3 columns.
1. [`reviewStatus`] with a width of 3 columns.
1. [`ci`] with a width of 3 columns.
1. [`lines`] with a width of 16 columns.

<Aside type="caution" title="Watch out!">
  Even though the `state`, `title`, `comments`, and `reactions` settings
  aren't explicitly defined in your configuration file, they're added to
  the table unless you set their [`hidden`] option to `false`.

[`hidden`]: /configuration/layout/options/#hide-column

</Aside>
      
[`updatedAt`]:    #pr-updated-at-column
[`state`]:        #pr-updated-at-column
[`repo`]:         #pr-repo-column
[`title`]:        #pr-title-column
[`author`]:       #pr-author-column
[`numComments`]: #pr-number-of-comments-column
[`reviewStatus`]: #pr-review-status-column
[`ci`]:           #pr-continuous-integration-column
[`lines`]:        #pr-lines-column

```yaml
updatedAt:
  width: 7
repo:
  width: 15
title:
  grow: true
author:
  width: 15
assignees:
  width: 20
  hidden: true
base:
  width: 15
  hidden: true
lines:
  width: 16
```

## PR Updated At Column

| Property    | Type | Default                                            |
| :---------- | :--- | :------------------------------------------------- |
| `updatedAt` | yaml | <Code code={`width: 7`} lang="yaml" frame="none"/> |

This column displays how recently the PR was updated. The entry shows the time elapsed
since the last update, like `1h` or `3d`.

The heading for this column is <NerdFontIcon icon="nf-oct-clock"/>

## PR State Column

| Property | Type | Default                                            |
| :------- | :--- | :------------------------------------------------- |
| `state`  | yaml | <Code code={`width: 3`} lang="yaml" frame="none"/> |

This column displays the PR's state as one of the following icons:

- When a PR is open and ready for review, the icon is <NerdFontIcon icon="nf-oct-git_pull_request"/> and
  the color is `#42a0fa`.
- When a PR is in draft mode, the icon is <NerdFontIcon icon="nf-oct-git_pull_request_draft"/> and the color is
  set to the value of [`theme.colors.text.faint`].
- When a PR is merged, the icon is <NerdFontIcon icon="nf-oct-feed_merged"/> and the color is `#a371f7`.
- When a PR is closed without merging, the icon is <NerdFontIcon icon="nf-oct-trash"/> and the
  color is `#c38080`.

This heading for this column is <NerdFontIcon icon="nf-dev-git_merge"/>

[`theme.colors.text.faint`]: /configuration/theme#faint-text-color

## PR Repo Column

| Property | Type | Default                                             |
| :------- | :--- | :-------------------------------------------------- |
| `repo`   | yaml | <Code code={`width: 15`} lang="yaml" frame="none"/> |

This column displays the name of the repository the PR is filed in. The entry shows the
name of the repository without the owner, like `gh-dash` for the
`https://github.com/dlvhdr/gh-dash` repository.

The heading for this column is <NerdFontIcon icon="nf-oct-repo"/>

[`width`]: /configuration/layout/options/#column-width

## PR Title Column

| Property | Type | Default                                                         |
| :------- | :--- | :-------------------------------------------------------------- |
| `title`  | yaml | <Code code={`width: 15\ngrow: true`} lang="yaml" frame="none"/> |

This column displays the PR's number followed by its title. This column is always displayed
unless you set [`hidden`] to `false`. By default, it grows to fill the available space
in the terminal after accounting for other column widths.

The heading for this column is `Title`.

The [`theme.colors.text.primary`] setting defines the issue number's color.

[`hidden`]: /configuration/layout/options/#hide-column
[`theme.colors.text.primary`]: /configuration/theme#primary-text-color

## PR Author Column

| Property | Type | Default                                             |
| :------- | :--- | :-------------------------------------------------- |
| `author` | yaml | <Code code={`width: 15`} lang="yaml" frame="none"/> |

This column displays the username for the person who created the PR.

The heading for this column is `Author`.

## PR Author Role Icon

| Property     | Type | Default                                            |
| :----------- | :--- | :------------------------------------------------- |
| `authorIcon` | yaml | <Code code={`width: 3`} lang="yaml" frame="none"/> |

This setting affects display of the role icon for the person who created the PR.

## PR Assignees Column

| Property    | Type | Default                                                           |
| :---------- | :--- | :---------------------------------------------------------------- |
| `assignees` | yaml | <Code code={`width: 20\nhidden: true`} lang="yaml" frame="none"/> |

This column displays the usernames for the people assigned to the PR.

The heading for this column is `Assignees`.

## PR Base Column

| Property | Type | Default                                                           |
| :------- | :--- | :---------------------------------------------------------------- |
| `base`   | yaml | <Code code={`width: 15\nhidden: true`} lang="yaml" frame="none"/> |

This column displays the base branch the PR is targeting, like `main`.

The heading for this column is `Base`.

## PR Number of Comments Column

| Property      | Type | Default                                            |
| :------------ | :--- | :------------------------------------------------- |
| `numComments` | yaml | <Code code={`width: 3`} lang="yaml" frame="none"/> |

This column displays the number of comments left on a PR.
This is a sum of the direct comments and the number of review threads.

The heading for this column is <NerdFontIcon icon="nf-fa-comments_o"/>.

[`theme.colors.text.faint`]: /configuration/theme#faint-text-color
[`theme.colors.text.primary`]: /configuration/theme#primary-text-color
[`theme.colors.text.warning`]: /configuration/theme#warning-text-color

## PR Review Status Column

| Property       | Type | Default                                            |
| :------------- | :--- | :------------------------------------------------- |
| `reviewStatus` | yaml | <Code code={`width: 3`} lang="yaml" frame="none"/> |

This column displays the review status of a PR as an icon:

- When the PR hasn't been reviewed, the icon is <NerdFontIcon icon="nf-fa-clock" /> and the
  color is the value of [`theme.colors.text.faint`].
- When the PR is approved, the icon is <NerdFontIcon icon="nf-cod-check" /> and the color is
  the value of [`theme.colors.text.primary`].
- When the PR has requested changes, the icon is <NerdFontIcon icon="nf-md-keyboard_return" /> and the
  color is the value of [`theme.colors.text.warning`].

The heading for this column is <NerdFontIcon icon="nf-md-account_check_outline"/>.

[`theme.colors.text.faint`]: /configuration/theme#faint-text-color
[`theme.colors.text.primary`]: /configuration/theme#primary-text-color
[`theme.colors.text.warning`]: /configuration/theme#warning-text-color

## PR Continuous Integration Column

| Property | Type | Default                                            |
| :------- | :--- | :------------------------------------------------- |
| `ci`     | yaml | <Code code={`width: 3`} lang="yaml" frame="none"/> |

This column displays the CI status of a PR as an icon:

- When the checks haven't finished running, the icon is <NerdFontIcon icon="nf-fa-clock"/> and
  the color is the value of [`theme.colors.text.faint`].
- When the checks have all passed, the icon is <NerdFontIcon icon="nf-md-check_circle"/> and the
  color is the value of [`theme.colors.text.success`].
- When at least one check failed, the icon is <NerdFontIcon icon="nf-md-close_circle"/> and the
  color is the value of [`theme.colors.text.warning`].

The heading for this column is <NerdFontIcon icon="nf-oct-checklist"/>

[`theme.colors.text.faint`]: /configuration/theme#faint-text-color
[`theme.colors.text.primary`]: /configuration/theme#primary-text-color
[`theme.colors.text.warning`]: /configuration/theme#warning-text-color

# PR Lines Column

| Property | Type | Default                                             |
| :------- | :--- | :-------------------------------------------------- |
| `lines`  | yaml | <Code code={`width: 16`} lang="yaml" frame="none"/> |

This column displays the line changes for a PR. The column represents the changes as
`<added> / -<removed>`. For example, `66 / -46` indicates 66 lines added and 46
lines removed.

The heading for this column is <NerdFontIcon icon="nf-oct-diff"/>.


================================================
FILE: docs/src/content/docs/configuration/notification-section.mdx
================================================
---
title: Notification Sections
---

# Notification Section Options (`notificationsSections`)

Defines sections in the dashboard's Notifications view.

- Every section must define a [`title`] and [`filters`].
- When you define [`limit`] for a section, that value overrides the
  [`defaults.notificationsLimit`] setting.

[`title`]: #notification-title-title
[`filters`]: #notification-filters-filters
[`limit`]: #notification-fetch-limit-limit
[`defaults.notificationsLimit`]: /configuration/defaults/#notifications-fetch-limit-notificationslimit

## Search Section

The Notifications view includes a search section (indicated by a magnifying glass icon) as the first tab. This serves as a scratchpad for one-off searches without modifying your configured sections.

- Default filter: `archived:false`
- Respects `smartFilteringAtLaunch`: when enabled and running from a git repository, the search automatically scopes to that repo
- Use the `/` key to focus the search bar and enter custom queries

## Default Sections

By default, the dashboard includes these notification sections:

```yaml
notificationsSections:
  - title: All
    filters: ""
  - title: Created
    filters: "reason:author"
  - title: Participating
    filters: "reason:participating"
  - title: Mentioned
    filters: "reason:mention"
  - title: Review Requested
    filters: "reason:review-requested"
  - title: Assigned
    filters: "reason:assign"
  - title: Subscribed
    filters: "reason:subscribed"
  - title: Team Mentioned
    filters: "reason:team-mention"
```

You can customize these by defining your own `notificationsSections` in your config file.

## Notification Title (`title`)

This setting defines the section's name. The dashboard displays this value in the tabs for
the Notifications view.

## Notification Filters (`filters`)

This setting defines the filters for notifications in the section's table. Notification filters differ from PR and Issue filters because they use client-side filtering.

### Available Filters

#### Read State Filters

| Filter | Description |
|--------|-------------|
| `is:unread` | Show only unread notifications |
| `is:read` | Show only read notifications |
| `is:all` | Show both read and unread notifications |
| `is:done` | Show archived/done notifications |

#### Reason Filters

| Filter | Description |
|--------|-------------|
| `reason:author` | Activity on threads you created |
| `reason:comment` | Someone commented on a thread you're subscribed to |
| `reason:mention` | You were @mentioned |
| `reason:review-requested` | Your review was requested on a PR |
| `reason:assign` | You were assigned |
| `reason:subscribed` | Activity on threads you're watching |
| `reason:team-mention` | Your team was @mentioned |
| `reason:state-change` | Thread state changed (merged, closed, etc.) |
| `reason:ci-activity` | CI workflow activity |
| `reason:participating` | Meta-filter that expands to: author, comment, mention, review-requested, assign, state-change |

#### Repository Filters

| Filter | Description |
|--------|-------------|
| `repo:owner/name` | Show notifications only from the specified repository |

### Filter Examples

```yaml
# Show only notifications where you were mentioned
- title: Mentioned
  filters: "reason:mention"

# Show unread notifications from a specific repo
- title: My Project
  filters: "is:unread repo:myorg/myproject"

# Show notifications where you're actively participating
- title: Participating
  filters: "reason:participating"

# Combine multiple reason filters
- title: Review & Mentions
  filters: "reason:review-requested reason:mention"
```

### Filter Behavior

- **Default behavior**: With no filters or empty filters, the section shows all notifications (both read and unread), matching GitHub's default behavior. To show only unread notifications by default, set `includeReadNotifications: false` in your config.
- **Explicit `is:unread`**: Shows only unread notifications, excluding bookmarked read notifications. This overrides the `includeReadNotifications` setting.
- **Reason filters**: Applied client-side after fetching from GitHub's API

## Notification Fetch Limit (`limit`)

| Type    | Minimum | Default |
| :------ | :-----: | :-----: |
| Integer |    1    |   20    |

This setting defines how many notifications the dashboard should fetch for the section when:

- The dashboard first loads.
- You navigate to the next notification in a table without another fetched notification to display.
- You use the [refresh current section] or [refresh all sections] commands.

This setting overrides the [`defaults.notificationsLimit`] setting.

[refresh current section]: /getting-started/keybindings/global/#r---refresh-current-section
[refresh all sections]: /getting-started/keybindings/global/#r---refresh-all-sections
[`defaults.notificationsLimit`]: /configuration/defaults/#notifications-fetch-limit-notificationslimit


================================================
FILE: docs/src/content/docs/configuration/pr-section.mdx
================================================
---
title: PR Sections
---

# PR Section Options (`prSections`)

Defines a section in the dashboard's PRs view.

- Every section must define a [`title`] and [`filters`].
- When you define [`limit`] for a section, that value overrides the
  [`defaults.prsLimit`] setting.
- When you define [`layout`] for a section, that value overrides the
  [`defaults.layout.pr`] setting.

[`title`]: #pr-title-title
[`filters`]: #pr-filters-filters
[`limit`]: #pr-fetch-limit-limit
[`layout`]: #pr-section-layout-layout
[`defaults.prsLimit`]: /configuration/defaults/#pr-fetch-limit
[`defaults.layout.pr`]: /configuration/defaults/#layout-options-layout

## PR Title (`title`)

This setting defines the section's name. The dashboard displays this value in the tabs for
the PRs view.

## PR Filters (`filters`)

This setting defines the [GitHub search filters][01] for the PRs in the section's table.

Don't specify `is:pr` for this setting. The dashboard always adds that filter for PR
sections.

Note pull requests from archived repositories are excluded by default with `archived:false`.

You can define any combination of search filters. To make it easier to read and maintain
your filters, we recommend using the `>-` syntax after the `filter` key and writing one
filter per line.

For example:

```yaml
- # Involved
  filter: >-
    is:open
    involves:@me
    -author:@me
    updated:>={{ nowModify "-2w" }}
```

For more information about writing filters for searching GitHub, see [Searching].

[Searching]: /configuration/searching

## PR Section Layout (`layout`)

You can define how a PR section displays items in its table by setting options for the
available columns. You can define a column's width, whether it grows to fill available space,
and whether the column should be visible at all.

Note that if the length of a column's text exceeds the defined column [`width`], the view
truncates the column's text to two characters shorter than the column's width. For example, if
the width is `6`, `gh-dash` displays as `gh-d`.

Column headings have their color defined by the [`theme.colors.text.primary`] setting.

[`width`]: /configuration/layout/options#layout-options-width
[`theme.colors.text.primary`]: /configuration/theme

## PR Fetch Limit (`limit`)

| Type    | Minimum | Default |
| :------ | :-----: | :-----: |
| Integer |    1    |   20    |

This setting defines how many PRs the dashboard should fetch for the section when:

- The dashboard first loads.
- The [fetch interval] elapses.
- You navigate to the next issue in a table without another fetched issue to display.
- You use the [refresh current section] or [refresh all sections] commands.

This setting overrides the [`defaults.prsLimit`] setting.

[01]: https://docs.github.com/en/search-github/searching-on-github/searching-issues-and-pull-requests
[fetch interval]: /configuration/defaults/#refetch-interval-in-minutes-refetchintervalminutes
[refresh current section]: /getting-started/keybindings/global/#r---refresh-current-section
[refresh all sections]: /getting-started/keybindings/global/#r---refresh-all-sections
[`defaults.prsLimit`]: /configuration/defaults/#pr-fetch-limit


================================================
FILE: docs/src/content/docs/configuration/repo-paths.mdx
================================================
---
title: Repo Paths
---

You can use the `repoPaths` setting to map repository names (as keys) to local paths
(as values). This map configures where to locate repositories when checking out PRs.

The mappings can be exact matches, like the full name or path of a repository, or wildcard
matches using the `owner` and a partial path.

An exact match for the full repository name to a full path takes priority over a matching
wildcard. Wildcard keys must match to a wildcard path.

The `RepoName` and `RepoPath` keybinding arguments are fully expanded when sent to the
command.

## Examples

### Matching Repositories

```yaml
repoPaths:
  dlvhdr/*: ~/code/repos/*
  dlvhdr/gh-dash: ~/code/gh-dash
```

In this example, the first key is defined with a wildcard (`*`) as `dlvhdr/*`, so the
dashboard will use this entry to resolve the path for any repo in the `dlvhdr`
namespace, like `dlvhdr/jb` or `dlvhdr/harbor`. Note that the value for this key
also uses a wildcard. If the key specifies a wildcard, the value must specify one too.

If a repository in the `dlvhdr` namespace has been cloned into the `~/code/repos`
folder, the dashboard will be able to checkout PRs for that repository locally.

If the repository isn't found, the checkout command raises an error.

The second key defines an exact mapping between the `dlvhdr/gh-dash` repository and the
`~/code/gh-dash` folder. Because this is a non-wildcard mapping, the dashboard will use
this value to resolve the repository path for `dlvhdr/gh-dash` even though there's also
an entry for `dlvhdr/*`.

## Pattern Properties

### With a Wildcard

If the key for an `repoPath` entry ends with a wildcard (`*`), its value must also have
a wildcard. If a key ends with a wildcard but the value doesn't, `gh-dash` won't be
able to correctly map repositories to folders.

### Without a Wildcard

If the key for an `repoPath` entry doesn't have a wildcard (`*`), its value must not
have a wildcard. If a key ends without a wildcard but the value does, `gh-dash` won't
be able to correctly map repositories to folders.


================================================
FILE: docs/src/content/docs/configuration/reusing.mdx
================================================
---
title: Reusing Settings
---

`DASH` supports defining global settings that will always be applied, and lets you override them with a per-repo or one-time basis.

This lets you set your [theme](./theme), [keybindings](./keybindings) and any other setting by defining them once.

## The Global Config

The global config is usually under `$HOME/.config/gh-dash/config.yml` - but that follows the XDG spec. See [How to Configure](/configuration) for more details.

The global config is loaded first, with the option to override anything it defines.
Here you'd usually want to define stuff like your theme, keybindings etc.

## Per-Repo / One-Time Overrides

`DASH` supports passing ad-hoc or per-repo config files by:

- Creating a `.gh-dash.yml` file in a git repo's root directory.
- Passing a path to a `.yml` file you supplied with the `--config` flag or the `GH_DASH_CONFIG` environment variable.

Any settings defined here will override your global config settings.

## Example

Your global config under `~/.config/gh-dash/config.yml` could look like this:

```yaml
pager:
  diff: diffnav
theme:
  colors:
    text:
      primary: "#E2E1ED"
      secondary: "#666CA6"
      inverted: "#242347"
      # ...
keybindings:
  universal:
    - key: g
      name: lazygit
      command: cd {{.RepoPath}} && lazygit
```

Then in a git repo you could create a `.gh-dash.yml` file defining just the
sections:

```yaml
prSections:
  - title: Bugs
    filters: is:open author:@me [BUG]
  - title: Our Packages
    filters: is:open review-requested:@me repo:work-org/our-pkg
```

Starting `DASH` from the git repo, the final config used will have the `pager`, `theme` and `keybindings`
from your global config and the `prSections` from your repo's config.


================================================
FILE: docs/src/content/docs/configuration/schema.mdx
================================================
---
title: Schema
---

The `dash` configuration schema is published here:

[`https://gh-dash.dev/schema.json`][02]

## Using the Schema in Neovim

1. Install the [yaml-language-server](https://github.com/redhat-developer/yaml-language-server) LSP
2. Follow the guide in [nvim-lspconfig](https://github.com/neovim/nvim-lspconfig/blob/master/doc/configs.md#yamlls) to set it up
3. Add the following line to the top of your configuration file:

   ```
   # yaml-language-server: $schema=https://gh-dash.dev/schema.json
   ```

With the directive comment at the top of your configuration or the VS Code settings file, you can
then open your configurations and edit them with support for validation. When you hover on an
option in your configuration file, you'll get a brief synopsis of the option and a link to its
documentation on this site.

## Using the Schema in VS Code

You can get edit-time feedback, validation, and IntelliSense for your configurations in VS Code by
following these steps:

1. Install [Red Hat's YAML extension for VS Code][03].
1. Open your `dash` configuration file.
1. Add the following line to the top of your configuration file:

   ```
   # yaml-language-server: $schema=https://gh-dash.dev/schema.json
   ```

1. Instead of adding a comment to your configuration file, you could create the
   `.vscode/settings.json` file in your `dash` configuration folder and add this setting:

   ```json
   {
     "yaml.schemas": {
       "https://gh-dash.dev/schema.json": "*.yml"
     }
   }
   ```

[01]: /getting-started/usage#--config
[02]: /schema.json
[03]: https://marketplace.visualstudio.com/items?itemName=redhat.vscode-yaml


================================================
FILE: docs/src/content/docs/configuration/searching.mdx
================================================
---
title: Searching
linkTitle: >-
  ![icon:search](lucide)&nbsp;Searching
summary: >-
  How to search and filter issues and prs
weight: 3
---

# Searching

Searching for prs and issues is done by defining sections and their filters.
Search filters are defined using [GitHub search filters][01].

For example, this section, shows open PRs authored by anyone but me, which were updated in the last 2 weeks.

```yaml
prsSections:
  - title: Review
    filter: >-
      is:open
      -author:@me
      updated:>={{ nowModify "-2w" }}
```

Note: don't specify `is:pr` for this setting. The dashboard always adds that filter for PR
sections. Results from archived repositories are excluded by default with `archived:false`.

You can define any combination of search filters. To make it easier to read and maintain
your filters, we recommend using the `>-` syntax after the `filter` key and writing one
filter per line.

For more information about writing filters for searching GitHub, see [Searching issues and pull requests][02].

## Search Templates

In addition to GitHub's filters, gh-dash adds templating functions.

### `nowModify`

The `nowModify` function helps you calculate relative dates in the ISO-8601 format (which is what GitHub expects).

Given the date today is 2025-02-02, a search filter of `updated:>={{ nowModify "-1mo" }}` will output `updated:>=2025-01-02`.

A duration string is a possibly signed sequence of decimal numbers, each with optional fraction and a unit suffix, such as `1w`, `-8h` or `1mo2w`.

The available units are:

- [Go's builtin durations](https://pkg.go.dev/time#ParseDuration) - `ns`, `us` (or `µs`), `ms`, `s`, `m`, `h`
- Additionally:
  - `d`/`D` for days
  - `w`/`W` for weeks
  - `M`/`mo` for months
  - `y`/`Y` for years

## Smart Filtering

By default, if the directory you launch `dash` from is a clone of a remote GitHub repo (or if you
have the `GH_REPO` environment variable set to a particular remote), then for any of your PR
sections and issue sections with `filters` values in your [configuration](/configuration) that don’t
have an explicit `repo:` field, `dash` adds a `repo:<RepoName>` field to the search-bar value for
them (where _`<RepoName>`_ is the name of the remote repo).

That is, `dash` further filters those sections down to only the PRs/issues for the GitHub
repo name specified in your `GH_REPO` environment variable — or else the repo name of the remote
tracked by the clone directory from which `dash` launched.

For that, `dash` first checks and uses the repo name in the `GH_REPO` environment variable (if
you have that set). If `dash` doesn’t find that, then it next checks for the value of the remote
repo name tracked by the clone directory from which you launched `dash` — by looking through all
GitHub remotes configured for that clone in the following order:

1. `upstream`
2. `github`
3. `origin`

…and, otherwise, if `dash` finds no remotes with any of those names, then it uses the repo name
for the first remote in the output that `git remote` shows.

To disable Smart Filtering at launch, set `smartFilteringAtLaunch` to `false` in your [configuration](/configuration).

```yaml
smartFilteringAtLaunch: false
```

To toggle Smart Filtering on or off for the current section you’re currently viewing, either use the
`t` key — or else use whatever custom keybinding you have set for the `togglesearch` builtin in the
`keybindings` section of your [configuration](/configuration).

You can also manually edit the search bar (press `/`) to remove or replace the `repo:` filter, then
press Enter. The Smart Filtering state automatically syncs to match your edit — so if you remove the
`repo:` filter from the search bar, Smart Filtering turns off for that section, and vice versa.

[01]: https://docs.github.com/en/search-github/searching-on-github/searching-issues-and-pull-requests
[02]: https://docs.github.com/en/search-github/getting-started-with-searching-on-github/understanding-the-search-syntax


================================================
FILE: docs/src/content/docs/configuration/theme.mdx
================================================
---
title: Theme
---

import { Aside } from "@astrojs/starlight/components";

# Theme Options

This setting defines the dashboard's theme. It only effects the presentation of the dashboard,
not the data. Currently, the theme only defines colors and icons. To control how table columns
and preview pane display for the views, use the [`defaults`], [`prSections`], and
[`issueSections`] settings.

To define any color for your dashboard, you **must** define **every** color. All properties are
required properties. Every color for the dashboard's theme must be a valid [hex color] like
`#a3c` or `#aa33cc`, or an ANSI color index from `0` to `255`.

To find hex colors to use in your dashboard, visit [`color-hex.com`]. You can browse colors,
inspect a given color, get alternate shades and tints for a color, derive a color palette, and
more.

[`defaults`]: /configuration/defaults
[`prSections`]: /configuration/pr-section
[`issueSections`]: /configuration/issue-section
[hex color]: https://developer.mozilla.org/en-US/docs/Web/CSS/hex-color
[`color-hex.com`]: https://www.color-hex.com/

## Defaults

```yaml
ui:
  sectionsShowCount: true
table:
  showSeparators: true
  compact: false
colors:
  text:
    primary: "#ffffff"
    secondary: "#c6c6c6"
    inverted: "#303030"
    faint: "#8a8a8a"
    warning: "#800000"
    success: "#008000"
    actor: "#c6c6c6"
  background:
    selected: "#808080"
  border:
    primary: "#808080"
    secondary: "#c0c0c0"
    faint: "#000000"
  inline:
    icons:
      newcontributor: "077"
      contributor: "075"
      collaborator: "178"
      member: "178"
      owner: "178"
      unknownrole: "178"
icons:
  inline:
    newcontributor: "󰎔"
    contributor: ""
    collaborator: ""
    member: ""
    owner: ""
    unknownrole: "󰭙"
```

## UI Settings (`ui`)

### Sections Show Count

| Property            | Type    | default |
| :------------------ | :------ | :------ |
| `sectionsShowCount` | boolean | true    |

Whether the number of results show up next to each section's title in the tab bar.

### Table Settings (`table`)

#### Show Separators

| Property         | Type    | default |
| :--------------- | :------ | :------ |
| `showSeparators` | boolean | true    |

Whether to show the separators between lines in the prs/issues tables.

#### Compact

| Property  | Type    | default |
| :-------- | :------ | :------ |
| `compact` | boolean | false   |

Whether to show table rows in a compact way or not

## Theme Colors (`colors`)

This setting defines a map of colors for the dashboard's text, background, and border
colors.

The following elements can't be styled through your configuration and have their colors
set as:

| Element                                 |          Color           |
| :-------------------------------------- | :----------------------: |
| Search input terms when inactive        | Terminal default (faint) |
| Search input terms when active          |     Terminal default     |
| Inactive section names in the tab list  |     Terminal default     |
| The status icon for open issues and PRs |        `#42A0FA`         |
| The status icon for closed issues       |        `#C38080`         |
| The status icon for closed PRs          |        `#C38080`         |
| The status icon for merged PRs          |        `#A371F7`         |

Required:

- text
- background
- border

### Text Colors (`text`)

Defines the foreground (text) colors for the dashboard.

#### Primary Text Color

| Property  | Type | default                                   |
| :-------- | :--- | :---------------------------------------- |
| `primary` | color | `#ffffff` for dark or `#000000` for light |

This setting determines the color of the text for the following elements in the
dashboard UI:

- The active section's name in the tab list
- The active view's name
- The column headers for the section's table of work items
- Open work item entries in the table except when a column's icon has an alternate
  color.
- The keybindings in the help view
- The title of the work item in the preview pane heading
- The comments and checks headers in the preview pane.
- The username for comment authors in the preview pane.

#### Secondary Text Color

| Property    | Type | default                                   |
| :---------- | :--- | :---------------------------------------- |
| `secondary` | color | `#c6c6c6` for dark or `#808080` for light |

This setting determines the color of the text for the following elements in the
dashboard UI:

- The search icon, `is:pr`, and `is:issue` components of the search bar
- The inactive view's name
- The work item number in the table entries
- The work item number and repository name in the preview pane heading
- The base and target branch in the preview pane for PRs

#### Inverted Text Color

| Property   | Type | default                                   |
| :--------- | :--- | :---------------------------------------- |
| `inverted` | color | `#303030` for dark or `#ffffff` for light |

This setting determines the color of the text for the following elements in the
dashboard UI:

- The work item status in the preview pane
- Work item labels

#### Faint Text Color

| Property | Type | default                                   |
| :------- | :--- | :---------------------------------------- |
| `faint`  | color | `#8a8a8a` for dark or `#c0c0c0` for light |

This setting determines the color of the text for the following elements in the
dashboard UI:

- Closed work item entries in the table
- The current time, active/total work item count, and fetched work item count
  beneath the table
- The help text for the keybinding commands
- The percentage scrolled at the bottom of the preview pane
- The date/time information on comments in the preview pane
- The review status icon when a PR is waiting for a review

#### Warning Text Color

| Property  | Type | default                                   |
| :-------- | :--- | :---------------------------------------- |
| `warning` | color | `#800000` for dark or `#800000` for light |

This setting determines the color of the text for the following elements in the
dashboard UI:

- The icon for the `reviewStatus` column's icon when a PR has requested changes
- The icon for the `ci` column's icon when a PR has failing checks
- The icon for failing checks for PRs in the preview pane
- Error messages for commands, like when the dashboard fails to fetch work items.

#### Success Text Color

| Property  | Type | default                                  |
| :-------- | :--- | :--------------------------------------- |
| `success` | color | `#008000` for dark or `008000` for light |

This setting determines the color of the text for the following elements in the
dashboard UI:

- The icon for the `reviewStatus` column's icon when a PR is approved
- The icon for the `ci` column's icon when a PR's checks are all passing
- The icon for passing checks for PRs in the preview pane
- Success messages for commands, like when the dashboard fetches work items.

#### Actor Text Color

| Property | Type | default                                   |
| :------- | :--- | :---------------------------------------- |
| `actor`  | color | `#c6c6c6` for dark or `#808080` for light |

This setting determines the color of the text for the following elements in the
dashboard UI:

- The username of the person who triggered a notification, displayed after the
  notification title in the notifications view

### Background Colors (`background`)

Defines the background colors for the dashboard. By default, the background color for
all elements in the dashboard UI is the terminal's background color.

Required:

- selected

#### Selected Background Color

| Property   | Type | default                                   |
| :--------- | :--- | :---------------------------------------- |
| `selected` | color | `#808080` for dark or `#c0c0c0` for light |

This setting determines the background color for the following elements in the
dashboard UI:

- The active section's name in the tab list
- The active view's name
- The active entry in the section's work item table.

### Border Colors (`border`)

| Property | Type | default                                   |
| :------- | :--- | :---------------------------------------- |
| `border` | color | `#808080` for dark or `#c0c0c0` for light |

Defines the border colors for the dashboard.

Required:

- primary
- secondary
- faint

#### Primary Border Color

| Property  | Type | default                                   |
| :-------- | :--- | :---------------------------------------- |
| `primary` | color | `#808080` for dark or `#ff00ff` for light |

This setting determines the color for the following elements in the dashboard UI:

- The border beneath the section tabs
- The border around the search input
- The border between the table and the preview pane
- The border above the command help info

#### Secondary Border Color

| Property    | Type | default                                   |
| :---------- | :--- | :---------------------------------------- |
| `secondary` | color | `#c0c0c0` for dark or `#808080` for light |

This setting determines the color for the following elements in the dashboard UI:

- The borders that separate the sections in the tab list

#### Faint Border Color

| Property | Type | default                                   |
| :------- | :--- | :---------------------------------------- |
| `faint`  | color | `#000000` for dark or `#e4e4e4` for light |

This setting determines the color for the following elements in the dashboard UI:

- The border between rows in the table

### Icon Colors (`inline.icons`)

Defines author-role icon colors for the dashboard.

#### New Contributor Role Icon Color

`newcontributor`
| Property | Type | default |
| :-------- | :--- | :---------------------------------------- |
| `newcontributor` | color | |

Specifies the icon color for the new-contributor-role icon.

#### Contributor Role Icon Color

| Property      | Type | default |
| :------------ | :--- | :------ |
| `contributor` | color |         |

Specifies the icon color for the contributor-role icon.

#### Collaborator Role Icon Color

collaborator:
| Property | Type | default |
| :-------- | :--- | :---------------------------------------- |
| `collaborator` | color | |

Specifies the icon color for the collaborator-role icon.

#### Member Role Icon Color

| Property | Type | default |
| :------- | :--- | :------ |
| `member` | color |         |

Specifies the icon color for the member-role icon.

#### Owner Role Icon Color

Specifies the icon color for the owner-role icon.

#### Unknown Role Icon Color

| Property  | Type | default |
| :-------- | :--- | :------ |
| `unknown` | color |         |

Specifies the icon color for the unknown-role icon.

## Icons (`icons.inline`)

This setting defines a map of author-role icons for the dashboard.

### New Contributor Role Icon

Specifies the character to use as the new-contributor-role icon.

| Property         | Type   | default |
| :--------------- | :----- | :------ |
| `newcontributor` | string | 󰎔       |

### Contributor Role Icon Color

Specifies the character to use as the contributor-role icon.

| Property      | Type   | default |
| :------------ | :----- | :------ |
| `contributor` | string |        |

### Collaborator Role Icon Color

Specifies the character to use as the collaborator-role icon.

| Property       | Type   | default |
| :------------- | :----- | :------ |
| `collaborator` | string |        |

### Member Role Icon Color

Specifies the character to use as the member-role icon.

| Property | Type   | default |
| :------- | :----- | :------ |
| `member` | string |        |

### Owner Role Icon Color

Specifies the character to use as the owner-role icon.

| Property | Type   | default |
| :------- | :----- | :------ |
| `owner`  | string |        |

### Unknown Role Icon Color

Specifies the character to use as the unknown-role icon.

| Property      | Type   | default |
| :------------ | :----- | :------ |
| `unknownrole` | string | 󰭙       |


================================================
FILE: docs/src/content/docs/contributing/index.mdx
================================================
---
title: Contributing
---

Thank you for investing your time in contributing to our project!

In this guide you will get an overview of the contribution workflow from opening an issue, creating a PR, reviewing, and merging the PR.

## The Critical Rule

- The most important rule: you must understand your code. If you can't explain what your changes do and how they interact with the greater system without the aid of AI tools, do not contribute to this project.
- The second most important rule: when you submit a PR you must be willing to address comments and maintain this code. Dot not submit drive-by PRs that solve your own issue without the willingness to iterate on it. Keep these in your own fork.
- Using AI to write code is fine. You can gain understanding by interrogating an agent with access to the codebase until you grasp all edge cases and effects of your changes. What's not fine is submitting agent-generated slop without that understanding. Be sure to read the [AI Usage Policy](https://github.com/dlvhdr/gh-dash/blob/main/AI_POLICY.md).

## AI Usage

The project has strict rules for AI usage. Please see the [AI Usage Policy](https://github.com/dlvhdr/gh-dash/blob/main/AI_POLICY.md). This is very important.

## Quick Guide

### I Have an Idea for a Feature

Like bug reports, first search through both issues and discussions and try to find if your feature has already been requested. Otherwise, open a discussion in the ["Feature Requests, Ideas"](https://github.com/dlvhdr/gh-dash/issues/new?template=feature_request.md) category.

### I've Implemented a Feature

- If there is an issue for the feature, open a pull request straight away.
- If there is no issue, open a discussion and link to your branch.
- If you want to live dangerously, open a pull request and hope for the best.

### I Have a Question Which Is Neither a Bug Report nor a Feature Request

Open a [Q&A discussion](https://github.com/dlvhdr/gh-dash/discussions/categories/q-a), or join our [Discord Server](https://discord.gg/SXNXp9NctV) and ask away in the #help forum channel.

## Working on the Code

### Installing Required Tooling

Our project uses [Devbox](https://github.com/jetpack-io/devbox) to manage its development environment.

Using Devbox will get your dev environment up and running easily and make sure we're all using the same tools with the same versions.

- Clone this repo

```sh
git clone git@github.com:dlvhdr/gh-dash.git && cd gh-dash
```

- Install `devbox`

```sh
curl -fsSL https://get.jetpack.io/devbox | bash
```

- Start the `devbox` shell and run the setup (will take a while on first time)

```sh
devbox shell
```

_This will create a shell where all required tools are installed._

- _(Optional)_ Set up `direnv` so `devbox shell` runs automatically
  - [direnv](https://www.jetify.com/devbox/docs/ide_configuration/direnv/) is a tool that allows setting unique environment variables per directory in your filesystem.
    - Install `direnv` with: `brew install direnv`
    - Add the following line at the end of the `~/.bashrc` file: `eval "$(direnv hook bash)"`
      - See [direnv's installation instructions](https://direnv.net/docs/hook.html) for other shells.
    - Enable `direnv` by running `direnv allow`
- _(Optional)_ Install the VSCode Extension
  - Follow [this guide](https://www.jetify.com/devbox/docs/ide_configuration/vscode/) to set up VSCode to automatically run `devbox shell`.

#### Troubleshooting

- delete the `.devbox` directory at the project's root

### Navigating the Codebase

To navigate our codebase with confidence, familiarize yourself with:

- [Bubbletea](https://github.com/charmbracelet/bubbletea) - the TUI framework we're using
- [The Elm architecture](https://guide.elm-lang.org/architecture/)
- [charmbracelet/glow](https://github.com/charmbracelet/glow) - for parsing and presenting Markdown

#### Code Structure

- `ui/` - this is the code that's responsible for rendering the different parts of the TUI
- `data/` - the code that fetches data from GitHub's GraphQL API
- `config/` - code to parse the user's `config.yml` file
- `utils/` - various utilities

### Debugging

- Write to the log by using Charm's `log` package
- Tail the log by running `task logs`
- Run `dash` in debug mode with `task debug` in another terminal window / pane

```go
import "charm.land/log/v2"

// more code...

log.Debug("Some message", "someVariable", someVariable)
```

### Running the Docs Locally

- Run the docs site by running `task docs`

* Go to `localhost:4321` to view them


================================================
FILE: docs/src/content/docs/donating/index.mdx
================================================
---
title: Donating ❤️
---

import { Aside } from "@astrojs/starlight/components";
import Sponsorship from "../../../components/Sponsorship.astro";

Donations are the primary way to support me in maintaining these projects.
If you enjoy my work and want to help, consider supporting me with a donation!

I'm also trying out a Sponsorware model where you can support me by joining the <a href="../insiders">Insiders</a> program to get early access features and apps.

## Goal

<div class="m-auto mt-12 flex flex-col gap-2 text-center md:w-full lg:w-1/2">
  <p>This is my current sponsorship goal</p>
  <Sponsorship server:defer />
</div>

Reaching this goal would help me spend more time on my projects and hopefully 🤞🏽
become a full time OSS maintainer one day.

_This is my dream_, to build projects sponsored by individuals with the sole focus on its users - no investors, no line go
up.

## How to Donate?

To become a sponsor go to:

<iframe
  src="https://github.com/sponsors/dlvhdr/card"
  title="Sponsor dlvhdr"
  height="120"
  width="100%"
  class="h-[200px] lg:h-[120px]"
></iframe>

Thank you very much! ❤️


================================================
FILE: docs/src/content/docs/getting-started/index.mdx
================================================
---
title: Installation
---

Get started using `dash` to review and manage your GitHub work items.

## Recommended Steps

1. Install the `gh` CLI

   ```bash
   brew install gh # e.g. if on macOS
   ```

   Or, see the [installation instructions][01] for other platforms.

2. Install this extension:

   ```sh
   gh extension install dlvhdr/gh-dash
   ```

3. To get the icons to render properly, you should download and install a [Nerd font][02]. Then,
   select that font as your font for your terminal of choice.

   ```bash
    brew install --cask font-fira-code-nerd-font
   ```

---

<details>
<summary>How do I get these exact colors and font?</summary>
The screenshots in this documentation use [Ghostty][n01] with the
[tokyonight theme][n02] and the [Fira Code][n03] Nerd Font. For the full setup,
see [these dotfiles][n04].

[n01]: https://ghostty.org/
[n02]: https://github.com/folke/tokyonight.nvim
[n03]: https://github.com/ryanoasis/nerd-fonts/tree/master/patched-fonts/FiraCode
[n04]: https://github.com/dlvhdr/dotfiles

</details>

---

## Manual Steps

If you want to install this extension **manually**, follow these steps:

1. Clone the repo

   ```bash
   # git
   git clone https://github.com/dlvhdr/gh-dash

   # GitHub CLI
   gh repo clone dlvhdr/gh-dash
   ```

2. `cd` into it

   ```bash
   cd gh-dash
   ```

3. Install it locally

   ```bash
   gh extension install .
   ```

[01]: https://github.com/cli/cli#installation
[02]: https://www.nerdfonts.com/


================================================
FILE: docs/src/content/docs/getting-started/keybindings/global.mdx
================================================
---
title: Global
linkTitle: >-
  ![icon:globe](lucide)&nbsp;Global
weight: 1
summary: >-
  Lists the default keybindings for controlling the dashboard globally.
---

This section lists the default keybindings for controlling the dashboard globally. These are
available in both the PRs and Issues views.

## `?` - Toggle Help

Press <kbd>?</kbd> to toggle the help menu in the UI. The help menu lists the available
keybindings for the current context.

## `/` - Search

Press <kbd>/</kbd> to focus on the dashboard's search input box. When you move the focus to the
search input box you can edit the current section's GitHub search criteria. To refresh the section
with your updated query, press <kbd>Enter</kbd>. After the dashboard updates, focus is returned to
the active section.

Any changes you make to the search query for a section aren't persistent. If you close the
dashboard and reopen it, the dashboard displays the sections with the queries defined in your
[configuration file](/configuration/). To make persistent changes to your sections
or add a new section, update your configuration.

## `r` - Refresh Current Section

Press <kbd>r</kbd> to refresh the current section's work items. When you do, the dashboard reruns
the defined query for the section and displays the returned work items.

## `R` - Refresh All Sections

Press <kbd>R</kbd> to refresh every section in the dashboard's current view. When you do, the
dashboard reruns the defined query for every section and displays the returned work items for the
current section. When you navigate to another section, it displays the updated work items for that
section.

## `s` - Switch View

Press the <kbd>s</kbd> key to switch the dashboard from the PRs view to the Issues view or the
Issues view to the PRs view. The first time you switch to a view in your dashboard, the dashboard
runs the defined query for every section in that view.

## `q` - Quit

Press the <kbd>q</kbd> key to quit the dashboard and return to your normal terminal view.


================================================
FILE: docs/src/content/docs/getting-started/keybindings/index.mdx
================================================
---
title: Overview
weight: 3
summary: >-
  Get started using key presses to interact with the dashboard.
---

import { LinkCard, CardGrid } from "@astrojs/starlight/components";

When you use `dash` to display a dashboard for your GitHub work items, you can interact with the
dashboard using key combinations.

This section lists the default keybindings for the dashboard's commands and what they do. Most of
the commands are universal across the dashboard's views. There are also commands that are specific
to the [PRs][01] and [Issues][02] views.

You can also define your own custom keybindings with the `keybindings` setting in your dashboard's
[configuration file][03].

<CardGrid>
  <LinkCard
    title="Global"
    href="./global"
    description="Lists the default keybindings for controlling the dashboard globally."
  />
  <LinkCard
    title="Selected Item"
    href="./selected-item"
    description="Lists the default keybindings for interacting with active items in the dashboard in any view."
  />
  <LinkCard
    title="Selected PR"
    href="./selected-pr"
    description="Lists the default keybindings for interacting with an actively selected item in the PRs view for the dashboard."
  />
  <LinkCard
    title="Selected Issue"
    href="./selected-issue"
    description="Lists the default keybindings for interacting with an actively selected item in the Issues view for the dashboard."
  />
  <LinkCard
    title="Preview Pane"
    href="./preview"
    description="Lists the default keybindings for interacting with the preview pane in the Dashboard."
  />
</CardGrid>

[01]: ./selected-pr
[02]: ./selected-issue
[03]: /configuration/


================================================
FILE: docs/src/content/docs/getting-started/keybindings/navigation.mdx
================================================
---
title: Navigation
linkTitle: >-
  ![icon:navigation](lucide)&nbsp;Navigation
weight: 2
summary: >-
  Lists the default keybindings for navigating the dashboard.
---

## `↑/k` - Move Up

Press <kbd>↑</kbd> or <kbd>k</kbd> to move to the previous work item in the current section.

## `↓/j` - Move Down

Press <kbd>↓</kbd> or <kbd>j</kbd> to move to the next work item in the current section.

## `←/h` - Previous Section

Press <kbd>←</kbd> or <kbd>h</kbd> to move to the previous section in the current view.

## `→/l` - Next Section

Press <kbd>→</kbd> or <kbd>l</kbd> to move to the next section in the current view.

## `g/home` - First Item

Press <kbd>g</kbd> or <kbd>Home</kbd> to move to the first work item in the current section.

## `G/end` - Last Item

Press <kbd>G</kbd> or <kbd>End</kbd> to move to the last work item in the current section.


================================================
FILE: docs/src/content/docs/getting-started/keybindings/preview.mdx
================================================
---
title: Preview Pane
linkTitle: >-
  ![icon:view](lucide)&nbsp;Preview Pane
weight: 6
summary: >-
  Lists the default keybindings for interacting with the preview pane in the Dashboard.
---

## `p` - Toggle Preview Pane

Press <kbd>p</kbd> to open the preview pane for the selected work item if it's hidden or hide the
preview pane if it's visible.

## `ctrl+d` - Preview Page Down

Press <kbd>Ctrl</kbd>+<kbd>d</kbd> to shift the view for the preview pane down one step. The first line in
the updated view is always the line after the last line of the previous view.

## `ctrl+u` - Preview Page Up

Press <kbd>Ctrl</kbd>+<kbd>u</kbd> to shift the view for the preview pane up one step. The last line in the
updated view is always the line before the first line of the previous view.

## `[` - Next Preview Tab

Press <kbd>[</kbd> to move to the next tab in the preview sidebar, if one exists.

## `]` - Previous Preview Tab

Press <kbd>]</kbd> to move to the previous tab in the preview sidebar, if one exists.


================================================
FILE: docs/src/content/docs/getting-started/keybindings/selected-issue.mdx
================================================
---
title: Selected Issue
linkTitle: >-
  ![icon:circle-dot](lucide)&nbsp;Selected Issue
weight: 4
summary: >-
  Lists the default keybindings for interacting with an actively selected item
  in the Issues view for the dashboard.
---

import { Aside } from "@astrojs/starlight/components";

## `a` - Assign Issue

Press <kbd>a</kbd> to assign one or more users to the issue. When you do, the dashboard opens the
preview pane and displays a new input.

When the unassign input is active, you can specify one or more GitHub usernames to assign to the
issue. By default, the input includes your username if you're not already assigned. If you're
already assigned, the input is empty by default.

To assign more than one user to the issue, specify additional users after one or more whitespace
characters, like a space, tab, or newline. We recommend separating the additional users with a
newline by pressing <kbd>Enter</kbd> after each username.

To submit the list of users to assign to the issue, press <kbd>Ctrl</kbd>+<kbd>d</kbd>. To cancel the
change instead, press <kbd>Ctrl</kbd>+<kbd>c</kbd> or <kbd>Esc</kbd>.

## `A` - Unassign Issue

Press <kbd>A</kbd> to unassign one or more users from the issue. When you do, the dashboard opens
the preview pane and displays a new input.

When the unassign input is active, you can specify one or more GitHub usernames to unassign from
the issue. By default, the input includes all assigned users separated by newlines.

Make sure the list of users to unassign only includes the users you want to unassign before you
submit the list.

To submit the list of users to unassign from the issue, press <kbd>Ctrl</kbd>+<kbd>d</kbd>. To cancel the
change instead, press <kbd>Ctrl</kbd>+<kbd>c</kbd> or <kbd>Esc</kbd>.

## `c` - Comment on Issue

Press <kbd>c</kbd> to add a comment to the issue. When you do, the dashboard opens a preview pane and
displays a new input.

You can write your comment as GitHub-flavored Markdown in the input.

To submit the comment on the issue, press <kbd>Ctrl</kbd>+<kbd>d</kbd>. To cancel the comment instead, press

<kbd>Ctrl</kbd>+<kbd>c</kbd> or <kbd>Esc</kbd>.

## `x` - Close Issue

Press <kbd>x</kbd> to close the issue. When you do, the dashboard uses the `gh issue close` command
to close the issue.

<Aside type="caution" title="Watch out!">
**Prior to v3.10.0:** When you use this command, the dashboard closes the issue immediately and
without prompting for confirmation. Only use this command when you're sure you
want to close the issue.

**Since v3.10.0:** When you use this command, the dashboard displays a confirmation prompt and
closes the issue only after you approve the action.

This command doesn't support closing the issue with a comment. If you want to
add a comment that explains why you're closing the issue, use the
[comment](#c---comment-on-issue) command before or after you use this one.

</Aside>

## `X` - Reopen Issue

Press <kbd>X</kbd> to reopen a closed issue. When you do, the dashboard uses the `gh issue reopen`
command to reopen the issue.

<Aside type="caution" title="Watch out!">
**Prior to v3.10.0:** When you use this command, the dashboard reopens the issue immediately and
without prompting for confirmation. Only use this command when you're sure you
want to reopen the closed issue.

**Since v3.10.0:** When you use this command, the dashboard displays a confirmation prompt and
reopens the issue only after you approve the action.

</Aside>


================================================
FILE: docs/src/content/docs/getting-started/keybindings/selected-item.mdx
================================================
---
title: Selected Item
weight: 3
summary: >-
  Lists the default keybindings for interacting with active items in the dashboard in any view.
---

## `o` - Open in GitHub

Press <kbd>o</kbd> to open the selected item on GitHub in your default web browser.

## `y` - Copy Number

Press <kbd>y</kbd> to copy the selected item's issue or PR number without the `#` prefix.

## `Y` - Copy URL

Press <kbd>Y</kbd> to copy the URL to the selected item on GitHub.


================================================
FILE: docs/src/content/docs/getting-started/keybindings/selected-notification.mdx
================================================
---
title: Selected Notification
weight: 5
---

## Key Bindings

| Key   | Action                                             |
| ----- | -------------------------------------------------- |
| D     | Mark as done (removes from inbox)                  |
| Alt+d | Mark all as done                                   |
| m     | Mark as read                                       |
| M     | Mark all as read                                   |
| u     | Unsubscribe from thread                            |
| b     | Toggle bookmark                                    |
| t     | Toggle smart filtering (filter to current repo)    |
| y     | Copy PR/Issue number                               |
| Y     | Copy URL                                           |
| S     | Sort by repository                                 |
| s     | Switch to PRs view                                 |
| o     | Open in browser                                    |
| Enter | View notification (fetches content, marks as read) |

### PR/Issue Keybindings in Notifications View

When viewing a PR notification in the preview pane, all PR-specific keybindings become available:

| Key     | Action                  |
| ------- | ----------------------- |
| v       | Approve PR              |
| a       | Assign                  |
| A       | Unassign                |
| c       | Comment                 |
| d       | View diff               |
| C/Space | Checkout branch         |
| x       | Close PR                |
| X       | Reopen PR               |
| W       | Mark ready for review   |
| m       | Merge PR                |
| u       | Update from base branch |
| w       | Watch checks            |
| [       | Previous sidebar tab    |
| ]       | Next sidebar tab        |
| e       | Expand description      |

Similarly, when viewing an Issue notification, Issue-specific keybindings are available:

| Key | Action            |
| --- | ----------------- |
| L   | Add/remove labels |
| a   | Assign            |
| A   | Unassign          |
| c   | Comment           |
| x   | Close issue       |
| X   | Reopen issue      |

The `?` help display dynamically updates to show the applicable keybindings based on what type of notification content is being viewed.


================================================
FILE: docs/src/content/docs/getting-started/keybindings/selected-pr.mdx
================================================
---
title: Selected PR
weight: 5
summary: >-
  Lists the default keybindings for interacting with an actively selected item
  in the PRs view for the dashboard.
---

import { Aside } from "@astrojs/starlight/components";

## `a` - Assign PR

Press <kbd>a</kbd> to assign one or more users to the PR. When you do, the dashboard opens the
preview pane and displays a new input.

When the unassign input is active, you can specify one or more GitHub usernames to assign to the
PR. By default, the input includes your username if you're not already assigned. If you're already
assigned, the input is empty by default.

To assign more than one user to the PR, specify additional users after one or more whitespace
characters, like a space, tab, or newline. We recommend separating the additional users with a
newline by pressing <kbd>Enter</kbd> after each username.

To submit the list of users to assign to the PR, press <kbd>Ctrl</kbd>+<kbd>d</kbd>. To cancel the
change instead, press <kbd>Ctrl</kbd>+<kbd>c</kbd> or <kbd>Esc</kbd>.

## `A` - Unassign PR

Press <kbd>A</kbd> to unassign one or more users from the PR. When you do, the dashboard opens the
preview pane and displays a new input.

When the unassign input is active, you can specify one or more GitHub usernames to unassign from
the PR. By default, the input includes all assigned users separated by newlines.

Make sure the list of users to unassign only includes the users you want to unassign before you
submit the list.

To submit the list of users to unassign from the PR, press <kbd>Ctrl</kbd>+<kbd>d</kbd>. To cancel the
change instead, press <kbd>Ctrl</kbd>+<kbd>c</kbd> or <kbd>Esc</kbd>.

## `c` - Comment on PR

Press <kbd>c</kbd> to add a comment to the PR. When you do, the dashboard opens a preview pane and
displays a new input.

You can write your comment as GitHub-flavored Markdown in the input.

To submit the comment on the PR, press <kbd>Ctrl</kbd>+<kbd>d</kbd>. To cancel the comment instead, press <kbd>Ctrl</kbd>+<kbd>c</kbd> or <kbd>Esc</kbd>.

## `C` - Checkout PR

Press <kbd>C</kbd> to checkout the PR locally. The dashboard checks for the `repoPaths` key in your
configuration to find the repository on your local filesystem.

The dashboard errors if you haven't defined `repoPaths` in your configuration or if the dashboard
can't determine where the repository for this PR is located using that setting.

If the dashboard is able to locate the repository for the PR on your local filesystem, it uses the
`gh pr checkout` command to checkout the PR locally.

## `d` - View PR Diff

Press <kbd>d</kbd> to display the PRs diff in the terminal. The dashboard uses the `pager.diff`
setting in your configuration, which defaults to `less`, to display the diff.

The dashboard view is replaced by PRs change diff displayed with the configured pager. When you
exit the pager, the view returns to the dashboard.

## `e` - Expand Description

Press <kbd>e</kbd> to display the full description for the PR.
By default `dash` only displays the first 5 lines.

## `m` - Merge PR

Press <kbd>m</kbd> to merge the PR. When you do, the dashboard uses the `gh pr merge` command to
merge the PR.

## `u` - Update PR

Press <kbd>u</kbd> to update the PR branch. When you do, the dashboard uses the
`gh pr update-branch` command to update the PR. This command updates the branch with a merge commit.

## `v` - Approve PR

Press <kbd>v</kbd> to approve the PR. When you do, the dashboard uses the
`gh pr review --approve` command to approve the PR. This will prompt you to add an optional comment to the approval. The comment prompt will be prefilled with
`defaults.prApproveComment` if it is set in your configuration, which defaults to "LGTM".

## `w` - Watch PR checks

Press <kbd>w</kbd> to watch the PR check and get a desktop notification if they succeed or fail. When you do, the dashboard uses the
`gh pr checks --watch` command to watch the PR checks.

## `W` - Mark PR as Ready for Review

Press <kbd>W</kbd> to mark the PR as ready for review. When you do, the dashboard uses the
`gh pr ready` command to convert the PR from draft status to ready for review.

## `x` - Close PR

Press <kbd>x</kbd> to close the PR. When you do, the dashboard uses the `gh pr close` command to
close the PR.

## `X` - Reopen PR

Press <kbd>X</kbd> to reopen a closed PR. When you do, the dashboard uses the `gh pr reopen`
command to reopen the PR.

<Aside type="caution" title="Watch out!">
**Prior to v3.10.0:** When you use some commands, the dashboard acts immediately and without
prompting for confirmation.

**Since v3.10.0:** When you use these command,s the dashboard displays a confirmation prompt.

</Aside>


================================================
FILE: docs/src/content/docs/getting-started/updating.mdx
================================================
---
title: Updating
---

You can update `dash` either with the [GitHub CLI](https://cli.github.com) or by
downloading the binaries manually.

## Update Using `gh`

To update `dash` simply run:

```sh
gh extension upgrade dlvhdr/gh-dash
```

You should see an output similar to:

```sh
[dash]: upgraded from v4.16.2 to v4.17.0
✓ Successfully checked extension upgrades
```

Run `gh extension --help` for info on more commands.

## Update Manually

To manually update `dash`, you can download the binaries from the latest release on GitHub under:
https://github.com/dlvhdr/gh-dash/releases

Search for the binary that corresponds to your operating system and CPU
architecture.


================================================
FILE: docs/src/content/docs/getting-started/usage.mdx
================================================
---
title: Usage
linkTitle: >-
  ![icon:terminal](lucide)&nbsp;Usage
summary: >-
  Get started using `dash`.
sidebar:
  order: 2
---

To use `dash`, follow these steps after you've [installed it][01]:

1. Run

   ```bash
   gh dash
   ```

2. Press <kbd>?</kbd> for help.
3. Run `gh dash --help` for more info:

   ```bash
   Usage:
     gh dash [flags]

   Flags:
     -c, --config string   use this configuration file (default lookup: a .gh-dash.yml file if inside a git repo, $GH_DASH_CONFIG env var, or if not set, $XDG_CONFIG_HOME/gh-dash/config.yml)
         --debug           passing this flag will allow writing debug output to debug.log
     -h, --help            help for Dash
   ```

## Flags

### `--config`

Specify the path to a configuration file to use for the dashboard. If the configuration file
doesn't exist or is invalid, `dash` returns an error.

```bash
gh dash --config path/to/configuration/file.yml
```

| Aliases |  Type  | Default                                                                                                                   |
| :------ | :----: | :------------------------------------------------------------------------------------------------------------------------ |
| `-c`    | String | `.gh-dash.yml` file if inside a git repo, `$GH_DASH_CONFIG` env var, or if not set, `$XDG_CONFIG_HOME/gh-dash/config.yml` |

If you don't specify this flag, `dash` uses the default configuration.
If the file doesn't exist, `dash` will create it.

The location of the default configuration file depends on your system:

1. If `$GH_DASH_CONFIG` is a non-empty string, `dash` will use this file for
   its configuration.
2. If `$GH_DASH_CONFIG` isn't set and you're in a git repository, it will look for `.gh-dash.yml` or `.gh-dash.yaml`
   in the repository root.
3. If neither of the above applies, then:
   - If `$XDG_CONFIG_HOME` is a non-empty string, the default path is `$XDG_CONFIG_HOME/gh-dash/config.yml`.
   - If `$XDG_CONFIG_HOME` isn't set, then:
     - On Linux and macOS systems, the default path is `$HOME/.config/gh-dash/config.yml`.
     - On Windows systems, the default path is `%USERPROFILE%\.config\gh-dash\config.yml`.

For more information about authoring configurations, see [Configuration][02].

### `--debug`

Specify whether `dash` should write logs to the `debug.log` file in the current directory. By
default, `dash` doesn't output debug information.

```bash
gh dash --debug
```

| Aliases |  Type   | Default |
| :------ | :-----: | :------ |
| (None)  | Boolean | `false` |

When you use this flag, `dash` creates the `debug.log` file in the current directory if it doesn't exist. If the file does exist, `dash` appends new log entries to it.

### `--help`

Use this flag to display the help information for `dash` in the terminal. If you specify this
flag, `dash` ignores all other flags. It only displays the help information.

```bash
gh dash --help
```

| Aliases |  Type   | Default |
| :------ | :-----: | :------ |
| `-h`    | Boolean | `false` |

### `--version`

Use this flag to display the version information for `dash` in the terminal. If you specify this
flag with the `--config` or `--debug` flags, `dash` ignores them. It only displays the version
information.

```bash
gh dash --version
```

| Aliases |  Type   | Default |
| :------ | :-----: | :------ |
| `-v`    | Boolean | `false` |

When you use this flag, `dash` emits the following information:

```text
gh-dash version <version>
commit: <commit_sha>
built at: <build_timestamp>
built by: <build_user>
goos: <operating_system>
goarch: <cpu_architecture>
```

- `<version>` is the extension's semantic version without a `v` prefix.
- `<commit_sha>` is the exact commit SHA the extension was built from.
- `<build_timestamp>` is the UTC date and time when the extension was built.
- `<build_user>` is who built the extension. For official releases, this is always `goreleaser`.

For example, the version information for the [v3.7.7 release][03] on Windows with an x64 processor
is:

```text
gh-dash version 3.7.7
commit: 6ce3f89ab0d73dd88e359133699d1cf920f88699
built at: 2023-04-15T08:42:16Z
built by: goreleaser
goos: windows
goarch: amd64
```

## Default Keybindings

When you use `dash`, it displays 
Download .txt
gitextract_yckel_xs/

├── .envrc
├── .gh-dash.yml
├── .github/
│   ├── FUNDING.yml
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.md
│   │   └── feature_request.md
│   ├── pull_request_template.md
│   └── workflows/
│       ├── build-and-test.yaml
│       ├── build-docs.yaml
│       ├── dependabot-sync.yml
│       ├── go-release.yml
│       ├── lint.yml
│       └── publish-docs.yaml
├── .gitignore
├── .golangci.yml
├── .goreleaser.yaml
├── AI_POLICY.md
├── CONTRIBUTING.md
├── LICENSE.txt
├── README.md
├── Taskfile.yaml
├── cmd/
│   ├── root.go
│   └── sponsors.go
├── devbox.json
├── docs/
│   ├── .dockerignore
│   ├── .envrc
│   ├── .eslint.config.js
│   ├── .gitignore
│   ├── .prettierrc.mjs
│   ├── Dockerfile
│   ├── README.mdx
│   ├── astro.config.mjs
│   ├── devbox.json
│   ├── package.json
│   ├── public/
│   │   ├── custom-commands.webm
│   │   ├── enhance-demo.webm
│   │   ├── overview.webm
│   │   ├── rerun.webm
│   │   ├── sections.webm
│   │   └── watch.webm
│   ├── src/
│   │   ├── assets/
│   │   │   ├── custom-commands.tape
│   │   │   ├── custom-commands.yml
│   │   │   ├── demo.yml
│   │   │   ├── overview.tape
│   │   │   ├── sections.tape
│   │   │   ├── sections.yml
│   │   │   ├── theme-catpuccin.yml
│   │   │   ├── theme-gruvbox.yml
│   │   │   └── theme-tokyonight.yml
│   │   ├── components/
│   │   │   ├── Box.astro
│   │   │   ├── DashHeroLogo.astro
│   │   │   ├── DecorationBottom.astro
│   │   │   ├── DecorationSeparator.astro
│   │   │   ├── DecorationTop.astro
│   │   │   ├── DiffnavCard.astro
│   │   │   ├── DiffnavMiniLogo.astro
│   │   │   ├── Discord.astro
│   │   │   ├── EnhanceCard.astro
│   │   │   ├── EnhanceLogo.astro
│   │   │   ├── EnhanceMiniLogo.astro
│   │   │   ├── EnhanceOneLineLogo.astro
│   │   │   ├── FadeImages.astro
│   │   │   ├── FeatureCard.astro
│   │   │   ├── FeatureSponsorshipGoal.astro
│   │   │   ├── Footer.astro
│   │   │   ├── Header.astro
│   │   │   ├── Hero.astro
│   │   │   ├── Logo.astro
│   │   │   ├── NerdFontIcon.astro
│   │   │   ├── PillLink.astro
│   │   │   ├── ReleaseVersionButton.astro
│   │   │   ├── Showcase.astro
│   │   │   ├── Sponsorship.astro
│   │   │   ├── SponsorshipGoal.astro
│   │   │   ├── StargazersCount.astro
│   │   │   ├── StargazersFallback.astro
│   │   │   ├── SupportSection.astro
│   │   │   ├── Terminal.astro
│   │   │   └── ThemeSelect.astro
│   │   ├── content/
│   │   │   └── docs/
│   │   │       ├── companions/
│   │   │       │   ├── enhance/
│   │   │       │   │   ├── dash-integration.mdx
│   │   │       │   │   ├── getting-started.mdx
│   │   │       │   │   ├── index.mdx
│   │   │       │   │   ├── keybindings.mdx
│   │   │       │   │   ├── theme.mdx
│   │   │       │   │   └── usage.mdx
│   │   │       │   └── index.mdx
│   │   │       ├── configuration/
│   │   │       │   ├── defaults.mdx
│   │   │       │   ├── examples.mdx
│   │   │       │   ├── index.mdx
│   │   │       │   ├── issue-section.mdx
│   │   │       │   ├── keybindings/
│   │   │       │   │   ├── index.mdx
│   │   │       │   │   ├── issues.mdx
│   │   │       │   │   └── prs.mdx
│   │   │       │   ├── layout/
│   │   │       │   │   ├── issue.mdx
│   │   │       │   │   ├── options.mdx
│   │   │       │   │   └── pr.mdx
│   │   │       │   ├── notification-section.mdx
│   │   │       │   ├── pr-section.mdx
│   │   │       │   ├── repo-paths.mdx
│   │   │       │   ├── reusing.mdx
│   │   │       │   ├── schema.mdx
│   │   │       │   ├── searching.mdx
│   │   │       │   └── theme.mdx
│   │   │       ├── contributing/
│   │   │       │   └── index.mdx
│   │   │       ├── donating/
│   │   │       │   └── index.mdx
│   │   │       ├── getting-started/
│   │   │       │   ├── index.mdx
│   │   │       │   ├── keybindings/
│   │   │       │   │   ├── global.mdx
│   │   │       │   │   ├── index.mdx
│   │   │       │   │   ├── navigation.mdx
│   │   │       │   │   ├── preview.mdx
│   │   │       │   │   ├── selected-issue.mdx
│   │   │       │   │   ├── selected-item.mdx
│   │   │       │   │   ├── selected-notification.mdx
│   │   │       │   │   └── selected-pr.mdx
│   │   │       │   ├── updating.mdx
│   │   │       │   └── usage.mdx
│   │   │       └── insiders/
│   │   │           └── index.mdx
│   │   ├── content.config.ts
│   │   ├── data/
│   │   │   ├── latestVersion.ts
│   │   │   ├── schemas/
│   │   │   │   ├── defaults.yaml
│   │   │   │   ├── definitions/
│   │   │   │   │   ├── grow.yaml
│   │   │   │   │   └── hexcolor.yaml
│   │   │   │   ├── gh-dash.yaml
│   │   │   │   ├── issue-section.yaml
│   │   │   │   ├── keybindings/
│   │   │   │   │   ├── entry.yaml
│   │   │   │   │   ├── issues.yaml
│   │   │   │   │   └── prs.yaml
│   │   │   │   ├── layout/
│   │   │   │   │   ├── issue.yaml
│   │   │   │   │   ├── options.yaml
│   │   │   │   │   └── pr.yaml
│   │   │   │   ├── pr-section.yaml
│   │   │   │   └── theme.yaml
│   │   │   ├── sponsorshipGoal.ts
│   │   │   └── stars.ts
│   │   ├── fonts/
│   │   │   ├── CommitMono-400-Regular.otf
│   │   │   ├── CommitMonoNerdFontMono-Regular.otf
│   │   │   └── font-face.css
│   │   ├── pages/
│   │   │   ├── enhance.astro
│   │   │   ├── index.astro
│   │   │   ├── robots.txt.ts
│   │   │   ├── schema/
│   │   │   │   ├── defaults.json.ts
│   │   │   │   ├── definitions/
│   │   │   │   │   ├── grow.json.ts
│   │   │   │   │   └── hexcolor.json.ts
│   │   │   │   ├── issue-section.json.ts
│   │   │   │   ├── keybindings/
│   │   │   │   │   ├── entry.json.ts
│   │   │   │   │   ├── issues.json.ts
│   │   │   │   │   └── prs.json.ts
│   │   │   │   ├── layout/
│   │   │   │   │   ├── issue.json.ts
│   │   │   │   │   ├── options.json.ts
│   │   │   │   │   └── pr.json.ts
│   │   │   │   ├── pr-section.json.ts
│   │   │   │   └── theme.json.ts
│   │   │   └── schema.json.ts
│   │   └── styles/
│   │       ├── custom.css
│   │       ├── fade-images.css
│   │       ├── index.css
│   │       ├── nerd-font.css
│   │       └── terminal.css
│   └── tsconfig.json
├── gh-dash.go
├── go.mod
├── go.sum
├── internal/
│   ├── config/
│   │   ├── feature_flags.go
│   │   ├── parser.go
│   │   ├── parser_test.go
│   │   ├── testdata/
│   │   │   ├── .gh-dash.yml
│   │   │   ├── ansi-color-config.yml
│   │   │   ├── gh-dash/
│   │   │   │   └── config.yml
│   │   │   ├── global-config.golden.yml
│   │   │   ├── merged-config.golden.yml
│   │   │   ├── other-test-config.yml
│   │   │   └── test-config.yml
│   │   └── utils.go
│   ├── data/
│   │   ├── assignee.go
│   │   ├── bookmarks.go
│   │   ├── bookmarks_test.go
│   │   ├── cache.go
│   │   ├── commonapi.go
│   │   ├── donestore.go
│   │   ├── donestore_test.go
│   │   ├── donestore_testing.go
│   │   ├── issueapi.go
│   │   ├── labelapi.go
│   │   ├── notificationapi.go
│   │   ├── notificationapi_test.go
│   │   ├── prapi.go
│   │   ├── prapi_test.go
│   │   ├── repository.go
│   │   ├── user.go
│   │   └── utils.go
│   ├── git/
│   │   └── git.go
│   ├── tui/
│   │   ├── common/
│   │   │   ├── diff.go
│   │   │   ├── diff_test.go
│   │   │   ├── labels.go
│   │   │   ├── labels_test.go
│   │   │   ├── repopath.go
│   │   │   ├── repopath_test.go
│   │   │   └── styles.go
│   │   ├── components/
│   │   │   ├── autocomplete/
│   │   │   │   └── autocomplete.go
│   │   │   ├── branch/
│   │   │   │   ├── branch.go
│   │   │   │   ├── data.go
│   │   │   │   ├── data_test.go
│   │   │   │   └── utils.go
│   │   │   ├── branchsidebar/
│   │   │   │   ├── branchsidebar.go
│   │   │   │   └── branchsidebar_test.go
│   │   │   ├── carousel/
│   │   │   │   └── carousel.go
│   │   │   ├── common/
│   │   │   │   └── interface.go
│   │   │   ├── footer/
│   │   │   │   └── footer.go
│   │   │   ├── inputbox/
│   │   │   │   └── inputbox.go
│   │   │   ├── issuerow/
│   │   │   │   └── issuerow.go
│   │   │   ├── issuessection/
│   │   │   │   ├── constants.go
│   │   │   │   └── issuessection.go
│   │   │   ├── issueview/
│   │   │   │   ├── action.go
│   │   │   │   ├── action_test.go
│   │   │   │   ├── activity.go
│   │   │   │   ├── issueview.go
│   │   │   │   └── labels.go
│   │   │   ├── listviewport/
│   │   │   │   └── listviewport.go
│   │   │   ├── notificationrow/
│   │   │   │   ├── data.go
│   │   │   │   ├── data_test.go
│   │   │   │   ├── notificationrow.go
│   │   │   │   └── notificationrow_test.go
│   │   │   ├── notificationssection/
│   │   │   │   ├── DESIGN.md
│   │   │   │   ├── commands.go
│   │   │   │   ├── commands_test.go
│   │   │   │   ├── filters_test.go
│   │   │   │   └── notificationssection.go
│   │   │   ├── notificationview/
│   │   │   │   ├── notificationview.go
│   │   │   │   └── notificationview_test.go
│   │   │   ├── prompt/
│   │   │   │   └── prompt.go
│   │   │   ├── prrow/
│   │   │   │   ├── data.go
│   │   │   │   ├── prrow.go
│   │   │   │   └── prrow_test.go
│   │   │   ├── prssection/
│   │   │   │   ├── checkout.go
│   │   │   │   ├── diff.go
│   │   │   │   ├── prssection.go
│   │   │   │   ├── prssection_test.go
│   │   │   │   └── watchChecks.go
│   │   │   ├── prview/
│   │   │   │   ├── action.go
│   │   │   │   ├── action_test.go
│   │   │   │   ├── activity.go
│   │   │   │   ├── checks.go
│   │   │   │   ├── checks_test.go
│   │   │   │   ├── commits.go
│   │   │   │   ├── files.go
│   │   │   │   ├── prview.go
│   │   │   │   └── reviewers_test.go
│   │   │   ├── reposection/
│   │   │   │   ├── commands.go
│   │   │   │   └── reposection.go
│   │   │   ├── search/
│   │   │   │   └── search.go
│   │   │   ├── section/
│   │   │   │   ├── section.go
│   │   │   │   └── section_test.go
│   │   │   ├── sidebar/
│   │   │   │   └── sidebar.go
│   │   │   ├── table/
│   │   │   │   └── table.go
│   │   │   ├── tabs/
│   │   │   │   ├── tabs.go
│   │   │   │   ├── tabs_test.go
│   │   │   │   └── testdata/
│   │   │   │       ├── TestTabs/
│   │   │   │       │   ├── Should_allow_setting_new_tabs.golden
│   │   │   │       │   ├── Should_display_loading_tabs.golden
│   │   │   │       │   ├── Should_display_tab_counts.golden
│   │   │   │       │   └── Should_show_overflow_symbol.golden
│   │   │   │       └── test_section.go
│   │   │   ├── tasks/
│   │   │   │   ├── issue.go
│   │   │   │   ├── issue_test.go
│   │   │   │   ├── pr.go
│   │   │   │   └── pr_test.go
│   │   │   └── utils.go
│   │   ├── constants/
│   │   │   ├── constants.go
│   │   │   ├── errMsg.go
│   │   │   ├── initMsg.go
│   │   │   └── progressMsg.go
│   │   ├── context/
│   │   │   ├── context.go
│   │   │   └── styles.go
│   │   ├── keys/
│   │   │   ├── branchKeys.go
│   │   │   ├── issueKeys.go
│   │   │   ├── keys.go
│   │   │   ├── keys_test.go
│   │   │   ├── notificationKeys.go
│   │   │   └── prKeys.go
│   │   ├── markdown/
│   │   │   ├── markdownRenderer.go
│   │   │   └── theme.go
│   │   ├── modelUtils.go
│   │   ├── tasks.go
│   │   ├── testdata/
│   │   │   ├── searchIssues.json
│   │   │   └── searchPullRequests.json
│   │   ├── testutils/
│   │   │   └── utils.go
│   │   ├── theme/
│   │   │   ├── theme.go
│   │   │   └── theme_test.go
│   │   ├── ui.go
│   │   └── ui_test.go
│   └── utils/
│       ├── templateHandler.go
│       ├── utils.go
│       └── utils_test.go
└── testdata/
    ├── api.github.com.graphql-schema.json
    ├── gh-dash/
    │   └── config.yml
    └── graphql.http
Download .txt
SYMBOL INDEX (1381 symbols across 134 files)

FILE: cmd/root.go
  function Execute (line 68) | func Execute() {
  function setDebugLogLevel (line 80) | func setDebugLogLevel() {
  function createModel (line 93) | func createModel(location config.Location, debug bool) (tui.Model, *os.F...
  function buildVersion (line 121) | func buildVersion(version, commit, date, builtBy string) string {
  function init (line 145) | func init() {

FILE: cmd/sponsors.go
  function init (line 57) | func init() {

FILE: docs/src/data/latestVersion.ts
  constant GH_TOKEN (line 1) | const GH_TOKEN = import.meta.env.GH_TOKEN;

FILE: docs/src/data/sponsorshipGoal.ts
  constant GH_TOKEN (line 1) | const GH_TOKEN = import.meta.env.GH_TOKEN;

FILE: docs/src/data/stars.ts
  constant GH_TOKEN (line 1) | const GH_TOKEN = import.meta.env.GH_TOKEN;

FILE: docs/src/pages/schema.json.ts
  function GET (line 1) | function GET() {

FILE: docs/src/pages/schema/defaults.json.ts
  function GET (line 1) | function GET() {

FILE: docs/src/pages/schema/definitions/grow.json.ts
  function GET (line 1) | function GET() {

FILE: docs/src/pages/schema/definitions/hexcolor.json.ts
  function GET (line 1) | function GET() {

FILE: docs/src/pages/schema/issue-section.json.ts
  function GET (line 1) | function GET() {

FILE: docs/src/pages/schema/keybindings/entry.json.ts
  function GET (line 1) | function GET() {

FILE: docs/src/pages/schema/keybindings/issues.json.ts
  function GET (line 1) | function GET() {

FILE: docs/src/pages/schema/keybindings/prs.json.ts
  function GET (line 1) | function GET() {

FILE: docs/src/pages/schema/layout/issue.json.ts
  function GET (line 1) | function GET() {

FILE: docs/src/pages/schema/layout/options.json.ts
  function GET (line 1) | function GET() {

FILE: docs/src/pages/schema/layout/pr.json.ts
  function GET (line 1) | function GET() {

FILE: docs/src/pages/schema/pr-section.json.ts
  function GET (line 2) | function GET() {

FILE: docs/src/pages/schema/theme.json.ts
  function GET (line 2) | function GET() {

FILE: gh-dash.go
  function main (line 7) | func main() {

FILE: internal/config/feature_flags.go
  constant FF_REPO_VIEW (line 5) | FF_REPO_VIEW = "FF_REPO_VIEW"
  constant FF_MOCK_DATA (line 7) | FF_MOCK_DATA = "FF_MOCK_DATA"
  function IsFeatureEnabled (line 9) | func IsFeatureEnabled(name string) bool {

FILE: internal/config/parser.go
  constant DashDir (line 34) | DashDir = "gh-dash"
  constant RepoConfigFileName (line 36) | RepoConfigFileName = ".gh-dash.yml"
  constant ConfigYmlFileName (line 38) | ConfigYmlFileName = "config.yml"
  constant ConfigYamlFileName (line 41) | ConfigYamlFileName = "config.yaml"
  constant DEFAULT_XDG_CONFIG_DIRNAME (line 43) | DEFAULT_XDG_CONFIG_DIRNAME = ".config"
  type ViewType (line 48) | type ViewType
    method String (line 50) | func (vt ViewType) String() string {
    method MarshalJSON (line 54) | func (vt ViewType) MarshalJSON() ([]byte, error) {
    method UnmarshalJSON (line 58) | func (a *ViewType) UnmarshalJSON(b []byte) error {
  constant NotificationsView (line 78) | NotificationsView ViewType = "notifications"
  constant PRsView (line 79) | PRsView           ViewType = "prs"
  constant IssuesView (line 80) | IssuesView        ViewType = "issues"
  constant RepoView (line 81) | RepoView          ViewType = "repo"
  type SectionConfig (line 84) | type SectionConfig struct
  type PrsSectionConfig (line 91) | type PrsSectionConfig struct
  type IssuesSectionConfig (line 99) | type IssuesSectionConfig struct
  type NotificationsSectionConfig (line 106) | type NotificationsSectionConfig struct
  type PreviewConfig (line 112) | type PreviewConfig struct
  type NullableBool (line 117) | type NullableBool struct
    method MarshalJSON (line 121) | func (nb NullableBool) MarshalJSON() ([]byte, error) {
    method UnmarshalJSON (line 130) | func (nullBool *NullableBool) UnmarshalJSON(b []byte) error {
  type ColumnConfig (line 146) | type ColumnConfig struct
  type PrsLayoutConfig (line 151) | type PrsLayoutConfig struct
  type IssuesLayoutConfig (line 167) | type IssuesLayoutConfig struct
  type LayoutConfig (line 180) | type LayoutConfig struct
  type Defaults (line 185) | type Defaults struct
  type RepoConfig (line 197) | type RepoConfig struct
  type Keybinding (line 202) | type Keybinding struct
    method NewBinding (line 209) | func (kb Keybinding) NewBinding(previous *key.Binding) key.Binding {
  type Keybindings (line 225) | type Keybindings struct
  type Pager (line 233) | type Pager struct
  type Color (line 237) | type Color
    method String (line 239) | func (c Color) String() string {
    method IsZero (line 243) | func (c Color) IsZero() bool {
  type ColorThemeIcon (line 247) | type ColorThemeIcon struct
  type ColorThemeText (line 256) | type ColorThemeText struct
  type ColorThemeBorder (line 267) | type ColorThemeBorder struct
  type ColorThemeBackground (line 273) | type ColorThemeBackground struct
  type ColorTheme (line 277) | type ColorTheme struct
  type ColorThemeConfig (line 284) | type ColorThemeConfig struct
  type IconTheme (line 288) | type IconTheme struct
  type IconThemeConfig (line 297) | type IconThemeConfig struct
  type TableUIThemeConfig (line 301) | type TableUIThemeConfig struct
  type UIThemeConfig (line 306) | type UIThemeConfig struct
  type ThemeConfig (line 311) | type ThemeConfig struct
  type Config (line 317) | type Config struct
  type configError (line 333) | type configError struct
    method Error (line 507) | func (e configError) Error() string {
  type ConfigParser (line 339) | type ConfigParser struct
    method getDefaultConfig (line 343) | func (parser ConfigParser) getDefaultConfig() Config {
    method getDefaultConfigYamlContents (line 496) | func (parser ConfigParser) getDefaultConfigYamlContents() (string, err...
    method writeDefaultConfigContents (line 532) | func (parser ConfigParser) writeDefaultConfigContents(
    method createConfigFileIfMissing (line 547) | func (parser ConfigParser) createConfigFileIfMissing(
    method getGlobalConfigPathOrCreateIfMissing (line 569) | func (parser ConfigParser) getGlobalConfigPathOrCreateIfMissing() (str...
    method getProvidedConfigPath (line 601) | func (parser ConfigParser) getProvidedConfigPath(location Location) st...
    method loadGlobalConfig (line 624) | func (parser ConfigParser) loadGlobalConfig(globalCfgPath string) error {
    method mergeConfigs (line 628) | func (parser ConfigParser) mergeConfigs(globalCfgPath, userProvidedCfg...
    method unmarshalConfigWithDefaults (line 802) | func (parser ConfigParser) unmarshalConfigWithDefaults() (Config, erro...
  function mergeKeybindings (line 665) | func mergeKeybindings(src, dest map[string]any, typ string) []map[string...
  type parsingError (line 722) | type parsingError struct
    method Error (line 727) | func (e parsingError) Error() string {
  function validateColor (line 731) | func validateColor(fl validator.FieldLevel) bool {
  function initParser (line 740) | func initParser() ConfigParser {
  type Location (line 758) | type Location struct
  function ParseConfig (line 764) | func ParseConfig(location Location) (Config, error) {

FILE: internal/config/parser_test.go
  constant repoPath (line 34) | repoPath = "testdata"
  function init (line 36) | func init() {
  function Testwd (line 48) | func Testwd(t *testing.T) string {
  function TestParser (line 53) | func TestParser(t *testing.T) {
  function loadExpected (line 158) | func loadExpected(t *testing.T, fpath string) Config {
  function setXDGConfigHomeEnvVar (line 172) | func setXDGConfigHomeEnvVar(t *testing.T, dir string) func() {
  function TestValidateColor (line 181) | func TestValidateColor(t *testing.T) {
  function setupConfigEnvVar (line 216) | func setupConfigEnvVar(t *testing.T) func() {

FILE: internal/config/utils.go
  method GetFullScreenDiffPagerEnv (line 9) | func (cfg Config) GetFullScreenDiffPagerEnv() []string {
  method ToSectionConfig (line 31) | func (cfg PrsSectionConfig) ToSectionConfig() SectionConfig {
  method ToSectionConfig (line 40) | func (cfg IssuesSectionConfig) ToSectionConfig() SectionConfig {
  method ToSectionConfig (line 48) | func (cfg NotificationsSectionConfig) ToSectionConfig() SectionConfig {
  function MergeColumnConfigs (line 56) | func MergeColumnConfigs(defaultCfg, sectionCfg ColumnConfig) ColumnConfig {
  function TruncateCommand (line 67) | func TruncateCommand(cmd string) string {

FILE: internal/data/assignee.go
  type Assignees (line 3) | type Assignees struct
  type Assignee (line 7) | type Assignee struct

FILE: internal/data/bookmarks.go
  constant defaultXDGStateDir (line 13) | defaultXDGStateDir = ".local/state"
  constant dashDir (line 14) | dashDir            = "gh-dash"
  type NotificationIDStore (line 19) | type NotificationIDStore struct
    method load (line 54) | func (s *NotificationIDStore) load() error {
    method save (line 82) | func (s *NotificationIDStore) save() error {
    method Has (line 131) | func (s *NotificationIDStore) Has(id string) bool {
    method Add (line 138) | func (s *NotificationIDStore) Add(id string) {
    method Remove (line 146) | func (s *NotificationIDStore) Remove(id string) {
    method Toggle (line 154) | func (s *NotificationIDStore) Toggle(id string) bool {
    method GetAll (line 168) | func (s *NotificationIDStore) GetAll() []string {
    method Flush (line 179) | func (s *NotificationIDStore) Flush() error {
    method IsBookmarked (line 201) | func (s *NotificationIDStore) IsBookmarked(id string) bool {
    method ToggleBookmark (line 206) | func (s *NotificationIDStore) ToggleBookmark(id string) bool {
    method GetBookmarkedIds (line 211) | func (s *NotificationIDStore) GetBookmarkedIds() []string {
  function newNotificationIDStore (line 26) | func newNotificationIDStore(filename, name string) *NotificationIDStore {
  function getStateFilePath (line 42) | func getStateFilePath(filename string) (string, error) {
  function GetBookmarkStore (line 191) | func GetBookmarkStore() *NotificationIDStore {

FILE: internal/data/bookmarks_test.go
  function TestNotificationIDStore (line 9) | func TestNotificationIDStore(t *testing.T) {

FILE: internal/data/cache.go
  type Cache (line 9) | type Cache struct
  function New (line 15) | func New() Cache {
  function Get (line 31) | func Get() Cache {

FILE: internal/data/commonapi.go
  type VersionResponse (line 9) | type VersionResponse struct
  function FetchLatestVersion (line 17) | func FetchLatestVersion() (VersionResponse, error) {
  type SponsorsResponse (line 43) | type SponsorsResponse struct
  function FetchSponsors (line 61) | func FetchSponsors() (SponsorsResponse, error) {

FILE: internal/data/donestore.go
  type DoneStore (line 17) | type DoneStore struct
    method load (line 44) | func (s *DoneStore) load() error {
    method prune (line 99) | func (s *DoneStore) prune() {
    method save (line 108) | func (s *DoneStore) save() error {
    method MarkDone (line 157) | func (s *DoneStore) MarkDone(id string, updatedAt time.Time) {
    method IsDone (line 166) | func (s *DoneStore) IsDone(id string, updatedAt time.Time) bool {
    method Remove (line 177) | func (s *DoneStore) Remove(id string) {
    method Flush (line 185) | func (s *DoneStore) Flush() error {
  function newDoneStore (line 23) | func newDoneStore(filename string) *DoneStore {
  function GetDoneStore (line 197) | func GetDoneStore() *DoneStore {

FILE: internal/data/donestore_test.go
  function TestDoneStore (line 11) | func TestDoneStore(t *testing.T) {

FILE: internal/data/donestore_testing.go
  function NewDoneStoreForTesting (line 8) | func NewDoneStoreForTesting(filePath string) *DoneStore {
  function OverrideDoneStoreForTesting (line 17) | func OverrideDoneStoreForTesting(store *DoneStore) func() {

FILE: internal/data/issueapi.go
  type IssueData (line 16) | type IssueData struct
    method GetAuthor (line 61) | func (data IssueData) GetAuthor(theme theme.Theme, showAuthorIcons boo...
    method GetTitle (line 69) | func (data IssueData) GetTitle() string {
    method GetRepoNameWithOwner (line 73) | func (data IssueData) GetRepoNameWithOwner() string {
    method GetNumber (line 77) | func (data IssueData) GetNumber() int {
    method GetUrl (line 81) | func (data IssueData) GetUrl() string {
    method GetUpdatedAt (line 85) | func (data IssueData) GetUpdatedAt() time.Time {
    method GetCreatedAt (line 89) | func (data IssueData) GetCreatedAt() time.Time {
  type IssueComments (line 35) | type IssueComments struct
  type IssueComment (line 40) | type IssueComment struct
  type IssueReactions (line 48) | type IssueReactions struct
  type Label (line 52) | type Label struct
  type IssueLabels (line 57) | type IssueLabels struct
  function makeIssuesQuery (line 93) | func makeIssuesQuery(query string) string {
  function FetchIssues (line 97) | func FetchIssues(query string, limit int, pageInfo *PageInfo) (IssuesRes...
  type IssuesResponse (line 144) | type IssuesResponse struct
  function FetchIssue (line 151) | func FetchIssue(issueUrl string) (IssueData, error) {

FILE: internal/data/labelapi.go
  function GetCachedRepoLabels (line 17) | func GetCachedRepoLabels(repoNameWithOwner string) ([]Label, bool) {
  function FetchRepoLabels (line 24) | func FetchRepoLabels(repoNameWithOwner string) ([]Label, error) {
  function ClearLabelCache (line 69) | func ClearLabelCache() {
  function ClearRepoLabelCache (line 75) | func ClearRepoLabelCache(repoNameWithOwner string) {
  function GetLabelNames (line 81) | func GetLabelNames(labels []Label) []string {

FILE: internal/data/notificationapi.go
  constant SubjectTypePullRequest (line 14) | SubjectTypePullRequest = "PullRequest"
  constant SubjectTypeIssue (line 15) | SubjectTypeIssue       = "Issue"
  constant SubjectTypeDiscussion (line 16) | SubjectTypeDiscussion  = "Discussion"
  constant SubjectTypeRelease (line 17) | SubjectTypeRelease     = "Release"
  constant SubjectTypeCommit (line 18) | SubjectTypeCommit      = "Commit"
  constant SubjectTypeCheckSuite (line 19) | SubjectTypeCheckSuite  = "CheckSuite"
  constant ReasonSubscribed (line 24) | ReasonSubscribed      = "subscribed"
  constant ReasonReviewRequested (line 25) | ReasonReviewRequested = "review_requested"
  constant ReasonMention (line 26) | ReasonMention         = "mention"
  constant ReasonAuthor (line 27) | ReasonAuthor          = "author"
  constant ReasonComment (line 28) | ReasonComment         = "comment"
  constant ReasonAssign (line 29) | ReasonAssign          = "assign"
  constant ReasonStateChange (line 30) | ReasonStateChange     = "state_change"
  constant ReasonCIActivity (line 31) | ReasonCIActivity      = "ci_activity"
  constant ReasonTeamMention (line 32) | ReasonTeamMention     = "team_mention"
  constant ReasonSecurityAlert (line 33) | ReasonSecurityAlert   = "security_alert"
  type NotificationSubject (line 38) | type NotificationSubject struct
  type NotificationRepository (line 45) | type NotificationRepository struct
  type NotificationData (line 56) | type NotificationData struct
    method GetTitle (line 68) | func (n NotificationData) GetTitle() string {
    method GetRepoNameWithOwner (line 72) | func (n NotificationData) GetRepoNameWithOwner() string {
    method GetNumber (line 76) | func (n NotificationData) GetNumber() int {
    method GetUrl (line 81) | func (n NotificationData) GetUrl() string {
    method GetUpdatedAt (line 88) | func (n NotificationData) GetUpdatedAt() time.Time {
    method GetCreatedAt (line 92) | func (n NotificationData) GetCreatedAt() time.Time {
  type NotificationsResponse (line 97) | type NotificationsResponse struct
  function getRESTClient (line 103) | func getRESTClient() (*gh.RESTClient, error) {
  type NotificationReadState (line 113) | type NotificationReadState
  constant NotificationStateUnread (line 116) | NotificationStateUnread NotificationReadState = "unread"
  constant NotificationStateRead (line 117) | NotificationStateRead   NotificationReadState = "read"
  constant NotificationStateAll (line 118) | NotificationStateAll    NotificationReadState = "all"
  function FetchNotifications (line 121) | func FetchNotifications(
  function FetchNotificationByThreadId (line 246) | func FetchNotificationByThreadId(threadId string) (*NotificationData, er...
  function MarkNotificationDone (line 264) | func MarkNotificationDone(threadId string) error {
  function MarkNotificationRead (line 282) | func MarkNotificationRead(threadId string) error {
  function UnsubscribeFromThread (line 301) | func UnsubscribeFromThread(threadId string) error {
  function MarkAllNotificationsRead (line 320) | func MarkAllNotificationsRead() error {
  type CommentResponse (line 339) | type CommentResponse struct
  type WorkflowRun (line 346) | type WorkflowRun struct
  type WorkflowRunsResponse (line 356) | type WorkflowRunsResponse struct
  function FetchCommentAuthor (line 363) | func FetchCommentAuthor(apiUrl string) (string, error) {
  function FindBestWorkflowRunMatch (line 393) | func FindBestWorkflowRunMatch(runs []WorkflowRun, notificationUpdatedAt ...
  function FetchRecentWorkflowRun (line 427) | func FetchRecentWorkflowRun(

FILE: internal/data/notificationapi_test.go
  function TestFindBestWorkflowRunMatch (line 8) | func TestFindBestWorkflowRunMatch(t *testing.T) {
  function TestNotificationDataGetUrl (line 192) | func TestNotificationDataGetUrl(t *testing.T) {

FILE: internal/data/prapi.go
  type SuggestedReviewer (line 20) | type SuggestedReviewer struct
  type EnrichedPullRequestData (line 28) | type EnrichedPullRequestData struct
    method ToPullRequestData (line 427) | func (e EnrichedPullRequestData) ToPullRequestData() PullRequestData {
  type PullRequestData (line 66) | type PullRequestData struct
    method GetAuthor (line 393) | func (data PullRequestData) GetAuthor(theme theme.Theme, showAuthorIco...
    method GetTitle (line 401) | func (data PullRequestData) GetTitle() string {
    method GetRepoNameWithOwner (line 405) | func (data PullRequestData) GetRepoNameWithOwner() string {
    method GetNumber (line 409) | func (data PullRequestData) GetNumber() int {
    method GetUrl (line 413) | func (data PullRequestData) GetUrl() string {
    method GetUpdatedAt (line 417) | func (data PullRequestData) GetUpdatedAt() time.Time {
    method GetCreatedAt (line 421) | func (data PullRequestData) GetCreatedAt() time.Time {
  type CheckRun (line 104) | type CheckRun struct
  type StatusContext (line 120) | type StatusContext struct
  type CheckSuiteNode (line 128) | type CheckSuiteNode struct
  type CheckSuites (line 143) | type CheckSuites struct
  type StatusCheckRollupStats (line 148) | type StatusCheckRollupStats struct
  type AllCommits (line 159) | type AllCommits struct
  type LastCommitWithStatusChecks (line 176) | type LastCommitWithStatusChecks struct
  type CommentsWithBody (line 211) | type CommentsWithBody struct
  type Commits (line 221) | type Commits struct
  type Comment (line 239) | type Comment struct
  type ReviewComment (line 247) | type ReviewComment struct
  type ReviewComments (line 257) | type ReviewComments struct
  type Comments (line 262) | type Comments struct
  type ReviewThreads (line 266) | type ReviewThreads struct
  type Review (line 270) | type Review struct
  type Reviews (line 279) | type Reviews struct
  type ReviewThreadsWithComments (line 284) | type ReviewThreadsWithComments struct
  type ChangedFile (line 296) | type ChangedFile struct
  type ChangedFiles (line 303) | type ChangedFiles struct
  type RequestedReviewerUser (line 308) | type RequestedReviewerUser struct
  type RequestedReviewerTeam (line 312) | type RequestedReviewerTeam struct
  type RequestedReviewerBot (line 317) | type RequestedReviewerBot struct
  type RequestedReviewerMannequin (line 321) | type RequestedReviewerMannequin struct
  type ReviewRequestNode (line 325) | type ReviewRequestNode struct
    method GetReviewerDisplayName (line 340) | func (r ReviewRequestNode) GetReviewerDisplayName() string {
    method GetReviewerType (line 356) | func (r ReviewRequestNode) GetReviewerType() string {
    method IsTeam (line 372) | func (r ReviewRequestNode) IsTeam() bool {
  type ReviewRequests (line 335) | type ReviewRequests struct
  type PRLabel (line 376) | type PRLabel struct
  type PRLabels (line 381) | type PRLabels struct
  type MergeStateStatus (line 385) | type MergeStateStatus
  type PageInfo (line 387) | type PageInfo struct
  function makePullRequestsQuery (line 457) | func makePullRequestsQuery(query string) string {
  type PullRequestsResponse (line 461) | type PullRequestsResponse struct
  function SetClient (line 472) | func SetClient(c *gh.GraphQLClient) {
  function ClearEnrichmentCache (line 479) | func ClearEnrichmentCache() {
  function IsEnrichmentCacheCleared (line 485) | func IsEnrichmentCacheCleared() bool {
  function FetchPullRequests (line 489) | func FetchPullRequests(query string, limit int, pageInfo *PageInfo) (Pul...
  function FetchPullRequest (line 546) | func FetchPullRequest(prUrl string) (EnrichedPullRequestData, error) {

FILE: internal/data/prapi_test.go
  function TestClearEnrichmentCache (line 10) | func TestClearEnrichmentCache(t *testing.T) {
  function TestIsEnrichmentCacheCleared (line 44) | func TestIsEnrichmentCacheCleared(t *testing.T) {
  function TestSetClient (line 62) | func TestSetClient(t *testing.T) {

FILE: internal/data/repository.go
  type BranchProtectionRules (line 7) | type BranchProtectionRules struct
  type Repository (line 17) | type Repository struct

FILE: internal/data/user.go
  function CurrentLoginName (line 7) | func CurrentLoginName() (string, error) {

FILE: internal/data/utils.go
  type RowData (line 12) | type RowData interface
  function GetAuthorRoleIcon (line 20) | func GetAuthorRoleIcon(role string, theme theme.Theme) string {

FILE: internal/git/git.go
  type Repo (line 18) | type Repo struct
  type Branch (line 27) | type Branch struct
  function GetOriginUrl (line 38) | func GetOriginUrl(dir string) (string, error) {
  function GetRepo (line 63) | func GetRepo(dir string) (*Repo, error) {
  function GetStatus (line 145) | func GetStatus(dir string) (gitm.NameStatus, error) {
  function getUnstagedStatus (line 154) | func getUnstagedStatus(repo *gitm.Repository) (gitm.NameStatus, error) {
  function FetchRepo (line 180) | func FetchRepo(dir string) (*Repo, error) {
  function GetRepoInPwd (line 194) | func GetRepoInPwd() (*gitm.Repository, error) {
  function GetRepoShortName (line 198) | func GetRepoShortName(url string) string {

FILE: internal/tui/common/diff.go
  function DiffPR (line 14) | func DiffPR(prNumber int, repoName string, env []string) tea.Cmd {

FILE: internal/tui/common/diff_test.go
  function TestDiffPR (line 7) | func TestDiffPR(t *testing.T) {

FILE: internal/tui/common/labels.go
  function RenderLabels (line 9) | func RenderLabels(sidebarWidth int, labels []data.Label, pillStyle lipgl...

FILE: internal/tui/common/labels_test.go
  function TestRenderLabels (line 15) | func TestRenderLabels(t *testing.T) {

FILE: internal/tui/common/repopath.go
  function GetRepoLocalPath (line 25) | func GetRepoLocalPath(repoName string, cfgPaths map[string]string) (stri...

FILE: internal/tui/common/repopath_test.go
  function TestGetRepoLocalPath (line 28) | func TestGetRepoLocalPath(t *testing.T) {

FILE: internal/tui/common/styles.go
  type CommonStyles (line 26) | type CommonStyles struct
  function BuildStyles (line 43) | func BuildStyles(theme theme.Theme) CommonStyles {
  function RenderPreviewHeader (line 93) | func RenderPreviewHeader(theme theme.Theme, width int, text string) stri...
  function RenderPreviewTitle (line 103) | func RenderPreviewTitle(theme theme.Theme, styles CommonStyles, width in...

FILE: internal/tui/components/autocomplete/autocomplete.go
  type suggestionList (line 20) | type suggestionList struct
    method String (line 24) | func (s suggestionList) String(i int) string {
    method Len (line 30) | func (s suggestionList) Len() int {
  type FetchState (line 28) | type FetchState
  constant FetchStateIdle (line 65) | FetchStateIdle FetchState = iota
  constant FetchStateLoading (line 66) | FetchStateLoading
  constant FetchStateSuccess (line 67) | FetchStateSuccess
  constant FetchStateError (line 68) | FetchStateError
  type ClearFetchStatusMsg (line 72) | type ClearFetchStatusMsg struct
  type FetchSuggestionsRequestedMsg (line 78) | type FetchSuggestionsRequestedMsg struct
  function NewFetchSuggestionsRequestedCmd (line 84) | func NewFetchSuggestionsRequestedCmd(force bool) tea.Cmd {
  type Model (line 88) | type Model struct
    method SetSuggestions (line 124) | func (m *Model) SetSuggestions(suggestions []string) {
    method Show (line 128) | func (m *Model) Show(currentItem string, excludeItems []string) {
    method Selected (line 171) | func (m *Model) Selected() string {
    method Next (line 178) | func (m *Model) Next() {
    method Prev (line 184) | func (m *Model) Prev() {
    method Hide (line 194) | func (m *Model) Hide() {
    method Reset (line 201) | func (m *Model) Reset() {
    method Suppress (line 212) | func (m *Model) Suppress() {
    method Unsuppress (line 218) | func (m *Model) Unsuppress() {
    method IsVisible (line 222) | func (m *Model) IsVisible() bool {
    method HasSuggestions (line 227) | func (m *Model) HasSuggestions() bool {
    method SetWidth (line 231) | func (m *Model) SetWidth(width int) {
    method View (line 235) | func (m *Model) View() string {
    method SetFetchLoading (line 303) | func (m *Model) SetFetchLoading() tea.Cmd {
    method SetFetchSuccess (line 319) | func (m *Model) SetFetchSuccess() tea.Cmd {
    method SetFetchError (line 325) | func (m *Model) SetFetchError(err error) tea.Cmd {
    method clearFetchStatusAfterDelay (line 332) | func (m *Model) clearFetchStatusAfterDelay() tea.Cmd {
    method UpdateVisible (line 338) | func (m *Model) UpdateVisible() {
    method Update (line 346) | func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
    method UpdateProgramContext (line 364) | func (m *Model) UpdateProgramContext(ctx *context.ProgramContext) {
  function NewModel (line 105) | func NewModel(ctx *context.ProgramContext) Model {

FILE: internal/tui/components/branch/branch.go
  type Branch (line 18) | type Branch struct
    method getTextStyle (line 25) | func (b *Branch) getTextStyle() lipgloss.Style {
    method renderReviewStatus (line 29) | func (b *Branch) renderReviewStatus() string {
    method renderState (line 51) | func (b *Branch) renderState() string {
    method GetStatusChecksRollup (line 76) | func (b *Branch) GetStatusChecksRollup() string {
    method renderCiStatus (line 85) | func (b *Branch) renderCiStatus() string {
    method renderLines (line 105) | func (b *Branch) renderLines(isSelected bool) string {
    method renderTitle (line 137) | func (b *Branch) renderTitle() string {
    method renderExtendedTitle (line 146) | func (b *Branch) renderExtendedTitle(isSelected bool) string {
    method renderAuthor (line 155) | func (pr *Branch) renderAuthor() string {
    method renderAssignees (line 159) | func (b *Branch) renderAssignees() string {
    method renderRepoName (line 170) | func (b *Branch) renderRepoName() string {
    method renderUpdateAt (line 180) | func (b *Branch) renderUpdateAt() string {
    method renderBaseName (line 202) | func (b *Branch) renderBaseName() string {
    method RenderState (line 209) | func (b *Branch) RenderState() string {
    method ToTableRow (line 226) | func (b *Branch) ToTableRow(isSelected bool) table.Row {
    method renderBranch (line 254) | func (b *Branch) renderBranch(isSelected bool, width int) string {
    method getBaseStyle (line 269) | func (b *Branch) getBaseStyle(isSelected bool) lipgloss.Style {
    method getMaxWidth (line 278) | func (b *Branch) getMaxWidth() int {
    method renderCommitsAheadBehind (line 288) | func (b *Branch) renderCommitsAheadBehind(isSelected bool) string {
    method renderLastCommitMsg (line 305) | func (b *Branch) renderLastCommitMsg(isSelected bool, width int) string {

FILE: internal/tui/components/branch/data.go
  type BranchData (line 10) | type BranchData struct
    method GetRepoNameWithOwner (line 15) | func (b BranchData) GetRepoNameWithOwner() string {
    method GetTitle (line 22) | func (b BranchData) GetTitle() string {
    method GetNumber (line 26) | func (b BranchData) GetNumber() int {
    method GetUrl (line 33) | func (b BranchData) GetUrl() string {
    method GetUpdatedAt (line 40) | func (b BranchData) GetUpdatedAt() time.Time {

FILE: internal/tui/components/branch/data_test.go
  function TestBranchData_GetRepoNameWithOwner_EmptyRemotes (line 12) | func TestBranchData_GetRepoNameWithOwner_EmptyRemotes(t *testing.T) {
  function TestBranchData_GetRepoNameWithOwner_WithRemotes (line 26) | func TestBranchData_GetRepoNameWithOwner_WithRemotes(t *testing.T) {
  function TestBranchData_GetUpdatedAt_NilLastUpdatedAt (line 38) | func TestBranchData_GetUpdatedAt_NilLastUpdatedAt(t *testing.T) {
  function TestBranchData_GetUpdatedAt_WithValue (line 52) | func TestBranchData_GetUpdatedAt_WithValue(t *testing.T) {

FILE: internal/tui/components/branch/utils.go
  function keepSameSpacesOnAddDeletions (line 8) | func keepSameSpacesOnAddDeletions(str string) string {

FILE: internal/tui/components/branchsidebar/branchsidebar.go
  type Model (line 16) | type Model struct
    method Update (line 28) | func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
    method View (line 37) | func (m Model) View() string {
    method SetRow (line 82) | func (m *Model) SetRow(b *branch.BranchData) tea.Cmd {
    method refreshBranchStatusCmd (line 87) | func (m *Model) refreshBranchStatusCmd() tea.Msg {
    method UpdateProgramContext (line 97) | func (m *Model) UpdateProgramContext(ctx *context.ProgramContext) {
  function NewModel (line 22) | func NewModel(ctx *context.ProgramContext) Model {
  type updateBranchStatusMsg (line 78) | type updateBranchStatusMsg struct

FILE: internal/tui/components/branchsidebar/branchsidebar_test.go
  function testCtx (line 16) | func testCtx() *context.ProgramContext {
  function TestView_NoBranch (line 23) | func TestView_NoBranch(t *testing.T) {
  function TestView_StatusLoading (line 32) | func TestView_StatusLoading(t *testing.T) {
  function TestView_NoChanges (line 42) | func TestView_NoChanges(t *testing.T) {
  function TestView_WithFileChanges (line 53) | func TestView_WithFileChanges(t *testing.T) {
  function TestView_WithPR (line 70) | func TestView_WithPR(t *testing.T) {

FILE: internal/tui/components/carousel/carousel.go
  type Model (line 13) | type Model struct
    method SetStyles (line 74) | func (m *Model) SetStyles(s Styles) {
    method Update (line 172) | func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
    method Focused (line 191) | func (m Model) Focused() bool {
    method Focus (line 197) | func (m *Model) Focus() {
    method Blur (line 203) | func (m *Model) Blur() {
    method View (line 209) | func (m Model) View() string {
    method UpdateSize (line 217) | func (m *Model) UpdateSize() {
    method SelectedItem (line 287) | func (m Model) SelectedItem() string {
    method Items (line 292) | func (m Model) Items() []string {
    method SetItems (line 297) | func (m *Model) SetItems(items []string) {
    method SetWidth (line 305) | func (m *Model) SetWidth(w int) {
    method SetHeight (line 311) | func (m *Model) SetHeight(h int) {
    method Height (line 317) | func (m Model) Height() int {
    method Width (line 322) | func (m Model) Width() int {
    method Cursor (line 327) | func (m Model) Cursor() int {
    method HasRightItems (line 332) | func (m Model) HasRightItems() bool {
    method HasLeftItems (line 337) | func (m Model) HasLeftItems() bool {
    method SetCursor (line 342) | func (m *Model) SetCursor(n int) {
    method MoveLeft (line 349) | func (m *Model) MoveLeft() {
    method MoveRight (line 356) | func (m *Model) MoveRight() {
    method renderItem (line 361) | func (m *Model) renderItem(itemID int, maxWidth int) string {
  type KeyMap (line 35) | type KeyMap struct
  function DefaultKeyMap (line 41) | func DefaultKeyMap() KeyMap {
  type Styles (line 56) | type Styles struct
  function DefaultStyles (line 64) | func DefaultStyles() Styles {
  type Option (line 82) | type Option
  function New (line 85) | func New(opts ...Option) Model {
  function WithItems (line 106) | func WithItems(items []string) Option {
  function WithHeight (line 113) | func WithHeight(h int) Option {
  function WithWidth (line 120) | func WithWidth(w int) Option {
  function WithOverflowIndicators (line 128) | func WithOverflowIndicators(indicators ...string) Option {
  function WithSeparators (line 141) | func WithSeparators(sep ...string) Option {
  function WithFocused (line 151) | func WithFocused(f bool) Option {
  function WithStyles (line 158) | func WithStyles(s Styles) Option {
  function WithKeyMap (line 165) | func WithKeyMap(km KeyMap) Option {
  function max (line 389) | func max(a, b int) int {
  function min (line 397) | func min(a, b int) int {
  function clamp (line 405) | func clamp(v, low, high int) int {

FILE: internal/tui/components/common/interface.go
  type Model (line 6) | type Model interface

FILE: internal/tui/components/footer/footer.go
  constant viewSeparator (line 21) | viewSeparator = " │ "
  type Model (line 23) | type Model struct
    method View (line 46) | func (m Model) View() string {
    method SetShowConfirmQuit (line 102) | func (m *Model) SetShowConfirmQuit(val bool) {
    method SetWidth (line 106) | func (m *Model) SetWidth(width int) {
    method UpdateProgramContext (line 110) | func (m *Model) UpdateProgramContext(ctx *context.ProgramContext) {
    method renderViewButton (line 115) | func (m *Model) renderViewButton(view config.ViewType) string {
    method renderViewSwitcher (line 164) | func (m *Model) renderViewSwitcher(ctx *context.ProgramContext) string {
    method SetLeftSection (line 198) | func (m *Model) SetLeftSection(leftSection string) {
    method SetRightSection (line 202) | func (m *Model) SetRightSection(rightSection string) {
  function NewModel (line 32) | func NewModel(ctx *context.ProgramContext) Model {

FILE: internal/tui/components/inputbox/inputbox.go
  type Model (line 16) | type Model struct
    method SetAutocomplete (line 73) | func (m *Model) SetAutocomplete(ac *autocomplete.Model) {
    method Update (line 77) | func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
    method View (line 137) | func (m Model) View() string {
    method ViewWithAutocomplete (line 155) | func (m Model) ViewWithAutocomplete() string {
    method Value (line 179) | func (m *Model) Value() string {
    method SetValue (line 183) | func (m *Model) SetValue(s string) {
    method Blur (line 187) | func (m *Model) Blur() {
    method Focus (line 191) | func (m *Model) Focus() tea.Cmd {
    method SetWidth (line 195) | func (m *Model) SetWidth(width int) {
    method SetHeight (line 199) | func (m *Model) SetHeight(height int) {
    method SetPrompt (line 203) | func (m *Model) SetPrompt(prompt string) {
    method Reset (line 207) | func (m *Model) Reset() {
    method UpdateProgramContext (line 211) | func (m *Model) UpdateProgramContext(ctx *context.ProgramContext) {
    method GetCursorPosition (line 222) | func (m *Model) GetCursorPosition() int {
  function NewModel (line 43) | func NewModel(ctx *context.ProgramContext) Model {

FILE: internal/tui/components/issuerow/issuerow.go
  type Issue (line 16) | type Issue struct
    method ToTableRow (line 22) | func (issue *Issue) ToTableRow() table.Row {
    method getTextStyle (line 36) | func (issue *Issue) getTextStyle() lipgloss.Style {
    method renderUpdateAt (line 40) | func (issue *Issue) renderUpdateAt() string {
    method renderCreatedAt (line 53) | func (issue *Issue) renderCreatedAt() string {
    method renderRepoName (line 66) | func (issue *Issue) renderRepoName() string {
    method renderTitle (line 71) | func (issue *Issue) renderTitle() string {
    method renderOpenedBy (line 80) | func (issue *Issue) renderOpenedBy() string {
    method renderAssignees (line 84) | func (issue *Issue) renderAssignees() string {
    method renderStatus (line 92) | func (issue *Issue) renderStatus() string {
    method renderNumComments (line 100) | func (issue *Issue) renderNumComments() string {
    method renderNumReactions (line 104) | func (issue *Issue) renderNumReactions() string {

FILE: internal/tui/components/issuessection/issuessection.go
  constant SectionType (line 23) | SectionType = "issue"
  type Model (line 25) | type Model struct
    method Update (line 56) | func (m *Model) Update(msg tea.Msg) (section.Section, tea.Cmd) {
    method BuildRows (line 264) | func (m Model) BuildRows() []table.Row {
    method NumRows (line 278) | func (m *Model) NumRows() int {
    method GetCurrRow (line 282) | func (m *Model) GetCurrRow() data.RowData {
    method FetchNextPageSectionRows (line 291) | func (m *Model) FetchNextPageSectionRows() []tea.Cmd {
    method UpdateLastUpdated (line 353) | func (m *Model) UpdateLastUpdated(t time.Time) {
    method ResetRows (line 357) | func (m *Model) ResetRows() {
    method GetItemSingularForm (line 422) | func (m Model) GetItemSingularForm() string {
    method GetItemPluralForm (line 426) | func (m Model) GetItemPluralForm() string {
    method GetTotalCount (line 430) | func (m Model) GetTotalCount() int {
    method GetIsLoading (line 434) | func (m *Model) GetIsLoading() bool {
    method SetIsLoading (line 438) | func (m *Model) SetIsLoading(val bool) {
    method GetPagerContent (line 443) | func (m Model) GetPagerContent() string {
  function NewModel (line 30) | func NewModel(
  function GetSectionColumns (line 183) | func GetSectionColumns(
  function FetchAllSections (line 362) | func FetchAllSections(
  type SectionIssuesFetchedMsg (line 387) | type SectionIssuesFetchedMsg struct
  function addAssignees (line 394) | func addAssignees(assignees, addedAssignees []data.Assignee) []data.Assi...
  function removeAssignees (line 405) | func removeAssignees(
  function assigneesContains (line 418) | func assigneesContains(assignees []data.Assignee, assignee data.Assignee...

FILE: internal/tui/components/issueview/action.go
  type IssueActionType (line 4) | type IssueActionType
  constant IssueActionNone (line 7) | IssueActionNone IssueActionType = iota
  constant IssueActionLabel (line 8) | IssueActionLabel
  constant IssueActionAssign (line 9) | IssueActionAssign
  constant IssueActionUnassign (line 10) | IssueActionUnassign
  constant IssueActionComment (line 11) | IssueActionComment
  constant IssueActionClose (line 12) | IssueActionClose
  constant IssueActionReopen (line 13) | IssueActionReopen
  type IssueAction (line 17) | type IssueAction struct

FILE: internal/tui/components/issueview/action_test.go
  function newTestModelForAction (line 17) | func newTestModelForAction(t *testing.T) Model {
  function TestUpdateReturnsCorrectActions (line 42) | func TestUpdateReturnsCorrectActions(t *testing.T) {
  function TestUpdateReturnsNilActionForUnknownKeys (line 77) | func TestUpdateReturnsNilActionForUnknownKeys(t *testing.T) {
  function TestUpdateReturnsNilActionWhenCommenting (line 86) | func TestUpdateReturnsNilActionWhenCommenting(t *testing.T) {
  function TestUpdateReturnsNilActionWhenLabeling (line 96) | func TestUpdateReturnsNilActionWhenLabeling(t *testing.T) {
  function TestUpdateReturnsNilActionWhenAssigning (line 106) | func TestUpdateReturnsNilActionWhenAssigning(t *testing.T) {
  function TestUpdateReturnsNilActionWhenUnassigning (line 116) | func TestUpdateReturnsNilActionWhenUnassigning(t *testing.T) {
  function TestIssueActionTypes (line 126) | func TestIssueActionTypes(t *testing.T) {
  function TestUpdateWithReboundKeys (line 148) | func TestUpdateWithReboundKeys(t *testing.T) {
  function TestAutocompleteStateResetWhenSwitchingModes (line 171) | func TestAutocompleteStateResetWhenSwitchingModes(t *testing.T) {
  function TestAutocompleteResetOnAssignMode (line 203) | func TestAutocompleteResetOnAssignMode(t *testing.T) {
  function TestAutocompleteResetOnUnassignMode (line 220) | func TestAutocompleteResetOnUnassignMode(t *testing.T) {
  function TestInputBoxTextNotReplacedByStaleAutocomplete (line 239) | func TestInputBoxTextNotReplacedByStaleAutocomplete(t *testing.T) {

FILE: internal/tui/components/issueview/activity.go
  type RenderedActivity (line 15) | type RenderedActivity struct
  method renderActivity (line 20) | func (m *Model) renderActivity() string {
  method renderActivitiesTitle (line 55) | func (m Model) renderActivitiesTitle() string {
  function renderEmptyState (line 62) | func renderEmptyState() string {
  method renderComment (line 66) | func (m *Model) renderComment(

FILE: internal/tui/components/issueview/issueview.go
  type RepoLabelsFetchedMsg (line 34) | type RepoLabelsFetchedMsg struct
  type RepoLabelsFetchFailedMsg (line 38) | type RepoLabelsFetchFailedMsg struct
  type Model (line 42) | type Model struct
    method Update (line 85) | func (m Model) Update(msg tea.Msg) (Model, tea.Cmd, *IssueAction) {
    method View (line 277) | func (m Model) View() string {
    method renderFullNameAndNumber (line 309) | func (m *Model) renderFullNameAndNumber() string {
    method renderTitle (line 314) | func (m *Model) renderTitle() string {
    method renderStatusPill (line 318) | func (m *Model) renderStatusPill() string {
    method renderAuthor (line 336) | func (m *Model) renderAuthor() string {
    method renderBody (line 356) | func (m *Model) renderBody() string {
    method renderLabels (line 383) | func (m *Model) renderLabels() string {
    method getIndentedContentWidth (line 391) | func (m *Model) getIndentedContentWidth() int {
    method SetWidth (line 395) | func (m *Model) SetWidth(width int) {
    method SetSectionId (line 401) | func (m *Model) SetSectionId(id int) {
    method SetRow (line 405) | func (m *Model) SetRow(data *data.IssueData) {
    method IsTextInputBoxFocused (line 413) | func (m *Model) IsTextInputBoxFocused() bool {
    method GetIsCommenting (line 417) | func (m *Model) GetIsCommenting() bool {
    method shouldCancelComment (line 421) | func (m *Model) shouldCancelComment() bool {
    method SetIsCommenting (line 435) | func (m *Model) SetIsCommenting(isCommenting bool) tea.Cmd {
    method GetIsAssigning (line 453) | func (m *Model) GetIsAssigning() bool {
    method SetIsAssigning (line 457) | func (m *Model) SetIsAssigning(isAssigning bool) tea.Cmd {
    method SetIsLabeling (line 478) | func (m *Model) SetIsLabeling(isLabeling bool) tea.Cmd {
    method fetchLabels (line 521) | func (m *Model) fetchLabels() tea.Cmd {
    method userAssignedToIssue (line 536) | func (m *Model) userAssignedToIssue(login string) bool {
    method GetIsUnassigning (line 545) | func (m *Model) GetIsUnassigning() bool {
    method SetIsUnassigning (line 549) | func (m *Model) SetIsUnassigning(isUnassigning bool) tea.Cmd {
    method issueAssignees (line 568) | func (m *Model) issueAssignees() []string {
    method UpdateProgramContext (line 576) | func (m *Model) UpdateProgramContext(ctx *context.ProgramContext) {
  function NewModel (line 59) | func NewModel(ctx *context.ProgramContext) Model {

FILE: internal/tui/components/issueview/labels.go
  type LabelInfo (line 10) | type LabelInfo struct
  function extractLabelAtCursor (line 22) | func extractLabelAtCursor(input string, cursorPos int) LabelInfo {
  function labelAtCursor (line 78) | func labelAtCursor(cursorPos int, currentValue string) string {
  function allLabels (line 84) | func allLabels(value string) []string {
  function handleLabelSelection (line 104) | func handleLabelSelection(selected string, cursorPos int, currentValue s...

FILE: internal/tui/components/listviewport/listviewport.go
  type Model (line 14) | type Model struct
    method SetNumItems (line 57) | func (m *Model) SetNumItems(numItems int) {
    method SetTotalItems (line 62) | func (m *Model) SetTotalItems(total int) {
    method SetItemHeight (line 66) | func (m *Model) SetItemHeight(height int) {
    method SyncViewPort (line 70) | func (m *Model) SyncViewPort(content string) {
    method getNumPrsPerPage (line 74) | func (m *Model) getNumPrsPerPage() int {
    method ResetCurrItem (line 81) | func (m *Model) ResetCurrItem() {
    method GetCurrItem (line 86) | func (m *Model) GetCurrItem() int {
    method NextItem (line 90) | func (m *Model) NextItem() int {
    method PrevItem (line 104) | func (m *Model) PrevItem() int {
    method FirstItem (line 116) | func (m *Model) FirstItem() int {
    method LastItem (line 122) | func (m *Model) LastItem() int {
    method SetDimensions (line 128) | func (m *Model) SetDimensions(dimensions constants.Dimensions) {
    method View (line 133) | func (m *Model) View() string {
    method UpdateProgramContext (line 143) | func (m *Model) UpdateProgramContext(ctx *context.ProgramContext) {
  function NewModel (line 28) | func NewModel(

FILE: internal/tui/components/notificationrow/data.go
  constant StateOpen (line 14) | StateOpen   = "OPEN"
  constant StateClosed (line 15) | StateClosed = "CLOSED"
  constant StateMerged (line 16) | StateMerged = "MERGED"
  type Data (line 19) | type Data struct
    method GetTitle (line 29) | func (d Data) GetTitle() string {
    method GetRepoNameWithOwner (line 39) | func (d Data) GetRepoNameWithOwner() string {
    method GetNumber (line 43) | func (d Data) GetNumber() int {
    method GetUrl (line 54) | func (d Data) GetUrl() string {
    method GetUpdatedAt (line 93) | func (d Data) GetUpdatedAt() time.Time {
    method GetCreatedAt (line 97) | func (d Data) GetCreatedAt() time.Time {
    method GetId (line 101) | func (d Data) GetId() string {
    method GetSubjectType (line 105) | func (d Data) GetSubjectType() string {
    method GetReason (line 109) | func (d Data) GetReason() string {
    method IsUnread (line 113) | func (d Data) IsUnread() bool {
    method GetLatestCommentUrl (line 117) | func (d Data) GetLatestCommentUrl() string {
  function repoBaseUrl (line 86) | func repoBaseUrl(repo data.NotificationRepository) string {
  function extractNumberFromUrl (line 122) | func extractNumberFromUrl(apiUrl string) string {
  function GenerateActivityDescription (line 135) | func GenerateActivityDescription(reason, subjectType, actor string) stri...

FILE: internal/tui/components/notificationrow/data_test.go
  function TestExtractNumberFromUrl (line 9) | func TestExtractNumberFromUrl(t *testing.T) {
  function TestGetNumber (line 67) | func TestGetNumber(t *testing.T) {
  function TestGetUrl (line 157) | func TestGetUrl(t *testing.T) {
  function TestIsUnread (line 434) | func TestIsUnread(t *testing.T) {
  function TestGetReason (line 470) | func TestGetReason(t *testing.T) {
  function TestGetLatestCommentUrl (line 533) | func TestGetLatestCommentUrl(t *testing.T) {
  function TestGetTitle (line 573) | func TestGetTitle(t *testing.T) {
  function TestGetRepoNameWithOwner (line 646) | func TestGetRepoNameWithOwner(t *testing.T) {
  function TestGetSubjectType (line 686) | func TestGetSubjectType(t *testing.T) {
  function TestGetId (line 737) | func TestGetId(t *testing.T) {
  function TestGenerateActivityDescription (line 773) | func TestGenerateActivityDescription(t *testing.T) {

FILE: internal/tui/components/notificationrow/notificationrow.go
  type Notification (line 18) | type Notification struct
    method ToTableRow (line 23) | func (n *Notification) ToTableRow() table.Row {
    method getTextStyle (line 32) | func (n *Notification) getTextStyle() lipgloss.Style {
    method getReadAwareStyle (line 38) | func (n *Notification) getReadAwareStyle() lipgloss.Style {
    method renderType (line 42) | func (n *Notification) renderType() string {
    method renderTitleBlock (line 139) | func (n *Notification) renderTitleBlock() string {
    method getReasonDescription (line 192) | func (n *Notification) getReasonDescription() string {
    method renderActivity (line 226) | func (n *Notification) renderActivity() string {
    method renderUpdatedAt (line 242) | func (n *Notification) renderUpdatedAt() string {

FILE: internal/tui/components/notificationrow/notificationrow_test.go
  function TestGetReasonDescription (line 10) | func TestGetReasonDescription(t *testing.T) {
  function TestParseCheckSuiteStatus (line 126) | func TestParseCheckSuiteStatus(t *testing.T) {
  function TestRenderActivityOutput (line 206) | func TestRenderActivityOutput(t *testing.T) {
  function TestDataState (line 261) | func TestDataState(t *testing.T) {
  function TestActivityDescriptionFallback (line 333) | func TestActivityDescriptionFallback(t *testing.T) {

FILE: internal/tui/components/notificationssection/commands.go
  method markAsDone (line 24) | func (m *Model) markAsDone() tea.Cmd {
  method markAllAsDone (line 63) | func (m *Model) markAllAsDone() tea.Cmd {
  method markAllAsRead (line 121) | func (m *Model) markAllAsRead() tea.Cmd {
  type RefetchNotificationsMsg (line 155) | type RefetchNotificationsMsg struct
  type ClearAllNotificationsMsg (line 158) | type ClearAllNotificationsMsg struct
  type MarkAllAsReadMsg (line 161) | type MarkAllAsReadMsg struct
  method markAsRead (line 164) | func (m *Model) markAsRead() tea.Cmd {
  method unsubscribe (line 195) | func (m *Model) unsubscribe() tea.Cmd {
  type UnsubscribedMsg (line 226) | type UnsubscribedMsg struct
  type UpdateNotificationReadStateMsg (line 231) | type UpdateNotificationReadStateMsg struct
  method openInBrowser (line 237) | func (m *Model) openInBrowser() tea.Cmd {
  function CheckoutPR (line 267) | func CheckoutPR(ctx *context.ProgramContext, prNumber int, repoName stri...

FILE: internal/tui/components/notificationssection/commands_test.go
  function noopStartTask (line 18) | func noopStartTask(task context.Task) tea.Cmd {
  function TestCheckoutPR (line 22) | func TestCheckoutPR(t *testing.T) {
  function TestCheckoutPRErrorMessage (line 96) | func TestCheckoutPRErrorMessage(t *testing.T) {
  function TestMarkAsDoneStoresCorrectTimestamp (line 127) | func TestMarkAsDoneStoresCorrectTimestamp(t *testing.T) {

FILE: internal/tui/components/notificationssection/filters_test.go
  function TestParseNotificationFilters (line 9) | func TestParseNotificationFilters(t *testing.T) {
  function TestParseReasonFilters (line 146) | func TestParseReasonFilters(t *testing.T) {
  function TestParseNotificationFiltersWithReasons (line 247) | func TestParseNotificationFiltersWithReasons(t *testing.T) {
  function TestParseRepoFilters (line 289) | func TestParseRepoFilters(t *testing.T) {
  function TestParseNotificationFiltersEdgeCases (line 361) | func TestParseNotificationFiltersEdgeCases(t *testing.T) {
  function TestParseReasonFiltersEdgeCases (line 472) | func TestParseReasonFiltersEdgeCases(t *testing.T) {
  function TestParseNotificationFiltersIncludeRead (line 538) | func TestParseNotificationFiltersIncludeRead(t *testing.T) {

FILE: internal/tui/components/notificationssection/notificationssection.go
  constant SectionType (line 26) | SectionType = "notification"
  function parseRepoFilters (line 38) | func parseRepoFilters(search string) []string {
  type NotificationFilters (line 50) | type NotificationFilters struct
  function parseReasonFilters (line 61) | func parseReasonFilters(search string) []string {
  function parseNotificationFilters (line 102) | func parseNotificationFilters(search string, includeRead bool) Notificat...
  type SortOrder (line 158) | type SortOrder
  constant SortByUpdated (line 161) | SortByUpdated SortOrder = iota
  constant SortByRepo (line 162) | SortByRepo
  type Model (line 165) | type Model struct
    method Update (line 209) | func (m *Model) Update(msg tea.Msg) (section.Section, tea.Cmd) {
    method toggleSortOrder (line 461) | func (m *Model) toggleSortOrder() {
    method sortNotifications (line 470) | func (m *Model) sortNotifications() {
    method BuildRows (line 504) | func (m Model) BuildRows() []table.Row {
    method NumRows (line 519) | func (m *Model) NumRows() int {
    method GetCurrRow (line 523) | func (m *Model) GetCurrRow() data.RowData {
    method GetCurrNotification (line 531) | func (m *Model) GetCurrNotification() *notificationrow.Data {
    method FetchNextPageSectionRows (line 539) | func (m *Model) FetchNextPageSectionRows() []tea.Cmd {
    method UpdateLastUpdated (line 799) | func (m *Model) UpdateLastUpdated(t time.Time) {
    method ResetRows (line 803) | func (m *Model) ResetRows() {
    method GetItemSingularForm (line 883) | func (m Model) GetItemSingularForm() string {
    method GetItemPluralForm (line 887) | func (m Model) GetItemPluralForm() string {
    method GetTotalCount (line 891) | func (m Model) GetTotalCount() int {
    method GetIsLoading (line 895) | func (m *Model) GetIsLoading() bool {
    method SetIsLoading (line 899) | func (m *Model) SetIsLoading(val bool) {
    method GetPagerContent (line 904) | func (m Model) GetPagerContent() string {
    method UpdateProgramContext (line 920) | func (m *Model) UpdateProgramContext(ctx *context.ProgramContext) {
    method fetchCommentCountsForNotifications (line 935) | func (m *Model) fetchCommentCountsForNotifications(notifications []not...
  function NewModel (line 174) | func NewModel(
  function GetSectionColumns (line 437) | func GetSectionColumns(ctx *context.ProgramContext) []table.Column {
  function FetchAllSections (line 813) | func FetchAllSections(
  type SectionNotificationsFetchedMsg (line 852) | type SectionNotificationsFetchedMsg struct
  type UpdateNotificationMsg (line 861) | type UpdateNotificationMsg struct
  type UpdateNotificationCommentsMsg (line 868) | type UpdateNotificationCommentsMsg struct
  type UpdateNotificationUrlMsg (line 878) | type UpdateNotificationUrlMsg struct
  function countNewPRComments (line 1064) | func countNewPRComments(pr data.EnrichedPullRequestData, lastReadAt *tim...
  function countNewIssueComments (line 1092) | func countNewIssueComments(issue data.IssueData, lastReadAt *time.Time) ...

FILE: internal/tui/components/notificationview/notificationview.go
  type Model (line 17) | type Model struct
    method SetRow (line 37) | func (m *Model) SetRow(row *notificationrow.Data) {
    method SetWidth (line 41) | func (m *Model) SetWidth(width int) {
    method ResetSubject (line 45) | func (m *Model) ResetSubject() {
    method SetSubjectPR (line 51) | func (m *Model) SetSubjectPR(pr *prrow.Data, notificationId string) {
    method SetSubjectIssue (line 57) | func (m *Model) SetSubjectIssue(issue *data.IssueData, notificationId ...
    method GetSubjectPR (line 63) | func (m *Model) GetSubjectPR() *prrow.Data {
    method GetSubjectIssue (line 67) | func (m *Model) GetSubjectIssue() *data.IssueData {
    method GetSubjectId (line 71) | func (m *Model) GetSubjectId() string {
    method ClearSubject (line 75) | func (m *Model) ClearSubject() {
    method UpdateProgramContext (line 81) | func (m *Model) UpdateProgramContext(ctx *context.ProgramContext) {
    method SetPendingPRAction (line 88) | func (m *Model) SetPendingPRAction(action string) string {
    method SetPendingIssueAction (line 111) | func (m *Model) SetPendingIssueAction(action string) string {
    method HasPendingAction (line 125) | func (m *Model) HasPendingAction() bool {
    method GetPendingAction (line 130) | func (m *Model) GetPendingAction() string {
    method ClearPendingAction (line 135) | func (m *Model) ClearPendingAction() {
    method Update (line 141) | func (m Model) Update(msg tea.Msg) (Model, string) {
    method View (line 160) | func (m Model) View() string {
  function NewModel (line 31) | func NewModel(ctx *context.ProgramContext) Model {
  function getTypeIcon (line 286) | func getTypeIcon(subjectType string) string {
  function formatReason (line 305) | func formatReason(reason string) string {

FILE: internal/tui/components/notificationview/notificationview_test.go
  function TestSetPendingPRAction (line 14) | func TestSetPendingPRAction(t *testing.T) {
  function TestSetPendingPRAction_NilSubject (line 82) | func TestSetPendingPRAction_NilSubject(t *testing.T) {
  function TestSetPendingIssueAction (line 92) | func TestSetPendingIssueAction(t *testing.T) {
  function TestSetPendingIssueAction_NilSubject (line 130) | func TestSetPendingIssueAction_NilSubject(t *testing.T) {
  function TestClearPendingAction (line 140) | func TestClearPendingAction(t *testing.T) {
  function TestHasPendingAction (line 155) | func TestHasPendingAction(t *testing.T) {
  function TestUpdate_NoPendingAction (line 174) | func TestUpdate_NoPendingAction(t *testing.T) {
  function TestUpdate_ConfirmWithLowercaseY (line 185) | func TestUpdate_ConfirmWithLowercaseY(t *testing.T) {
  function TestUpdate_ConfirmWithUppercaseY (line 199) | func TestUpdate_ConfirmWithUppercaseY(t *testing.T) {
  function TestUpdate_ConfirmWithEnter (line 213) | func TestUpdate_ConfirmWithEnter(t *testing.T) {
  function TestUpdate_CancelWithN (line 225) | func TestUpdate_CancelWithN(t *testing.T) {
  function TestUpdate_CancelWithEscape (line 239) | func TestUpdate_CancelWithEscape(t *testing.T) {
  function TestUpdate_CancelWithRandomKey (line 253) | func TestUpdate_CancelWithRandomKey(t *testing.T) {
  function TestUpdate_ConfirmReturnsAction (line 268) | func TestUpdate_ConfirmReturnsAction(t *testing.T) {
  function TestUpdate_NonKeyMsg (line 283) | func TestUpdate_NonKeyMsg(t *testing.T) {
  function TestUpdate_AllPRActions (line 303) | func TestUpdate_AllPRActions(t *testing.T) {
  function TestUpdate_AllIssueActions (line 324) | func TestUpdate_AllIssueActions(t *testing.T) {
  function TestUpdate_ReturnsActionOnConfirm (line 343) | func TestUpdate_ReturnsActionOnConfirm(t *testing.T) {

FILE: internal/tui/components/prompt/prompt.go
  type Model (line 9) | type Model struct
    method Update (line 26) | func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
    method View (line 32) | func (m Model) View() string {
    method Init (line 36) | func (m Model) Init() tea.Cmd {
    method Blur (line 40) | func (m *Model) Blur() {
    method Focus (line 44) | func (m *Model) Focus() tea.Cmd {
    method SetValue (line 48) | func (m *Model) SetValue(value string) {
    method Value (line 52) | func (m *Model) Value() string {
    method SetPrompt (line 56) | func (m *Model) SetPrompt(prompt string) {
    method Reset (line 60) | func (m *Model) Reset() {
    method UpdateProgramContext (line 64) | func (m *Model) UpdateProgramContext(ctx *context.ProgramContext) {
  function NewModel (line 14) | func NewModel(ctx *context.ProgramContext) Model {

FILE: internal/tui/components/prrow/data.go
  type Data (line 9) | type Data struct
    method GetTitle (line 15) | func (data Data) GetTitle() string {
    method GetRepoNameWithOwner (line 19) | func (data Data) GetRepoNameWithOwner() string {
    method GetNumber (line 23) | func (data Data) GetNumber() int {
    method GetUrl (line 27) | func (data Data) GetUrl() string {
    method GetUpdatedAt (line 31) | func (data Data) GetUpdatedAt() time.Time {
    method GetCreatedAt (line 35) | func (data Data) GetCreatedAt() time.Time {

FILE: internal/tui/components/prrow/prrow.go
  type PullRequest (line 19) | type PullRequest struct
    method getTextStyle (line 27) | func (pr *PullRequest) getTextStyle() lipgloss.Style {
    method renderNumComments (line 31) | func (pr *PullRequest) renderNumComments() string {
    method renderReviewStatus (line 44) | func (pr *PullRequest) renderReviewStatus() string {
    method renderState (line 70) | func (pr *PullRequest) renderState() string {
    method GetStatusChecksRollup (line 99) | func (pr *PullRequest) GetStatusChecksRollup() checks.CommitState {
    method renderCiStatus (line 111) | func (pr *PullRequest) renderCiStatus() string {
    method RenderLines (line 134) | func (pr *PullRequest) RenderLines(isSelected bool) string {
    method renderTitle (line 178) | func (pr *PullRequest) renderTitle() string {
    method renderExtendedTitle (line 187) | func (pr *PullRequest) renderExtendedTitle(isSelected bool) string {
    method renderAuthor (line 223) | func (pr *PullRequest) renderAuthor() string {
    method renderAssignees (line 227) | func (pr *PullRequest) renderAssignees() string {
    method renderRepoName (line 238) | func (pr *PullRequest) renderRepoName() string {
    method renderUpdateAt (line 248) | func (pr *PullRequest) renderUpdateAt() string {
    method renderCreatedAt (line 270) | func (pr *PullRequest) renderCreatedAt() string {
    method renderBaseName (line 292) | func (pr *PullRequest) renderBaseName() string {
    method RenderState (line 299) | func (pr *PullRequest) RenderState() string {
    method RenderMergeStateStatus (line 319) | func (pr *PullRequest) RenderMergeStateStatus() string {
    method ToTableRow (line 332) | func (pr *PullRequest) ToTableRow(isSelected bool) table.Row {
  function keepSameSpacesOnAddDeletions (line 167) | func keepSameSpacesOnAddDeletions(str string) string {

FILE: internal/tui/components/prrow/prrow_test.go
  function TestGetStatusChecksRollup (line 12) | func TestGetStatusChecksRollup(t *testing.T) {

FILE: internal/tui/components/prssection/checkout.go
  method checkout (line 17) | func (m *Model) checkout() (tea.Cmd, error) {

FILE: internal/tui/components/prssection/diff.go
  method diff (line 9) | func (m Model) diff() tea.Cmd {

FILE: internal/tui/components/prssection/prssection.go
  constant SectionType (line 24) | SectionType = "pr"
  type Model (line 26) | type Model struct
    method Update (line 57) | func (m *Model) Update(msg tea.Msg) (section.Section, tea.Cmd) {
    method EnrichPR (line 225) | func (m *Model) EnrichPR(data data.EnrichedPullRequestData) {
    method BuildRows (line 392) | func (m Model) BuildRows() []table.Row {
    method NumRows (line 414) | func (m *Model) NumRows() int {
    method GetCurrRow (line 425) | func (m *Model) GetCurrRow() data.RowData {
    method FetchNextPageSectionRows (line 434) | func (m *Model) FetchNextPageSectionRows() []tea.Cmd {
    method ResetRows (line 508) | func (m *Model) ResetRows() {
    method GetItemSingularForm (line 571) | func (m Model) GetItemSingularForm() string {
    method GetItemPluralForm (line 575) | func (m Model) GetItemPluralForm() string {
    method GetTotalCount (line 579) | func (m Model) GetTotalCount() int {
    method SetIsLoading (line 583) | func (m *Model) SetIsLoading(val bool) {
    method GetPagerContent (line 588) | func (m Model) GetPagerContent() string {
  function NewModel (line 31) | func NewModel(
  function GetSectionColumns (line 236) | func GetSectionColumns(
  type SectionPullRequestsFetchedMsg (line 418) | type SectionPullRequestsFetchedMsg struct
  function FetchAllSections (line 513) | func FetchAllSections(
  function addAssignees (line 543) | func addAssignees(assignees, addedAssignees []data.Assignee) []data.Assi...
  function removeAssignees (line 554) | func removeAssignees(
  function assigneesContains (line 567) | func assigneesContains(assignees []data.Assignee, assignee data.Assignee...

FILE: internal/tui/components/prssection/prssection_test.go
  function newTestModel (line 18) | func newTestModel(action string) Model {
  function TestConfirmation_AcceptWithEmptyInput (line 39) | func TestConfirmation_AcceptWithEmptyInput(t *testing.T) {
  function TestConfirmation_AcceptWithLowercaseY (line 52) | func TestConfirmation_AcceptWithLowercaseY(t *testing.T) {
  function TestConfirmation_AcceptWithUppercaseY (line 62) | func TestConfirmation_AcceptWithUppercaseY(t *testing.T) {
  function TestConfirmation_RejectWithN (line 72) | func TestConfirmation_RejectWithN(t *testing.T) {
  function TestConfirmation_CancelWithEsc (line 86) | func TestConfirmation_CancelWithEsc(t *testing.T) {
  function TestConfirmation_CancelWithCtrlC (line 97) | func TestConfirmation_CancelWithCtrlC(t *testing.T) {
  function TestConfirmation_AllActions (line 108) | func TestConfirmation_AllActions(t *testing.T) {

FILE: internal/tui/components/prssection/watchChecks.go
  method watchChecks (line 18) | func (m *Model) watchChecks() tea.Cmd {

FILE: internal/tui/components/prview/action.go
  type PRActionType (line 11) | type PRActionType
  constant PRActionNone (line 14) | PRActionNone PRActionType = iota
  constant PRActionApprove (line 15) | PRActionApprove
  constant PRActionAssign (line 16) | PRActionAssign
  constant PRActionUnassign (line 17) | PRActionUnassign
  constant PRActionComment (line 18) | PRActionComment
  constant PRActionDiff (line 19) | PRActionDiff
  constant PRActionCheckout (line 20) | PRActionCheckout
  constant PRActionClose (line 21) | PRActionClose
  constant PRActionReady (line 22) | PRActionReady
  constant PRActionReopen (line 23) | PRActionReopen
  constant PRActionMerge (line 24) | PRActionMerge
  constant PRActionUpdate (line 25) | PRActionUpdate
  constant PRActionSummaryViewMore (line 26) | PRActionSummaryViewMore
  constant PRActionApproveWorkflows (line 27) | PRActionApproveWorkflows
  type PRAction (line 31) | type PRAction struct
  function MsgToAction (line 36) | func MsgToAction(msg tea.Msg) *PRAction {

FILE: internal/tui/components/prview/action_test.go
  function newTestModelForAction (line 17) | func newTestModelForAction(t *testing.T) Model {
  function TestMsgToActionReturnsCorrectActions (line 45) | func TestMsgToActionReturnsCorrectActions(t *testing.T) {
  function TestMsgToActionReturnsNilForUnknownKeys (line 87) | func TestMsgToActionReturnsNilForUnknownKeys(t *testing.T) {
  function TestIsTextInputBoxFocusedWhenCommenting (line 95) | func TestIsTextInputBoxFocusedWhenCommenting(t *testing.T) {
  function TestIsTextInputBoxFocusedWhenApproving (line 106) | func TestIsTextInputBoxFocusedWhenApproving(t *testing.T) {
  function TestIsTextInputBoxFocusedWhenAssigning (line 117) | func TestIsTextInputBoxFocusedWhenAssigning(t *testing.T) {
  function TestIsTextInputBoxFocusedWhenUnassigning (line 128) | func TestIsTextInputBoxFocusedWhenUnassigning(t *testing.T) {
  function TestUpdateHandlesSidebarTabNavigation (line 139) | func TestUpdateHandlesSidebarTabNavigation(t *testing.T) {
  function TestPRActionTypes (line 165) | func TestPRActionTypes(t *testing.T) {
  function TestMsgToActionWithReboundKeys (line 194) | func TestMsgToActionWithReboundKeys(t *testing.T) {

FILE: internal/tui/components/prview/activity.go
  type RenderedActivity (line 17) | type RenderedActivity struct
  method renderActivity (line 22) | func (m *Model) renderActivity() string {
  function renderEmptyState (line 99) | func renderEmptyState() string {
  type comment (line 103) | type comment struct
  method renderComment (line 111) | func (m *Model) renderComment(
  method renderReview (line 153) | func (m *Model) renderReview(
  method renderReviewHeader (line 166) | func (m *Model) renderReviewHeader(review data.Review) string {
  method renderReviewDecision (line 177) | func (m *Model) renderReviewDecision(decision string) string {

FILE: internal/tui/components/prview/checks.go
  type checkSectionStatus (line 14) | type checkSectionStatus
  constant statusSuccess (line 17) | statusSuccess checkSectionStatus = iota
  constant statusFailure (line 18) | statusFailure
  constant statusWaiting (line 19) | statusWaiting
  constant statusNonRequested (line 20) | statusNonRequested
  method renderChecksOverview (line 23) | func (m *Model) renderChecksOverview() string {
  method viewChecksStatus (line 63) | func (m *Model) viewChecksStatus() (string, checkSectionStatus) {
  method viewMergeStatus (line 130) | func (m *Model) viewMergeStatus() (string, checkSectionStatus) {
  method viewMergedStatus (line 163) | func (m *Model) viewMergedStatus() string {
  method viewClosedStatus (line 177) | func (m *Model) viewClosedStatus() string {
  method viewReviewStatus (line 191) | func (m *Model) viewReviewStatus() (string, checkSectionStatus) {
  method viewCheckCategory (line 257) | func (m *Model) viewCheckCategory(icon, title, subtitle string, isLast b...
  method viewChecksBar (line 283) | func (m *Model) viewChecksBar() string {
  function renderCheckRunName (line 341) | func renderCheckRunName(checkRun data.CheckRun) string {
  type CheckCategory (line 364) | type CheckCategory
  constant CheckWaiting (line 367) | CheckWaiting CheckCategory = iota
  constant CheckFailure (line 368) | CheckFailure
  constant CheckSuccess (line 369) | CheckSuccess
  method renderCheckRunConclusion (line 372) | func (m *Model) renderCheckRunConclusion(checkRun data.CheckRun) (CheckC...
  method renderStatusContextConclusion (line 384) | func (m *Model) renderStatusContextConclusion(
  function renderStatusContextName (line 399) | func renderStatusContextName(statusContext data.StatusContext) string {
  method renderChecks (line 416) | func (sidebar *Model) renderChecks() string {
  type checksStats (line 575) | type checksStats struct
  method getStatusCheckRollupStats (line 584) | func (m *Model) getStatusCheckRollupStats(rollup data.StatusCheckRollupS...
  method getChecksStats (line 608) | func (m *Model) getChecksStats() checksStats {
  method numRequestedReviewOwners (line 651) | func (m *Model) numRequestedReviewOwners() int {

FILE: internal/tui/components/prview/checks_test.go
  type checksTestOptions (line 19) | type checksTestOptions struct
  function newTestModelForChecks (line 26) | func newTestModelForChecks(t *testing.T, opts checksTestOptions) Model {
  function makeCheckRun (line 160) | func makeCheckRun(name string, status string, conclusion checks.CheckRun...
  function makeCheckSuite (line 168) | func makeCheckSuite(workflowName string, status string, conclusion strin...
  function TestRenderChecks_AwaitingApproval (line 186) | func TestRenderChecks_AwaitingApproval(t *testing.T) {
  function TestRenderChecks_PendingCheckSuites (line 222) | func TestRenderChecks_PendingCheckSuites(t *testing.T) {
  function TestRenderChecks_RequiredButNotReported (line 255) | func TestRenderChecks_RequiredButNotReported(t *testing.T) {
  function TestRenderChecks_MixedStates (line 301) | func TestRenderChecks_MixedStates(t *testing.T) {
  function TestRenderChecks_NoChecks (line 358) | func TestRenderChecks_NoChecks(t *testing.T) {
  function TestRenderChecks_FailedChecks (line 377) | func TestRenderChecks_FailedChecks(t *testing.T) {
  function TestRenderChecks_InProgressChecks (line 409) | func TestRenderChecks_InProgressChecks(t *testing.T) {
  function TestGetChecksStats_AwaitingApproval (line 437) | func TestGetChecksStats_AwaitingApproval(t *testing.T) {
  function TestGetChecksStats_PendingCheckSuites (line 459) | func TestGetChecksStats_PendingCheckSuites(t *testing.T) {
  function TestGetChecksStats_Mixed (line 480) | func TestGetChecksStats_Mixed(t *testing.T) {
  function TestViewChecksBar_NarrowWidth_NoPanic (line 512) | func TestViewChecksBar_NarrowWidth_NoPanic(t *testing.T) {

FILE: internal/tui/components/prview/commits.go
  method renderCommits (line 14) | func (m *Model) renderCommits() string {
  method commitStateSign (line 88) | func (m *Model) commitStateSign(state checks.CommitState) string {

FILE: internal/tui/components/prview/files.go
  method renderChangesOverview (line 12) | func (m *Model) renderChangesOverview() string {
  method renderChangedFiles (line 53) | func (m *Model) renderChangedFiles() string {
  method renderFile (line 62) | func (m *Model) renderFile(file data.ChangedFile) string {
  method renderChangeTypeIcon (line 92) | func (m *Model) renderChangeTypeIcon(changeType string) string {

FILE: internal/tui/components/prview/prview.go
  type Model (line 34) | type Model struct
    method Update (line 75) | func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
    method View (line 194) | func (m Model) View() string {
    method renderFullNameAndNumber (line 266) | func (m *Model) renderFullNameAndNumber() string {
    method renderTitle (line 278) | func (m *Model) renderTitle() string {
    method renderBranches (line 287) | func (m *Model) renderBranches() string {
    method renderStatusPill (line 297) | func (m *Model) renderStatusPill() string {
    method renderLabels (line 318) | func (m *Model) renderLabels() string {
    method renderRequestedReviewers (line 339) | func (m *Model) renderRequestedReviewers() string {
    method renderAuthor (line 506) | func (m *Model) renderAuthor() string {
    method renderSummary (line 526) | func (m *Model) renderSummary() string {
    method SetSectionId (line 583) | func (m *Model) SetSectionId(id int) {
    method SetRow (line 587) | func (m *Model) SetRow(d *prrow.Data) {
    method EnrichCurrRow (line 602) | func (m *Model) EnrichCurrRow() tea.Cmd {
    method SetWidth (line 618) | func (m *Model) SetWidth(width int) {
    method IsTextInputBoxFocused (line 624) | func (m *Model) IsTextInputBoxFocused() bool {
    method GetIsCommenting (line 628) | func (m *Model) GetIsCommenting() bool {
    method UpdateProgramContext (line 632) | func (m *Model) UpdateProgramContext(ctx *context.ProgramContext) {
    method shouldCancelComment (line 643) | func (m *Model) shouldCancelComment() bool {
    method SetIsCommenting (line 658) | func (m *Model) SetIsCommenting(isCommenting bool) tea.Cmd {
    method getIndentedContentWidth (line 675) | func (m *Model) getIndentedContentWidth() int {
    method GetIsApproving (line 679) | func (m *Model) GetIsApproving() bool {
    method SetIsApproving (line 683) | func (m *Model) SetIsApproving(isApproving bool) tea.Cmd {
    method GetIsAssigning (line 701) | func (m *Model) GetIsAssigning() bool {
    method SetIsAssigning (line 705) | func (m *Model) SetIsAssigning(isAssigning bool) tea.Cmd {
    method userAssignedToPr (line 725) | func (m *Model) userAssignedToPr(login string) bool {
    method GetIsUnassigning (line 734) | func (m *Model) GetIsUnassigning() bool {
    method SetIsUnassigning (line 738) | func (m *Model) SetIsUnassigning(isUnassigning bool) tea.Cmd {
    method prAssignees (line 756) | func (m *Model) prAssignees() []string {
    method GoToFirstTab (line 764) | func (m *Model) GoToFirstTab() {
    method GoToActivityTab (line 768) | func (m *Model) GoToActivityTab() {
    method SelectedTab (line 772) | func (m Model) SelectedTab() string {
    method SetSummaryViewMore (line 776) | func (m *Model) SetSummaryViewMore() {
    method SetSummaryViewLess (line 780) | func (m *Model) SetSummaryViewLess() {
    method SetEnrichedPR (line 784) | func (m *Model) SetEnrichedPR(data data.EnrichedPullRequestData) {
  function NewModel (line 53) | func NewModel(ctx *context.ProgramContext) Model {
  type reviewerItem (line 335) | type reviewerItem struct
  type EnrichedPrMsg (line 595) | type EnrichedPrMsg struct

FILE: internal/tui/components/prview/reviewers_test.go
  function newTestModel (line 18) | func newTestModel(t *testing.T, prData *data.PullRequestData) Model {
  function newTestModelWithWidth (line 22) | func newTestModelWithWidth(t *testing.T, prData *data.PullRequestData, w...
  function TestRenderRequestedReviewers (line 57) | func TestRenderRequestedReviewers(t *testing.T) {
  function TestRenderRequestedReviewersWrapping (line 284) | func TestRenderRequestedReviewersWrapping(t *testing.T) {
  function TestRenderRequestedReviewersLoading (line 329) | func TestRenderRequestedReviewersLoading(t *testing.T) {
  function TestRenderSuggestedReviewers (line 361) | func TestRenderSuggestedReviewers(t *testing.T) {

FILE: internal/tui/components/reposection/commands.go
  type UpdatePRMsg (line 19) | type UpdatePRMsg struct
  method fastForward (line 29) | func (m *Model) fastForward() (tea.Cmd, error) {
  type pushOptions (line 80) | type pushOptions struct
  method push (line 84) | func (m *Model) push(opts pushOptions) (tea.Cmd, error) {
  method checkout (line 142) | func (m *Model) checkout() (tea.Cmd, error) {
  type repoMsg (line 174) | type repoMsg struct
  method readRepoCmd (line 179) | func (m *Model) readRepoCmd() []tea.Cmd {
  method fetchRepoCmd (line 209) | func (m *Model) fetchRepoCmd() []tea.Cmd {
  method fetchPRsCmd (line 239) | func (m *Model) fetchPRsCmd() tea.Cmd {
  method fetchPRCmd (line 281) | func (m *Model) fetchPRCmd(branch string) []tea.Cmd {
  type RefreshBranchesMsg (line 328) | type RefreshBranchesMsg struct
  type RefreshPrsMsg (line 333) | type RefreshPrsMsg struct
  function nextID (line 344) | func nextID() int {
  method tickRefreshBranchesCmd (line 351) | func (m *Model) tickRefreshBranchesCmd() tea.Cmd {
  method tickFetchPrsCmd (line 360) | func (m *Model) tickFetchPrsCmd() tea.Cmd {
  method onRefreshBranchesMsg (line 369) | func (m *Model) onRefreshBranchesMsg() []tea.Cmd {
  method onRefreshPrsMsg (line 376) | func (m *Model) onRefreshPrsMsg() []tea.Cmd {
  method OpenGithub (line 383) | func (m *Model) OpenGithub() tea.Cmd {
  method deleteBranch (line 389) | func (m *Model) deleteBranch() tea.Cmd {
  method newBranch (line 421) | func (m *Model) newBranch(name string) tea.Cmd {

FILE: internal/tui/components/reposection/reposection.go
  constant SectionType (line 28) | SectionType = "repo"
  type Model (line 30) | type Model struct
    method Update (line 68) | func (m *Model) Update(msg tea.Msg) (section.Section, tea.Cmd) {
    method View (line 216) | func (m *Model) View() string {
    method updateBranchesWithPrs (line 364) | func (m *Model) updateBranchesWithPrs() {
    method BuildRows (line 391) | func (m Model) BuildRows() []table.Row {
    method getFilteredBranches (line 413) | func (m *Model) getFilteredBranches() []branch.Branch {
    method NumRows (line 433) | func (m *Model) NumRows() int {
    method getCurrBranch (line 444) | func (m *Model) getCurrBranch() *branch.Branch {
    method GetCurrRow (line 452) | func (m *Model) GetCurrRow() data.RowData {
    method FetchNextPageSectionRows (line 465) | func (m *Model) FetchNextPageSectionRows() []tea.Cmd {
    method GetDimensions (line 511) | func (m Model) GetDimensions() constants.Dimensions {
    method UpdateProgramContext (line 521) | func (m *Model) UpdateProgramContext(ctx *context.ProgramContext) {
    method ResetRows (line 534) | func (m *Model) ResetRows() {
    method GetItemSingularForm (line 538) | func (m *Model) GetItemSingularForm() string {
    method GetItemPluralForm (line 542) | func (m *Model) GetItemPluralForm() string {
    method GetTotalCount (line 546) | func (m *Model) GetTotalCount() int {
    method SetIsLoading (line 550) | func (m *Model) SetIsLoading(val bool) {
    method GetPagerContent (line 555) | func (m *Model) GetPagerContent() string {
  function NewModel (line 39) | func NewModel(
  function GetSectionColumns (line 236) | func GetSectionColumns(
  function findPRForRef (line 424) | func findPRForRef(prs []data.PullRequestData, branch string) *data.PullR...
  type SectionPullRequestsFetchedMsg (line 437) | type SectionPullRequestsFetchedMsg struct
  function FetchAllBranches (line 480) | func FetchAllBranches(ctx *context.ProgramContext) (Model, tea.Cmd) {

FILE: internal/tui/components/search/search.go
  type Model (line 13) | type Model struct
    method Init (line 63) | func (m Model) Init() tea.Cmd {
    method Update (line 67) | func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
    method View (line 74) | func (m Model) View(ctx *context.ProgramContext) string {
    method Focus (line 81) | func (m *Model) Focus() tea.Cmd {
    method Blur (line 86) | func (m *Model) Blur() {
    method SetValue (line 91) | func (m *Model) SetValue(val string) {
    method UpdateProgramContext (line 95) | func (m *Model) UpdateProgramContext(ctx *context.ProgramContext) {
    method getInputWidth (line 104) | func (m *Model) getInputWidth(ctx *context.ProgramContext) int {
    method Value (line 115) | func (m Model) Value() string {
  type SearchOptions (line 19) | type SearchOptions struct
  function NewModel (line 25) | func NewModel(ctx *context.ProgramContext, opts SearchOptions) Model {

FILE: internal/tui/components/section/section.go
  type BaseModel (line 30) | type BaseModel struct
    method GetDimensions (line 199) | func (m *BaseModel) GetDimensions() constants.Dimensions {
    method GetConfig (line 209) | func (m *BaseModel) GetConfig() config.SectionConfig {
    method HasRepoNameInConfiguredFilter (line 213) | func (m *BaseModel) HasRepoNameInConfiguredFilter() bool {
    method HasCurrentRepoNameInConfiguredFilter (line 223) | func (m *BaseModel) HasCurrentRepoNameInConfiguredFilter() bool {
    method SyncSmartFilterWithSearchValue (line 238) | func (m *BaseModel) SyncSmartFilterWithSearchValue() {
    method GetSearchValue (line 242) | func (m *BaseModel) GetSearchValue() string {
    method enrichSearchWithTemplateVars (line 266) | func (m *BaseModel) enrichSearchWithTemplateVars() string {
    method UpdateProgramContext (line 292) | func (m *BaseModel) UpdateProgramContext(ctx *context.ProgramContext) {
    method GetId (line 314) | func (m *BaseModel) GetId() int {
    method GetType (line 318) | func (m *BaseModel) GetType() string {
    method CurrRow (line 322) | func (m *BaseModel) CurrRow() int {
    method NextRow (line 326) | func (m *BaseModel) NextRow() int {
    method PrevRow (line 330) | func (m *BaseModel) PrevRow() int {
    method FirstItem (line 334) | func (m *BaseModel) FirstItem() int {
    method LastItem (line 338) | func (m *BaseModel) LastItem() int {
    method IsSearchFocused (line 342) | func (m *BaseModel) IsSearchFocused() bool {
    method GetIsLoading (line 346) | func (m *BaseModel) GetIsLoading() bool {
    method SetIsSearching (line 350) | func (m *BaseModel) SetIsSearching(val bool) tea.Cmd {
    method ResetFilters (line 360) | func (m *BaseModel) ResetFilters() {
    method ResetPageInfo (line 364) | func (m *BaseModel) ResetPageInfo() {
    method IsPromptConfirmationFocused (line 368) | func (m *BaseModel) IsPromptConfirmationFocused() bool {
    method SetIsPromptConfirmationShown (line 372) | func (m *BaseModel) SetIsPromptConfirmationShown(val bool) tea.Cmd {
    method SetPromptConfirmationAction (line 383) | func (m *BaseModel) SetPromptConfirmationAction(action string) {
    method GetPromptConfirmationAction (line 387) | func (m *BaseModel) GetPromptConfirmationAction() string {
    method MakeSectionCmd (line 397) | func (m *BaseModel) MakeSectionCmd(cmd tea.Cmd) tea.Cmd {
    method GetFilters (line 412) | func (m *BaseModel) GetFilters() string {
    method GetMainContent (line 416) | func (m *BaseModel) GetMainContent() string {
    method View (line 437) | func (m *BaseModel) View() string {
    method ResetRows (line 448) | func (m *BaseModel) ResetRows() {
    method LastUpdated (line 454) | func (m *BaseModel) LastUpdated() time.Time {
    method CreatedAt (line 458) | func (m *BaseModel) CreatedAt() time.Time {
    method UpdateTotalItemsCount (line 462) | func (m *BaseModel) UpdateTotalItemsCount(count int) {
    method GetPromptConfirmation (line 466) | func (m *BaseModel) GetPromptConfirmation() string {
  type NewSectionOptions (line 55) | type NewSectionOptions struct
    method GetConfigFiltersWithCurrentRemoteAdded (line 67) | func (options NewSectionOptions) GetConfigFiltersWithCurrentRemoteAdded(
  function NewModel (line 86) | func NewModel(
  type Section (line 143) | type Section interface
  type Identifier (line 158) | type Identifier interface
  type Component (line 163) | type Component interface
  type Table (line 168) | type Table interface
  type Search (line 183) | type Search interface
  type PromptConfirmation (line 191) | type PromptConfirmation interface
  type SectionRowsFetchedMsg (line 305) | type SectionRowsFetchedMsg struct
    method GetSectionId (line 310) | func (msg SectionRowsFetchedMsg) GetSectionId() int {
  type SectionMsg (line 391) | type SectionMsg struct

FILE: internal/tui/components/section/section_test.go
  function currentRepoFilter (line 16) | func currentRepoFilter(t *testing.T) string {
  function TestHasRepoNameInConfiguredFilter (line 26) | func TestHasRepoNameInConfiguredFilter(t *testing.T) {
  function TestHasCurrentRepoNameInConfiguredFilter (line 69) | func TestHasCurrentRepoNameInConfiguredFilter(t *testing.T) {
  function TestSyncSmartFilterWithSearchValue (line 122) | func TestSyncSmartFilterWithSearchValue(t *testing.T) {
  function TestGetSearchValue (line 164) | func TestGetSearchValue(t *testing.T) {
  function TestGetSearchValue_SimilarRepoNameNotStripped (line 253) | func TestGetSearchValue_SimilarRepoNameNotStripped(t *testing.T) {
  function TestGetSearchValue_ManualRepoFilterRemoval (line 268) | func TestGetSearchValue_ManualRepoFilterRemoval(t *testing.T) {
  function TestGetConfigFiltersWithCurrentRemoteAdded (line 341) | func TestGetConfigFiltersWithCurrentRemoteAdded(t *testing.T) {
  function TestGetPromptConfirmation (line 407) | func TestGetPromptConfirmation(t *testing.T) {

FILE: internal/tui/components/sidebar/sidebar.go
  type Model (line 15) | type Model struct
    method Update (line 36) | func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
    method View (line 51) | func (m Model) View() string {
    method SetContent (line 76) | func (m *Model) SetContent(data string) {
    method GetSidebarContentWidth (line 81) | func (m *Model) GetSidebarContentWidth() int {
    method ScrollToTop (line 88) | func (m *Model) ScrollToTop() {
    method ScrollToBottom (line 92) | func (m *Model) ScrollToBottom() {
    method ScrollToPercent (line 96) | func (m *Model) ScrollToPercent(percent float64) {
    method UpdateProgramContext (line 102) | func (m *Model) UpdateProgramContext(ctx *context.ProgramContext) {
  function NewModel (line 23) | func NewModel() Model {

FILE: internal/tui/components/table/table.go
  type Model (line 19) | type Model struct
    method Update (line 88) | func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
    method StartLoadingSpinner (line 96) | func (m Model) StartLoadingSpinner() tea.Cmd {
    method View (line 100) | func (m Model) View() string {
    method SetIsLoading (line 107) | func (m *Model) SetIsLoading(isLoading bool) {
    method SetDimensions (line 111) | func (m *Model) SetDimensions(dimensions constants.Dimensions) {
    method ResetCurrItem (line 119) | func (m *Model) ResetCurrItem() {
    method GetCurrItem (line 123) | func (m *Model) GetCurrItem() int {
    method PrevItem (line 127) | func (m *Model) PrevItem() int {
    method NextItem (line 134) | func (m *Model) NextItem() int {
    method FirstItem (line 141) | func (m *Model) FirstItem() int {
    method LastItem (line 148) | func (m *Model) LastItem() int {
    method cacheColumnWidths (line 155) | func (m *Model) cacheColumnWidths() {
    method SyncViewPortContent (line 165) | func (m *Model) SyncViewPortContent() {
    method SetRows (line 178) | func (m *Model) SetRows(rows []Row) {
    method SetContentHeight (line 185) | func (m *Model) SetContentHeight(height int) {
    method OnLineDown (line 195) | func (m *Model) OnLineDown() {
    method OnLineUp (line 199) | func (m *Model) OnLineUp() {
    method getShownColumns (line 203) | func (m *Model) getShownColumns() []Column {
    method renderHeaderColumns (line 215) | func (m *Model) renderHeaderColumns() []string {
    method renderHeader (line 273) | func (m *Model) renderHeader() string {
    method renderBody (line 286) | func (m *Model) renderBody() string {
    method renderRow (line 308) | func (m *Model) renderRow(rowId int, headerColumns []string) string {
    method UpdateProgramContext (line 378) | func (m *Model) UpdateProgramContext(ctx *context.ProgramContext) {
    method LastUpdated (line 383) | func (m *Model) LastUpdated() time.Time {
    method CreatedAt (line 387) | func (m *Model) CreatedAt() time.Time {
    method UpdateLastUpdated (line 391) | func (m *Model) UpdateLastUpdated(t time.Time) {
    method UpdateTotalItemsCount (line 395) | func (m *Model) UpdateTotalItemsCount(count int) {
    method IsLoading (line 399) | func (m *Model) IsLoading() bool {
  type Column (line 32) | type Column struct
  type Row (line 41) | type Row
  function NewModel (line 43) | func NewModel(

FILE: internal/tui/components/tabs/tabs.go
  type SectionTab (line 19) | type SectionTab struct
  type Model (line 24) | type Model struct
    method Init (line 46) | func (m Model) Init() tea.Cmd {
    method Update (line 50) | func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
    method View (line 70) | func (m Model) View() string {
    method fetchHasNewVersion (line 86) | func (m *Model) fetchHasNewVersion() tea.Cmd {
    method CurrSectionId (line 96) | func (m *Model) CurrSectionId() int {
    method SetCurrSectionId (line 100) | func (m *Model) SetCurrSectionId(id int) {
    method UpdateProgramContext (line 104) | func (m *Model) UpdateProgramContext(ctx *context.ProgramContext) {
    method SetSections (line 116) | func (m *Model) SetSections(sections []section.Section) {
    method UpdateTabTitles (line 128) | func (m *Model) UpdateTabTitles() {
    method viewLogo (line 153) | func (m *Model) viewLogo() string {
    method SetAllLoading (line 177) | func (m *Model) SetAllLoading() []tea.Cmd {
  function NewModel (line 32) | func NewModel(ctx *context.ProgramContext) Model {
  type latestVersionMsg (line 81) | type latestVersionMsg struct

FILE: internal/tui/components/tabs/tabs_test.go
  type testModel (line 135) | type testModel struct
    method Init (line 164) | func (m testModel) Init() tea.Cmd {
    method Update (line 168) | func (m testModel) Update(msg tea.Msg) (testModel, tea.Cmd) {
    method View (line 221) | func (m testModel) View() string {
  type initMsg (line 159) | type initMsg struct
  type dataFetchedMsg (line 160) | type dataFetchedMsg struct
  type changeTabsMsg (line 161) | type changeTabsMsg struct

FILE: internal/tui/components/tabs/testdata/test_section.go
  type TestSection (line 13) | type TestSection struct
    method BuildRows (line 19) | func (t *TestSection) BuildRows() []table.Row {
    method CurrRow (line 24) | func (t *TestSection) CurrRow() int {
    method FetchNextPageSectionRows (line 29) | func (t *TestSection) FetchNextPageSectionRows() []tea.Cmd {
    method FirstItem (line 34) | func (t *TestSection) FirstItem() int {
    method GetConfig (line 39) | func (t *TestSection) GetConfig() config.SectionConfig {
    method GetCurrRow (line 44) | func (t *TestSection) GetCurrRow() data.RowData {
    method GetFilters (line 49) | func (t *TestSection) GetFilters() string {
    method GetId (line 54) | func (t *TestSection) GetId() int {
    method GetIsLoading (line 59) | func (t *TestSection) GetIsLoading() bool {
    method GetItemPluralForm (line 64) | func (t *TestSection) GetItemPluralForm() string {
    method GetItemSingularForm (line 69) | func (t *TestSection) GetItemSingularForm() string {
    method GetPagerContent (line 74) | func (t *TestSection) GetPagerContent() string {
    method GetPromptConfirmation (line 79) | func (t *TestSection) GetPromptConfirmation() string {
    method GetPromptConfirmationAction (line 84) | func (t *TestSection) GetPromptConfirmationAction() string {
    method GetTotalCount (line 89) | func (t *TestSection) GetTotalCount() int {
    method GetType (line 94) | func (t *TestSection) GetType() string {
    method IsPromptConfirmationFocused (line 99) | func (t *TestSection) IsPromptConfirmationFocused() bool {
    method IsSearchFocused (line 104) | func (t *TestSection) IsSearchFocused() bool {
    method LastItem (line 109) | func (t *TestSection) LastItem() int {
    method MakeSectionCmd (line 114) | func (t *TestSection) MakeSectionCmd(cmd tea.Cmd) tea.Cmd {
    method NextRow (line 119) | func (t *TestSection) NextRow() int {
    method NumRows (line 124) | func (t *TestSection) NumRows() int {
    method PrevRow (line 129) | func (t *TestSection) PrevRow() int {
    method ResetFilters (line 134) | func (t *TestSection) ResetFilters() {
    method ResetPageInfo (line 139) | func (t *TestSection) ResetPageInfo() {
    method ResetRows (line 144) | func (t *TestSection) ResetRows() {
    method SetIsLoading (line 149) | func (t *TestSection) SetIsLoading(val bool) {
    method SetIsPromptConfirmationShown (line 154) | func (t *TestSection) SetIsPromptConfirmationShown(val bool) tea.Cmd {
    method SetIsSearching (line 159) | func (t *TestSection) SetIsSearching(val bool) tea.Cmd {
    method SetPromptConfirmationAction (line 164) | func (t *TestSection) SetPromptConfirmationAction(action string) {
    method Update (line 169) | func (t *TestSection) Update(msg tea.Msg) (section.Section, tea.Cmd) {
    method UpdateProgramContext (line 174) | func (t *TestSection) UpdateProgramContext(ctx *context.ProgramContext) {
    method View (line 179) | func (t *TestSection) View() string {

FILE: internal/tui/components/tasks/issue.go
  type UpdateIssueMsg (line 15) | type UpdateIssueMsg struct
  function CloseIssue (line 24) | func CloseIssue(
  function ReopenIssue (line 51) | func ReopenIssue(
  function AssignIssue (line 78) | func AssignIssue(
  function UnassignIssue (line 117) | func UnassignIssue(
  function CommentOnIssue (line 156) | func CommentOnIssue(
  function LabelIssue (line 190) | func LabelIssue(

FILE: internal/tui/components/tasks/issue_test.go
  type mockIssue (line 17) | type mockIssue struct
    method GetNumber (line 25) | func (m mockIssue) GetNumber() int               { return m.number }
    method GetRepoNameWithOwner (line 26) | func (m mockIssue) GetRepoNameWithOwner() string { return m.repoName }
    method GetTitle (line 27) | func (m mockIssue) GetTitle() string             { return m.title }
    method GetUrl (line 28) | func (m mockIssue) GetUrl() string               { return m.url }
    method GetUpdatedAt (line 29) | func (m mockIssue) GetUpdatedAt() time.Time      { return m.updatedAt }
  function noopStartTask (line 32) | func noopStartTask(task context.Task) tea.Cmd {
  function TestUpdateIssueMsg_Fields (line 36) | func TestUpdateIssueMsg_Fields(t *testing.T) {
  function TestCloseIssue (line 76) | func TestCloseIssue(t *testing.T) {
  function TestCloseIssue_TaskConfiguration (line 117) | func TestCloseIssue_TaskConfiguration(t *testing.T) {
  function TestReopenIssue (line 141) | func TestReopenIssue(t *testing.T) {
  function TestReopenIssue_TaskConfiguration (line 182) | func TestReopenIssue_TaskConfiguration(t *testing.T) {
  function TestCloseIssue_SectionIdentifierPropagation (line 206) | func TestCloseIssue_SectionIdentifierPropagation(t *testing.T) {
  function TestReopenIssue_SectionIdentifierPropagation (line 239) | func TestReopenIssue_SectionIdentifierPropagation(t *testing.T) {
  function TestUpdateIssueMsg_ImplementsTeaMsg (line 272) | func TestUpdateIssueMsg_ImplementsTeaMsg(t *testing.T) {
  function TestCloseIssue_UsesCorrectIssueNumber (line 280) | func TestCloseIssue_UsesCorrectIssueNumber(t *testing.T) {
  function TestReopenIssue_UsesCorrectIssueNumber (line 303) | func TestReopenIssue_UsesCorrectIssueNumber(t *testing.T) {
  function TestCloseIssue_MsgCallbackReturnsCorrectUpdateIssueMsg (line 326) | func TestCloseIssue_MsgCallbackReturnsCorrectUpdateIssueMsg(t *testing.T) {
  function TestReopenIssue_MsgCallbackReturnsCorrectUpdateIssueMsg (line 359) | func TestReopenIssue_MsgCallbackReturnsCorrectUpdateIssueMsg(t *testing....
  function TestCloseIssue_CommandArgs (line 392) | func TestCloseIssue_CommandArgs(t *testing.T) {
  function TestReopenIssue_CommandArgs (line 434) | func TestReopenIssue_CommandArgs(t *testing.T) {
  function boolPtr (line 477) | func boolPtr(b bool) *bool {

FILE: internal/tui/components/tasks/pr.go
  type SectionIdentifier (line 18) | type SectionIdentifier struct
  type UpdatePRMsg (line 23) | type UpdatePRMsg struct
  type UpdateBranchMsg (line 33) | type UpdateBranchMsg struct
  function buildTaskId (line 39) | func buildTaskId(prefix string, prNumber int) string {
  type GitHubTask (line 43) | type GitHubTask struct
  function fireTask (line 52) | func fireTask(ctx *context.ProgramContext, task GitHubTask) tea.Cmd {
  function OpenBranchPR (line 77) | func OpenBranchPR(ctx *context.ProgramContext, section SectionIdentifier...
  function ReopenPR (line 97) | func ReopenPR(ctx *context.ProgramContext, section SectionIdentifier, pr...
  function ClosePR (line 120) | func ClosePR(ctx *context.ProgramContext, section SectionIdentifier, pr ...
  function PRReady (line 143) | func PRReady(ctx *context.ProgramContext, section SectionIdentifier, pr ...
  function MergePR (line 166) | func MergePR(ctx *context.ProgramContext, section SectionIdentifier, pr ...
  function CreatePR (line 203) | func CreatePR(
  function UpdatePR (line 242) | func UpdatePR(ctx *context.ProgramContext, section SectionIdentifier, pr...
  function AssignPR (line 265) | func AssignPR(
  function UnassignPR (line 304) | func UnassignPR(
  function CommentOnPR (line 343) | func CommentOnPR(
  function ApprovePR (line 377) | func ApprovePR(
  function ApproveWorkflows (line 409) | func ApproveWorkflows(

FILE: internal/tui/components/tasks/pr_test.go
  function TestApproveWorkflows_TaskConfiguration (line 13) | func TestApproveWorkflows_TaskConfiguration(t *testing.T) {
  function TestApproveWorkflows_ReturnsNonNilCommand (line 37) | func TestApproveWorkflows_ReturnsNonNilCommand(t *testing.T) {
  function TestApproveWorkflows_UsesCorrectPRNumber (line 78) | func TestApproveWorkflows_UsesCorrectPRNumber(t *testing.T) {
  function TestApproveWorkflows_SectionIdentifierPropagation (line 102) | func TestApproveWorkflows_SectionIdentifierPropagation(t *testing.T) {

FILE: internal/tui/components/utils.go
  function FormatNumber (line 14) | func FormatNumber(num int) string {
  function GetIssueTextStyle (line 26) | func GetIssueTextStyle(
  function RenderIssueTitle (line 32) | func RenderIssueTitle(

FILE: internal/tui/constants/constants.go
  type KeyMap (line 7) | type KeyMap struct
  type Dimensions (line 23) | type Dimensions struct
  constant Ellipsis (line 29) | Ellipsis = "…"
  constant ApprovedIcon (line 31) | ApprovedIcon         = "󰄬"
  constant ChangesRequestedIcon (line 32) | ChangesRequestedIcon = ""
  constant DotIcon (line 33) | DotIcon              = ""
  constant SmallDotIcon (line 34) | SmallDotIcon         = "⋅"
  constant HorizontalLineIcon (line 35) | HorizontalLineIcon   = "─"
  constant EmptyIcon (line 36) | EmptyIcon            = ""
  constant FailureIcon (line 37) | FailureIcon          = "󰅙"
  constant PersonIcon (line 38) | PersonIcon           = ""
  constant SuccessIcon (line 39) | SuccessIcon          = ""
  constant TeamIcon (line 40) | TeamIcon             = ""
  constant WaitingIcon (line 41) | WaitingIcon          = ""
  constant ActionRequiredIcon (line 42) | ActionRequiredIcon   = ""
  constant BehindIcon (line 44) | BehindIcon         = "󰇮"
  constant BlockedIcon (line 45) | BlockedIcon        = ""
  constant ClosedIcon (line 46) | ClosedIcon         = ""
  constant CodeReviewIcon (line 47) | CodeReviewIcon     = ""
  constant CommentIcon (line 48) | CommentIcon        = ""
  constant CommentsIcon (line 49) | CommentsIcon       = ""
  constant DonateIcon (line 50) | DonateIcon         = "󱃱"
  constant DraftIcon (line 51) | DraftIcon          = ""
  constant CommitIcon (line 52) | CommitIcon         = ""
  constant VerticalCommitIcon (line 53) | VerticalCommitIcon = "󰜘"
  constant LabelsIcon (line 54) | LabelsIcon         = "󰌖"
  constant MergedIcon (line 55) | MergedIcon         = ""
  constant MergeQueueIcon (line 56) | MergeQueueIcon     = ""
  constant OpenIcon (line 57) | OpenIcon           = ""
  constant SelectionIcon (line 58) | SelectionIcon      = "❯"
  constant NewContributorIcon (line 61) | NewContributorIcon = "󰎔"
  constant ContributorIcon (line 64) | ContributorIcon = ""
  constant CollaboratorIcon (line 68) | CollaboratorIcon = ""
  constant MemberIcon (line 71) | MemberIcon = ""
  constant OwnerIcon (line 74) | OwnerIcon = ""
  constant UnknownRoleIcon (line 76) | UnknownRoleIcon = "󰭙"
  constant WorkflowIcon (line 79) | WorkflowIcon     = ""
  constant WorkflowRunIcon (line 80) | WorkflowRunIcon  = ""
  constant SecurityIcon (line 81) | SecurityIcon     = "󰒃"
  constant NotificationIcon (line 82) | NotificationIcon = ""
  constant SearchIcon (line 83) | SearchIcon       = ""
  constant AssignPrompt (line 86) | AssignPrompt   = "Assign users (whitespace-separated)" + Ellipsis
  constant UnassignPrompt (line 87) | UnassignPrompt = "Unassign users (whitespace-separated)" + Ellipsis
  constant CommentPrompt (line 88) | CommentPrompt  = "Leave a comment" + Ellipsis
  constant ApprovalPrompt (line 89) | ApprovalPrompt = "Approve with comment" + Ellipsis
  constant LabelPrompt (line 90) | LabelPrompt    = "Add/remove labels (comma-separated)" + Ellipsis
  constant Logo (line 92) | Logo = `▜▔▚▐▔▌▚▔▐ ▌

FILE: internal/tui/constants/errMsg.go
  type ErrMsg (line 3) | type ErrMsg struct
    method Error (line 7) | func (e ErrMsg) Error() string { return e.Err.Error() }

FILE: internal/tui/constants/initMsg.go
  type InitMsg (line 5) | type InitMsg struct

FILE: internal/tui/constants/progressMsg.go
  type TaskFinishedMsg (line 5) | type TaskFinishedMsg struct
  type ClearTaskMsg (line 13) | type ClearTaskMsg struct

FILE: internal/tui/context/context.go
  constant TaskStart (line 16) | TaskStart State = iota
  constant TaskFinished (line 17) | TaskFinished
  constant TaskError (line 18) | TaskError
  type Task (line 21) | type Task struct
  type ProgramContext (line 31) | type ProgramContext struct
    method GetViewSectionsConfig (line 51) | func (ctx *ProgramContext) GetViewSectionsConfig() []config.SectionCon...

FILE: internal/tui/context/styles.go
  type Styles (line 12) | type Styles struct
  function InitStyles (line 92) | func InitStyles(theme theme.Theme) Styles {

FILE: internal/tui/keys/branchKeys.go
  type BranchKeyMap (line 12) | type BranchKeyMap struct
  function BranchFullHelp (line 63) | func BranchFullHelp() []key.Binding {
  function rebindBranchKeys (line 77) | func rebindBranchKeys(keys []config.Keybinding) error {

FILE: internal/tui/keys/issueKeys.go
  type IssueKeyMap (line 12) | type IssueKeyMap struct
  function IssueFullHelp (line 58) | func IssueFullHelp() []key.Binding {
  function rebindIssueKeys (line 71) | func rebindIssueKeys(keys []config.Keybinding) error {

FILE: internal/tui/keys/keys.go
  type NotificationSubjectType (line 14) | type NotificationSubjectType
  constant NotificationSubjectNone (line 17) | NotificationSubjectNone NotificationSubjectType = iota
  constant NotificationSubjectPR (line 18) | NotificationSubjectPR
  constant NotificationSubjectIssue (line 19) | NotificationSubjectIssue
  function SetNotificationSubject (line 26) | func SetNotificationSubject(subjectType NotificationSubjectType) {
  type KeyMap (line 30) | type KeyMap struct
    method ShortHelp (line 57) | func (k KeyMap) ShortHelp() []key.Binding {
    method FullHelp (line 61) | func (k KeyMap) FullHelp() [][]key.Binding {
    method NavigationKeys (line 108) | func (k KeyMap) NavigationKeys() []key.Binding {
    method AppKeys (line 121) | func (k KeyMap) AppKeys() []key.Binding {
    method QuitAndHelpKeys (line 133) | func (k KeyMap) QuitAndHelpKeys() []key.Binding {
  function CreateKeyMapForView (line 52) | func CreateKeyMapForView(viewType config.ViewType) help.KeyMap {
  function Rebind (line 209) | func Rebind(universal, issueKeys, prKeys, branchKeys, notificationKeys [...
  function rebindUniversal (line 242) | func rebindUniversal(universal []config.Keybinding) error {

FILE: internal/tui/keys/keys_test.go
  function TestSetNotificationSubject (line 11) | func TestSetNotificationSubject(t *testing.T) {
  function TestFullHelpIncludesPRKeysForPRSubject (line 32) | func TestFullHelpIncludesPRKeysForPRSubject(t *testing.T) {
  function TestFullHelpIncludesIssueKeysForIssueSubject (line 73) | func TestFullHelpIncludesIssueKeysForIssueSubject(t *testing.T) {
  function TestFullHelpExcludesPRKeysForNoSubject (line 107) | func TestFullHelpExcludesPRKeysForNoSubject(t *testing.T) {
  function TestFullHelpForPRViewDoesNotIncludeNotificationKeys (line 139) | func TestFullHelpForPRViewDoesNotIncludeNotificationKeys(t *testing.T) {
  function findKeyByHelp (line 166) | func findKeyByHelp(keys []key.Binding, helpDesc string) bool {
  function TestRebindNotificationKeys_Builtin (line 175) | func TestRebindNotificationKeys_Builtin(t *testing.T) {
  function TestRebindNotificationKeys_UnknownBuiltin (line 197) | func TestRebindNotificationKeys_UnknownBuiltin(t *testing.T) {
  function TestRebindNotificationKeys_CustomCommand (line 206) | func TestRebindNotificationKeys_CustomCommand(t *testing.T) {
  function TestFullHelpIncludesCustomNotificationBindings (line 225) | func TestFullHelpIncludesCustomNotificationBindings(t *testing.T) {

FILE: internal/tui/keys/notificationKeys.go
  type NotificationKeyMap (line 12) | type NotificationKeyMap struct
  function NotificationFullHelp (line 78) | func NotificationFullHelp() []key.Binding {
  function rebindNotificationKeys (line 95) | func rebindNotificationKeys(keys []config.Keybinding) error {

FILE: internal/tui/keys/prKeys.go
  type PRKeyMap (line 12) | type PRKeyMap struct
  function PRFullHelp (line 108) | func PRFullHelp() []key.Binding {
  function rebindPRKeys (line 130) | func rebindPRKeys(keys []config.Keybinding) error {

FILE: internal/tui/markdown/markdownRenderer.go
  function InitializeMarkdownStyle (line 11) | func InitializeMarkdownStyle(hasDarkBackground bool) {
  function GetMarkdownRenderer (line 22) | func GetMarkdownRenderer(width int) glamour.TermRenderer {

FILE: internal/tui/markdown/theme.go
  function boolPtr (line 242) | func boolPtr(b bool) *bool { return &b }
  function stringPtr (line 244) | func stringPtr(s string) *string { return &s }
  function uintPtr (line 246) | func uintPtr(u uint) *uint { return &u }

FILE: internal/tui/modelUtils.go
  method getCurrSection (line 29) | func (m *Model) getCurrSection() section.Section {
  method getCurrRowData (line 37) | func (m *Model) getCurrRowData() data.RowData {
  method getSectionAt (line 45) | func (m *Model) getSectionAt(id int) section.Section {
  method getPrevSectionId (line 53) | func (m *Model) getPrevSectionId() int {
  method getNextSectionId (line 57) | func (m *Model) getNextSectionId() int {
  type IssueCommandTemplateInput (line 61) | type IssueCommandTemplateInput struct
  method executeKeybinding (line 68) | func (m *Model) executeKeybinding(key string) tea.Cmd {
  method runCustomCommand (line 177) | func (m *Model) runCustomCommand(commandTemplate string, contextData *ma...
  method runCustomPRCommand (line 217) | func (m *Model) runCustomPRCommand(commandTemplate string, prData *prrow...
  method runCustomIssueCommand (line 228) | func (m *Model) runCustomIssueCommand(commandTemplate string, issueData ...
  method runCustomBranchCommand (line 238) | func (m *Model) runCustomBranchCommand(commandTemplate string, branchDat...
  method runCustomUniversalCommand (line 258) | func (m *Model) runCustomUniversalCommand(commandTemplate string) tea.Cmd {
  method runCustomNotificationPRCommand (line 263) | func (m *Model) runCustomNotificationPRCommand(
  method runCustomNotificationIssueCommand (line 279) | func (m *Model) runCustomNotificationIssueCommand(
  method runCustomNotificationCommand (line 293) | func (m *Model) runCustomNotificationCommand(
  type execProcessFinishedMsg (line 304) | type execProcessFinishedMsg struct
  method executeCustomCommand (line 306) | func (m *Model) executeCustomCommand(cmd string) tea.Cmd {
  method notify (line 331) | func (m *Model) notify(text string) tea.Cmd {
  method notifyErr (line 350) | func (m *Model) notifyErr(text string) tea.Cmd {

FILE: internal/tui/tasks.go
  method openBrowser (line 17) | func (m *Model) openBrowser() tea.Cmd {

FILE: internal/tui/testutils/utils.go
  function bytesContains (line 9) | func bytesContains(t *testing.T, bts []byte, str string) bool {
  function AssertNoError (line 53) | func AssertNoError(t testing.TB, got error) {

FILE: internal/tui/theme/theme.go
  type Theme (line 12) | type Theme struct
  function ParseTheme (line 120) | func ParseTheme(cfg *config.Config) Theme {

FILE: internal/tui/theme/theme_test.go
  function init (line 14) | func init() {
  function TestTheme (line 18) | func TestTheme(t *testing.T) {

FILE: internal/tui/ui.go
  type Model (line 48) | type Model struct
    method initScreen (line 104) | func (m *Model) initScreen() tea.Msg {
    method Init (line 161) | func (m Model) Init() tea.Cmd {
    method Update (line 165) | func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
    method View (line 846) | func (m Model) View() tea.View {
    method setCurrSectionId (line 918) | func (m *Model) setCurrSectionId(newSectionId int) {
    method updateNotificationSections (line 923) | func (m *Model) updateNotificationSections(msg tea.Msg) tea.Cmd {
    method markNotificationAsRead (line 935) | func (m *Model) markNotificationAsRead(notificationId string) {
    method onViewedRowChanged (line 943) | func (m *Model) onViewedRowChanged() tea.Cmd {
    method onWindowSizeChanged (line 954) | func (m *Model) onWindowSizeChanged(msg tea.WindowSizeMsg) {
    method syncProgramContext (line 967) | func (m *Model) syncProgramContext() {
    method updateSection (line 980) | func (m *Model) updateSection(id int, sType string, msg tea.Msg) (cmd ...
    method updateRelevantSection (line 1009) | func (m *Model) updateRelevantSection(msg section.SectionMsg) (cmd tea...
    method updateCurrentSection (line 1013) | func (m *Model) updateCurrentSection(msg tea.Msg) (cmd tea.Cmd) {
    method syncMainContentWidth (line 1021) | func (m *Model) syncMainContentWidth() {
    method openSidebarForPRInput (line 1035) | func (m *Model) openSidebarForPRInput(setFunc func(bool) tea.Cmd) tea....
    method openSidebarForInput (line 1040) | func (m *Model) openSidebarForInput(setFunc func(bool) tea.Cmd) tea.Cmd {
    method backToNotification (line 1049) | func (m *Model) backToNotification() tea.Cmd {
    method promptConfirmation (line 1060) | func (m *Model) promptConfirmation(currSection section.Section, action...
    method syncSidebar (line 1068) | func (m *Model) syncSidebar() tea.Cmd {
    method renderNotificationPrompt (line 1128) | func (m *Model) renderNotificationPrompt(row *notificationrow.Data) st...
    method loadNotificationContent (line 1229) | func (m *Model) loadNotificationContent() tea.Cmd {
    method fetchAllViewSections (line 1302) | func (m *Model) fetchAllViewSections() ([]section.Section, tea.Cmd) {
    method getCurrentViewSections (line 1329) | func (m *Model) getCurrentViewSections() []section.Section {
    method getCurrentViewDefaultSection (line 1348) | func (m *Model) getCurrentViewDefaultSection() int {
    method setCurrentViewSections (line 1361) | func (m *Model) setCurrentViewSections(newSections []section.Section) {
    method switchSelectedView (line 1436) | func (m *Model) switchSelectedView() tea.Cmd {
    method isUserDefinedKeybinding (line 1485) | func (m *Model) isUserDefinedKeybinding(msg tea.KeyMsg) bool {
    method renderRunningTask (line 1545) | func (m *Model) renderRunningTask() string {
    method doRefreshAtInterval (line 1627) | func (m *Model) doRefreshAtInterval() tea.Cmd {
    method doUpdateFooterAtInterval (line 1642) | func (m *Model) doUpdateFooterAtInterval() tea.Cmd {
    method promptConfirmationForNotificationPR (line 1654) | func (m *Model) promptConfirmationForNotificationPR(action string) tea...
    method promptConfirmationForNotificationIssue (line 1665) | func (m *Model) promptConfirmationForNotificationIssue(action string) ...
    method executeNotificationAction (line 1675) | func (m *Model) executeNotificationAction(action string) tea.Cmd {
  function NewModel (line 67) | func NewModel(location config.Location) Model {
  type initMsg (line 898) | type initMsg struct
  type notificationPRFetchedMsg (line 904) | type notificationPRFetchedMsg struct
  type notificationIssueFetchedMsg (line 911) | type notificationIssueFetchedMsg struct
  type userFetchedMsg (line 1608) | type userFetchedMsg struct
  function fetchUser (line 1612) | func fetchUser() tea.Msg {
  type intervalRefresh (line 1625) | type intervalRefresh
  type updateFooterMsg (line 1640) | type updateFooterMsg struct

FILE: internal/tui/ui_test.go
  type localRoundTripper (line 87) | type localRoundTripper struct
    method RoundTrip (line 91) | func (l localRoundTripper) RoundTrip(req *http.Request) (*http.Respons...
  function TestGetCurrentViewSections_RepoViewWithNilRepo (line 151) | func TestGetCurrentViewSections_RepoViewWithNilRepo(t *testing.T) {
  function TestPromptConfirmation_NilSection (line 168) | func TestPromptConfirmation_NilSection(t *testing.T) {
  function TestNotificationView_SwitchViewWithSKey (line 175) | func TestNotificationView_SwitchViewWithSKey(t *testing.T) {
  function TestNotificationView_SwitchViewWithSKey_WhileViewingPR (line 211) | func TestNotificationView_SwitchViewWithSKey_WhileViewingPR(t *testing.T) {
  function TestNotificationView_SwitchViewWithSKey_WhileViewingIssue (line 257) | func TestNotificationView_SwitchViewWithSKey_WhileViewingIssue(t *testin...
  function TestNotificationView_PRViewTabNavigation (line 303) | func TestNotificationView_PRViewTabNavigation(t *testing.T) {
  function TestNotificationView_EnterKeyWorksAfterViewingPR (line 356) | func TestNotificationView_EnterKeyWorksAfterViewingPR(t *testing.T) {
  function TestNotificationView_EnterKeyWorksAfterViewingIssue (line 429) | func TestNotificationView_EnterKeyWorksAfterViewingIssue(t *testing.T) {
  function TestNotificationView_BackKeyClearsPRSubjectAndRestoresNotificationActions (line 498) | func TestNotificationView_BackKeyClearsPRSubjectAndRestoresNotificationA...
  function TestNotificationView_BackKeyClearsIssueSubject (line 575) | func TestNotificationView_BackKeyClearsIssueSubject(t *testing.T) {
  function executeCommandTemplate (line 649) | func executeCommandTemplate(
  function TestPRCommandTemplateVariables (line 669) | func TestPRCommandTemplateVariables(t *testing.T) {
  function TestIssueCommandTemplateVariables (line 716) | func TestIssueCommandTemplateVariables(t *testing.T) {
  function TestCommandTemplateMissingVariable (line 756) | func TestCommandTemplateMissingVariable(t *testing.T) {
  function TestSyncMainContentWidth (line 767) | func TestSyncMainContentWidth(t *testing.T) {
  function TestSyncSidebar_NoOpWhenSidebarClosed (line 869) | func TestSyncSidebar_NoOpWhenSidebarClosed(t *testing.T) {
  function TestPromptConfirmationForNotificationPR (line 937) | func TestPromptConfirmationForNotificationPR(t *testing.T) {
  function TestPromptConfirmationForNotificationPR_NilSubject (line 973) | func TestPromptConfirmationForNotificationPR_NilSubject(t *testing.T) {
  function TestPromptConfirmationForNotificationIssue (line 990) | func TestPromptConfirmationForNotificationIssue(t *testing.T) {
  function TestNotificationConfirmation_CancelOnOtherKey (line 1023) | func TestNotificationConfirmation_CancelOnOtherKey(t *testing.T) {
  function TestNotificationConfirmation_AcceptWithY (line 1063) | func TestNotificationConfirmation_AcceptWithY(t *testing.T) {
  function TestNotificationConfirmation_AcceptWithUpperY (line 1106) | func TestNotificationConfirmation_AcceptWithUpperY(t *testing.T) {
  function TestNotificationConfirmation_AcceptWithEnter (line 1149) | func TestNotificationConfirmation_AcceptWithEnter(t *testing.T) {
  function TestPromptConfirmationForNotificationIssue_NilSubject (line 1194) | func TestPromptConfirmationForNotificationIssue_NilSubject(t *testing.T) {
  function TestRefresh_ClearsEnrichmentCache (line 1211) | func TestRefresh_ClearsEnrichmentCache(t *testing.T) {
  function TestRefreshAll_ClearsEnrichmentCache (line 1270) | func TestRefreshAll_ClearsEnrichmentCache(t *testing.T) {
  function TestPromptConfirmationForNotificationPR_ApproveWorkflows (line 1337) | func TestPromptConfirmationForNotificationPR_ApproveWorkflows(t *testing...
  function TestNotificationConfirmation_ApproveWorkflows_AcceptWithY (line 1373) | func TestNotificationConfirmation_ApproveWorkflows_AcceptWithY(t *testin...
  function TestIsUserDefinedKeybinding_NotificationsView_PRNotification (line 1419) | func TestIsUserDefinedKeybinding_NotificationsView_PRNotification(t *tes...
  function TestIsUserDefinedKeybinding_NotificationsView_IssueNotification (line 1480) | func TestIsUserDefinedKeybinding_NotificationsView_IssueNotification(t *...
  function TestIsUserDefinedKeybinding_NotificationsView_NonPRIssueNotification (line 1536) | func TestIsUserDefinedKeybinding_NotificationsView_NonPRIssueNotificatio...
  function TestNotificationPRCommandTemplateVariables (line 1591) | func TestNotificationPRCommandTemplateVariables(t *testing.T) {
  function TestNotificationPRCommandTemplateVariables_WithSidebar (line 1625) | func TestNotificationPRCommandTemplateVariables_WithSidebar(t *testing.T) {
  function TestNotificationIssueCommandTemplateVariables (line 1672) | func TestNotificationIssueCommandTemplateVariables(t *testing.T) {
  function TestNotificationIssueCommandTemplateVariables_WithSidebar (line 1706) | func TestNotificationIssueCommandTemplateVariables_WithSidebar(t *testin...
  function TestNotificationCommandTemplate_PRFieldsWithoutSidebar (line 1740) | func TestNotificationCommandTemplate_PRFieldsWithoutSidebar(t *testing.T) {
  function TestIsUserDefinedKeybinding_NotificationsView_NotificationKeybinding (line 1766) | func TestIsUserDefinedKeybinding_NotificationsView_NotificationKeybindin...
  function TestNotificationCommandTemplateVariables (line 1827) | func TestNotificationCommandTemplateVariables(t *testing.T) {

FILE: internal/utils/templateHandler.go
  type TemplateRegistry (line 12) | type TemplateRegistry struct
    method UID (line 20) | func (or *TemplateRegistry) UID() string {
    method LinkHandler (line 24) | func (or *TemplateRegistry) LinkHandler(fh sprout.Handler) error {
    method NowModify (line 29) | func (or *TemplateRegistry) NowModify(input string) (string, error) {
    method RegisterFunctions (line 40) | func (or *TemplateRegistry) RegisterFunctions(funcsMap sprout.Function...
    method RegisterAliases (line 45) | func (or *TemplateRegistry) RegisterAliases(aliasMap sprout.FunctionAl...
  function NewRegistry (line 16) | func NewRegistry() *TemplateRegistry {
  function ParseDuration (line 52) | func ParseDuration(s string) (time.Duration, error) {

FILE: internal/utils/utils.go
  constant ApproxDaysInYear (line 12) | ApproxDaysInYear  = 365
  constant ApproxDaysInMonth (line 13) | ApproxDaysInMonth = 28
  constant DaysInWeek (line 14) | DaysInWeek        = 7
  function Max (line 17) | func Max(a, b int) int {
  function Min (line 24) | func Min(a, b int) int {
  function TimeElapsed (line 31) | func TimeElapsed(then time.Time) string {
  function BoolPtr (line 80) | func BoolPtr(b bool) *bool { return &b }
  function StringPtr (line 82) | func StringPtr(s string) *string { return &s }
  function UintPtr (line 84) | func UintPtr(u uint) *uint { return &u }
  function IntPtr (line 86) | func IntPtr(u int) *int { return &u }
  function ShortNumber (line 88) | func ShortNumber(n int) string {
  function GetStylePrefix (line 102) | func GetStylePrefix(s lipgloss.Style) string {

FILE: internal/utils/utils_test.go
  function TestGetStylePrefix (line 10) | func TestGetStylePrefix(t *testing.T) {
  function TestGetStylePrefix_StripsReset (line 46) | func TestGetStylePrefix_StripsReset(t *testing.T) {
  function TestGetStylePrefix_VariousStyles (line 70) | func TestGetStylePrefix_VariousStyles(t *testing.T) {
  function TestGetStylePrefix_ConcatenationPreservesStyle (line 134) | func TestGetStylePrefix_ConcatenationPreservesStyle(t *testing.T) {
Condensed preview — 294 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (4,613K chars).
[
  {
    "path": ".envrc",
    "chars": 268,
    "preview": "#!/bin/bash\n\n# Automatically sets up your devbox environment whenever you cd into this\n# directory via our direnv integr"
  },
  {
    "path": ".gh-dash.yml",
    "chars": 1357,
    "preview": "# yaml-language-server: $schema=https://gh-dash.dev/schema.json\nprSections:\n  - title: Mine\n    filters: is:open author:"
  },
  {
    "path": ".github/FUNDING.yml",
    "chars": 17,
    "preview": "github: [dlvhdr]\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "chars": 581,
    "preview": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: \"[BUG]\"\nlabels: bug\nassignees: \"\"\n---\n\n**Describe "
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "chars": 595,
    "preview": "---\nname: Feature request\nabout: Suggest an idea for this project\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n**Is your fea"
  },
  {
    "path": ".github/pull_request_template.md",
    "chars": 287,
    "preview": "# Summary\n\n- [] Closes issue #...\n- [] I have read the [CONTIBUTING.md](../CONTRIBUTING.md) and [AI_POLICY.md](../AI_POL"
  },
  {
    "path": ".github/workflows/build-and-test.yaml",
    "chars": 1167,
    "preview": "name: build and test\n\non:\n  pull_request:\n    paths-ignore:\n      - \"docs/**\"\n\npermissions:\n  contents: read\n\njobs:\n  bu"
  },
  {
    "path": ".github/workflows/build-docs.yaml",
    "chars": 354,
    "preview": "name: Build Docs\n\non:\n  pull_request:\n    paths:\n      - \"docs/**\"\n  workflow_dispatch:\n\njobs:\n  build:\n    runs-on: ubu"
  },
  {
    "path": ".github/workflows/dependabot-sync.yml",
    "chars": 419,
    "preview": "name: dependabot-sync\non:\n  schedule:\n    - cron: \"0 0 * * 0\" # every Sunday at midnight\n  workflow_dispatch: # allows m"
  },
  {
    "path": ".github/workflows/go-release.yml",
    "chars": 824,
    "preview": "name: goreleaser\n\non:\n  push:\n    tags:\n      - \"*\"\n\npermissions:\n  contents: write\n\njobs:\n  goreleaser:\n    runs-on: ub"
  },
  {
    "path": ".github/workflows/lint.yml",
    "chars": 320,
    "preview": "name: lint\non:\n  pull_request:\n\npermissions:\n  contents: read\n\njobs:\n  golangci:\n    name: lint\n    runs-on: ubuntu-late"
  },
  {
    "path": ".github/workflows/publish-docs.yaml",
    "chars": 897,
    "preview": "name: Build and Push Docs Docker image\n\non:\n  push:\n    branches: [\"main\"]\n    paths:\n      - \"docs/**\"\n\njobs:\n  build-a"
  },
  {
    "path": ".gitignore",
    "chars": 140,
    "preview": "debug.log\ndist\ngh-prs\n/gh-dash\n.direnv/\n/result*\n.DS_Store\n.killgrave.log\ndocs/broken-links.log\n.devbox\n__debug*\ntestdat"
  },
  {
    "path": ".golangci.yml",
    "chars": 860,
    "preview": "version: \"2\"\nlinters:\n  enable:\n    - bodyclose\n    # - exhaustive\n    # - goconst\n    # - godot\n    # - godox\n    # - g"
  },
  {
    "path": ".goreleaser.yaml",
    "chars": 2910,
    "preview": "version: 2\n\nbefore:\n  hooks:\n    - go mod tidy\n\ngomod:\n  proxy: true\n  env:\n    - GOPROXY=https://proxy.golang.org,direc"
  },
  {
    "path": "AI_POLICY.md",
    "chars": 1921,
    "preview": "# AI Usage Policy\n\nThis project has strict rules for AI usage:\n\n- **All AI usage in any form must be disclosed.** You mu"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 4449,
    "preview": "# Contributing To `gh-dash`\n\nThank you for investing your time in contributing to our project!\n\nIn this guide you will g"
  },
  {
    "path": "LICENSE.txt",
    "chars": 1068,
    "preview": "MIT License\n\nCopyright (c) 2025 Dolev Hadar\n\nPermission is hereby granted, free of charge, to any person obtaining a cop"
  },
  {
    "path": "README.md",
    "chars": 2738,
    "preview": "<br />\n<p align=\"center\">\n  <a  class=\"underline: none;\" href=\"https://gh-dash.dev\">\n    <picture>\n      <source media=\""
  },
  {
    "path": "Taskfile.yaml",
    "chars": 2647,
    "preview": "# https://taskfile.dev\n\nversion: \"3\"\nsilent: true\n\ntasks:\n  default:\n    cmds:\n      - go run . {{.CLI_ARGS}}\n    intera"
  },
  {
    "path": "cmd/root.go",
    "chars": 5091,
    "preview": "/*\nCopyright © 2022 NAME HERE <EMAIL ADDRESS>\n*/\npackage cmd\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\tslog \"log\"\n\t\"os\"\n\t\"runtime\"\n\t\""
  },
  {
    "path": "cmd/sponsors.go",
    "chars": 1629,
    "preview": "/*\nCopyright © 2025 NAME HERE <EMAIL ADDRESS>\n*/\npackage cmd\n\nimport (\n\t\"fmt\"\n\n\t\"charm.land/lipgloss/v2\"\n\t\"charm.land/lo"
  },
  {
    "path": "devbox.json",
    "chars": 729,
    "preview": "{\n  \"$schema\": \"https://raw.githubusercontent.com/jetify-com/devbox/0.16.0/.schema/devbox.schema.json\",\n  \"env\": {\n    \""
  },
  {
    "path": "docs/.dockerignore",
    "chars": 28,
    "preview": ".DS_Store\nnode_modules\ndist\n"
  },
  {
    "path": "docs/.envrc",
    "chars": 268,
    "preview": "#!/bin/bash\n\n# Automatically sets up your devbox environment whenever you cd into this\n# directory via our direnv integr"
  },
  {
    "path": "docs/.eslint.config.js",
    "chars": 143,
    "preview": "import eslintPluginAstro from \"eslint-plugin-astro\";\nexport default [\n  js.configs.recommended,\n  ...eslintPluginAstro.c"
  },
  {
    "path": "docs/.gitignore",
    "chars": 229,
    "preview": "# build output\ndist/\n# generated types\n.astro/\n\n# dependencies\nnode_modules/\n\n# logs\nnpm-debug.log*\nyarn-debug.log*\nyarn"
  },
  {
    "path": "docs/.prettierrc.mjs",
    "chars": 257,
    "preview": "// .prettierrc.mjs\n/** @type {import(\"prettier\").Config} */\nexport default {\n  plugins: [\"prettier-plugin-astro\", \"prett"
  },
  {
    "path": "docs/Dockerfile",
    "chars": 583,
    "preview": "FROM node:20-slim AS base\nENV PNPM_HOME=\"/pnpm\"\nENV PATH=\"$PNPM_HOME:$PATH\"\nRUN corepack enable\n\nCOPY . /app\nWORKDIR /ap"
  },
  {
    "path": "docs/README.mdx",
    "chars": 1433,
    "preview": "# Docs Site\n\n[![Built with Starlight](https://astro.badg.es/v2/built-with-starlight/tiny.svg)](https://starlight.astro.b"
  },
  {
    "path": "docs/astro.config.mjs",
    "chars": 3317,
    "preview": "// @ts-check\nimport { defineConfig } from \"astro/config\";\nimport starlight from \"@astrojs/starlight\";\nimport tailwindcss"
  },
  {
    "path": "docs/devbox.json",
    "chars": 291,
    "preview": "{\n  \"$schema\": \"https://raw.githubusercontent.com/jetify-com/devbox/0.16.0/.schema/devbox.schema.json\",\n  \"env\": {\n    \""
  },
  {
    "path": "docs/package.json",
    "chars": 863,
    "preview": "{\n  \"name\": \"docs\",\n  \"type\": \"module\",\n  \"version\": \"0.0.1\",\n  \"scripts\": {\n    \"dev\": \"astro dev\",\n    \"start\": \"astro"
  },
  {
    "path": "docs/src/assets/custom-commands.tape",
    "chars": 357,
    "preview": "Output custom-commands.webm\nOutput custom-commands.mp4\nOutput custom-commands.gif\n\nSet Theme TokyoNight\nSet Padding 0\nSe"
  },
  {
    "path": "docs/src/assets/custom-commands.yml",
    "chars": 1059,
    "preview": "prSections:\n  - title: My Pull Requests\n    filters: is:open author:@me owner:dlvhdr\n  - title: Needs My Review\n    filt"
  },
  {
    "path": "docs/src/assets/demo.yml",
    "chars": 1033,
    "preview": "prSections:\n  - title: My Pull Requests\n    filters: is:open author:@me owner:charmbracelet\n  - title: Review Requested\n"
  },
  {
    "path": "docs/src/assets/overview.tape",
    "chars": 752,
    "preview": "Output overview.webm\nOutput overview.mp4\nOutput overview.gif\n\nSet PlaybackSpeed 1.3\nSet Theme TokyoNight\nSet Padding 0\nS"
  },
  {
    "path": "docs/src/assets/sections.tape",
    "chars": 366,
    "preview": "Output sections.webm\nOutput sections.mp4\nOutput sections.gif\n\nSet Theme TokyoNight\nSet Padding 0\nSet FontSize 24\nSet Fon"
  },
  {
    "path": "docs/src/assets/sections.yml",
    "chars": 783,
    "preview": "prSections:\n  - title: My Pull Requests\n    filters: is:open author:@me owner:dlvhdr\n  - title: Needs My Review\n    filt"
  },
  {
    "path": "docs/src/assets/theme-catpuccin.yml",
    "chars": 782,
    "preview": "prSections:\n  - title: My Pull Requests\n    filters: is:open author:@me owner:dlvhdr\n  - title: Needs My Review\n    filt"
  },
  {
    "path": "docs/src/assets/theme-gruvbox.yml",
    "chars": 782,
    "preview": "prSections:\n  - title: My Pull Requests\n    filters: is:open author:@me owner:dlvhdr\n  - title: Needs My Review\n    filt"
  },
  {
    "path": "docs/src/assets/theme-tokyonight.yml",
    "chars": 782,
    "preview": "prSections:\n  - title: My Pull Requests\n    filters: is:open author:@me owner:dlvhdr\n  - title: Needs My Review\n    filt"
  },
  {
    "path": "docs/src/components/Box.astro",
    "chars": 696,
    "preview": "---\nimport { Icon } from \"@astrojs/starlight/components\";\n\nconst { header, icon } = Astro.props;\n---\n\n<div class=\"relati"
  },
  {
    "path": "docs/src/components/DashHeroLogo.astro",
    "chars": 1437,
    "preview": "---\nimport Logo from \"./Logo.astro\";\n---\n\n<style>\n  @keyframes dash-in {\n    from {\n      opacity: 0;\n      filter: blur"
  },
  {
    "path": "docs/src/components/DecorationBottom.astro",
    "chars": 220,
    "preview": "---\n\n---\n\n<pre\n  class=\"!bg-transparent leading-normal text-[var(--sl-color-gray-4)]\">\n ────────────────·.   .·─────────"
  },
  {
    "path": "docs/src/components/DecorationSeparator.astro",
    "chars": 140,
    "preview": "---\n\n---\n\n<pre\n  class=\"!bg-transparent leading-normal text-[var(--sl-color-gray-4)]\">\n  {\"<~-----------------◇---------"
  },
  {
    "path": "docs/src/components/DecorationTop.astro",
    "chars": 220,
    "preview": "---\n\n---\n\n<pre\n  class=\"!bg-transparent leading-normal text-[var(--sl-color-gray-4)]\">\n _                  _            "
  },
  {
    "path": "docs/src/components/DiffnavCard.astro",
    "chars": 809,
    "preview": "---\nimport { Icon } from \"@astrojs/starlight/components\";\nimport DiffnavMiniLogo from \"./DiffnavMiniLogo.astro\";\n---\n\n<a"
  },
  {
    "path": "docs/src/components/DiffnavMiniLogo.astro",
    "chars": 823,
    "preview": "---\nconst { class: className } = Astro.props;\n---\n\n<style>\n  [aria-label=\"DIFFNAV ASCII Logo\"] {\n    position: relative;"
  },
  {
    "path": "docs/src/components/Discord.astro",
    "chars": 515,
    "preview": "---\nimport { Icon } from \"@astrojs/starlight/components\";\n\nconst { class: className } = Astro.props;\n---\n\n<div class:lis"
  },
  {
    "path": "docs/src/components/EnhanceCard.astro",
    "chars": 761,
    "preview": "---\nimport { Icon } from \"@astrojs/starlight/components\";\nimport EnhanceMiniLogo from \"./EnhanceMiniLogo.astro\";\n---\n\n<a"
  },
  {
    "path": "docs/src/components/EnhanceLogo.astro",
    "chars": 1348,
    "preview": "---\nconst { className } = Astro.props;\n---\n\n<style>\n  [aria-label=\"ENHANCE ASCII Logo\"] {\n    position: relative;\n    ba"
  },
  {
    "path": "docs/src/components/EnhanceMiniLogo.astro",
    "chars": 798,
    "preview": "---\nconst { class: className } = Astro.props;\n---\n\n<style>\n  [aria-label=\"ENHANCE ASCII Logo\"] {\n    position: relative;"
  },
  {
    "path": "docs/src/components/EnhanceOneLineLogo.astro",
    "chars": 649,
    "preview": "---\nconst { class: className } = Astro.props;\n---\n\n<style>\n  [aria-label=\"ENHANCE ASCII Logo\"] {\n    position: relative;"
  },
  {
    "path": "docs/src/components/FadeImages.astro",
    "chars": 98,
    "preview": "---\nimport \"../styles/fade-images.css\";\n---\n\n<div class=\"fadein h-full w-full\">\n  <slot />\n</div>\n"
  },
  {
    "path": "docs/src/components/FeatureCard.astro",
    "chars": 1673,
    "preview": "---\nimport FeatureSponsorshipGoal from \"./FeatureSponsorshipGoal.astro\";\n\nconst PROJECTS = {\n  dash: {\n    url: \"/\",\n   "
  },
  {
    "path": "docs/src/components/FeatureSponsorshipGoal.astro",
    "chars": 2462,
    "preview": "---\nimport { getSponsorshipGoal } from \"../data/sponsorshipGoal\";\nimport { Icon } from \"@astrojs/starlight/components\";\n"
  },
  {
    "path": "docs/src/components/Footer.astro",
    "chars": 1384,
    "preview": "---\nimport DecorationTop from \"./DecorationTop.astro\";\nimport DecorationBottom from \"./DecorationBottom.astro\";\n\nconst {"
  },
  {
    "path": "docs/src/components/Header.astro",
    "chars": 2625,
    "preview": "---\nimport Search from \"@astrojs/starlight/components/Search.astro\";\nimport Logo from \"./Logo.astro\";\nimport { Icon } fr"
  },
  {
    "path": "docs/src/components/Hero.astro",
    "chars": 2231,
    "preview": "---\nimport Default from \"@astrojs/starlight/components/PageTitle.astro\";\nimport Logo from \"./Logo.astro\";\nimport Enhance"
  },
  {
    "path": "docs/src/components/Logo.astro",
    "chars": 586,
    "preview": "---\nconst { className } = Astro.props;\n---\n\n<style>\n  [aria-label=\"DASH ASCII Logo\"] {\n    transform: skew(-20deg);\n    "
  },
  {
    "path": "docs/src/components/NerdFontIcon.astro",
    "chars": 169,
    "preview": "---\nconst { icon } = Astro.props;\nimport \"../styles/nerd-font.css\";\n---\n\n<code class=\"rounded bg-blue-950 text-xl text-b"
  },
  {
    "path": "docs/src/components/PillLink.astro",
    "chars": 490,
    "preview": "---\nconst { href, target, class: className } = Astro.props;\n---\n\n<a\n  class:list={[\n    \"flex items-center gap-2 text-[v"
  },
  {
    "path": "docs/src/components/ReleaseVersionButton.astro",
    "chars": 328,
    "preview": "---\nimport { getLatestVersion } from \"../data/latestVersion\";\n\nconst response = await getLatestVersion();\n---\n\n<form act"
  },
  {
    "path": "docs/src/components/Showcase.astro",
    "chars": 336,
    "preview": "---\nconst { reversed } = Astro.props;\n---\n\n<div class={`flex flex-col gap-8 w-full lg:w-auto lg:gap-18 items-center`}>\n "
  },
  {
    "path": "docs/src/components/Sponsorship.astro",
    "chars": 1342,
    "preview": "---\nimport { getSponsorshipGoal } from \"../data/sponsorshipGoal\";\n\nconst response = await getSponsorshipGoal();\nconst cu"
  },
  {
    "path": "docs/src/components/SponsorshipGoal.astro",
    "chars": 2378,
    "preview": "---\nimport { getSponsorshipGoal } from \"../data/sponsorshipGoal\";\nimport { Icon } from \"@astrojs/starlight/components\";\n"
  },
  {
    "path": "docs/src/components/StargazersCount.astro",
    "chars": 533,
    "preview": "---\nimport { Icon } from \"@astrojs/starlight/components\";\nimport PillLink from \"./PillLink.astro\";\nimport { getStars } f"
  },
  {
    "path": "docs/src/components/StargazersFallback.astro",
    "chars": 270,
    "preview": "---\nimport { Icon } from \"@astrojs/starlight/components\";\nimport PillLink from \"./PillLink.astro\";\n---\n\n<PillLink href=\""
  },
  {
    "path": "docs/src/components/SupportSection.astro",
    "chars": 1011,
    "preview": "---\nimport { Icon } from \"@astrojs/starlight/components\";\nimport Sponsorship from \"../components/Sponsorship.astro\";\n---"
  },
  {
    "path": "docs/src/components/Terminal.astro",
    "chars": 424,
    "preview": "---\nimport \"../styles/terminal.css\";\nconst { className, title = \"gh dash\" } = Astro.props;\n---\n\n<div class={`terminal ${"
  },
  {
    "path": "docs/src/components/ThemeSelect.astro",
    "chars": 2796,
    "preview": "---\nimport Select from \"@astrojs/starlight/components/Select.astro\";\n---\n\n<starlight-theme-select>\n  {\n    /* TODO: Can "
  },
  {
    "path": "docs/src/content/docs/companions/enhance/dash-integration.mdx",
    "chars": 614,
    "preview": "---\ntitle: DASH Integration\n---\n\nIn order to launch `ENHANCE` from `DASH` [add a custom keybind](../../../configuration/"
  },
  {
    "path": "docs/src/content/docs/companions/enhance/getting-started.mdx",
    "chars": 1935,
    "preview": "---\ntitle: Installation\n---\n\nimport { Aside } from \"@astrojs/starlight/components\";\n\nGet started using `ENHANCE` to mana"
  },
  {
    "path": "docs/src/content/docs/companions/enhance/index.mdx",
    "chars": 23,
    "preview": "---\ntitle: ENHANCE\n---\n"
  },
  {
    "path": "docs/src/content/docs/companions/enhance/keybindings.mdx",
    "chars": 1175,
    "preview": "---\ntitle: Keybindings\n---\n\n`ENHANCE` supports the following keybindings.\n\n## Navigating\n\n| Key            | Action     "
  },
  {
    "path": "docs/src/content/docs/companions/enhance/theme.mdx",
    "chars": 484,
    "preview": "---\ntitle: Theming\n---\n\n`ENHANCE` supports all the themes listed in [bubbletint's website](https://lrstanley.github.io/b"
  },
  {
    "path": "docs/src/content/docs/companions/enhance/usage.mdx",
    "chars": 963,
    "preview": "---\ntitle: Usage\n---\n\nTo use `enhance`, follow these steps after you've [installed it][01]:\n\n1. Run\n\n   ```\n    gh enhan"
  },
  {
    "path": "docs/src/content/docs/companions/index.mdx",
    "chars": 30,
    "preview": "---\ntitle: Companion Apps\n---\n"
  },
  {
    "path": "docs/src/content/docs/configuration/defaults.mdx",
    "chars": 9093,
    "preview": "---\ntitle: Defaults\n---\n\n## Default Options (`defaults`)\n\nThese settings define the default behavior for the dashboard. "
  },
  {
    "path": "docs/src/content/docs/configuration/examples.mdx",
    "chars": 3749,
    "preview": "---\ntitle: Examples\n---\n\nThese examples show a few ways you might configure your dashboard.\n\n## Complete Examples\n\n- The"
  },
  {
    "path": "docs/src/content/docs/configuration/index.mdx",
    "chars": 2830,
    "preview": "---\ntitle: How to Configure\n---\n\nimport { Aside, LinkCard, CardGrid } from \"@astrojs/starlight/components\";\n\n`dash` has "
  },
  {
    "path": "docs/src/content/docs/configuration/issue-section.mdx",
    "chars": 3261,
    "preview": "---\ntitle: Issue Sections\n---\n\n# Issues Section Options (`issuesSections`)\n\nDefines a section in the dashboard's issues "
  },
  {
    "path": "docs/src/content/docs/configuration/keybindings/index.mdx",
    "chars": 8835,
    "preview": "---\ntitle: Custom Keybindings\n---\n\n`dash` allows you to override existing keybindings as well as add custom ones.\n\nEvery"
  },
  {
    "path": "docs/src/content/docs/configuration/keybindings/issues.mdx",
    "chars": 246,
    "preview": "---\ntitle: Issues\nlinkTitle: >-\n  ![icon:circle-dot](lucide)&nbsp;Issues\nweight: 2\nsummary: >-\n  Documentation for defin"
  },
  {
    "path": "docs/src/content/docs/configuration/keybindings/prs.mdx",
    "chars": 39,
    "preview": "---\ntitle: PRs\nlinkTitle: >-\n  PRs\n---\n"
  },
  {
    "path": "docs/src/content/docs/configuration/layout/issue.mdx",
    "chars": 6434,
    "preview": "---\ntitle: Issue Layout\n---\n\nimport { Aside, Code } from \"@astrojs/starlight/components\";\nimport NerdFontIcon from \"../."
  },
  {
    "path": "docs/src/content/docs/configuration/layout/options.mdx",
    "chars": 1775,
    "preview": "---\ntitle: Valid Options\n---\n\n## Valid Layout Options\n\nAny column can define the [`align`], [`grow`], [`width`], and [`h"
  },
  {
    "path": "docs/src/content/docs/configuration/layout/pr.mdx",
    "chars": 9735,
    "preview": "---\ntitle: PR Layout\n---\n\nimport { Aside, Code } from \"@astrojs/starlight/components\";\nimport NerdFontIcon from \"../../."
  },
  {
    "path": "docs/src/content/docs/configuration/notification-section.mdx",
    "chars": 4920,
    "preview": "---\ntitle: Notification Sections\n---\n\n# Notification Section Options (`notificationsSections`)\n\nDefines sections in the "
  },
  {
    "path": "docs/src/content/docs/configuration/pr-section.mdx",
    "chars": 3159,
    "preview": "---\ntitle: PR Sections\n---\n\n# PR Section Options (`prSections`)\n\nDefines a section in the dashboard's PRs view.\n\n- Every"
  },
  {
    "path": "docs/src/content/docs/configuration/repo-paths.mdx",
    "chars": 2069,
    "preview": "---\ntitle: Repo Paths\n---\n\nYou can use the `repoPaths` setting to map repository names (as keys) to local paths\n(as valu"
  },
  {
    "path": "docs/src/content/docs/configuration/reusing.mdx",
    "chars": 1749,
    "preview": "---\ntitle: Reusing Settings\n---\n\n`DASH` supports defining global settings that will always be applied, and lets you over"
  },
  {
    "path": "docs/src/content/docs/configuration/schema.mdx",
    "chars": 1652,
    "preview": "---\ntitle: Schema\n---\n\nThe `dash` configuration schema is published here:\n\n[`https://gh-dash.dev/schema.json`][02]\n\n## U"
  },
  {
    "path": "docs/src/content/docs/configuration/searching.mdx",
    "chars": 3984,
    "preview": "---\ntitle: Searching\nlinkTitle: >-\n  ![icon:search](lucide)&nbsp;Searching\nsummary: >-\n  How to search and filter issues"
  },
  {
    "path": "docs/src/content/docs/configuration/theme.mdx",
    "chars": 12135,
    "preview": "---\ntitle: Theme\n---\n\nimport { Aside } from \"@astrojs/starlight/components\";\n\n# Theme Options\n\nThis setting defines the "
  },
  {
    "path": "docs/src/content/docs/contributing/index.mdx",
    "chars": 4537,
    "preview": "---\ntitle: Contributing\n---\n\nThank you for investing your time in contributing to our project!\n\nIn this guide you will g"
  },
  {
    "path": "docs/src/content/docs/donating/index.mdx",
    "chars": 1118,
    "preview": "---\ntitle: Donating ❤️\n---\n\nimport { Aside } from \"@astrojs/starlight/components\";\nimport Sponsorship from \"../../../com"
  },
  {
    "path": "docs/src/content/docs/getting-started/index.mdx",
    "chars": 1483,
    "preview": "---\ntitle: Installation\n---\n\nGet started using `dash` to review and manage your GitHub work items.\n\n## Recommended Steps"
  },
  {
    "path": "docs/src/content/docs/getting-started/keybindings/global.mdx",
    "chars": 2016,
    "preview": "---\ntitle: Global\nlinkTitle: >-\n  ![icon:globe](lucide)&nbsp;Global\nweight: 1\nsummary: >-\n  Lists the default keybinding"
  },
  {
    "path": "docs/src/content/docs/getting-started/keybindings/index.mdx",
    "chars": 1660,
    "preview": "---\ntitle: Overview\nweight: 3\nsummary: >-\n  Get started using key presses to interact with the dashboard.\n---\n\nimport { "
  },
  {
    "path": "docs/src/content/docs/getting-started/keybindings/navigation.mdx",
    "chars": 859,
    "preview": "---\ntitle: Navigation\nlinkTitle: >-\n  ![icon:navigation](lucide)&nbsp;Navigation\nweight: 2\nsummary: >-\n  Lists the defau"
  },
  {
    "path": "docs/src/content/docs/getting-started/keybindings/preview.mdx",
    "chars": 1015,
    "preview": "---\ntitle: Preview Pane\nlinkTitle: >-\n  ![icon:view](lucide)&nbsp;Preview Pane\nweight: 6\nsummary: >-\n  Lists the default"
  },
  {
    "path": "docs/src/content/docs/getting-started/keybindings/selected-issue.mdx",
    "chars": 3464,
    "preview": "---\ntitle: Selected Issue\nlinkTitle: >-\n  ![icon:circle-dot](lucide)&nbsp;Selected Issue\nweight: 4\nsummary: >-\n  Lists t"
  },
  {
    "path": "docs/src/content/docs/getting-started/keybindings/selected-item.mdx",
    "chars": 457,
    "preview": "---\ntitle: Selected Item\nweight: 3\nsummary: >-\n  Lists the default keybindings for interacting with active items in the "
  },
  {
    "path": "docs/src/content/docs/getting-started/keybindings/selected-notification.mdx",
    "chars": 2256,
    "preview": "---\ntitle: Selected Notification\nweight: 5\n---\n\n## Key Bindings\n\n| Key   | Action                                       "
  },
  {
    "path": "docs/src/content/docs/getting-started/keybindings/selected-pr.mdx",
    "chars": 4681,
    "preview": "---\ntitle: Selected PR\nweight: 5\nsummary: >-\n  Lists the default keybindings for interacting with an actively selected i"
  },
  {
    "path": "docs/src/content/docs/getting-started/updating.mdx",
    "chars": 675,
    "preview": "---\ntitle: Updating\n---\n\nYou can update `dash` either with the [GitHub CLI](https://cli.github.com) or by\ndownloading th"
  },
  {
    "path": "docs/src/content/docs/getting-started/usage.mdx",
    "chars": 4871,
    "preview": "---\ntitle: Usage\nlinkTitle: >-\n  ![icon:terminal](lucide)&nbsp;Usage\nsummary: >-\n  Get started using `dash`.\nsidebar:\n  "
  },
  {
    "path": "docs/src/content/docs/insiders/index.mdx",
    "chars": 5277,
    "preview": "---\ntitle: Join Insiders\n---\n\nimport { Icon } from \"@astrojs/starlight/components\";\nimport EnhanceCard from \"../../../co"
  },
  {
    "path": "docs/src/content.config.ts",
    "chars": 273,
    "preview": "import { defineCollection, z } from \"astro:content\";\nimport { docsLoader } from \"@astrojs/starlight/loaders\";\nimport { d"
  },
  {
    "path": "docs/src/data/latestVersion.ts",
    "chars": 451,
    "preview": "const GH_TOKEN = import.meta.env.GH_TOKEN;\n\nexport const getLatestVersion = async () => {\n  const response = await fetch"
  },
  {
    "path": "docs/src/data/schemas/defaults.yaml",
    "chars": 7771,
    "preview": "# yaml-language-server: $schema=https://json-schema.org/draft/2020-12/schema\n$schema: https://json-schema.org/draft/2020"
  },
  {
    "path": "docs/src/data/schemas/definitions/grow.yaml",
    "chars": 782,
    "preview": "# yaml-language-server: $schema=https://json-schema.org/draft/2020-12/schema\n$schema: https://json-schema.org/draft/2020"
  },
  {
    "path": "docs/src/data/schemas/definitions/hexcolor.yaml",
    "chars": 838,
    "preview": "# yaml-language-server: $schema=https://json-schema.org/draft/2020-12/schema\n$schema: https://json-schema.org/draft/2020"
  },
  {
    "path": "docs/src/data/schemas/gh-dash.yaml",
    "chars": 9999,
    "preview": "# yaml-language-server: $schema=https://json-schema.org/draft/2020-12/schema\n$schema: https://json-schema.org/draft/2020"
  },
  {
    "path": "docs/src/data/schemas/issue-section.yaml",
    "chars": 3270,
    "preview": "# yaml-language-server: $schema=https://json-schema.org/draft/2020-12/schema\n$schema: https://json-schema.org/draft/2020"
  },
  {
    "path": "docs/src/data/schemas/keybindings/entry.yaml",
    "chars": 2871,
    "preview": "# yaml-language-server: $schema=https://json-schema.org/draft/2020-12/schema\n$schema: https://json-schema.org/draft/2020"
  },
  {
    "path": "docs/src/data/schemas/keybindings/issues.yaml",
    "chars": 901,
    "preview": "# yaml-language-server: $schema=https://json-schema.org/draft/2020-12/schema\n$schema: https://json-schema.org/draft/2020"
  },
  {
    "path": "docs/src/data/schemas/keybindings/prs.yaml",
    "chars": 1002,
    "preview": "# yaml-language-server: $schema=https://json-schema.org/draft/2020-12/schema\n$schema: https://json-schema.org/draft/2020"
  },
  {
    "path": "docs/src/data/schemas/layout/issue.yaml",
    "chars": 7470,
    "preview": "# yaml-language-server: $schema=https://json-schema.org/draft/2020-12/schema\n$schema: https://json-schema.org/draft/2020"
  },
  {
    "path": "docs/src/data/schemas/layout/options.yaml",
    "chars": 1763,
    "preview": "# yaml-language-server: $schema=https://json-schema.org/draft/2020-12/schema\n$schema: https://json-schema.org/draft/2020"
  },
  {
    "path": "docs/src/data/schemas/layout/pr.yaml",
    "chars": 10187,
    "preview": "# yaml-language-server: $schema=https://json-schema.org/draft/2020-12/schema\n$schema: https://json-schema.org/draft/2020"
  },
  {
    "path": "docs/src/data/schemas/pr-section.yaml",
    "chars": 3180,
    "preview": "# yaml-language-server: $schema=https://json-schema.org/draft/2020-12/schema\n$schema: https://json-schema.org/draft/2020"
  },
  {
    "path": "docs/src/data/schemas/theme.yaml",
    "chars": 21105,
    "preview": "# yaml-language-server: $schema=https://json-schema.org/draft/2020-12/schema\n$schema: https://json-schema.org/draft/2020"
  },
  {
    "path": "docs/src/data/sponsorshipGoal.ts",
    "chars": 1051,
    "preview": "const GH_TOKEN = import.meta.env.GH_TOKEN;\n\nexport const getSponsorshipGoal = async () => {\n  const query = `query { use"
  },
  {
    "path": "docs/src/data/stars.ts",
    "chars": 416,
    "preview": "const GH_TOKEN = import.meta.env.GH_TOKEN;\n\nexport const getStars = async () => {\n  const response = await fetch(\"https:"
  },
  {
    "path": "docs/src/fonts/font-face.css",
    "chars": 416,
    "preview": "@font-face {\n  font-family: \"MyFallbackFont\";\n  /* Courier New closely matches CommitMono */\n  src: local(\"Courier New\")"
  },
  {
    "path": "docs/src/pages/enhance.astro",
    "chars": 3667,
    "preview": "---\nimport StarlightPage from \"@astrojs/starlight/components/StarlightPage.astro\";\nimport \"../styles/index.css\";\nimport "
  },
  {
    "path": "docs/src/pages/index.astro",
    "chars": 6335,
    "preview": "---\nimport StarlightPage from \"@astrojs/starlight/components/StarlightPage.astro\";\nimport \"../styles/index.css\";\nimport "
  },
  {
    "path": "docs/src/pages/robots.txt.ts",
    "chars": 295,
    "preview": "import type { APIRoute } from \"astro\";\n\nconst getRobotsTxt = (sitemapURL: URL) => `\\\nUser-agent: *\nAllow: /\n\nSitemap: ${"
  },
  {
    "path": "docs/src/pages/schema/defaults.json.ts",
    "chars": 3192,
    "preview": "export function GET() {\n  return new Response(\n    JSON.stringify({\n      $schema: \"https://json-schema.org/draft/2020-1"
  },
  {
    "path": "docs/src/pages/schema/definitions/grow.json.ts",
    "chars": 321,
    "preview": "export function GET() {\n  return new Response(\n    JSON.stringify({\n      $schema: \"https://json-schema.org/draft/2020-1"
  },
  {
    "path": "docs/src/pages/schema/definitions/hexcolor.json.ts",
    "chars": 526,
    "preview": "export function GET() {\n  return new Response(\n    JSON.stringify({\n      $schema: \"https://json-schema.org/draft/2020-1"
  },
  {
    "path": "docs/src/pages/schema/issue-section.json.ts",
    "chars": 974,
    "preview": "export function GET() {\n  return new Response(\n    JSON.stringify({\n      $schema: \"https://json-schema.org/draft/2020-1"
  },
  {
    "path": "docs/src/pages/schema/keybindings/entry.json.ts",
    "chars": 1072,
    "preview": "export function GET() {\n  return new Response(\n    JSON.stringify({\n      $schema: \"https://json-schema.org/draft/2020-1"
  },
  {
    "path": "docs/src/pages/schema/keybindings/issues.json.ts",
    "chars": 340,
    "preview": "export function GET() {\n  return new Response(\n    JSON.stringify({\n      $schema: \"https://json-schema.org/draft/2020-1"
  },
  {
    "path": "docs/src/pages/schema/keybindings/prs.json.ts",
    "chars": 340,
    "preview": "export function GET() {\n  return new Response(\n    JSON.stringify({\n      $schema: \"https://json-schema.org/draft/2020-1"
  },
  {
    "path": "docs/src/pages/schema/layout/issue.json.ts",
    "chars": 3699,
    "preview": "export function GET() {\n  return new Response(\n    JSON.stringify({\n      $schema: \"https://json-schema.org/draft/2020-1"
  },
  {
    "path": "docs/src/pages/schema/layout/options.json.ts",
    "chars": 807,
    "preview": "export function GET() {\n  return new Response(\n    JSON.stringify({\n      $schema: \"https://json-schema.org/draft/2020-1"
  },
  {
    "path": "docs/src/pages/schema/layout/pr.json.ts",
    "chars": 4696,
    "preview": "export function GET() {\n  return new Response(\n    JSON.stringify({\n      $schema: \"https://json-schema.org/draft/2020-1"
  },
  {
    "path": "docs/src/pages/schema/pr-section.json.ts",
    "chars": 964,
    "preview": "// Outputs: /schema.json\nexport function GET() {\n  return new Response(\n    JSON.stringify({\n      $schema: \"https://jso"
  },
  {
    "path": "docs/src/pages/schema/theme.json.ts",
    "chars": 10640,
    "preview": "// Outputs: /schema.json\nexport function GET() {\n  return new Response(\n    JSON.stringify({\n      $schema: \"https://jso"
  },
  {
    "path": "docs/src/pages/schema.json.ts",
    "chars": 5341,
    "preview": "export function GET() {\n  return new Response(\n    JSON.stringify({\n      $schema: \"https://json-schema.org/draft/2020-1"
  },
  {
    "path": "docs/src/styles/custom.css",
    "chars": 6928,
    "preview": "@layer base, starlight, theme, components, utilities, my-overrides, my-overrides-index;\n\n@import \"@astrojs/starlight-tai"
  },
  {
    "path": "docs/src/styles/fade-images.css",
    "chars": 794,
    "preview": ".fadein {\n  position: relative;\n  height: 100%;\n}\n.fadein img {\n  position: absolute;\n  left: 0px;\n  top: 0px;\n  -webkit"
  },
  {
    "path": "docs/src/styles/index.css",
    "chars": 1241,
    "preview": "@import \"./custom.css\";\n\nhtml:not([data-has-sidebar]) {\n  --sl-content-width: 100%;\n}\n\n@media (width >= 64rem) {\n  :root"
  },
  {
    "path": "docs/src/styles/nerd-font.css",
    "chars": 60,
    "preview": "@import \"https://www.nerdfonts.com/assets/css/webfont.css\";\n"
  },
  {
    "path": "docs/src/styles/terminal.css",
    "chars": 974,
    "preview": ".terminal {\n  position: relative;\n  border: 1px solid var(--sl-color-gray-5);\n  display: flex;\n  flex-direction: column;"
  },
  {
    "path": "docs/tsconfig.json",
    "chars": 109,
    "preview": "{\n  \"extends\": \"astro/tsconfigs/strict\",\n  \"include\": [\".astro/types.d.ts\", \"**/*\"],\n  \"exclude\": [\"dist\"]\n}\n"
  },
  {
    "path": "gh-dash.go",
    "chars": 93,
    "preview": "package main\n\nimport (\n\t\"github.com/dlvhdr/gh-dash/v4/cmd\"\n)\n\nfunc main() {\n\tcmd.Execute()\n}\n"
  },
  {
    "path": "go.mod",
    "chars": 4676,
    "preview": "module github.com/dlvhdr/gh-dash/v4\n\ngo 1.25.8\n\nrequire (\n\tcharm.land/bubbles/v2 v2.0.0\n\tcharm.land/bubbletea/v2 v2.0.2\n"
  },
  {
    "path": "go.sum",
    "chars": 22510,
    "preview": "charm.land/bubbles/v2 v2.0.0 h1:tE3eK/pHjmtrDiRdoC9uGNLgpopOd8fjhEe31B/ai5s=\ncharm.land/bubbles/v2 v2.0.0/go.mod h1:rCHo"
  },
  {
    "path": "internal/config/feature_flags.go",
    "chars": 187,
    "preview": "package config\n\nimport \"os\"\n\nconst FF_REPO_VIEW = \"FF_REPO_VIEW\"\n\nconst FF_MOCK_DATA = \"FF_MOCK_DATA\"\n\nfunc IsFeatureEna"
  },
  {
    "path": "internal/config/parser.go",
    "chars": 22707,
    "preview": "package config\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"os\"\n\t\"path\"\n\t\"path/filepath\"\n\t\"reflect\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"string"
  },
  {
    "path": "internal/config/parser_test.go",
    "chars": 6210,
    "preview": "package config\n\nimport (\n\t\"os\"\n\t\"path\"\n\t\"runtime\"\n\t\"sort\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"charm.land/log/v2\"\n\t\"github.com/googl"
  },
  {
    "path": "internal/config/testdata/.gh-dash.yml",
    "chars": 467,
    "preview": "# yaml-language-server: $schema=https://dlvhdr.github.io/gh-dash/configuration/gh-dash/schema.json\nprSections:\n  - title"
  },
  {
    "path": "internal/config/testdata/ansi-color-config.yml",
    "chars": 339,
    "preview": "prSections:\n  - title: My Pull Requests\n    filters: is:open author:@me\n\ntheme:\n  colors:\n    text:\n      primary: \"12\"\n"
  },
  {
    "path": "internal/config/testdata/gh-dash/config.yml",
    "chars": 2197,
    "preview": "# yaml-language-server: $schema=https://gh-dash.dev/schema.json\nprSections:\n  - title: Mine\n    filters: is:open author:"
  },
  {
    "path": "internal/config/testdata/global-config.golden.yml",
    "chars": 3614,
    "preview": "prSections:\n  - title: Mine\n    filters:\n      is:open author:@me repo:dlvhdr/gh-dash updated:>={{ nowModify \"-3w\" }}\n  "
  },
  {
    "path": "internal/config/testdata/merged-config.golden.yml",
    "chars": 3212,
    "preview": "prSections:\n  - title: Mine\n    filters: is:open author:@me repo:dlvhdr/gh-dash\n    layout:\n      repo:\n        hidden: "
  },
  {
    "path": "internal/config/testdata/other-test-config.yml",
    "chars": 912,
    "preview": "# yaml-language-server: $schema=https://gh-dash.dev/schema.json\nprSections:\n  - title: Mine\n    filters: is:open author:"
  },
  {
    "path": "internal/config/testdata/test-config.yml",
    "chars": 2514,
    "preview": "# yaml-language-server: $schema=https://gh-dash.dev/schema.json\nprSections:\n  - title: Mine\n    filters: is:open author:"
  },
  {
    "path": "internal/config/utils.go",
    "chars": 1261,
    "preview": "package config\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"strings\"\n)\n\nfunc (cfg Config) GetFullScreenDiffPagerEnv() []string {\n\tdiff := cf"
  },
  {
    "path": "internal/data/assignee.go",
    "chars": 98,
    "preview": "package data\n\ntype Assignees struct {\n\tNodes []Assignee\n}\n\ntype Assignee struct {\n\tLogin string\n}\n"
  },
  {
    "path": "internal/data/bookmarks.go",
    "chars": 4601,
    "preview": "package data\n\nimport (\n\t\"encoding/json\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"sync\"\n\n\t\"charm.land/log/v2\"\n)\n\nconst (\n\tdefaultXDGState"
  },
  {
    "path": "internal/data/bookmarks_test.go",
    "chars": 7709,
    "preview": "package data\n\nimport (\n\t\"os\"\n\t\"path/filepath\"\n\t\"testing\"\n)\n\nfunc TestNotificationIDStore(t *testing.T) {\n\t// Create a te"
  },
  {
    "path": "internal/data/cache.go",
    "chars": 532,
    "preview": "package data\n\nimport (\n\t\"time\"\n\n\t\"github.com/maypok86/otter/v2\"\n)\n\ntype Cache struct {\n\t*otter.Cache[string, string]\n}\n\n"
  },
  {
    "path": "internal/data/commonapi.go",
    "chars": 1796,
    "preview": "package data\n\nimport (\n\t\"charm.land/log/v2\"\n\tgh \"github.com/cli/go-gh/v2/pkg/api\"\n\tgraphql \"github.com/cli/shurcooL-grap"
  },
  {
    "path": "internal/data/donestore.go",
    "chars": 4719,
    "preview": "package data\n\nimport (\n\t\"encoding/json\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"sync\"\n\t\"time\"\n\n\t\"charm.land/log/v2\"\n)\n\n// DoneStore per"
  },
  {
    "path": "internal/data/donestore_test.go",
    "chars": 10702,
    "preview": "package data\n\nimport (\n\t\"encoding/json\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"testing\"\n\t\"time\"\n)\n\nfunc TestDoneStore(t *testing.T) {\n"
  },
  {
    "path": "internal/data/donestore_testing.go",
    "chars": 616,
    "preview": "package data\n\nimport (\n\t\"time\"\n)\n\n// NewDoneStoreForTesting creates a DoneStore backed by the given file path.\nfunc NewD"
  },
  {
    "path": "internal/data/issueapi.go",
    "chars": 4042,
    "preview": "package data\n\nimport (\n\t\"fmt\"\n\t\"net/url\"\n\t\"time\"\n\n\t\"charm.land/log/v2\"\n\tgh \"github.com/cli/go-gh/v2/pkg/api\"\n\tgraphql \"g"
  },
  {
    "path": "internal/data/labelapi.go",
    "chars": 1757,
    "preview": "package data\n\nimport (\n\t\"encoding/json\"\n\t\"os/exec\"\n\t\"strings\"\n\t\"sync\"\n)\n\nvar (\n\trepoLabelCache = make(map[string][]Label"
  },
  {
    "path": "internal/data/notificationapi.go",
    "chars": 12854,
    "preview": "package data\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"time\"\n\n\t\"charm.land/log/v2\"\n\tgh \"github.com/cli/go-gh/v2/pkg/api\"\n)\n\n// Notif"
  },
  {
    "path": "internal/data/notificationapi_test.go",
    "chars": 6248,
    "preview": "package data\n\nimport (\n\t\"testing\"\n\t\"time\"\n)\n\nfunc TestFindBestWorkflowRunMatch(t *testing.T) {\n\tbaseTime := time.Date(20"
  },
  {
    "path": "internal/data/prapi.go",
    "chars": 13874,
    "preview": "package data\n\nimport (\n\t\"crypto/tls\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"time\"\n\n\t\"charm.land/log/v2\"\n\tgh \"github.com/cli/go-"
  },
  {
    "path": "internal/data/prapi_test.go",
    "chars": 1955,
    "preview": "package data\n\nimport (\n\t\"testing\"\n\n\tgh \"github.com/cli/go-gh/v2/pkg/api\"\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc "
  },
  {
    "path": "internal/data/repository.go",
    "chars": 557,
    "preview": "package data\n\nimport (\n\tgraphql \"github.com/cli/shurcooL-graphql\"\n)\n\ntype BranchProtectionRules struct {\n\tNodes []struct"
  },
  {
    "path": "internal/data/user.go",
    "chars": 329,
    "preview": "package data\n\nimport (\n\tgh \"github.com/cli/go-gh/v2/pkg/api\"\n)\n\nfunc CurrentLoginName() (string, error) {\n\tclient, err :"
  },
  {
    "path": "internal/data/utils.go",
    "chars": 1341,
    "preview": "package data\n\nimport (\n\t\"time\"\n\n\t\"charm.land/lipgloss/v2\"\n\t\"charm.land/lipgloss/v2/compat\"\n\n\t\"github.com/dlvhdr/gh-dash/"
  },
  {
    "path": "internal/git/git.go",
    "chars": 4500,
    "preview": "package git\n\nimport (\n\t\"bufio\"\n\t\"bytes\"\n\t\"errors\"\n\t\"fmt\"\n\t\"sort\"\n\t\"strings\"\n\t\"time\"\n\n\tgitm \"github.com/aymanbagabas/git-"
  },
  {
    "path": "internal/tui/common/diff.go",
    "chars": 575,
    "preview": "package common\n\nimport (\n\t\"fmt\"\n\t\"os/exec\"\n\n\ttea \"charm.land/bubbletea/v2\"\n\n\t\"github.com/dlvhdr/gh-dash/v4/internal/tui/"
  },
  {
    "path": "internal/tui/common/diff_test.go",
    "chars": 848,
    "preview": "package common\n\nimport (\n\t\"testing\"\n)\n\nfunc TestDiffPR(t *testing.T) {\n\ttests := []struct {\n\t\tname     string\n\t\tprNumber"
  },
  {
    "path": "internal/tui/common/labels.go",
    "chars": 1223,
    "preview": "package common\n\nimport (\n\t\"charm.land/lipgloss/v2\"\n\n\t\"github.com/dlvhdr/gh-dash/v4/internal/data\"\n)\n\nfunc RenderLabels(s"
  },
  {
    "path": "internal/tui/common/labels_test.go",
    "chars": 1919,
    "preview": "package common_test\n\nimport (\n\t\"testing\"\n\n\t\"charm.land/lipgloss/v2\"\n\t\"github.com/stretchr/testify/require\"\n\n\t\"github.com"
  },
  {
    "path": "internal/tui/common/repopath.go",
    "chars": 1850,
    "preview": "package common\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n)\n\n// GetRepoLocalPath returns the local path for a given repo name.\n// It wi"
  },
  {
    "path": "internal/tui/common/repopath_test.go",
    "chars": 2952,
    "preview": "package common_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n\n\t\"github.com/dlvhdr/gh-dash/v4/interna"
  },
  {
    "path": "internal/tui/common/styles.go",
    "chars": 3272,
    "preview": "package common\n\nimport (\n\t\"charm.land/lipgloss/v2\"\n\t\"charm.land/lipgloss/v2/compat\"\n\n\t\"github.com/dlvhdr/gh-dash/v4/inte"
  },
  {
    "path": "internal/tui/components/autocomplete/autocomplete.go",
    "chars": 9115,
    "preview": "package autocomplete\n\nimport (\n\t\"strings\"\n\t\"time\"\n\n\t\"charm.land/bubbles/v2/help\"\n\t\"charm.land/bubbles/v2/key\"\n\t\"charm.la"
  },
  {
    "path": "internal/tui/components/branch/branch.go",
    "chars": 7728,
    "preview": "package branch\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\n\t\"charm.land/lipgloss/v2\"\n\n\t\"github.com/dlvhdr/gh-dash/v4/internal/data\"\n\t\"g"
  },
  {
    "path": "internal/tui/components/branch/data.go",
    "chars": 712,
    "preview": "package branch\n\nimport (\n\t\"time\"\n\n\t\"github.com/dlvhdr/gh-dash/v4/internal/data\"\n\t\"github.com/dlvhdr/gh-dash/v4/internal/"
  },
  {
    "path": "internal/tui/components/branch/data_test.go",
    "chars": 1491,
    "preview": "package branch\n\nimport (\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/stretchr/testify/require\"\n\n\t\"github.com/dlvhdr/gh-dash/v4/inte"
  },
  {
    "path": "internal/tui/components/branch/utils.go",
    "chars": 239,
    "preview": "package branch\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n)\n\nfunc keepSameSpacesOnAddDeletions(str string) string {\n\tstrAsList := strin"
  },
  {
    "path": "internal/tui/components/branchsidebar/branchsidebar.go",
    "chars": 2135,
    "preview": "package branchsidebar\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\n\ttea \"charm.land/bubbletea/v2\"\n\t\"charm.land/lipgloss/v2\"\n\tgitm \"githu"
  },
  {
    "path": "internal/tui/components/branchsidebar/branchsidebar_test.go",
    "chars": 2059,
    "preview": "package branchsidebar\n\nimport (\n\t\"testing\"\n\n\tgitm \"github.com/aymanbagabas/git-module\"\n\t\"github.com/stretchr/testify/req"
  },
  {
    "path": "internal/tui/components/carousel/carousel.go",
    "chars": 9376,
    "preview": "package carousel\n\nimport (\n\t\"charm.land/bubbles/v2/key\"\n\ttea \"charm.land/bubbletea/v2\"\n\t\"charm.land/lipgloss/v2\"\n\t\"githu"
  },
  {
    "path": "internal/tui/components/common/interface.go",
    "chars": 193,
    "preview": "package common\n\nimport tea \"charm.land/bubbletea/v2\"\n\n// Model represents a common interface for UI components.\ntype Mod"
  },
  {
    "path": "internal/tui/components/footer/footer.go",
    "chars": 5403,
    "preview": "package footer\n\nimport (\n\t\"fmt\"\n\t\"path\"\n\t\"strings\"\n\n\tbbHelp \"charm.land/bubbles/v2/help\"\n\t\"charm.land/lipgloss/v2\"\n\t\"cha"
  },
  {
    "path": "internal/tui/components/inputbox/inputbox.go",
    "chars": 6249,
    "preview": "package inputbox\n\nimport (\n\t\"fmt\"\n\n\t\"charm.land/bubbles/v2/help\"\n\t\"charm.land/bubbles/v2/key\"\n\t\"charm.land/bubbles/v2/te"
  }
]

// ... and 94 more files (download for full content)

About this extraction

This page contains the full source code of the dlvhdr/gh-dash GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 294 files (3.9 MB), approximately 1.0M tokens, and a symbol index with 1381 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!