From b738affde26f10e0ba59dad712ed86a302a9a273 Mon Sep 17 00:00:00 2001 From: uinstinct <61635505+uinstinct@users.noreply.github.com> Date: Fri, 6 Mar 2026 12:14:25 +0530 Subject: [PATCH 1/7] list all skills using /skills slash command --- extensions/cli/src/commands/commands.ts | 5 +++++ extensions/cli/src/slashCommands.ts | 28 +++++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/extensions/cli/src/commands/commands.ts b/extensions/cli/src/commands/commands.ts index 0c85f2228c1..9750cbdd4a7 100644 --- a/extensions/cli/src/commands/commands.ts +++ b/extensions/cli/src/commands/commands.ts @@ -106,6 +106,11 @@ export const SYSTEM_SLASH_COMMANDS: SystemCommand[] = [ description: "List background jobs", category: "system", }, + { + name: "skills", + description: "List all available skills", + category: "system", + }, ]; // Remote mode specific commands diff --git a/extensions/cli/src/slashCommands.ts b/extensions/cli/src/slashCommands.ts index 07c659d5939..e8a9813ae81 100644 --- a/extensions/cli/src/slashCommands.ts +++ b/extensions/cli/src/slashCommands.ts @@ -14,6 +14,7 @@ import { getCurrentSession, updateSessionTitle } from "./session.js"; import { posthogService } from "./telemetry/posthogService.js"; import { telemetryService } from "./telemetry/telemetryService.js"; import { SlashCommandResult } from "./ui/hooks/useChat.types.js"; +import { loadMarkdownSkills } from "./util/loadMarkdownSkills.js"; type CommandHandler = ( args: string[], @@ -173,6 +174,32 @@ function handleJobs() { return { openJobsSelector: true }; } +async function handleSkills(): Promise { + const { skills } = await loadMarkdownSkills(); + + if (!skills.length) { + return { + exit: false, + output: chalk.yellow( + "No skills found. Add skills under .continue/skills or .claude/skills.", + ), + }; + } + + const header = chalk.bold("Available skills:"); + const lines = skills.map( + (skill) => + `${chalk.cyan(skill.name)} - ${skill.description} ${chalk.gray( + `(${skill.path})`, + )}`, + ); + + return { + exit: false, + output: [header, "", ...lines].join("\n"), + }; +} + const commandHandlers: Record = { help: handleHelp, clear: () => { @@ -208,6 +235,7 @@ const commandHandlers: Record = { return { openUpdateSelector: true }; }, jobs: handleJobs, + skills: () => handleSkills(), }; export async function handleSlashCommands( From 0dd2a92b80c1b6564fd10bed4b9bf990231c9344 Mon Sep 17 00:00:00 2001 From: uinstinct <61635505+uinstinct@users.noreply.github.com> Date: Fri, 6 Mar 2026 13:06:29 +0530 Subject: [PATCH 2/7] make skills slash command invokable --- .../cli/src/__mocks__/commands/commands.ts | 2 +- .../src/commands/commands.integration.test.ts | 20 ++++---- extensions/cli/src/commands/commands.ts | 32 ++++++++++-- extensions/cli/src/slashCommands.ts | 22 +++++++- extensions/cli/src/ui/SlashCommandUI.tsx | 44 ++++++++++------ extensions/cli/src/ui/UserInput.tsx | 50 +++++++++++-------- extensions/cli/src/util/loadMarkdownSkills.ts | 24 +++++++++ 7 files changed, 143 insertions(+), 51 deletions(-) diff --git a/extensions/cli/src/__mocks__/commands/commands.ts b/extensions/cli/src/__mocks__/commands/commands.ts index 1b79602d3e4..01f270389f2 100644 --- a/extensions/cli/src/__mocks__/commands/commands.ts +++ b/extensions/cli/src/__mocks__/commands/commands.ts @@ -1,6 +1,6 @@ import { vi } from "vitest"; -export const getAllSlashCommands = vi.fn(() => [ +export const getAllSlashCommands = vi.fn(async () => [ { name: "help", description: "Show help", category: "system" }, { name: "login", description: "Login to Continue", category: "system" }, ]); diff --git a/extensions/cli/src/commands/commands.integration.test.ts b/extensions/cli/src/commands/commands.integration.test.ts index 59984fc9f46..c33ddb632fc 100644 --- a/extensions/cli/src/commands/commands.integration.test.ts +++ b/extensions/cli/src/commands/commands.integration.test.ts @@ -17,8 +17,8 @@ describe("Slash Commands Integration", () => { }; describe("System Commands Registration", () => { - it("should include all system commands in the commands list", () => { - const commands = getAllSlashCommands(mockAssistant); + it("should include all system commands in the commands list", async () => { + const commands = await getAllSlashCommands(mockAssistant); const commandNames = commands.map((cmd) => cmd.name); // Check that system commands are present (mode commands have been removed) @@ -33,15 +33,15 @@ describe("Slash Commands Integration", () => { expect(commandNames).toContain("config"); }); - it("should include assistant prompt commands", () => { - const commands = getAllSlashCommands(mockAssistant); + it("should include assistant prompt commands", async () => { + const commands = await getAllSlashCommands(mockAssistant); const commandNames = commands.map((cmd) => cmd.name); expect(commandNames).toContain("test-prompt"); }); - it("should categorize system commands correctly", () => { - const commands = getAllSlashCommands(mockAssistant); + it("should categorize system commands correctly", async () => { + const commands = await getAllSlashCommands(mockAssistant); const systemCommands = commands.filter((cmd) => [ "help", @@ -60,8 +60,8 @@ describe("Slash Commands Integration", () => { }); }); - it("should categorize assistant commands correctly", () => { - const commands = getAllSlashCommands(mockAssistant); + it("should categorize assistant commands correctly", async () => { + const commands = await getAllSlashCommands(mockAssistant); const assistantCommands = commands.filter( (cmd) => cmd.name === "test-prompt", ); @@ -71,8 +71,8 @@ describe("Slash Commands Integration", () => { }); }); - it("should only show remote mode commands in remote mode", () => { - const commands = getAllSlashCommands(mockAssistant, { + it("should only show remote mode commands in remote mode", async () => { + const commands = await getAllSlashCommands(mockAssistant, { isRemoteMode: true, }); const commandNames = commands.map((cmd) => cmd.name); diff --git a/extensions/cli/src/commands/commands.ts b/extensions/cli/src/commands/commands.ts index 9750cbdd4a7..1fc6d226a50 100644 --- a/extensions/cli/src/commands/commands.ts +++ b/extensions/cli/src/commands/commands.ts @@ -1,5 +1,10 @@ import { type AssistantConfig } from "@continuedev/sdk"; +import { + getSkillSlashCommandName, + loadMarkdownSkills, +} from "../util/loadMarkdownSkills.js"; + // Export command functions export { chat } from "./chat.js"; export { login } from "./login.js"; @@ -135,10 +140,10 @@ export const REMOTE_MODE_SLASH_COMMANDS: SlashCommand[] = [ /** * Get all available slash commands including system commands and assistant prompts */ -export function getAllSlashCommands( +export async function getAllSlashCommands( assistant: AssistantConfig, options: { isRemoteMode?: boolean } = {}, -): SlashCommand[] { +): Promise { const { isRemoteMode = false } = options; // In remote mode, only show the exit command @@ -160,7 +165,15 @@ export function getAllSlashCommands( // Get invokable rule commands const invokableRuleCommands = getInvokableRuleSlashCommands(assistant); - return [...systemCommands, ...assistantCommands, ...invokableRuleCommands]; + // Get skill commands + const skillCommands = await getSkillSlashCommands(); + + return [ + ...systemCommands, + ...assistantCommands, + ...invokableRuleCommands, + ...skillCommands, + ]; } /** @@ -207,3 +220,16 @@ export function getInvokableRuleSlashCommands( }; }); } + +/** + * Get skill-based slash commands from Markdown skills + */ +export async function getSkillSlashCommands(): Promise { + const { skills } = await loadMarkdownSkills(); + + return skills.map((skill) => ({ + name: getSkillSlashCommandName(skill), + description: skill.description, + category: "assistant" as const, + })); +} diff --git a/extensions/cli/src/slashCommands.ts b/extensions/cli/src/slashCommands.ts index e8a9813ae81..af171697c0f 100644 --- a/extensions/cli/src/slashCommands.ts +++ b/extensions/cli/src/slashCommands.ts @@ -14,7 +14,10 @@ import { getCurrentSession, updateSessionTitle } from "./session.js"; import { posthogService } from "./telemetry/posthogService.js"; import { telemetryService } from "./telemetry/telemetryService.js"; import { SlashCommandResult } from "./ui/hooks/useChat.types.js"; -import { loadMarkdownSkills } from "./util/loadMarkdownSkills.js"; +import { + getSkillSlashCommandName, + loadMarkdownSkills, +} from "./util/loadMarkdownSkills.js"; type CommandHandler = ( args: string[], @@ -282,8 +285,23 @@ export async function handleSlashCommands( return { newInput }; } + const { skills } = await loadMarkdownSkills(); + if (skills.length) { + const normalizedCommand = command.trim().toLowerCase(); + const matchingSkill = skills.find( + (skill) => getSkillSlashCommandName(skill) === normalizedCommand, + ); + + if (matchingSkill) { + return { + exit: false, + output: matchingSkill.content, + }; + } + } + // Check if this command would match any available commands (same logic as UI) - const allCommands = getAllSlashCommands(assistant, { + const allCommands = await getAllSlashCommands(assistant, { isRemoteMode: options?.isRemoteMode, }); const hasMatches = allCommands.some((cmd) => diff --git a/extensions/cli/src/ui/SlashCommandUI.tsx b/extensions/cli/src/ui/SlashCommandUI.tsx index 66107c0482b..672f3c21867 100644 --- a/extensions/cli/src/ui/SlashCommandUI.tsx +++ b/extensions/cli/src/ui/SlashCommandUI.tsx @@ -1,8 +1,11 @@ import { type AssistantConfig } from "@continuedev/sdk"; import { Box, Text } from "ink"; -import React, { useMemo } from "react"; +import React, { useEffect, useState } from "react"; -import { getAllSlashCommands } from "../commands/commands.js"; +import { + getAllSlashCommands, + type SlashCommand, +} from "../commands/commands.js"; const MAX_DESCRIPTION_LENGTH = 80; @@ -29,20 +32,31 @@ const SlashCommandUI: React.FC = ({ selectedIndex, isRemoteMode = false, }) => { - // Memoize the slash commands to prevent excessive re-renders - const allCommands = useMemo(() => { - if (assistant || isRemoteMode) { - return getAllSlashCommands(assistant || ({} as AssistantConfig), { - isRemoteMode, - }); - } - + const [allCommands, setAllCommands] = useState( // Fallback - basic commands without assistant - return [ - { name: "help", description: "Show help message" }, - { name: "clear", description: "Clear the chat history" }, - { name: "exit", description: "Exit the chat" }, - ]; + [ + { name: "help", description: "Show help message", category: "system" }, + { + name: "clear", + description: "Clear the chat history", + category: "system", + }, + { name: "exit", description: "Exit the chat", category: "system" }, + ], + ); + + useEffect(() => { + const loadCommands = async () => { + if (assistant || isRemoteMode) { + const commands = await getAllSlashCommands( + assistant || ({} as AssistantConfig), + { isRemoteMode }, + ); + setAllCommands(commands); + } + }; + + void loadCommands(); }, [isRemoteMode, assistant?.prompts, assistant?.rules]); // Filter commands based on the current filter diff --git a/extensions/cli/src/ui/UserInput.tsx b/extensions/cli/src/ui/UserInput.tsx index 205d48b2ebd..98a33ed8a63 100644 --- a/extensions/cli/src/ui/UserInput.tsx +++ b/extensions/cli/src/ui/UserInput.tsx @@ -2,9 +2,12 @@ import { type AssistantConfig } from "@continuedev/sdk"; import { Box, Text, useApp, useInput } from "ink"; -import React, { useCallback, useRef, useState } from "react"; +import React, { useCallback, useEffect, useRef, useState } from "react"; -import { getAllSlashCommands } from "../commands/commands.js"; +import { + getAllSlashCommands, + type SlashCommand, +} from "../commands/commands.js"; import { useServices } from "../hooks/useService.js"; import type { PermissionMode } from "../permissions/types.js"; import type { FileIndexServiceState } from "../services/FileIndexService.js"; @@ -180,20 +183,29 @@ const UserInput: React.FC = ({ fileIndex: FileIndexServiceState; }>(["fileIndex"]); - const getSlashCommands = () => { - if (assistant || isRemoteMode) { - return getAllSlashCommands(assistant || ({} as AssistantConfig), { - isRemoteMode, - }); - } + const [slashCommands, setSlashCommands] = useState([ + { name: "help", description: "Show help message", category: "system" }, + { + name: "clear", + description: "Clear the chat history", + category: "system", + }, + { name: "exit", description: "Exit the chat", category: "system" }, + ]); + + useEffect(() => { + const loadCommands = async () => { + if (assistant || isRemoteMode) { + const commands = await getAllSlashCommands( + assistant || ({} as AssistantConfig), + { isRemoteMode }, + ); + setSlashCommands(commands); + } + }; - // Fallback - basic commands without assistant - return [ - { name: "help", description: "Show help message" }, - { name: "clear", description: "Clear the chat history" }, - { name: "exit", description: "Exit the chat" }, - ]; - }; + void loadCommands(); + }, [isRemoteMode, assistant?.prompts, assistant?.rules]); // Cycle through permission modes const cycleModes = async () => { @@ -255,8 +267,7 @@ const UserInput: React.FC = ({ const afterSlash = trimmedText.slice(1).split(/[\s\n]/)[0]; // We're in a slash command context - check if it's a complete command - const allCommands = getSlashCommands(); - const exactMatch = allCommands.find((cmd) => cmd.name === afterSlash); + const exactMatch = slashCommands.find((cmd) => cmd.name === afterSlash); // Hide selector if we have an exact match and there's any additional content if (exactMatch) { @@ -275,7 +286,7 @@ const UserInput: React.FC = ({ } // Check if there are any matching commands - const filteredCommands = allCommands.filter((cmd) => + const filteredCommands = slashCommands.filter((cmd) => cmd.name.toLowerCase().includes(afterSlash.toLowerCase()), ); @@ -346,8 +357,7 @@ const UserInput: React.FC = ({ // Get filtered commands for navigation - using the same sorting logic as SlashCommandUI const getFilteredCommands = () => { - const allCommands = getSlashCommands(); - return allCommands + return slashCommands .filter((cmd) => cmd.name.toLowerCase().includes(slashCommandFilter.toLowerCase()), ) diff --git a/extensions/cli/src/util/loadMarkdownSkills.ts b/extensions/cli/src/util/loadMarkdownSkills.ts index a6b06ff936e..cd74dd8496d 100644 --- a/extensions/cli/src/util/loadMarkdownSkills.ts +++ b/extensions/cli/src/util/loadMarkdownSkills.ts @@ -144,3 +144,27 @@ export async function loadMarkdownSkills(): Promise { return { skills, errors }; } + +export function getSkillSlashCommandName(skill: Skill): string { + // Normalize skill name to lowercase and sanitize for use as command name + const base = skill.name.trim().toLowerCase(); + const safe = base + .replace(/[^a-z0-9]+/g, "-") + .replace(/^-+/, "") + .replace(/-+$/, ""); + + if (safe) { + return `skill-${safe}`; + } + + // Fallback to directory name if skill name is invalid + const dirName = path + .basename(path.dirname(skill.path)) + .toLowerCase() + .replace(/[^a-z0-9]+/g, "-") + .replace(/^-+/, "") + .replace(/-+$/, ""); + + const fallback = dirName || "skill"; + return `skill-${fallback}`; +} From 8f4d7d08be021aa0d04fde1998c24c61f54f6ef9 Mon Sep 17 00:00:00 2001 From: uinstinct <61635505+uinstinct@users.noreply.github.com> Date: Fri, 6 Mar 2026 13:18:06 +0530 Subject: [PATCH 3/7] load the skill using skills tool --- extensions/cli/src/slashCommands.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/extensions/cli/src/slashCommands.ts b/extensions/cli/src/slashCommands.ts index af171697c0f..5fc521c179c 100644 --- a/extensions/cli/src/slashCommands.ts +++ b/extensions/cli/src/slashCommands.ts @@ -294,8 +294,7 @@ export async function handleSlashCommands( if (matchingSkill) { return { - exit: false, - output: matchingSkill.content, + newInput: `Load the skill using the **Skills** tool and then set the **skill_name** parameter to "${matchingSkill.name}".`, }; } } From a7b544282586992501cf35c4c9bed645a601b2e0 Mon Sep 17 00:00:00 2001 From: uinstinct <61635505+uinstinct@users.noreply.github.com> Date: Fri, 6 Mar 2026 13:20:54 +0530 Subject: [PATCH 4/7] make skills tool allowed by default --- extensions/cli/src/permissions/defaultPolicies.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/extensions/cli/src/permissions/defaultPolicies.ts b/extensions/cli/src/permissions/defaultPolicies.ts index 8bc4bdf7576..caeac927f4a 100644 --- a/extensions/cli/src/permissions/defaultPolicies.ts +++ b/extensions/cli/src/permissions/defaultPolicies.ts @@ -16,6 +16,7 @@ export function getDefaultToolPolicies( { tool: "AskQuestion", permission: "allow" }, { tool: "Checklist", permission: "allow" }, { tool: "Diff", permission: "allow" }, + { tool: "Skills", permission: "allow" }, { tool: "Exit", permission: "allow" }, // Exit tool is generally safe (headless mode only) { tool: "Fetch", permission: "allow" }, // Technically not read only but edge casey to post w query params { tool: "List", permission: "allow" }, @@ -56,6 +57,7 @@ export const PLAN_MODE_POLICIES: ToolPermissionPolicy[] = [ { tool: "Read", permission: "allow" }, { tool: "ReportFailure", permission: "allow" }, { tool: "Search", permission: "allow" }, + { tool: "Skills", permission: "allow" }, { tool: "Status", permission: "allow" }, { tool: "UploadArtifact", permission: "allow" }, From 010d2890eb756d2cccd580af59c4fb954cfe0ff3 Mon Sep 17 00:00:00 2001 From: uinstinct <61635505+uinstinct@users.noreply.github.com> Date: Fri, 6 Mar 2026 14:23:22 +0530 Subject: [PATCH 5/7] add /import-skills slash command --- extensions/cli/src/commands/commands.ts | 5 ++++ extensions/cli/src/slashCommands.ts | 19 ++++++++++++++ extensions/cli/src/tools/skills.ts | 33 +++++++++++++++++++++++++ 3 files changed, 57 insertions(+) diff --git a/extensions/cli/src/commands/commands.ts b/extensions/cli/src/commands/commands.ts index 1fc6d226a50..76206f5ead6 100644 --- a/extensions/cli/src/commands/commands.ts +++ b/extensions/cli/src/commands/commands.ts @@ -116,6 +116,11 @@ export const SYSTEM_SLASH_COMMANDS: SystemCommand[] = [ description: "List all available skills", category: "system", }, + { + name: "import-skill", + description: "Import a skill from a URL or name into ~/.continue/skills", + category: "system", + }, ]; // Remote mode specific commands diff --git a/extensions/cli/src/slashCommands.ts b/extensions/cli/src/slashCommands.ts index 5fc521c179c..7a8f980760e 100644 --- a/extensions/cli/src/slashCommands.ts +++ b/extensions/cli/src/slashCommands.ts @@ -13,6 +13,7 @@ import { reloadService, SERVICE_NAMES, services } from "./services/index.js"; import { getCurrentSession, updateSessionTitle } from "./session.js"; import { posthogService } from "./telemetry/posthogService.js"; import { telemetryService } from "./telemetry/telemetryService.js"; +import { buildImportSkillPrompt } from "./tools/skills.js"; import { SlashCommandResult } from "./ui/hooks/useChat.types.js"; import { getSkillSlashCommandName, @@ -203,6 +204,23 @@ async function handleSkills(): Promise { }; } +async function handleImportSkill(args: string[]): Promise { + const query = args.join(" ").trim(); + + if (!query) { + return { + exit: false, + output: chalk.yellow( + "Please provide a skill URL or name. Usage: /import-skill ", + ), + }; + } + + return { + newInput: buildImportSkillPrompt(query), + }; +} + const commandHandlers: Record = { help: handleHelp, clear: () => { @@ -239,6 +257,7 @@ const commandHandlers: Record = { }, jobs: handleJobs, skills: () => handleSkills(), + "import-skill": (args) => handleImportSkill(args), }; export async function handleSlashCommands( diff --git a/extensions/cli/src/tools/skills.ts b/extensions/cli/src/tools/skills.ts index 51e7671bdde..172111d611a 100644 --- a/extensions/cli/src/tools/skills.ts +++ b/extensions/cli/src/tools/skills.ts @@ -80,3 +80,36 @@ ${skills.map((skill) => `\nname: ${skill.name}\ndescription: ${skill.description }, }; }; + +export function buildImportSkillPrompt(identifier: string): string { + return ` +# Overview + +The user wants to import skills. + +User-provided skill identifier: +${identifier} + +# Guidelines +- There can be multiple skills in a single repository. +- Use the available tools to fetch content and write files. When you are done, briefly summarize which skill you imported and where you saved it. +- Use the "AskQuestion" tool where required to clarify with the user. + +# Process: + +**Identifier can either be a URL or a skill name** + +- If it looks like a URL (for example, it starts with http:// or https://), open that URL and inspect its contents to find the code or files that define the skill. +- If the URL is a GitHub repository, look for the skills folder. There +- If it looks like a skill name, you should search for the most relevant open-source skill or repository that matches the skill identifier. +- Ask questions to the user to clarify which skill they are referring to if there are multiple options in your findings. + +**Create the skill files** + +- The skills should be created under the directory: ~/.continue/skills/ +- The subdirectory name should match the name of the skill directory in the fetched repository. +- The relevant files and folders along with SKILL.md should be present inside the created skill subdirectory. +- If the skill already exists, ask question to the user to clarify whether they want to update it. +- Important: Before writing any files, ask the user if they want to proceed with the import. +`; +} From 9a905fc568c064da6de0a4123319c36fa013bcd7 Mon Sep 17 00:00:00 2001 From: Aditya Mitra <61635505+uinstinct@users.noreply.github.com> Date: Mon, 9 Mar 2026 15:36:15 +0530 Subject: [PATCH 6/7] Update extensions/cli/src/tools/skills.ts Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com> --- extensions/cli/src/tools/skills.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/cli/src/tools/skills.ts b/extensions/cli/src/tools/skills.ts index 172111d611a..62ca1981956 100644 --- a/extensions/cli/src/tools/skills.ts +++ b/extensions/cli/src/tools/skills.ts @@ -100,7 +100,7 @@ ${identifier} **Identifier can either be a URL or a skill name** - If it looks like a URL (for example, it starts with http:// or https://), open that URL and inspect its contents to find the code or files that define the skill. -- If the URL is a GitHub repository, look for the skills folder. There +- If the URL is a GitHub repository, look for the skills folder. There can be multiple skills within subdirectories. - If it looks like a skill name, you should search for the most relevant open-source skill or repository that matches the skill identifier. - Ask questions to the user to clarify which skill they are referring to if there are multiple options in your findings. From 1b029cab13f7b9310059ad23ba8b33293d8bb684 Mon Sep 17 00:00:00 2001 From: uinstinct <61635505+uinstinct@users.noreply.github.com> Date: Mon, 9 Mar 2026 23:28:05 +0530 Subject: [PATCH 7/7] fix stale in use effect --- extensions/cli/src/ui/SlashCommandUI.tsx | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/extensions/cli/src/ui/SlashCommandUI.tsx b/extensions/cli/src/ui/SlashCommandUI.tsx index 672f3c21867..79d28e7f015 100644 --- a/extensions/cli/src/ui/SlashCommandUI.tsx +++ b/extensions/cli/src/ui/SlashCommandUI.tsx @@ -46,17 +46,25 @@ const SlashCommandUI: React.FC = ({ ); useEffect(() => { + let stale = false; + const loadCommands = async () => { if (assistant || isRemoteMode) { const commands = await getAllSlashCommands( assistant || ({} as AssistantConfig), { isRemoteMode }, ); - setAllCommands(commands); + if (!stale) { + setAllCommands(commands); + } } }; void loadCommands(); + + return () => { + stale = true; + }; }, [isRemoteMode, assistant?.prompts, assistant?.rules]); // Filter commands based on the current filter