Skip to content

feat(context): restore the last used cluster on startup - #1467

Open
arlenvasconcelos wants to merge 1 commit into
skyhook-io:mainfrom
arlenvasconcelos:restore-last-used-cluster
Open

feat(context): restore the last used cluster on startup#1467
arlenvasconcelos wants to merge 1 commit into
skyhook-io:mainfrom
arlenvasconcelos:restore-last-used-cluster

Conversation

@arlenvasconcelos

@arlenvasconcelos arlenvasconcelos commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Description

Radar starts on the cluster you were last working in instead of the kubeconfig's current-context. Every context switch is recorded in ~/.radar/settings.json and restored on the next start; an unresolvable memory is ignored so a stale pick can never keep Radar from starting.

The record carries the kubeconfig file the context came from, not just its name. With several kubeconfigs loaded, two files can define the same context name and which one keeps the unqualified form depends on directory read order — matching by name alone would let a newly added file silently redirect the restore to a different cluster. Resolution matches the file first and falls back to the name only when that file has moved.

Adds --context (and "context" in config.json) to choose the startup cluster explicitly; it wins over the memory and, once the cluster answers, becomes the remembered pick. "restoreLastContext": false turns the memory off and always starts on current-context.

Nothing is recorded, restored, or served over /api/settings when auth is enabled or when serving through a cloud tunnel — there the kubeconfig context is shared state and one user's switch must not steer everyone else's next start. CAPI workload clusters are never remembered: their kubeconfig is a temp file that no longer exists on the next run.

settings.Update now refuses to write over a settings file it could not read. Context switches call it automatically, so a single unreadable file would otherwise erase every other preference on the next switch.

Type of change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

How has this been tested?

Describe the tests you ran to verify your changes.

  • Tested locally with minikube/kind
  • Tested against a remote cluster
  • Added/updated unit tests

Checklist

  • My code follows the project's coding standards
  • I have performed a self-review of my code
  • I have added comments where necessary
  • My changes generate no new warnings
  • Any dependent changes have been merged

Related issues

Fixes #1454


Note

Medium Risk
Changes which Kubernetes cluster Radar connects to on startup and writes that pick to disk. Shared/auth/cloud paths are gated so one user’s switch cannot steer others, but a bad restore could still point a local session at the wrong cluster until they switch.

Overview
Radar now starts on the cluster you last used instead of the kubeconfig current-context. Each UI context switch is written to ~/.radar/settings.json as lastContext (name plus source file) so a later start reconnects there.

--context (and config.json "context") wins over memory and, once the cluster answers, becomes the remembered pick. "restoreLastContext": false always starts on current-context and stops recording switches. Stale or unknown names fall back to current-context; CAPI temp kubeconfigs are never remembered.

Memory is local single-user only: auth-enabled and cloud-tunnel instances neither persist nor restore, and GET /api/settings strips lastContext. settings.Update now refuses to overwrite an unreadable settings file so a context switch cannot wipe other preferences.

Reviewed by Cursor Bugbot for commit a0091af. Bugbot is set up for automated code reviews on this repo. Configure here.

Radar starts on the cluster you were last working in instead of the
kubeconfig's current-context. Every context switch is recorded in
~/.radar/settings.json and restored on the next start; an unresolvable
memory is ignored so a stale pick can never keep Radar from starting.

The record carries the kubeconfig file the context came from, not just
its name. With several kubeconfigs loaded, two files can define the same
context name and which one keeps the unqualified form depends on
directory read order — matching by name alone would let a newly added
file silently redirect the restore to a different cluster. Resolution
matches the file first and falls back to the name only when that file
has moved.

Adds --context (and "context" in config.json) to choose the startup
cluster explicitly; it wins over the memory and, once the cluster
answers, becomes the remembered pick. "restoreLastContext": false turns
the memory off and always starts on current-context.

Nothing is recorded, restored, or served over /api/settings when auth is
enabled or when serving through a cloud tunnel — there the kubeconfig
context is shared state and one user's switch must not steer everyone
else's next start. CAPI workload clusters are never remembered: their
kubeconfig is a temp file that no longer exists on the next run.

settings.Update now refuses to write over a settings file it could not
read. Context switches call it automatically, so a single unreadable
file would otherwise erase every other preference on the next switch.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit a0091af. Configure here.

Comment thread internal/server/server.go
// viewer the operator's cluster name from whenever this $HOME last ran
// Radar locally.
loaded.LastContext = nil
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Settings PUT leaks last context

Medium Severity

handleGetSettings clears lastContext when auth or cloud mode is on, but handlePutSettings returns the full updated settings—including lastContext—without the same strip. A theme or pinned-kinds save on a shared instance therefore exposes the operator’s previously remembered cluster name in the response body, contrary to the privacy rule this change documents.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit a0091af. Configure here.

if name != "" && name == contextName && kubeconfigPath != "" {
return ContextRef{Name: name, SourceFile: kubeconfigPath, InFileName: name}
}
return ContextRef{Name: name}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Source file omitted for single dir

Medium Severity

ContextSourceFor only attaches sourceFile from the multi-file registry or from kubeconfigPath. When --kubeconfig-dir discovers exactly one file, init leaves the registry unset and never sets kubeconfigPath, so the remembered pick is stored as a bare name. A later-added kubeconfig that reuses that name can then silently restore a different cluster—the failure mode this feature set out to prevent.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit a0091af. Configure here.

@nadaverell nadaverell left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this I guess makes sense for desktop but may be counter intuitive for CLI-driven radar (or 'kubectl radar', or --diagnose invocations), where it is probably more expected to respect the kubectl context.

Posting a more detailed AI-assisted review in a sec but I think the change should be limited to desktop, maybe with a setting that users can opt in/out of this (choose between remembering last context and defaulting to current kubeconfig context). Claude/codex found a couple more things to note on handling deleted context etc.

@nadaverell

Copy link
Copy Markdown
Contributor

AI-assisted product review for consideration. This was generated by Codex, independently cross-reviewed by Claude, and then triaged rather than accepted wholesale. Please use your own judgment—there is no expectation to automatically accept every suggestion below. This review is about the product behavior and user expectations, not code correctness.

The premise from #1454 is right: the Desktop app should reopen on the cluster the user was last working in. That is the natural behavior for a stateful GUI launched from the Dock, and the PR has made several thoughtful choices around recording only successful switches, surviving force-quits, avoiding CAPI temporary kubeconfigs, and not rewriting kubeconfig.

The main concern is scope. The same remembered state currently also changes the default for kubectl radar, radar, and radar diagnose --standalone. For a kubectl plugin or terminal-driven diagnostic, the expected contract is different: an explicit --context should win, otherwise the kubeconfig's current-context should win. With the proposed behavior, kubectl config use-context staging && kubectl radar can instead open a cluster selected in Radar days earlier. Since Radar includes mutating actions such as apply, scale, restart, drain, rollback, and sync, landing on an unexpected cluster is a safety problem rather than merely a small surprise.

Suggested product shape for consideration:

  1. Remember by default in Desktop only. cmd/desktop should restore its last successfully selected cluster. kubectl radar, the radar CLI launch, and diagnose --standalone should remain deterministic on kubeconfig current-context unless the user explicitly opts the CLI into remembered behavior. Keep the remembered value Desktop-scoped, or otherwise enforce a hard separation so a Desktop switch cannot steer a later terminal command.

  2. Make explicit targeting strict and non-persistent. --context should affect that invocation only. An unknown context should exit with a clear error (ideally with close matches), not silently connect to current-context and remember the fallback. Keep "context" in config.json as a useful durable pin: while set, always start there, but do not use it to overwrite remembered Desktop state.

  3. Do not guess when remembered identity is ambiguous. Restore only when Radar can establish that it found the same context/cluster. If the saved source is gone or identity cannot be established, open kubeconfig current-context and explain the fallback. A same-named context from another file is not sufficient evidence because connecting to the wrong cluster is worse than losing the convenience.

  4. Handle missing and unreachable memories differently. Missing/renamed/ambiguous memory can safely fall back to current-context with visible notice. If the exact remembered cluster still exists but is unreachable (for example, VPN is down), keep the current fail-loud behavior rather than silently redirecting; explain that Radar reopened the last-used cluster and offer the context switcher.

  5. Make the changed startup behavior legible. At minimum, surface exceptional fallback and restored-but-unreachable states in the UI rather than only logs. A small one-time notice on the first successful restore after this feature ships (for example, “Reopened on prod-eu — where you left off”) would teach the new behavior; it should not become recurring toast noise. If an opt-out remains, expose “Startup cluster: Last used / kubeconfig current context” in the Desktop Connection settings rather than requiring Desktop users to edit JSON. Turning remembrance off should clear/reset the latent selection instead of reviving a months-old value when re-enabled.

  6. Apply the single-user rule consistently. In addition to auth and Cloud modes, a deliberately non-loopback/shared listener should not persist or expose one viewer's remembered cluster.

I don't think this necessarily needs to be split into multiple PRs—the important split is in the product semantics, not the contribution process. The concise target is: stateful Desktop, deterministic CLI, strict explicit overrides, and no silent wrong-cluster guesses.

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.

Restore app from the last cluster used

2 participants