Skip to content

Add terminal profile settings groundwork#1589

Draft
gmackie wants to merge 2 commits intopingdotgg:mainfrom
gmackie:terminal-profile-config
Draft

Add terminal profile settings groundwork#1589
gmackie wants to merge 2 commits intopingdotgg:mainfrom
gmackie:terminal-profile-config

Conversation

@gmackie
Copy link
Copy Markdown

@gmackie gmackie commented Mar 30, 2026

Summary

  • add persisted terminal profile settings and runtime shell/profile handling for integrated terminals
  • expose terminal capability data from the server, including current shell and discovered Windows shells, for future shell-selection UX
  • add a minimal terminal settings panel for shell override, shell args, and env overrides without taking on the full Support more integrated terminal shells #292 picker flow

Notes

Test Plan

  • bun --cwd apps/server test src/terminal/terminalProfile.test.ts src/wsServer.test.ts
  • bunx vitest run --config vitest.browser.config.ts src/components/settings/SettingsPanels.browser.tsx
  • bun fmt
  • bun lint
  • bun typecheck

Refs #292

Note

Add terminal profile settings for shell path, args, and environment variables

  • Adds TerminalProfileSettings schema to packages/contracts/src/settings.ts with shellPath, shellArgs, and env fields, extending ServerSettings and ServerSettingsPatch to support terminal profile configuration.
  • Adds a terminal settings section to GeneralSettingsPanel where users can configure shell path, arguments, and environment variables, persisted via updateSettings.
  • Introduces terminalProfile.ts with resolveTerminalShellSpawnConfig, discoverTerminalShells, and discoverWindowsTerminalShells to resolve which shell and args to use when spawning terminals.
  • Updates TerminalManagerRuntime in Manager.ts to source shell config from the terminal profile resolver at spawn time, merging profile env with runtime env.
  • Extends server.getConfig in wsServer.ts to include a terminal field with platform, currentShell, and discoveredShells.
📊 Macroscope summarized 7bdfbf6. 13 files reviewed, 3 issues evaluated, 0 issues filtered, 2 comments posted

🗂️ Filtered Issues

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 30, 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: 21297e32-dee2-470a-ab39-dabafc8df0f0

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

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.

@github-actions github-actions bot added size:XL 500-999 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list. labels Mar 30, 2026
Comment on lines +314 to +319
return yield* Effect.promise(() =>
discoverTerminalShells({
platform: process.platform,
env: process.env,
probe: (candidatePath) => Effect.runPromise(fileSystem.exists(candidatePath)),
}),
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.

🟡 Medium src/wsServer.ts:314

In loadTerminalDiscovery, the probe callback returns Effect.runPromise(fileSystem.exists(candidatePath)). If fileSystem.exists throws (e.g., permission denied), the promise rejects instead of resolving to false. Since discoverTerminalShells expects Promise<boolean> and doesn't catch probe rejections, this causes the entire terminal discovery to fail as a defect, breaking serverGetConfig instead of gracefully marking shells as unavailable. Consider catching errors and returning false.

        probe: (candidatePath) => Effect.runPromise(fileSystem.exists(candidatePath).pipe(Effect.catch(() => Effect.succeed(false)))),
🤖 Copy this AI Prompt to have your agent fix this:
In file apps/server/src/wsServer.ts around lines 314-319:

In `loadTerminalDiscovery`, the `probe` callback returns `Effect.runPromise(fileSystem.exists(candidatePath))`. If `fileSystem.exists` throws (e.g., permission denied), the promise rejects instead of resolving to `false`. Since `discoverTerminalShells` expects `Promise<boolean>` and doesn't catch probe rejections, this causes the entire terminal discovery to fail as a defect, breaking `serverGetConfig` instead of gracefully marking shells as unavailable. Consider catching errors and returning `false`.

Evidence trail:
apps/server/src/wsServer.ts:318 - probe callback uses Effect.runPromise(fileSystem.exists(candidatePath))
apps/server/src/wsServer.ts:267 - fileSystem from Effect's FileSystem.FileSystem
apps/server/src/terminal/terminalProfile.ts:186-196 - firstExistingPath has no try-catch around await probe(candidate)
apps/server/src/terminal/terminalProfile.ts:198-230 - discoverWindowsTerminalShells has no try-catch around firstExistingPath calls
apps/server/src/terminal/terminalProfile.ts:233-262 - discoverTerminalShells has no try-catch around discoverWindowsTerminalShells call
apps/server/src/terminal/terminalProfile.ts:25 - TerminalShellPathProbe type expects Promise<boolean>
apps/server/src/wsServer.ts:328-330 - shows Error handling pattern with Effect.catch for fileSystem.stat used elsewhere

[settings.terminal.profile, updateSettings],
);

useEffect(() => {
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.

🟠 High settings/SettingsPanels.tsx:668

When the user types a newline in the "Shell arguments" or "Environment variables" textareas, the newline is immediately deleted. This happens because parseTerminalShellArgs filters empty lines (stripping the trailing newline), then formatTerminalShellArgs joins without trailing newlines, and the useEffect at lines 668–675 immediately overwrites the draft with the reformatted value. Users cannot type a newline to start a new entry.

🤖 Copy this AI Prompt to have your agent fix this:
In file apps/web/src/components/settings/SettingsPanels.tsx around line 668:

When the user types a newline in the "Shell arguments" or "Environment variables" textareas, the newline is immediately deleted. This happens because `parseTerminalShellArgs` filters empty lines (stripping the trailing newline), then `formatTerminalShellArgs` joins without trailing newlines, and the `useEffect` at lines 668–675 immediately overwrites the draft with the reformatted value. Users cannot type a newline to start a new entry.

Evidence trail:
apps/web/src/components/settings/SettingsPanels.tsx lines 442-444 (formatTerminalShellArgs), lines 446-450 (parseTerminalShellArgs), lines 668-670 (useEffect that overwrites draft), lines 1528-1531 (onChange handler that parses and updates settings). apps/web/src/hooks/useSettings.ts lines 100-125 (updateSettings uses setQueryData creating new references).

Copy link
Copy Markdown
Author

@gmackie gmackie Mar 30, 2026

Choose a reason for hiding this comment

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

I wasn't able to reproduce this locally. I tightened the browser test to try the more realistic interaction path as well, focusing the existing shell-args textarea and sending an Enter key instead of just using fill(), and it still preserved the trailing newline. Since I couldn't get a failing repro from the current Electron/browser harness, I left the production UI code unchanged rather than landing a speculative state-sync fix.

If there's a concrete repro path or platform-specific case you're seeing, I can take another pass with that exact flow.

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.

Sorry, I'm unable to act on this request because you do not have permissions within this repository.

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.

Sorry, I'm unable to act on this request because you do not have permissions within this repository.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XL 500-999 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.

Support more integrated terminal shells

1 participant