diff --git a/src/cli/App.tsx b/src/cli/App.tsx index 93026da..5c82946 100644 --- a/src/cli/App.tsx +++ b/src/cli/App.tsx @@ -102,7 +102,6 @@ import type { ToolsetName, ToolsetPreference } from "../tools/toolset"; import { debugLog, debugWarn } from "../utils/debug"; import { handleMcpAdd, - handleMcpUsage, type McpCommandContext, setActiveCommandId as setActiveMcpCommandId, } from "./commands/mcp"; @@ -5990,15 +5989,33 @@ export default function App({ return { submitted: true }; } + // /mcp help - show usage + if (firstWord === "help") { + const cmd = commandRunner.start(msg, "Showing MCP help..."); + const output = [ + "/mcp help", + "", + "Manage MCP servers.", + "", + "USAGE", + " /mcp — open MCP server manager", + " /mcp add ... — add a new server (without OAuth)", + " /mcp connect — interactive wizard with OAuth support", + " /mcp help — show this help", + "", + "EXAMPLES", + " /mcp add --transport http notion https://mcp.notion.com/mcp", + ].join("\n"); + cmd.finish(output, true); + return { submitted: true }; + } + // Unknown subcommand { const cmd = commandRunner.start(msg, "Checking MCP usage..."); - setActiveMcpCommandId(cmd.id); - try { - handleMcpUsage(mcpCtx, msg); - } finally { - setActiveMcpCommandId(null); - } + cmd.fail( + `Unknown subcommand: "${firstWord}". Run /mcp help for usage.`, + ); } return { submitted: true }; } @@ -6716,18 +6733,38 @@ export default function App({ // Supports: /compact, /compact all, /compact sliding_window if (msg.trim().startsWith("/compact")) { const parts = msg.trim().split(/\s+/); - const modeArg = parts[1] as "all" | "sliding_window" | undefined; + const rawModeArg = parts[1]; const validModes = ["all", "sliding_window"]; + if (rawModeArg === "help") { + const cmd = commandRunner.start( + msg.trim(), + "Showing compact help...", + ); + const output = [ + "/compact help", + "", + "Summarize conversation history (compaction).", + "", + "USAGE", + " /compact — compact with default mode", + " /compact all — compact all messages", + " /compact sliding_window — compact with sliding window", + " /compact help — show this help", + ].join("\n"); + cmd.finish(output, true); + return { submitted: true }; + } + + const modeArg = rawModeArg as "all" | "sliding_window" | undefined; + // Validate mode if provided if (modeArg && !validModes.includes(modeArg)) { const cmd = commandRunner.start( msg.trim(), - `Invalid mode "${modeArg}". Valid modes: ${validModes.join(", ")}`, - ); - cmd.fail( - `Invalid mode "${modeArg}". Valid modes: ${validModes.join(", ")}`, + `Invalid mode "${modeArg}".`, ); + cmd.fail(`Invalid mode "${modeArg}". Run /compact help for usage.`); return { submitted: true }; } @@ -6839,6 +6876,21 @@ export default function App({ const subcommand = parts[1]?.toLowerCase(); const cmd = commandRunner.start(msg.trim(), "Processing rename..."); + if (subcommand === "help") { + const output = [ + "/rename help", + "", + "Rename the current agent or conversation.", + "", + "USAGE", + " /rename agent — rename the agent", + " /rename convo — rename the conversation", + " /rename help — show this help", + ].join("\n"); + cmd.finish(output, true); + return { submitted: true }; + } + if ( !subcommand || (subcommand !== "agent" && subcommand !== "convo") @@ -6919,8 +6971,22 @@ export default function App({ "Updating description...", ); + if (newDescription === "help") { + const output = [ + "/description help", + "", + "Update the current agent's description.", + "", + "USAGE", + " /description — set agent description", + " /description help — show this help", + ].join("\n"); + cmd.finish(output, true); + return { submitted: true }; + } + if (!newDescription) { - cmd.fail("Please provide a description: /description "); + cmd.fail("Usage: /description "); return { submitted: true }; } @@ -6966,6 +7032,25 @@ export default function App({ const parts = msg.trim().split(/\s+/); const targetConvId = parts[1]; // Optional conversation ID + if (targetConvId === "help") { + const cmd = commandRunner.start( + msg.trim(), + "Showing resume help...", + ); + const output = [ + "/resume help", + "", + "Resume a previous conversation.", + "", + "USAGE", + " /resume — open conversation selector", + " /resume — switch directly to a conversation", + " /resume help — show this help", + ].join("\n"); + cmd.finish(output, true); + return { submitted: true }; + } + if (targetConvId) { const cmd = commandRunner.start( msg.trim(), @@ -7255,6 +7340,22 @@ export default function App({ if (msg.trim() === "/pin" || msg.trim().startsWith("/pin ")) { const argsStr = msg.trim().slice(4).trim(); + if (argsStr === "help") { + const cmd = commandRunner.start(msg.trim(), "Showing pin help..."); + const output = [ + "/pin help", + "", + "Pin the current agent.", + "", + "USAGE", + " /pin — pin globally (interactive)", + " /pin -l — pin locally to this directory", + " /pin help — show this help", + ].join("\n"); + cmd.finish(output, true); + return { submitted: true }; + } + // Parse args to check if name was provided const parts = argsStr.split(/\s+/).filter(Boolean); let hasNameArg = false; @@ -7304,6 +7405,27 @@ export default function App({ // Special handling for /unpin command - unpin current agent from project (or globally with -g) if (msg.trim() === "/unpin" || msg.trim().startsWith("/unpin ")) { + const unpinArgsStr = msg.trim().slice(6).trim(); + + if (unpinArgsStr === "help") { + const cmd = commandRunner.start( + msg.trim(), + "Showing unpin help...", + ); + const output = [ + "/unpin help", + "", + "Unpin the current agent.", + "", + "USAGE", + " /unpin — unpin globally", + " /unpin -l — unpin locally", + " /unpin help — show this help", + ].join("\n"); + cmd.finish(output, true); + return { submitted: true }; + } + const profileCtx: ProfileCommandContext = { buffersRef, refreshDerived, @@ -7454,12 +7576,17 @@ export default function App({ if (!subcommand || subcommand === "help") { const output = [ - "memfs commands:", - "- /memfs status — show status", - "- /memfs enable — enable filesystem-backed memory", - "- /memfs disable — disable filesystem-backed memory", - "- /memfs sync — sync blocks and files now", - "- /memfs reset — move local memfs to /tmp and recreate dirs", + "/memfs help", + "", + "Manage filesystem-backed memory.", + "", + "USAGE", + " /memfs status — show status", + " /memfs enable — enable filesystem-backed memory", + " /memfs disable — disable filesystem-backed memory", + " /memfs sync — sync blocks and files now", + " /memfs reset — move local memfs to /tmp and recreate dirs", + " /memfs help — show this help", ].join("\n"); cmd.finish(output, true); return { submitted: true }; @@ -7668,7 +7795,7 @@ export default function App({ // Unknown subcommand cmd.fail( - `Unknown subcommand: ${subcommand}. Use /memfs, /memfs enable, /memfs disable, /memfs sync, or /memfs reset.`, + `Unknown subcommand: "${subcommand}". Run /memfs help for usage.`, ); return { submitted: true }; } diff --git a/src/cli/commands/connect.ts b/src/cli/commands/connect.ts index 9884b0a..b044f58 100644 --- a/src/cli/commands/connect.ts +++ b/src/cli/commands/connect.ts @@ -617,13 +617,36 @@ export async function handleDisconnect( const parts = msg.trim().split(/\s+/); const provider = parts[1]?.toLowerCase(); + // /disconnect help + if (provider === "help") { + addCommandResult( + ctx.buffersRef, + ctx.refreshDerived, + msg, + [ + "/disconnect help", + "", + "Disconnect an existing account.", + "", + "USAGE", + " /disconnect — disconnect a provider", + " /disconnect help — show this help", + "", + "PROVIDERS", + " codex, claude, zai, minimax, openrouter, bedrock", + ].join("\n"), + true, + ); + return; + } + // If no provider specified, show usage if (!provider) { addCommandResult( ctx.buffersRef, ctx.refreshDerived, msg, - "Usage: /disconnect \n\nAvailable providers: codex, claude, zai, minimax, openrouter, bedrock", + "Usage: /disconnect ", false, ); return; @@ -670,7 +693,7 @@ export async function handleDisconnect( ctx.buffersRef, ctx.refreshDerived, msg, - `Error: Unknown provider "${provider}"\n\nAvailable providers: codex, claude, zai, minimax, openrouter, bedrock\nUsage: /disconnect `, + `Unknown provider: "${provider}". Run /disconnect help for usage.`, false, ); } diff --git a/src/cli/commands/registry.ts b/src/cli/commands/registry.ts index 56e966d..9af7678 100644 --- a/src/cli/commands/registry.ts +++ b/src/cli/commands/registry.ts @@ -274,6 +274,19 @@ export const commands: Record = { desc: "Setup terminal shortcuts [--revert]", order: 37, handler: async (args: string[]) => { + if (args.includes("help")) { + return [ + "/terminal help", + "", + "Setup terminal keyboard shortcuts.", + "", + "USAGE", + " /terminal — install Shift+Enter keybinding", + " /terminal --revert — remove keybinding", + " /terminal help — show this help", + ].join("\n"); + } + const { detectTerminalType, getKeybindingsPath,