Skip to content

Add slash command management UI#4180

Draft
JoshuaRileyDev wants to merge 3 commits into
pingdotgg:mainfrom
JoshuaRileyDev:t3code/slash-command-management-ui-rebased
Draft

Add slash command management UI#4180
JoshuaRileyDev wants to merge 3 commits into
pingdotgg:mainfrom
JoshuaRileyDev:t3code/slash-command-management-ui-rebased

Conversation

@JoshuaRileyDev

@JoshuaRileyDev JoshuaRileyDev commented Jul 20, 2026

Copy link
Copy Markdown

Summary

Rebase the custom slash command UI work onto the current upstream/main and keep it compatible with the current composer, timeline, and settings surfaces.

What changed

  • adds slash command management UI and routing for settings
  • wires custom and provider slash commands through the composer and markdown rendering paths
  • preserves current upstream timeline anchoring and composer behavior after the rebase
  • updates the desktop settings test fixture and slash-command test expectations for the rebased branch

Validation

  • mise exec node@24.13.1 -- pnpm exec vp check
  • mise exec node@24.13.1 -- pnpm exec vp run typecheck
  • mise exec node@24.13.1 -- pnpm exec vp test run --project unit src/composer-logic.test.ts src/components/chat/composerSlashCommands.test.ts src/components/chat/composerSlashCommandSearch.test.ts

Notes

  • vp check completed with existing lint warnings in upstream files such as ChatMarkdown.tsx, CommandPalette.tsx, and SidebarUpdatePill.tsx; no hard errors were reported.
  • The original fork branch also contained unrelated docs, Docker, and icon commits. Those were intentionally excluded so this PR only carries the slash-command work.

Note

Medium Risk
Touches core composer cursor/token logic and prompt serialization; incorrect slash-token handling could break editing or display, but changes are covered by unit tests and are mostly UI/settings scoped.

Overview
Adds slash command management end-to-end: a new Settings → Slash Commands route, persisted client settings for custom commands and visibility/collapse preferences, and richer composer/timeline behavior.

Settings & persistenceClientSettings gains customSlashCommands, per-scope hide lists (hiddenCustomSlashCommands, hiddenGlobalSlashCommands, hiddenProviderSlashCommands), and UI collapse flags. Users can create local custom prompts, toggle agent (.agents) and provider commands, and search/filter in a unified settings section.

Composer & chat — Slash commands from all enabled providers (not only the selected one) feed autocomplete via collectComposerSlashCommands / buildComposerSlashCommandItems. The Lexical composer gets a ComposerSlashCommandNode with source-specific icons (app logo, bot, provider). Cursor expand/collapse and inline-token navigation treat slash commands like skills/mentions. Chat markdown and timelines render known /commands as inline chips through SlashCommandInlineText, using the same visibility-aware command list as the composer.

Menu UX — Slash autocomplete is grouped (Custom, Global, Built-in, per-provider); skill search dedupes across provider instances and marks .agents skills. Search ranking for slash items now keys tie-breaks on item id and prefers command names over descriptions for built-ins.

Reviewed by Cursor Bugbot for commit dbd46ff. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Add slash command management UI with settings page and inline rendering

  • Adds a /settings/slash-commands page with three sections: custom commands (create/delete/hide), agent-sourced global commands, and per-provider commands with bulk show/hide and collapse controls.
  • Introduces customSlashCommands, hiddenCustomSlashCommands, hiddenGlobalSlashCommands, hiddenProviderSlashCommands, and related collapse fields to ClientSettings.
  • Slash commands are now rendered as inline chips in both the composer editor and chat message timelines, with icons reflecting the command source (custom, agent, or provider).
  • The composer autocomplete groups slash commands into Custom, Global, Built-in, and per-provider sections, and cursor movement logic treats slash command tokens as inline tokens equivalent to skill pills.
  • Risk: tie-breaking order for equal-score slash command search results changes from a constructed string to item ID, which may alter autocomplete ordering.
📊 Macroscope summarized dbd46ff. 18 files reviewed, 0 issues evaluated, 0 issues filtered, 0 comments posted

🗂️ Filtered Issues

No issues evaluated.

@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown

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: 963bb3f6-8bbb-4fd0-afbe-4389173bbb5d

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.

@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:XXL 1,000+ changed lines (additions + deletions). labels Jul 20, 2026
boundaryBase: 24,
includesBase: 26,
}),
...(item.type === "slash-command"

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 chat/composerSlashCommandSearch.ts:32

Built-in slash commands no longer match description-only queries. A search like normal build mode for /default previously returned the command via description scoring, but now returns no result because scoreSlashCommandItem skips the description score entirely when item.type === "slash-command". Consider keeping the description score for built-in commands so description text remains searchable.

🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/web/src/components/chat/composerSlashCommandSearch.ts around line 32:

Built-in slash commands no longer match description-only queries. A search like `normal build mode` for `/default` previously returned the command via description scoring, but now returns no result because `scoreSlashCommandItem` skips the description score entirely when `item.type === "slash-command"`. Consider keeping the description score for built-in commands so description text remains searchable.

sources: ReadonlyArray<{ command: { name: string } }>,
isVisible: boolean,
) => {
const nextHidden = isVisible ? [] : sources.map((source) => source.command.name);

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 settings/ProviderSlashCommandsSection.tsx:104

setAllCommandsVisibility overwrites the provider's entire hidden-command list with only the currently displayed sources, so any hidden commands that don't match the active search filter are silently made visible. When a search narrows the group, clicking "Exclude all" only hides the visible matches and un-hides everything else, and "Include all" deletes the hidden state for nonmatching commands. The bulk update should merge or remove only the displayed command names against the existing list instead of replacing the whole entry.

Suggested change
const nextHidden = isVisible ? [] : sources.map((source) => source.command.name);
const currentHidden: ReadonlyArray<string> = hiddenSlashCommandsByProvider[providerId] ?? [];
const displayedNames = new Set(sources.map((source) => source.command.name.trim().toLowerCase()));
const nextHidden = isVisible
? currentHidden.filter((value) => !displayedNames.has(value.trim().toLowerCase()))
: [
...currentHidden.filter((value) => !displayedNames.has(value.trim().toLowerCase())),
...sources.map((source) => source.command.name),
];
🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/web/src/components/settings/ProviderSlashCommandsSection.tsx around line 104:

`setAllCommandsVisibility` overwrites the provider's entire hidden-command list with only the currently displayed `sources`, so any hidden commands that don't match the active search filter are silently made visible. When a search narrows the group, clicking "Exclude all" only hides the visible matches and un-hides everything else, and "Include all" deletes the hidden state for nonmatching commands. The bulk update should merge or remove only the displayed command names against the existing list instead of replacing the whole entry.

options?: {
readonly hiddenSlashCommandsByProvider?: Readonly<Record<string, ReadonlyArray<string>>>;
},
): ComposerSlashCommandSource[] {

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 lib/composerSlashCommands.ts:154

collectComposerSlashCommandSources drops commands that match hiddenSlashCommandsByProvider, so collectComposerSlashCommands omits those names entirely. The UI copy says hiding a command affects only "chat slash autocomplete," but hiding a provider command also stops collectComposerSlashCommandTokens from recognizing it, so its /name chip stops rendering in existing and new messages. Consider excluding hidden commands only in the autocomplete-filtering path instead of dropping them from the collection.

🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/web/src/lib/composerSlashCommands.ts around line 154:

`collectComposerSlashCommandSources` drops commands that match `hiddenSlashCommandsByProvider`, so `collectComposerSlashCommands` omits those names entirely. The UI copy says hiding a command affects only "chat slash autocomplete," but hiding a provider command also stops `collectComposerSlashCommandTokens` from recognizing it, so its `/name` chip stops rendering in existing and new messages. Consider excluding hidden commands only in the autocomplete-filtering path instead of dropping them from the collection.

onTaskListChange?: ((input: { markerOffset: number; checked: boolean }) => void) | undefined;
isStreaming?: boolean;
skills?: ReadonlyArray<Pick<ServerProviderSkill, "name" | "displayName">>;
slashCommands?: ReadonlyArray<ComposerSlashCommandLike>;

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 components/ChatMarkdown.tsx:117

The markdownComponents memo omits slashCommands from its dependency array, so when the slashCommands prop changes while ChatMarkdown is mounted — e.g. after creating or editing a custom command — the memoized p/li renderers keep using the stale list and command highlighting never updates until an unrelated dependency changes. Add slashCommands to the memo's dependency array.

Also found in 1 other location(s)

apps/web/src/components/ComposerPromptEditor.tsx:681

slashCommandSignature omits displayName, provider, and sourceKind, even though all three are copied into ComposerSlashCommandNode metadata. If one of those fields changes while name, description, and input.hint remain unchanged (for example, editing only the capitalization of a custom command title so its slug stays the same), slashCommandsChanged remains false and the controlled-update effect does not rewrite the editor state. Existing slash-command tokens therefore continue displaying stale labels/source metadata until some unrelated value changes.

🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/web/src/components/ChatMarkdown.tsx around line 117:

The `markdownComponents` memo omits `slashCommands` from its dependency array, so when the `slashCommands` prop changes while `ChatMarkdown` is mounted — e.g. after creating or editing a custom command — the memoized `p`/`li` renderers keep using the stale list and command highlighting never updates until an unrelated dependency changes. Add `slashCommands` to the memo's dependency array.

Also found in 1 other location(s):
- apps/web/src/components/ComposerPromptEditor.tsx:681 -- `slashCommandSignature` omits `displayName`, `provider`, and `sourceKind`, even though all three are copied into `ComposerSlashCommandNode` metadata. If one of those fields changes while `name`, `description`, and `input.hint` remain unchanged (for example, editing only the capitalization of a custom command title so its slug stays the same), `slashCommandsChanged` remains false and the controlled-update effect does not rewrite the editor state. Existing slash-command tokens therefore continue displaying stale labels/source metadata until some unrelated value changes.

Comment on lines +87 to +88
const titleError = submitted && normalizedTitle.length === 0 ? "A title is required." : null;
const promptError = submitted && normalizedPrompt.length === 0 ? "A prompt is required." : null;

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 settings/CustomSlashCommandsSection.tsx:87

When the user enters a title that consists entirely of characters that slugify to nothing (e.g. 你好 or !!!), clicking "Add command" silently does nothing — no error message is shown and the dialog stays open. handleSave rejects the command because commandName.length === 0, but the UI only shows titleError when normalizedTitle.length === 0, so the user has no indication of why the save failed. Consider rendering a validation message when commandName is empty despite a non-empty title, so the user understands the title needs to contain supported characters.

Suggested change
const titleError = submitted && normalizedTitle.length === 0 ? "A title is required." : null;
const promptError = submitted && normalizedPrompt.length === 0 ? "A prompt is required." : null;
const titleError = submitted && normalizedTitle.length === 0 ? "A title is required." : null;
const titleSlugError = submitted && normalizedTitle.length > 0 && commandName.length === 0 ? "Title must contain at least one letter, number, or hyphen." : null;
🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/web/src/components/settings/CustomSlashCommandsSection.tsx around lines 87-88:

When the user enters a title that consists entirely of characters that slugify to nothing (e.g. `你好` or `!!!`), clicking "Add command" silently does nothing — no error message is shown and the dialog stays open. `handleSave` rejects the command because `commandName.length === 0`, but the UI only shows `titleError` when `normalizedTitle.length === 0`, so the user has no indication of why the save failed. Consider rendering a validation message when `commandName` is empty despite a non-empty title, so the user understands the title needs to contain supported characters.

readonly prompt: string;
};

function slugifySlashCommandName(value: string): string {

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 lib/composerSlashCommands.ts:89

slugifySlashCommandName produces names that don't start with an ASCII letter — e.g. "123 Fix" becomes "123-fix" and "_test" becomes "_test" — but SLASH_COMMAND_TOKEN_REGEX requires names to start with [a-zA-Z]. As a result, custom commands with these slugs appear in autocomplete and pass validation, yet typing them (e.g. /123-fix) never matches the token regex, so the command silently fails to render as a slash-command segment. The fix is to strip leading characters that aren't ASCII letters after collapsing non-allowed characters.

🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/web/src/lib/composerSlashCommands.ts around line 89:

`slugifySlashCommandName` produces names that don't start with an ASCII letter — e.g. `"123 Fix"` becomes `"123-fix"` and `"_test"` becomes `"_test"` — but `SLASH_COMMAND_TOKEN_REGEX` requires names to start with `[a-zA-Z]`. As a result, custom commands with these slugs appear in autocomplete and pass validation, yet typing them (e.g. `/123-fix`) never matches the token regex, so the command silently fails to render as a slash-command segment. The fix is to strip leading characters that aren't ASCII letters after collapsing non-allowed characters.

Comment on lines +38 to +41
const visibleGroups = useMemo(() => {
const normalizedQuery = query.trim().toLowerCase();
const sources = collectComposerSlashCommandSources(serverProviders);
const sourcesByProvider = new Map<ProviderInstanceId, typeof sources>();

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 settings/ProviderSlashCommandsSection.tsx:38

Shared .agents commands are rendered twice on the slash commands settings page — once by AgentsSlashCommandsSection (embedded above) and again inside the per-provider groups below. The duplicates use different visibility settings: the global copy respects hiddenGlobalSlashCommands, while the provider copy respects hiddenProviderSlashCommands, so toggling one does not affect the other. This happens because visibleGroups calls collectComposerSlashCommandSources(serverProviders) without filtering, so commands whose sourceKind is "agents" are included in the provider groups even though they are already shown globally. Filter out sourceKind === "agents" sources when building the provider groups.

  const visibleGroups = useMemo(() => {
    const normalizedQuery = query.trim().toLowerCase();
-    const sources = collectComposerSlashCommandSources(serverProviders);
+    const sources = collectComposerSlashCommandSources(serverProviders).filter(
+      (source) => source.command.sourceKind !== "agents",
+    );
    const sourcesByProvider = new Map<ProviderInstanceId, typeof sources>();
🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/web/src/components/settings/ProviderSlashCommandsSection.tsx around lines 38-41:

Shared `.agents` commands are rendered twice on the slash commands settings page — once by `AgentsSlashCommandsSection` (embedded above) and again inside the per-provider groups below. The duplicates use different visibility settings: the global copy respects `hiddenGlobalSlashCommands`, while the provider copy respects `hiddenProviderSlashCommands`, so toggling one does not affect the other. This happens because `visibleGroups` calls `collectComposerSlashCommandSources(serverProviders)` without filtering, so commands whose `sourceKind` is `"agents"` are included in the provider groups even though they are already shown globally. Filter out `sourceKind === "agents"` sources when building the provider groups.

updateSettings,
]);

const handleDelete = useCallback(

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 settings/CustomSlashCommandsSection.tsx:120

handleDelete removes the command from customSlashCommands but leaves its normalized name in hiddenCustomSlashCommands. If the user hides a custom command, deletes it, and later creates a new command with the same title, the new command inherits the stale hidden entry and is unexpectedly absent from slash-command autocomplete until manually enabled. When deleting a command, also remove its normalized name from hiddenCustomSlashCommands.

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

`handleDelete` removes the command from `customSlashCommands` but leaves its normalized name in `hiddenCustomSlashCommands`. If the user hides a custom command, deletes it, and later creates a new command with the same title, the new command inherits the stale hidden entry and is unexpectedly absent from slash-command autocomplete until manually enabled. When deleting a command, also remove its normalized name from `hiddenCustomSlashCommands`.

continue;
}
if (segment.type === "slash-command") {
const metadata = slashCommandMetadata.get(segment.name);

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 components/ComposerPromptEditor.tsx:1062

slashCommandMetadata.get(segment.name) uses an exact, untrimmed key lookup, so slash-command chips lose their configured label, description, provider icon, and source-kind when the configured name has different casing or surrounding whitespace. For example, a configured name of review matches typed /Review during recognition (which normalizes with trim().toLowerCase()), but the metadata lookup at render time misses and falls back to raw values. The metadata map should be built and queried with the same normalized key so lookups always hit.

Also found in 1 other location(s)

apps/web/src/components/chat/SlashCommandInlineText.tsx:28

SlashCommandInlineText builds commandsByName and looks up the matched spelling without normalization, while the shared collectComposerSlashCommandTokens logic trims and lowercases both command definitions and input. Thus a valid case-insensitive token such as /PLAN for command plan is recognized by composer parsing but is rendered as plain text in the timeline instead of the slash-command chip.

🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/web/src/components/ComposerPromptEditor.tsx around line 1062:

`slashCommandMetadata.get(segment.name)` uses an exact, untrimmed key lookup, so slash-command chips lose their configured label, description, provider icon, and source-kind when the configured name has different casing or surrounding whitespace. For example, a configured name of `review` matches typed `/Review` during recognition (which normalizes with `trim().toLowerCase()`), but the metadata lookup at render time misses and falls back to raw values. The metadata map should be built and queried with the same normalized key so lookups always hit.

Also found in 1 other location(s):
- apps/web/src/components/chat/SlashCommandInlineText.tsx:28 -- `SlashCommandInlineText` builds `commandsByName` and looks up the matched spelling without normalization, while the shared `collectComposerSlashCommandTokens` logic trims and lowercases both command definitions and input. Thus a valid case-insensitive token such as `/PLAN` for command `plan` is recognized by composer parsing but is rendered as plain text in the timeline instead of the slash-command chip.

return <p {...props}>{renderSkillInlineMarkdownChildren(children, skills)}</p>;
return (
<p {...props}>
{renderSlashCommandInlineMarkdownChildren(

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 components/ChatMarkdown.tsx:1358

Slash-command tokens in paragraph and list text are never converted into chips. renderSlashCommandInlineMarkdownChildren is called on the output of renderSkillInlineMarkdownChildren, which already replaced every string child with a SkillInlineText element that has no children prop. Since renderSlashCommandInlineMarkdownChildren only transforms string nodes, it finds no strings left and skips everything, so slash-command rendering in p and li is a no-op. Apply both transforms to the original string children (e.g. via a combined renderer) instead of chaining them.

🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/web/src/components/ChatMarkdown.tsx around line 1358:

Slash-command tokens in paragraph and list text are never converted into chips. `renderSlashCommandInlineMarkdownChildren` is called on the output of `renderSkillInlineMarkdownChildren`, which already replaced every string child with a `SkillInlineText` element that has no `children` prop. Since `renderSlashCommandInlineMarkdownChildren` only transforms string nodes, it finds no strings left and skips everything, so slash-command rendering in `p` and `li` is a no-op. Apply both transforms to the original string children (e.g. via a combined renderer) instead of chaining them.

@JoshuaRileyDev
JoshuaRileyDev marked this pull request as draft July 20, 2026 09:03
@macroscopeapp

macroscopeapp Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

10 blocking correctness issues found. New feature adding complete slash command management UI with settings page, custom command creation, visibility controls, and schema changes. Multiple unresolved review comments identify functional bugs, including a high-severity issue where slash-command chips fail to render in markdown content.

You can customize Macroscope's approvability policy. Learn more.

@cursor cursor Bot left a comment

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.

Cursor Bugbot has reviewed your changes using high effort and found 5 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want fixes drafted automatically? Bugbot Autofix can create code changes for findings. A team admin can enable Autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit dbd46ff. Configure here.

promptRef.current,
composerCursor,
composerSlashCommands,
),

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.

Custom slash menu selection ignored

High Severity

The onSelectComposerItem function doesn't process custom-slash-command items, even though they are correctly built and displayed in the composer's slash command menu. This prevents custom commands from being inserted into the prompt when selected from the autocomplete.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit dbd46ff. Configure here.

settings.customSlashCommands,
settings.hiddenProviderSlashCommands,
workspaceEntries.entries,
]);

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.

Hidden slash settings stale menu

Medium Severity

The composerMenuItems memo uses settings.hiddenCustomSlashCommands and settings.hiddenGlobalSlashCommands to filter slash commands, but these are missing from its dependency array. This can cause the open slash command menu to display stale visibility for commands after settings are changed.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit dbd46ff. Configure here.

}
return true;
});
}

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.

Disabled custom or global still chips

Medium Severity

The collectComposerSlashCommands function doesn't filter hidden custom or agent-sourced commands. While filterComposerSlashCommandsForAutocomplete contains the necessary logic, it's not applied to the command list used by the composer editor and timeline. This allows commands disabled in settings to still be tokenized into inline chips.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit dbd46ff. Configure here.

return {
value: promptRef.current,
cursor: composerCursor,
expandedCursor: expandCollapsedComposerCursor(promptRef.current, composerCursor),

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.

Stale slash list in callbacks

Medium Severity

Several composer callbacks that handle cursor positioning and prompt manipulation use composerSlashCommands but omit it from their dependency arrays. This can cause outdated slash command lists to be used, leading to incorrect cursor calculations and trigger detection, particularly around slash command chips.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit dbd46ff. Configure here.

const start = (match.index ?? 0) + prefix.length;
const rawText = `/${name}`;
const command = commandsByName.get(name);
if (!command) {

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.

Timeline slash chips case mismatch

Medium Severity

Timeline slash chip rendering indexes commands by raw command.name, while composer token parsing uses lowercased names. Message text matched as /ui will not resolve a provider command stored as UI, so chips render in the composer but stay plain text in chat markdown.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit dbd46ff. Configure here.

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

Labels

size:XXL 1,000+ 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.

1 participant