Skip to content

Commit 6fe05af

Browse files
committed
feat(commands): add custom slash commands with add/remove/list support
Users can now create, manage, and use custom slash commands: - /commands add <name> <prompt> - Create a new custom command - /commands remove <name> - Remove an existing custom command - /commands list - List all custom commands - Custom commands can be executed by typing /<name>
1 parent 4496468 commit 6fe05af

2 files changed

Lines changed: 123 additions & 9 deletions

File tree

src/hooks/use-input-handler.ts

Lines changed: 122 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -546,6 +546,10 @@ export function useInputHandler({
546546
{ command: "/chat load <name>", description: "Load a saved chat" },
547547
{ command: "/chat list", description: "List saved chats" },
548548
{ command: "/chat delete <name>", description: "Delete a saved chat" },
549+
{ command: "/skills", description: "Manage AI skills" },
550+
{ command: "/agents", description: "Manage AI agents" },
551+
{ command: "/import", description: "Import from other AI assistants" },
552+
{ command: "/index", description: "Index current directory" },
549553
{
550554
command: "/mcp <action>",
551555
description: "Manage MCP servers",
@@ -729,15 +733,106 @@ Config Commands:
729733
}
730734

731735
if (trimmedInput.startsWith("/commands ")) {
732-
setChatHistory(prev => [
733-
...prev,
734-
{
735-
type: "assistant",
736-
content:
737-
"🚧 Custom commands support implies storing them. Feature placeholder.",
738-
timestamp: new Date(),
739-
},
740-
]);
736+
const args = trimmedInput.split(" ");
737+
const action = args[1];
738+
const manager = getSettingsManager();
739+
const settings = manager.loadUserSettings();
740+
const customCommands = settings.custom_commands || {};
741+
742+
if (action === "add") {
743+
const name = args[2];
744+
const prompt = args.slice(3).join(" ");
745+
746+
if (!name || !prompt) {
747+
setChatHistory(prev => [
748+
...prev,
749+
{
750+
type: "assistant",
751+
content: "❌ Usage: /commands add <name> <prompt>",
752+
timestamp: new Date(),
753+
},
754+
]);
755+
clearInput();
756+
return true;
757+
}
758+
759+
const newCommands = { ...customCommands, [name]: prompt };
760+
manager.updateUserSetting("custom_commands", newCommands);
761+
762+
setChatHistory(prev => [
763+
...prev,
764+
{
765+
type: "assistant",
766+
content: `✅ Custom command '/${name}' created.`,
767+
timestamp: new Date(),
768+
},
769+
]);
770+
} else if (action === "remove") {
771+
const name = args[2];
772+
773+
if (!name || !customCommands[name]) {
774+
setChatHistory(prev => [
775+
...prev,
776+
{
777+
type: "assistant",
778+
content: `❌ Command '/${name}' not found.`,
779+
timestamp: new Date(),
780+
},
781+
]);
782+
clearInput();
783+
return true;
784+
}
785+
786+
const newCommands = { ...customCommands };
787+
delete newCommands[name];
788+
manager.updateUserSetting("custom_commands", newCommands);
789+
790+
setChatHistory(prev => [
791+
...prev,
792+
{
793+
type: "assistant",
794+
content: `✅ Custom command '/${name}' removed.`,
795+
timestamp: new Date(),
796+
},
797+
]);
798+
} else if (action === "list") {
799+
const commandList = Object.keys(customCommands);
800+
801+
if (commandList.length === 0) {
802+
setChatHistory(prev => [
803+
...prev,
804+
{
805+
type: "assistant",
806+
content:
807+
"No custom commands defined. Use /commands add to create one.",
808+
timestamp: new Date(),
809+
},
810+
]);
811+
} else {
812+
const list = commandList
813+
.map(name => ` /${name} - ${customCommands[name]}`)
814+
.join("\n");
815+
816+
setChatHistory(prev => [
817+
...prev,
818+
{
819+
type: "assistant",
820+
content: `Custom Commands:\n${list}`,
821+
timestamp: new Date(),
822+
},
823+
]);
824+
}
825+
} else {
826+
setChatHistory(prev => [
827+
...prev,
828+
{
829+
type: "assistant",
830+
content: "❌ Usage: /commands <add|remove|list> [name] [prompt]",
831+
timestamp: new Date(),
832+
},
833+
]);
834+
}
835+
741836
clearInput();
742837
return true;
743838
}
@@ -1750,6 +1845,24 @@ Respond with ONLY the commit message, no additional text.`;
17501845
}
17511846
}
17521847

1848+
// Check if input matches a custom command
1849+
if (userInput.startsWith("/")) {
1850+
const commandName = userInput.split(" ")[0].slice(1);
1851+
const manager = getSettingsManager();
1852+
const settings = manager.loadUserSettings();
1853+
const customCommands = settings.custom_commands || {};
1854+
1855+
if (customCommands[commandName]) {
1856+
// Replace the command with its prompt
1857+
const args = userInput.split(" ").slice(1);
1858+
resolvedInput = customCommands[commandName];
1859+
// If there are arguments, append them to the custom prompt
1860+
if (args.length > 0) {
1861+
resolvedInput += " " + args.join(" ");
1862+
}
1863+
}
1864+
}
1865+
17531866
// Add mode context if needed
17541867
if (agentMode === "plan") {
17551868
resolvedInput = `[MODE: PLAN] ${resolvedInput}`;

src/utils/settings-manager.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ export interface UserSettings {
9191
prompt: string;
9292
}>;
9393
};
94+
custom_commands?: Record<string, string>;
9495
env?: Record<string, string>;
9596
context?: {
9697
fileName: string[];

0 commit comments

Comments
 (0)