Skip to content

feat(desktop): add settings for shared web/desktop history#1161

Closed
glopyglerky wants to merge 5 commits intopingdotgg:mainfrom
glopyglerky:feat/shared-history-settings
Closed

feat(desktop): add settings for shared web/desktop history#1161
glopyglerky wants to merge 5 commits intopingdotgg:mainfrom
glopyglerky:feat/shared-history-settings

Conversation

@glopyglerky
Copy link

@glopyglerky glopyglerky commented Mar 17, 2026

What Changed

  • adds a first-class Settings -> Shared History flow for desktop
  • persists desktop shared-history settings in a small local settings file
  • keeps environment-variable overrides authoritative when T3CODE_DESKTOP_REMOTE_URL or T3CODE_DESKTOP_REMOTE_AUTH_TOKEN are set
  • prevents desktop from silently falling back to a second persistent local backend in remote mode
  • updates the shared Settings route so the browser shows the same shared-history concept and current endpoint as guidance
  • documents the workflow in README.md and REMOTE.md

Why

The remote/shared-history setup already works well when desktop and web both point at one server-backed history source, but the old env-only flow is hard to discover and awkward to manage day to day.

This keeps the same underlying behavior while making it easier to configure safely:

  • one remote source of truth for history
  • explicit precedence when env vars are present
  • no silent fallback to a second persistent local history store

UI Changes

  • Added a Shared History card to Settings.
  • Desktop can switch between local and remote mode, edit the same server endpoint the web UI already uses, then save and restart.
  • Browser shows the same section and the current endpoint without implying it can mutate a desktop process.

Validation

  • bun run --cwd packages/contracts typecheck
  • bun run --cwd apps/desktop test
  • bun run --cwd apps/desktop typecheck
  • bun run --cwd apps/web typecheck
  • bunx vitest run apps/web/src/connection.test.ts
  • bunx vitest run apps/desktop/src/remoteConnection.test.ts apps/desktop/src/desktopConnectionSettings.test.ts
  • bun run build:desktop

Notes

  • bun run --cwd apps/web test still fails in this checkout because of an existing unrelated harness issue in src/terminalStateStore.test.ts (localStorage.clear is not a function).

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes
  • I included a video for animation/interaction changes

This is my first GitHub PR. I'm a big fan of the team and the product, and this was built with T3 Code.

Note

Add shared web/desktop history settings to connect the desktop app to a remote server

  • Adds a remote connection mode to the desktop app that uses a configured server URL as the WebSocket backend instead of starting a local backend process.
  • Introduces desktopConnectionSettings.ts and remoteConnection.ts to persist, normalize, and validate remote connection settings, with atomic writes at user-only permissions.
  • Extends the desktop settings UI in _chat.settings.tsx to let users switch between local and remote modes, edit the server URL and auth token, and restart the app to apply changes.
  • Exposes getConnectionSettings, setConnectionSettings, and relaunch on the DesktopBridge IPC interface so the renderer can manage connection settings and trigger relaunches.
  • Centralizes WebSocket URL and HTTP origin resolution into connection.ts, replacing duplicated inline logic in Sidebar, store.ts, and wsTransport.ts.
  • Risk: when in remote mode, no local backend is started and there is no fallback to local history if the remote server is unreachable.

Macroscope summarized ca9e71a.

@coderabbitai
Copy link

coderabbitai bot commented Mar 17, 2026

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 42f6ac0e-2c0d-4b88-8d15-7405b84b951d

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Tip

CodeRabbit can suggest fixes for GitHub Check annotations.

Configure the reviews.tools.github-checks setting to adjust the time to wait for GitHub Checks to complete.

@github-actions github-actions bot added size:XXL 1,000+ changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list. labels Mar 17, 2026

export function resolveRuntimeWsUrl(explicitUrl?: string): string {
if (typeof window === "undefined") {
return explicitUrl ?? "ws://localhost:3773";
Copy link
Contributor

Choose a reason for hiding this comment

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

🟢 Low src/connection.ts:43

When resolveRuntimeWsUrl is called with an empty string explicitUrl in an SSR context (typeof window === "undefined"), the ?? operator returns "" instead of falling back to "ws://localhost:3773". This is inconsistent with the browser path, where asNonEmptyString treats empty strings as falsy. Consider using asNonEmptyString(explicitUrl) ?? "ws://localhost:3773" to align the two paths.

-    return explicitUrl ?? "ws://localhost:3773";
+    return asNonEmptyString(explicitUrl) ?? "ws://localhost:3773";
🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file apps/web/src/connection.ts around line 43:

When `resolveRuntimeWsUrl` is called with an empty string `explicitUrl` in an SSR context (`typeof window === "undefined"`), the `??` operator returns `""` instead of falling back to `"ws://localhost:3773"`. This is inconsistent with the browser path, where `asNonEmptyString` treats empty strings as falsy. Consider using `asNonEmptyString(explicitUrl) ?? "ws://localhost:3773"` to align the two paths.

Evidence trail:
apps/web/src/connection.ts lines 41-54 (resolveRuntimeWsUrl function), lines 3-9 (asNonEmptyString function). SSR path at line 43 uses `??` which only falls back for null/undefined, not empty strings. Browser path at line 46-54 calls resolveWsUrlFromSources which uses asNonEmptyString at line 28-31, which returns null for empty strings.

Copy link
Author

Choose a reason for hiding this comment

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

fix it for me

@glopyglerky
Copy link
Author

@codex review

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5fe7039198

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +60 to +62
const remoteUrlValue = sanitizeEnvValue(settings.remoteUrl);
if (!remoteUrlValue) {
return null;

Choose a reason for hiding this comment

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

P1 Badge Reject empty remote URL in remote mode

When settings.mode is "remote" and remoteUrl is blank, this function returns null instead of throwing a configuration error. That lets desktop:connection:set accept and persist an invalid remote config, and on restart bootstrap() treats it as non-remote and starts the local backend, so users can save "remote" mode and silently fall back to local history. Empty remote URLs should raise DesktopRemoteConnectionConfigError so the invalid state is blocked and surfaced in the settings UI.

Useful? React with 👍 / 👎.

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ca9e71a027

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +42 to +43
if (!remoteUrl) {
return null;

Choose a reason for hiding this comment

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

P2 Badge Honor token-only env override for remote desktop mode

resolveDesktopConnectionSettingsFromEnv bails out unless T3CODE_DESKTOP_REMOTE_URL is set, so T3CODE_DESKTOP_REMOTE_AUTH_TOKEN alone is ignored. This breaks the documented/expected override model for rotating secrets: if a user saves the remote URL in desktop settings and only injects a new auth token via environment, bootstrap keeps using the stale saved token and can fail remote auth while silently keeping old credentials active. Treating token-only env input as an override (or explicit config error) avoids this mismatch.

Useful? React with 👍 / 👎.

@maria-rcks maria-rcks closed this Mar 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL 1,000+ changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants