Doctor command gh auth check without GITHUB_TOKEN
NousResearch/hermes-agent · cluster 16115
Data as of
Nothing open on GitHub. Fix merged in #19868. Check it covers your case.
The short answer
0open issues
0open PRs
5items grouped
- Known?
- Yes. 5 related items grouped here, 1 issue already closed.
- Fix event
- A fix was merged to main in PR #19868. Check it covers your case. No release data is tracked.
- Tracker
- The maintainers' tracker marks this
unresolved. That is separate from the fix event. - Still open
- Nothing open on GitHub.
These issues and PRs address the doctor command's handling of GitHub authentication when GITHUB_TOKEN is not set, adding a fallback check of gh CLI auth status. One entry also mentions skipping a minimax China models check.
Open issues0
Open PRs0
Fixes on record
-
#19868 fix(doctor): check gh auth status when GITHUB_TOKEN absent
files:
hermes_cli/doctor.py,tests/hermes_cli/test_doctor.pyShow the diff
-
hermes_cli/doctor.py@@ -1264,9 +1264,23 @@ def run_doctor(args): check_warn("Skills Hub directory not initialized", "(run: hermes skills list)") from hermes_cli.config import get_env_value + + def _gh_authenticated() -> bool: + """Check if gh CLI is authenticated via token file or device flow.""" + try: + result = subprocess.run( + ["gh", "auth", "status", "--json", "authenticated"], + capture_output=True, timeout=10, + ) + return result.returncode == 0 + except (FileNotFoundError, subprocess.TimeoutExpired): + return False + github_token = [redacted:secret-assignment]"GITHUB_TOKEN") or get_env_value("GH_TOKEN") if github_token: [redacted:secret-assignment]"GitHub token configured (authenticated API access)") + elif _gh_authenticated(): + check_ok("GitHub authenticated via gh CLI", "(full API access — no GITHUB_TOKEN needed)") else: check_warn("No GITHUB_TOKEN", f"(60 req/hr rate limit — set in {_DHH}/.env for better rates)") -
tests/hermes_cli/test_doctor.py@@ -663,3 +663,79 @@ def fake_get(url, headers=None, timeout=None): ) assert not any(url == "https://opencode.ai/zen/go/v1/models" for url, _, _ in calls) assert not any("opencode" in url.lower() and "models" in url.lower() for url, _, _ in calls) + + +class TestGitHubTokenCheck: + """Tests for GitHub token / gh auth detection in doctor.""" + + def test_no_token_and_not_gh_authenticated_shows_warn(self, monkeypatch, tmp_path): + home = tmp_path / ".hermes" + home.mkdir(parents=True, exist_ok=True) + monkeypatch.setenv("HERMES_HOME", str(home)) + monkeypatch.setenv("PATH", "/nonexistent") # gh not found + + from hermes_cli.doctor import run_doctor, _DHH + import io, contextlib + + buf = io.StringIO() + with contextlib.redirect_stdout(buf): + run_doctor(Namespace(fix=False)) + out = buf.getvalue() + + assert "No GITHUB_TOKEN" in out + assert "60 req/hr" in out + + def test_token_env_present_shows_ok(self, monkeypatch, tmp_path): + home = tmp_path / ".hermes" + home.mkdir(parents=True, exist_ok=True) + monkeypatch.setenv("HERMES_HOME", str(home)) + monkeypatch.setenv("GITHUB_TOKEN", "ghp_test123") + monkeypatch.setenv("PATH", "/nonexistent") # gh not found + + from hermes_cli.doctor import run_doctor + import io, contextlib + + buf = io.StringIO() + with contextlib.redirect_stdout(buf): + run_doctor(Namespace(fix=False)) + out = buf.getvalue() + + assert "GitHub token configured" in out + + def test_gh_authenticated_without_env_token_shows_ok(self, monkeypatch, tmp_path): + home = tmp_path / ".hermes" + home.mkdir(parents=True, exist_ok=True) + monkeypatch.setenv("HERMES_HOME", str(home)) + # No GITHUB_TOKEN or GH_TOKEN + monkeypatch.delenv("GITHUB_TOKEN", raising=False) + monkeypatch.delenv("GH_TOKEN", raising=False) + + # Mock gh to return success + import shutil + real_which = shutil.which + def mock_which(cmd): + return "/usr/local/bin/gh" if cmd == "gh" else real_which(cmd) + monkeypatch.setattr(shutil, "which", mock_which) + + call_log = [] + def mock_run(cmd, **kwargs): + call_log.append(cmd) + if cmd[:2] == ["gh", "auth"]: + result = types.SimpleNamespace(returncode=0, stdout="", stderr="") + else: + result = types.SimpleNamespace(returncode=1, stdout="", stderr="") + return result + + import subprocess + monkeypatch.setattr(subprocess, "run", mock_run) + + from hermes_cli.doctor import run_doctor + import io, contextlib + + buf = io.StringIO() + with contextlib.redirect_stdout(buf): + run_doctor(Namespace(fix=False)) + out = buf.getvalue() + + assert "gh auth" in str(call_log) or any(c[0] == "gh" for c in call_log), f"gh not called: {call_log}" + assert "GitHub authenticated via gh CLI" in out or "token configured" in out
-
3 PRs closed without merging
From the close comments: merged via another change 1 · other 2
-
#16121 fix(doctor): check gh auth status when GITHUB_TOKEN is absent · other →
#16127 -
#16130 fix(doctor): check gh auth status when GITHUB_TOKEN absent; skip minimax China models check · other →
#12800,#12768,#13757,#16115 -
#16132 fix(doctor): check gh auth status when GITHUB_TOKEN absent · merged via another change →
#19868
Closed issues · 1
- Closed#16115doctor warns missing GITHUB_TOKEN when gh CLI is authenticated
How this cluster was grouped
-
Link evidence (
structural links throughout): every member is connected by structural evidence: shared changed files, or a closing/superseded reference. -
Pairwise link density
0.40: the share of item pairs that carry a link, counting a structural link in full and a relevance-only link at 0.36.1.00means every pair is linked.
Pick up a Lab task
Check whether a fix covers the open issues here, with your own agent. Bring back evidence for maintainers.
Open the LabAt a glance
- Merged PRs
- #19868
- Closed issues
- 1
- Attempts
- 3 PRs closed without merging
- Fix link checked
- 4 May 2026