Skip to content

fix(welcome): gate CLI welcome buttons on actual availability - #200

Merged
Ark0N merged 2 commits into
Ark0N:masterfrom
timkjr:pr/gate-gemini-drop-tunnel-button
Aug 4, 2026
Merged

fix(welcome): gate CLI welcome buttons on actual availability#200
Ark0N merged 2 commits into
Ark0N:masterfrom
timkjr:pr/gate-gemini-drop-tunnel-button

Conversation

@timkjr

Copy link
Copy Markdown

Summary

  • Drops the always-visible Cloudflare Tunnel welcome button/QR widget — offering it regardless of whether cloudflared is installed is a bad default.
  • Gates the Claude, Opencode, and Gemini welcome-screen buttons behind a real availability check (/api/claude/status, /api/opencode/status, /api/gemini/status) instead of showing them unconditionally and letting the click fail.
  • Adds isClaudeAvailable()/GET /api/claude/status, mirroring the existing opencode/codex/gemini CLI resolvers — Claude previously had no availability check at all.
  • Refactors the availability-check JS into a shared _loadCliAvailability(buttonId, statusUrl) helper instead of duplicating the fetch/try-catch per tool.

Run-mode dropdown entries (Opencode/Codex) are intentionally left unconditional here — same class of issue, but a separate follow-up to keep this PR small.

Test plan

  • tsc --noEmit clean
  • eslint clean on touched .ts files
  • check:frontend-syntax and check:public-assets pass
  • Verified /api/claude/status, /api/opencode/status, /api/gemini/status via curl against a throwaway dev server
  • Verified welcome-screen button visibility via Playwright: Claude/Opencode buttons visible (installed locally), Gemini button hidden (not installed), no console errors

timkjr pushed a commit to timkjr/Codeman that referenced this pull request Aug 2, 2026
Follow-up to the welcome-screen gating (Ark0N#200): the run-mode dropdown
(gear menu next to Run) had the same problem — Claude/Opencode/Codex/
Gemini entries were always shown regardless of whether the CLI is
actually installed, so picking one could spawn a session that
immediately errors out.
- Add _refreshRunModeAvailability() (session-ui.js), called each time
the dropdown opens; hides entries whose /api/<cli>/status reports
unavailable.
- Shell is intentionally never gated (no external CLI dependency).
Depends on isClaudeAvailable()/GET /api/claude/status, which don't
exist on upstream/master yet — duplicated here from Ark0N#200 so this PR
is self-contained and independently mergeable. Once Ark0N#200 lands this
branch should be rebased onto master, which will collapse the
duplicate cleanly.
timkjr pushed a commit to timkjr/Codeman that referenced this pull request Aug 4, 2026
Follow-up to the welcome-screen gating (Ark0N#200): the run-mode dropdown
(gear menu next to Run) had the same problem — Claude/Opencode/Codex/
Gemini entries were always shown regardless of whether the CLI is
actually installed, so picking one could spawn a session that
immediately errors out.
- Add _refreshRunModeAvailability() (session-ui.js), called each time
the dropdown opens; hides entries whose /api/<cli>/status reports
unavailable.
- Shell is intentionally never gated (no external CLI dependency).
Depends on isClaudeAvailable()/GET /api/claude/status, which don't
exist on upstream/master yet — duplicated here from Ark0N#200 so this PR
is self-contained and independently mergeable. Once Ark0N#200 lands this
branch should be rebased onto master, which will collapse the
duplicate cleanly.
timkjr added 2 commits August 4, 2026 16:21
…tunnel button
- Remove the always-visible Cloudflare Tunnel welcome button and QR
widget; offering it regardless of whether cloudflared is installed
is a bad default.
- Hide the "Run Gemini" welcome button by default and only show it
when /api/gemini/status reports available:true, via new
loadGeminiAvailability() called from showWelcome().
Extends the Gemini gating from bb7fb9e to the other welcome-screen
buttons that had the same problem: shown unconditionally even when the
underlying CLI isn't installed.
- Add isClaudeAvailable() (claude-cli-resolver.ts) and GET
/api/claude/status, mirroring the existing opencode/codex/gemini
resolvers and status endpoints.
- Opencode already had a working /api/opencode/status the welcome
screen just wasn't checking; wire it up the same way.
- Refactor loadGeminiAvailability() into a shared
_loadCliAvailability(buttonId, statusUrl) helper instead of
duplicating the fetch/try-catch three times.
Run-mode dropdown entries (Opencode/Codex) are intentionally left
unconditional here — follow-up PR.
@timkjr
timkjrforce-pushed the pr/gate-gemini-drop-tunnel-button branch from 7be7f55 to 3ea1ea2CompareAugust 4, 2026 21:23
@Ark0N
Ark0N merged commit b54094a into Ark0N:masterAug 4, 2026
Ark0N pushed a commit that referenced this pull request Aug 4, 2026
…over antigravity
Follow-up to #200 and #201, which gate the welcome buttons and the run-mode
dropdown on whether the CLI is actually installed. Four corrections:
1. #200 also DELETED the Cloudflare Tunnel welcome button and the QR widget
outright. Its rationale is right (offering a tunnel where cloudflared is not
installed is a bad default) but the conclusion overshoots: the welcome QR is
the whole scan-to-connect-from-your-phone flow, and deleting it left a large
block of live tunnel code in settings-ui.js driving elements that no longer
existed. Both are restored and the button is gated on cloudflared, which is
what the stated rationale actually asks for. New cloudflared-resolver.ts
mirrors the CLI resolvers, and TunnelManager now shares its search path so
the button and the spawn can never disagree about where cloudflared lives.
2. Antigravity was missing from the run-mode gating, the one run mode LEAST
likely to be installed. It slipped past because #201 predates it. Covered
now, plus a static test that fails if a sixth mode reaches the dropdown
without being gated, so the next one cannot slip the same way.
3. The per-surface fetches are replaced by the injected availability object
already used for the Codex settings tab, so the codebase has one mechanism
rather than two. The status routes buy nothing as a gating source: every
resolver memoizes its PATH probe server-side, so a fetch is exactly as stale
as an injected value while costing a round trip every time the dropdown opens
and leaving the welcome buttons to flicker in after paint. The routes
themselves stay, including the /api/claude/status that #200 adds.
4. Unknown availability now reads as AVAILABLE for run buttons. Both PRs hid the
button on a failed fetch, so a blip left a working install with nothing to
click; a genuinely missing CLI only ever produced an error toast. The Codex
settings TAB keeps the opposite default, since hiding it costs nothing.
The dropdown query is also scoped to the menu: `.run-mode-option` is the class
the saved-dashboard and history rows use too, and a document-wide querySelector
would have found whichever came first in the DOM.
Fixes a latent environment-sensitivity in 816d900 while here: the index-title
test asserted the template was untouched apart from the title, which held only
on a machine with no codex installed.
Verified end-to-end against a real server on an isolated instance+socket, with
Playwright: gemini/codex hidden and claude/opencode/antigravity/shell shown,
matching this host, tunnel button back, Codex settings tab still hidden, no
console errors. Full test:ci sweep green (3902 tests).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@Ark0N

Ark0N commented Aug 4, 2026

Copy link
Copy Markdown
Owner

Merged, thank you! Gating these is right, and adding isClaudeAvailable() / GET /api/claude/status closes a genuine gap: Claude was the one CLI with no availability check at all, despite being the default. The shared _loadCliAvailability helper was the right instinct too.

Follow-up in 5d28999 with three changes.

The Cloudflare Tunnel button and QR widget are back, gated instead of deleted. Your rationale is right, offering a tunnel where cloudflared is not installed is a bad default, but the conclusion overshoots: the welcome QR is the entire scan-to-connect-from-your-phone flow, and removing the markup left a large block of live tunnel code in settings-ui.js (_updateWelcomeTunnelBtn, toggleWelcomeQrSize, the SSE QR-rotation handlers) driving elements that no longer existed. Gating it on cloudflared is what the stated rationale actually asks for, and it keeps the feature for people who have it. New cloudflared-resolver.ts mirrors the CLI resolvers, and TunnelManager now shares its search path so the button and the spawn cannot disagree about where cloudflared lives.

Availability now comes from an injected object rather than a fetch per surface. Master already had this pattern from the Codex settings tab (816d900), and two mechanisms for one question is one too many. The status routes buy nothing as a gating source: every resolver memoizes its PATH probe server-side, so a fetch is exactly as stale as an injected value, while costing a round trip and leaving the buttons to flicker in after paint. The routes all stay, yours included, they are a fine API surface.

Unknown availability now reads as available. The catch hid the button on a failed fetch, so a transient blip left a working install with no run buttons at all, whereas a genuinely missing CLI only ever produced an error toast. Failing open is the cheaper mistake here. (The Codex settings tab keeps the opposite default, since hiding a tab costs a user nothing.)

Verified with Playwright against a real server: on this host Gemini is hidden and Claude/OpenCode/tunnel show, matching what is actually installed.

Thanks again, both of these were worth doing.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@timkjr@Ark0N