Skip to content

[Bug]: Custom keybindings are ignored when Local environment is off and the app connects to the background service #15668

Closed

Description

@Conte777

Before submitting

  • I searched existing issues and did not find a duplicate.
  • I included enough detail to reproduce or investigate the problem.

Area

apps/web

Steps to reproduce

  1. Run the server as the background service (com.t3tools.t3code.service, t3 serve on localhost:3773, T3CODE_HOME=~/.t3).
  2. In the desktop app, turn Local environment off (Settings → Connections) and connect to the service as a regular environment (http://localhost:3773/). It shows as Connected.
  3. Swap two bindings in ~/.t3/userdata/keybindings.json (or via Settings → Keybindings):
    { "key": "mod+shift+n", "command": "chat.new",      "when": "!terminalFocus" },
    { "key": "mod+n",       "command": "chat.newLocal", "when": "!terminalFocus" }
  4. Settings → Keybindings shows both rules with the Custom badge and the new keys.
  5. Focus the composer in a thread and press Cmd+N.

Expected behavior

Cmd+N runs chat.newLocal and creates a thread in the current project, as configured on the connected environment.

Actual behavior

Cmd+N still runs chat.new and opens the "New thread in…" project picker. Custom keybindings are ignored by the keydown handlers. Reloading the window, re-saving the binding through Settings → Keybindings and restarting the desktop app do not change it.

Cause, from reading the shipped client bundle (0.0.46-nightly.20261004.2648):

  • The keydown handler in the _chat route resolves commands from the web-primary-server-keybindings atom.
  • That atom reads the config of the environment whose connection target is PrimaryConnectionTarget (web-primary-environment-id).
  • With Local environment off there is no primary target, so the config is null and the atom returns mergeWithDefaultKeybindings([]) — the built-in defaults.
  • Settings → Keybindings reads the connected environments in scope, so it shows the custom rules, while the handlers that act on key presses use the defaults.

Turning Local environment back on is not a workaround here: the desktop backend then starts a second server on the next free port with the same T3CODE_HOME as the service (see #6097).

Suggested fix: when there is no primary environment, resolve keybindings from the connected environment (or the one the active thread belongs to) instead of falling back to defaults.

Impact

Minor bug or occasional failure

Version or commit

Desktop 0.0.46-nightly.20261004.2648, server runtime 0.0.46-nightly.20261004.2648

Environment

macOS 27.0.1, desktop app with Local environment off, server running as the launchd background service

Logs or stack traces

No errors. The server log only shows the usual startup line:
WARN: default keybinding rule already defined in user config
  path: '/Users/<user>/.t3/userdata/keybindings.json'

Workaround

None, other than using the default bindings.

Activity

  1. juliusmarminge commented on Oct 4, 2026

    @juliusmarminge
    Member

    Note

    Grok responding on behalf of Julius.

    Triage

    Thanks for the precise report, @Conte777. Your reading of the bundle holds up against the source.

    What I found

    Confirmed on main at 4ee6bfd50e.

    • No primary environment. With Local environment off, readPrimaryEnvironmentTarget returns null and no primary is registered. A saved http://localhost:3773 connection is a bearer environment, not a PrimaryConnectionTarget, so web-primary-environment-id stays null.
    • Shortcuts fall back to defaults. web-primary-server-keybindings does mergeWithDefaultKeybindings(config?.keybindings ?? []), and with an empty list that's just the compiled defaults from packages/shared/src/keybindings.ts. The chat route, sidebar, command palette, and other shortcut handlers all read that atom, so the swap is ignored everywhere, not only on Cmd+N.
    • Settings reads a different environment. selectScopedSettingsEnvironments prefers the primary, then falls back to the first connected environment. That's the background service, where keybindings.json lives, which is why Settings shows the Custom rules.
    • The hosted app is affected too. It also registers no primary. A same-origin t3 serve page and the desktop app with Local environment on aren't affected.
    • The startup warning is unrelated. default keybinding rule already defined in user config is the server noticing default rules already in the user file while it backfills the rest.

    As you noted, turning Local environment back on runs into #6097.

    Likely fix area

    • One option is to have web-primary-server-keybindings fall back to the same connected environment Settings already uses when there's no primary.
    • Another is to resolve keybindings from the active thread's environment. That only differs from the first option when several environments are connected and there's no primary, which isn't the single-connection setup in this report.

    A maintainer will decide on the fix direction.

  2. added
    bugSomething is broken or behaving incorrectly.
    via-triageFiled through npx t3 triage
    on Oct 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething is broken or behaving incorrectly.via-triageFiled through npx t3 triage

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions