Skip to content

Browser tab title: '<hostname> ccserver' - #40

Merged
nananek merged 1 commit into
masterfrom
fix/browser-tab-title
Aug 11, 2026
Merged

Browser tab title: '<hostname> ccserver'#40
nananek merged 1 commit into
masterfrom
fix/browser-tab-title

Conversation

@nananek

@nananek nananek commented Aug 11, 2026

Copy link
Copy Markdown
Owner

The browser tab title was the static Claude Code (hardcoded in client/index.html); this makes it <hostname> ccserver (e.g. ayaka ccserver).

Root cause

client/index.html:7 had <title>Claude Code</title> and nothing in the client ever rewrites document.title — the title was purely the static HTML, unrelated to the agent CLIs (they run inside xterm.js and never touch the document title).

Changes

  • server/ws/notify.js: exported resolvedHostname() — the existing attribution precedence CCSERVER_HOSTNAME > notify.hostname > os.hostname() extracted so non-notify consumers share it; loadNotifyConfig() now uses it (behavior unchanged).
  • server/routes/dirs.js: GET /api/dirs/home now also returns hostname (additive field, backward compatible; the client already fetches this endpoint on mount).
  • client/src/App.jsx: on mount, fetches /api/dirs/home and sets document.title = \${hostname} ccserver``. Idempotent (StrictMode-safe), silent on failure — the static fallback stays.
  • client/index.html: static fallback title changed to ccserver (covers pre-JS / API-unreachable, e.g. token auth gate; no longer shows the misleading Claude Code).

Server-side HTML rewriting was deliberately not used: it would only work in production (vite serves index.html in dev), while the fetch-based approach works in both.

Tests

  • server/ws/notify.test.js: +1 precedence test for resolvedHostname() (env > notify.hostname > os.hostname()).
  • tests/tab-title.spec.js (new): e2e asserts page.title() matches /^\S+ ccserver$/ against the production build — verified passing locally (ayaka ccserver).
  • npm test: 303 tests, 302 pass; the single failure (sandbox-resolve.test.js) is the known pre-existing environment-dependent failure.

Out of scope: per-session/per-group dynamic titles.

The <title>Claude Code</title> in client/index.html was the sole source of
the tab title. Replace it with '<hostname> ccserver', resolving the
hostname server-side with the same precedence as the notify footer's
_from: <host> (CCSERVER_HOSTNAME > notify.hostname > os.hostname()) so
the tab matches what notifications claim to come from.

- notify.js: export resolvedHostname() (refactored out of
  loadNotifyConfig, single resolution point).
- routes/dirs.js: GET /dirs/home gains a hostname field (extra field,
  backward compatible); the client already fetches this endpoint on
  mount.
- client/src/App.jsx: mount-time useEffect sets document.title =
  '<hostname> ccserver' (silent on failure, idempotent under StrictMode).
- client/index.html: static fallback title is now 'ccserver' (never
  'Claude Code').

Tests: resolvedHostname precedence unit test (env > config > os.hostname)
and e2e tests/tab-title.spec.js asserting toHaveTitle(/^\S+ ccserver$/),
which also covers the production-build delivery path.
@nananek
nananek merged commit fbe6530 into master Aug 11, 2026
4 checks passed
Sign up for free to 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.

1 participant