Repository navigation
Description
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
- Run the server as the background service (
com.t3tools.t3code.service,t3 serveonlocalhost:3773,T3CODE_HOME=~/.t3). - 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. - 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" } - Settings → Keybindings shows both rules with the Custom badge and the new keys.
- 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
_chatroute resolves commands from theweb-primary-server-keybindingsatom. - 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
nulland the atom returnsmergeWithDefaultKeybindings([])— 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
juliusmarminge commentedon Oct 4, 2026
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
mainat4ee6bfd50e.readPrimaryEnvironmentTargetreturns null and no primary is registered. A savedhttp://localhost:3773connection is a bearer environment, not aPrimaryConnectionTarget, soweb-primary-environment-idstays null.web-primary-server-keybindingsdoesmergeWithDefaultKeybindings(config?.keybindings ?? []), and with an empty list that's just the compiled defaults frompackages/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 onCmd+N.selectScopedSettingsEnvironmentsprefers the primary, then falls back to the first connected environment. That's the background service, wherekeybindings.jsonlives, which is why Settings shows the Custom rules.t3 servepage and the desktop app with Local environment on aren't affected.default keybinding rule already defined in user configis 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
web-primary-server-keybindingsfall back to the same connected environment Settings already uses when there's no primary.A maintainer will decide on the fix direction.
fix(web): honor custom keybindings without a primary environment
fix(web): honor custom keybindings without a primary environment
fix(web): honor custom keybindings without a primary environment
fix(web): honor custom keybindings without a primary environment
fix(web): honor custom keybindings without a primary environment