Show the Cursor icon for terminal profiles that run cursor-agent (#5379)

* Show the Cursor icon for terminal profiles that run cursor-agent

The Cursor CLI binary is cursor-agent, so a profile created in settings
with that command matched no known icon and fell back to the generic
terminal icon. Map cursor-agent to the cursor icon while keeping
command matching exact.

Closes #4702

* Verify Cursor terminal profile icons in real browser

---------

Co-authored-by: paseo-bot[bot] <266920839+paseo-bot[bot]@users.noreply.github.com>
Co-authored-by: Mohamed Boudra <boudra.moha@gmail.com>
This commit is contained in:
paseo-bot[bot]
2026-09-28 16:48:20 +01:00
committed by GitHub
co-authored by Mohamed Boudra
parent 792715e762
commit a43c8d888f
3 changed files with 77 additions and 2 deletions
@@ -250,6 +250,52 @@ test.describe("Tab creation", () => {
await expect(page).toHaveURL(/\/settings\/hosts\/[^/]+\/terminals$/);
});
test("Cursor CLI profile uses the Cursor icon in New tab and host settings", async ({ page }) => {
const guessed: TerminalProfile = {
id: "e2e-cursor-guessed",
name: "Cursor guessed",
command: "cursor-agent",
args: ["{{{prompt}}}"],
};
const explicit: TerminalProfile = {
...guessed,
id: "e2e-cursor-explicit",
name: "Cursor explicit",
icon: "cursor",
};
const profileSeed = await seedTerminalProfiles([guessed, explicit]);
try {
await gotoWorkspace(page, workspace.workspaceId);
await page.getByTestId("workspace-new-tab-button").filter({ visible: true }).click();
const menu = page.getByTestId("workspace-new-tab-menu").filter({ visible: true });
const menuIconPath = (name: string) =>
menu
.getByRole("menuitem", { name })
.evaluate((element) => element.querySelector("svg path")?.getAttribute("d") ?? null);
const guessedMenuPath = await menuIconPath(guessed.name);
const explicitMenuPath = await menuIconPath(explicit.name);
await menu.getByTestId("workspace-new-tab-menu-edit-terminal-profiles").click();
await expect(page).toHaveURL(/\/settings\/hosts\/[^/]+\/terminals$/);
const settingsIconPath = (id: string) =>
page
.getByTestId(`terminal-profile-row-${id}`)
.evaluate((element) => element.querySelector("svg path")?.getAttribute("d") ?? null);
const guessedSettingsPath = await settingsIconPath(guessed.id);
const explicitSettingsPath = await settingsIconPath(explicit.id);
expect(explicitMenuPath).not.toBeNull();
expect(explicitSettingsPath).not.toBeNull();
expect.soft(guessedMenuPath, "New tab Cursor profile icon").toBe(explicitMenuPath);
expect.soft(guessedSettingsPath, "Settings Cursor profile icon").toBe(explicitSettingsPath);
} finally {
await profileSeed.restore();
}
});
test("tab bar shows action buttons per pane", async ({ page }) => {
await gotoWorkspace(page, workspace.workspaceId);
await assertSingleNewTabButton(page);
@@ -196,11 +196,13 @@ describe("guessTerminalProfileIcon", () => {
["/usr/local/bin/gemini", "gemini"],
["agy", "agy"],
["/usr/local/bin/agy", "agy"],
["cursor-agent", "cursor"],
["/usr/local/bin/cursor-agent", "cursor"],
])("guesses %s -> %s", (command, expected) => {
expect(guessTerminalProfileIcon(command)).toBe(expected);
});
it.each([["zsh"], ["bash"], ["fish"], [""], ["/usr/bin/foo"], ["cursor-agent"]])(
it.each([["zsh"], ["bash"], ["fish"], [""], ["/usr/bin/foo"], ["cursor-tool"]])(
"returns undefined for unknown command %s",
(command) => {
expect(guessTerminalProfileIcon(command)).toBeUndefined();
@@ -219,6 +221,26 @@ describe("getTerminalProfileIcon", () => {
expect(getTerminalProfileIcon(profile)).toBe("claude");
});
it("shows the Cursor icon for a profile created in settings with the Cursor CLI", () => {
const profile = {
id: "profile_1",
name: "Cursor",
command: "cursor-agent",
args: [PROMPT_SENTINEL],
};
expect(getTerminalProfileIcon(profile)).toBe("cursor");
});
it("keeps an explicit icon over the Cursor CLI guess", () => {
const profile = {
id: "profile_1",
name: "Cursor",
command: "cursor-agent",
icon: "claude",
};
expect(getTerminalProfileIcon(profile)).toBe("claude");
});
it("returns undefined when no icon is set and command is unknown", () => {
const profile = { id: "1", name: "Foo", command: "zsh" };
expect(getTerminalProfileIcon(profile)).toBeUndefined();
+8 -1
View File
@@ -105,7 +105,14 @@ export function resolveTerminalProfileLaunch(
return { name: profile.name, ...substitutePrompt(profile, prompt) };
}
const WELL_KNOWN_COMMAND_ICONS = new Map(KNOWN_PROVIDER_ICON_NAMES.map((name) => [name, name]));
// CLIs whose binary is not named after their icon. Matching stays exact, so a
// command only gets an icon when its whole base name is listed.
const COMMAND_ICON_ALIASES: ReadonlyArray<[string, string]> = [["cursor-agent", "cursor"]];
const WELL_KNOWN_COMMAND_ICONS = new Map([
...KNOWN_PROVIDER_ICON_NAMES.map((name): [string, string] => [name, name]),
...COMMAND_ICON_ALIASES,
]);
function getCommandBaseName(command: string): string {
const lastSlash = command.lastIndexOf("/");