gastownhall/beads · error

gh CLI not found: install from https://cli.github.com

Error message

gh CLI not found: install from https://cli.github.com

What it means

queryGitHubRunsForWorkflowInRepo shells out to the GitHub `gh` CLI; before doing so it runs exec.LookPath("gh"). If no `gh` executable exists on PATH, gate checks that query workflow runs cannot proceed and this error is returned, pointing to the official install page.

Source

Thrown at cmd/bd/gate.go:945

	if repo == "" {
		return nil, nil
	}
	metadata, err := json.Marshal(map[string]string{"repo": repo})
	if err != nil {
		return nil, err
	}
	return metadata, nil
}

// queryGitHubRunsForWorkflow queries recent runs for a specific workflow using gh CLI.
// Returns runs sorted newest-first (GitHub API default).
func queryGitHubRunsForWorkflow(workflow string, limit int) ([]GHWorkflowRun, error) {
	return queryGitHubRunsForWorkflowInRepo(workflow, limit, "")
}

func queryGitHubRunsForWorkflowInRepo(workflow string, limit int, repo string) ([]GHWorkflowRun, error) {
	if _, err := exec.LookPath("gh"); err != nil {
		return nil, fmt.Errorf("gh CLI not found: install from https://cli.github.com")
	}
	return queryGitHubRunsForWorkflowInRepoWithRunner(workflow, limit, repo, runGHCommand)
}

func queryGitHubRunsForWorkflowInRepoWithRunner(workflow string, limit int, repo string, runGH ghCommandRunner) ([]GHWorkflowRun, error) {
	args := []string{
		"run", "list",
		"--workflow", workflow,
		"--json", "databaseId,name,status,conclusion,createdAt,workflowName",
		"--limit", fmt.Sprintf("%d", limit),
	}
	if repo != "" {
		args = append(args, "--repo", repo)
	}

	output, stderr, err := runGH(args...)
	if err != nil {
		if len(stderr) > 0 {

View on GitHub (pinned to 71377f2769)

Solutions

  1. Install gh CLI (https://cli.github.com): e.g. `brew install gh` or apt/dnf per the docs.
  2. Ensure the binary is on PATH for the user running bd: verify with `which gh`; adjust PATH in CI or service environments.
  3. In containers, add gh installation to the image build instead of runtime.
  4. Alternatively, provide a runner injection (ghCommandRunner) in tests/custom tooling so a real gh lookup is not required.

Example fix

// before (CI step without gh)
- run: bd doctor
// after
- run: |
    type -p gh >/dev/null || (curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg && sudo apt install gh)
- run: bd doctor
Defensive patterns

Strategy: fallback

Validate before calling

if _, err := exec.LookPath("gh"); err != nil {
    // skip GH gate checks or print install guidance instead of failing hard
    return nil // or fmt.Errorf("gh required for gate checks: %w", err)
}

Try / catch

runs, err := queryGitHubRunsForWorkflow("ci.yml", 5)
if err != nil {
    if strings.Contains(err.Error(), "gh CLI not found") {
        log.Printf("skipping GitHub gate checks: %v", err)
        return nil
    }
    return err
}

Prevention

When it happens

Trigger: Any flow calling queryGitHubRunsForWorkflow / queryGitHubRunsForWorkflowInRepo (e.g. CI-gate checks matching beads gates to GH Actions runs) on a machine where gh is not installed or not on PATH.

Common situations: Fresh CI containers without gh installed; PATH differences between user shell and service accounts; gh installed via GUI but not symlinked into PATH; restricted environments (minimal Docker images).

Related errors


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/e50fefa920aa138c. Report an issue: GitHub.