Fix: Agent Launchers Ignore Settings On Welcome Screen
Have you ever configured custom settings for your agents, only to find them ignored when launching from the welcome screen? This article dives into a bug where agent launchers on the welcome screen bypass your carefully configured settings. We'll explore the issue, its root cause, and the fix implemented to ensure your agents launch with the settings you expect. Plus, we'll touch on how this enhances your overall experience by making the application more consistent and reliable.
Summary
Agent launchers on the welcome screen, also known as the empty state, were found to bypass configured settings. Instead of respecting user-configured models, flags, and system prompts, they spawned terminals with default arguments. This meant that any custom configurations you set for your agents were not being applied when launching from the welcome screen. This inconsistency could be confusing and frustrating, especially for users who rely on specific settings for their workflows.
Current Behavior
When launching agents like Claude, Gemini, or Codex from the welcome screen launcher cards, several issues were observed:
- Custom agent settings were completely ignored. Any specific configurations you had set for these agents were not being applied.
- Configured models were not applied. If you had chosen a specific model for an agent (e.g., opus or haiku for Claude), the agent would launch with the default model instead.
- Custom command-line flags were not passed. Any flags you had added to customize the agent's behavior were not being used.
- System prompts from settings were bypassed. Custom system prompts designed to guide the agent's responses were being ignored.
- Agents launched with bare-minimum default configuration. This meant that the agents were running with the most basic settings, disregarding any user-defined preferences.
The affected component was identified as EmptyState in TerminalGrid.tsx. This component is responsible for rendering the welcome screen and handling agent launches from that screen.
Root Cause
The root cause of this issue was traced to the handleLaunchAgent function within TerminalGrid.tsx. Specifically, lines 219-230 of the code directly call addTerminal with basic options. This call bypasses the settings-aware logic that is used when launching agents from other parts of the application, such as the toolbar. The useAgentLauncher hook, which contains the logic for applying custom settings, was not being utilized in this particular launch path. This meant that the welcome screen launchers were essentially taking a shortcut, resulting in the agents being launched with default configurations.
Expected Behavior
The expected behavior for agent launchers on the welcome screen is that they should respect all configured settings. This means:
- Applying all configured settings (models, flags, system prompts). When you launch an agent from the welcome screen, it should use the specific settings you have defined.
- Behaving identically to agents launched from toolbar buttons. The launch behavior should be consistent regardless of where you initiate the launch from.
- Respecting user preferences stored in agent settings. Your preferences, such as the choice of model or custom flags, should be honored.
- Using the same launch code path regardless of UI entry point. Whether you launch from the welcome screen or the toolbar, the same underlying logic should be used to ensure consistency.
In essence, the agents should launch with the same configuration whether you click a launcher card on the welcome screen or use a toolbar button. This ensures a seamless and predictable user experience.
Steps to Reproduce
To reproduce this issue, you can follow these steps:
- Open the application's settings and configure custom agent settings. This includes:
- Setting a custom model for Claude (e.g., opus, haiku).
- Adding custom flags or system prompts to further customize the agent's behavior.
- Saving the settings to ensure they are applied.
- Close all terminals in the application. This will bring you to the welcome screen, where the agent launcher cards are displayed.
- Click a launcher card, such as the "Claude Code" card, to initiate an agent launch.
- Observe the spawned terminal. You will notice that it uses the default configuration instead of the custom settings you configured earlier.
This issue is consistently reproducible, occurring 100% of the time when launching agents from the welcome screen with custom settings defined.
Environment
This issue was observed in the following environment:
- OS: macOS 14.2+ / Windows / Linux. The issue is not specific to a particular operating system.
- Version: Current main branch (commit a9eda1e). This indicates the specific version of the codebase where the issue was identified.
- Affected Agents: Claude, Gemini, Codex. These are the specific agents that were affected by the bug.
- Component:
TerminalGridempty state. This pinpoints the specific part of the application where the issue occurs.
Evidence
To further illustrate the issue, let's examine the relevant code snippets.
Current Implementation
The following code from src/components/Terminal/TerminalGrid.tsx (lines 219-230) shows the broken handler:
const handleLaunchAgent = useCallback(
async (type: "claude" | "gemini" | "codex" | "shell") => {
try {
const cwd = defaultCwd || "";
const command = type !== "shell" ? type : undefined;
await addTerminal({ type, cwd, command });
} catch (error) {
console.error(`Failed to launch ${type}:`, error);
}
},
[addTerminal, defaultCwd]
);
This code directly calls addTerminal with minimal options, bypassing the settings-aware logic.
Settings-Aware Logic (NOT used by welcome screen)
In contrast, the following code from src/hooks/useAgentLauncher.ts (lines 140-191) demonstrates the settings-aware logic that should be used:
const launchAgent = useCallback(
async (type: AgentType): Promise<string | null> => {
// ... configuration logic ...
let command = config.command;
if (command && agentSettings) {
let flags: string[] = [];
switch (type) {
case "claude":
flags = generateClaudeFlags(agentSettings.claude);
break;
case "gemini":
flags = generateGeminiFlags(agentSettings.gemini);
break;
case "codex":
flags = generateCodexFlags(agentSettings.codex);
break;
}
if (flags.length > 0) {
command = `${config.command} ${flags.join(" ")}`;
}
}
// ... rest of implementation
},
[activeId, worktreeMap, addTerminal, currentProject, agentSettings]
);
This code snippet shows how the useAgentLauncher hook incorporates user-defined settings, such as flags and system prompts, when launching agents. However, this logic was not being used by the welcome screen launchers.
Affected Files
The following files were identified as being affected by this issue:
src/components/Terminal/TerminalGrid.tsx#L219-L230- Contains the broken handler.src/App.tsx#L418-L423- Has the correct handler but was not being passed down to theTerminalGridcomponent.src/hooks/useAgentLauncher.ts#L140-L191- Contains the settings-aware implementation that was not being utilized.
Deliverables
The fix for this issue involved several code changes and testing procedures to ensure the correct behavior and prevent regressions.
Code Changes
The primary code changes were made in the TerminalGrid and App components.
1. Update TerminalGrid Component
File: src/components/Terminal/TerminalGrid.tsx
Changes:
- Added an
onLaunchAgentoptional prop to theTerminalGridPropsinterface (line 25). This prop allows the parent component to pass down a custom agent launch handler. - Updated the
handleLaunchAgentfunction to delegate to theonLaunchAgentprop if provided (lines 219-230). This ensures that the custom handler is used when available. - Kept the fallback logic for standalone usage. If the
onLaunchAgentprop is not provided, the component falls back to the basic launch behavior.
2. Update App Component
File: src/App.tsx
Changes:
- Passed the
handleLaunchAgentprop to theTerminalGridcomponent (line 571). This connects the settings-aware launcher fromuseAgentLauncherto the welcome screen.
Tests
To ensure the fix was effective and did not introduce any regressions, the following tests were performed:
- Manual verification: Custom settings were configured, terminals were closed, and agents were launched from the welcome screen. The launched agents were then verified to use the configured settings.
- Integration test: Agents were launched from both the toolbar and the welcome screen, and the resulting terminal configurations were asserted to be identical. This ensures consistency across different launch points.
- Settings edge case: The fallback behavior was verified when settings were invalid or missing. This ensures that the application handles edge cases gracefully.
Documentation
No documentation changes were needed for this fix. It was an internal bug fix that did not affect the application's API or external interfaces.
Technical Specifications
Footprint
- UI Components:
TerminalGrid,App - Hook dependency:
useAgentLauncher - No IPC or service layer changes
Architecture
- Followed the React props pattern for passing handlers down the component tree. This is a standard React pattern that ensures data and behavior are passed down in a predictable way.
- Maintained a single source of truth for agent launching logic (
useAgentLauncher). This ensures that the launch logic is consistent across the application. - Preserved fallback behavior for component reusability. This allows the
TerminalGridcomponent to be used in other contexts without requiring theonLaunchAgentprop.
Dependencies
None - This was a standalone bug fix that did not introduce any new dependencies.
Tasks
The following tasks were completed as part of the fix:
- [x] Added
onLaunchAgentprop toTerminalGridPropsinterface insrc/components/Terminal/TerminalGrid.tsx:25-28 - [x] Updated
handleLaunchAgentcallback insrc/components/Terminal/TerminalGrid.tsx:219-230to check for and useonLaunchAgentprop - [x] Passed
handleLaunchAgentas prop toTerminalGridinsrc/App.tsx:571 - [x] Tested launching agents from the welcome screen with custom settings configured
- [x] Verified toolbar launches still work correctly (no regression)
- [x] Tested edge case: launching when settings are partially configured
Acceptance Criteria
The following acceptance criteria were used to ensure the fix was successful:
- [x] Agents launched from the welcome screen respect all configured settings (models, flags, prompts)
- [x] Settings-configured Claude/Gemini/Codex spawn with correct command-line arguments
- [x] Toolbar and welcome screen launchers produce identical terminal configurations
- [x] No regression in existing toolbar agent launch functionality
- [x] Fallback behavior still works if
onLaunchAgentprop is not provided
Edge Cases & Risks
Edge Cases
The following edge cases were considered during the fix:
- Settings partially configured (some agents have custom config, others do not). The fix handles this by applying the custom settings where available and falling back to defaults for others.
- Settings invalid or corrupted (should fallback gracefully). The application gracefully falls back to default settings if the configured settings are invalid or corrupted.
TerminalGridused withoutonLaunchAgentprop (preserve fallback). The fallback logic ensures that the component can still be used in other contexts without requiring the prop.
Risks
- Low risk: The fix involves a simple prop passing pattern and is a well-isolated change.
- Potential confusion if
TerminalGridis reused elsewhere without prop (mitigated by fallback logic).
Regression Risk
- Minimal - The change only affects the empty state launch path.
- Toolbar launches unchanged (already using the correct logic).
Conclusion
By addressing this bug, we've ensured that agent launchers on the welcome screen now respect your configured settings, providing a consistent and reliable experience across the application. This fix enhances usability by ensuring your custom settings are applied regardless of how you launch your agents. Remember to always test your configurations and report any unexpected behavior to help improve the application further.
For more information on related topics, you can check out this React documentation on component props and data flow.