From d8af9297580b984787b098dbf333d073e5656f1c Mon Sep 17 00:00:00 2001 From: Hikari Date: Fri, 13 Mar 2026 00:22:01 -0700 Subject: [PATCH] feat: add /context command to CLI built-ins list --- src/lib/commands/slashCommands.test.ts | 34 +++++++++++++++++++++++--- src/lib/commands/slashCommands.ts | 15 ++++++++++++ 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/src/lib/commands/slashCommands.test.ts b/src/lib/commands/slashCommands.test.ts index eed98ac..4b48783 100644 --- a/src/lib/commands/slashCommands.test.ts +++ b/src/lib/commands/slashCommands.test.ts @@ -94,10 +94,11 @@ describe("slashCommands", () => { expect(commandNames).toContain("loop"); expect(commandNames).toContain("batch"); expect(commandNames).toContain("memory"); + expect(commandNames).toContain("context"); }); - it("has 11 commands total", () => { - expect(slashCommands.length).toBe(11); + it("has 12 commands total", () => { + expect(slashCommands.length).toBe(12); }); it("each command has required properties", () => { @@ -189,6 +190,13 @@ describe("slashCommands", () => { expect(batchCmd!.usage).toBe("/batch [tasks]"); }); + it("context command has correct metadata and source", () => { + const contextCmd = slashCommands.find((cmd) => cmd.name === "context"); + expect(contextCmd).toBeDefined(); + expect(contextCmd!.source).toBe("cli"); + expect(contextCmd!.usage).toBe("/context"); + }); + it("app commands do not have source set", () => { const appCommandNames = ["cd", "clear", "new", "help", "search", "summarise", "skill"]; appCommandNames.forEach((name) => { @@ -199,7 +207,7 @@ describe("slashCommands", () => { }); it("cli commands have source set to 'cli'", () => { - const cliCommandNames = ["simplify", "loop", "batch"]; + const cliCommandNames = ["simplify", "loop", "batch", "memory", "context"]; cliCommandNames.forEach((name) => { const cmd = slashCommands.find((c) => c.name === name); expect(cmd).toBeDefined(); @@ -869,6 +877,26 @@ describe("slashCommands", () => { }); }); + describe("/context execute", () => { + it("shows error when no active conversation", async () => { + getMock.mockReturnValue(null); + const contextCmd = slashCommands.find((cmd) => cmd.name === "context")!; + await contextCmd.execute(""); + expect(claudeStore.addLine).toHaveBeenCalledWith("error", "No active conversation"); + }); + + it("sends /context prompt to Claude when there is an active conversation", async () => { + getMock.mockReturnValue("conv-123"); + invokeMock.mockResolvedValue(undefined); + const contextCmd = slashCommands.find((cmd) => cmd.name === "context")!; + await contextCmd.execute(""); + expect(invokeMock).toHaveBeenCalledWith("send_prompt", { + conversationId: "conv-123", + message: "/context", + }); + }); + }); + describe("/cd success path", () => { beforeEach(() => { vi.useFakeTimers(); diff --git a/src/lib/commands/slashCommands.ts b/src/lib/commands/slashCommands.ts index c59cb9b..c4fe697 100644 --- a/src/lib/commands/slashCommands.ts +++ b/src/lib/commands/slashCommands.ts @@ -297,6 +297,21 @@ export const slashCommands: SlashCommand[] = [ await invoke("send_prompt", { conversationId, message: "/memory" }); }, }, + { + name: "context", + description: + "Show current context window usage with optimisation suggestions (Claude Code built-in)", + usage: "/context", + source: "cli", + execute: async () => { + const conversationId = get(claudeStore.activeConversationId); + if (!conversationId) { + claudeStore.addLine("error", "No active conversation"); + return; + } + await invoke("send_prompt", { conversationId, message: "/context" }); + }, + }, { name: "skill", description: "Invoke a Claude Code skill from ~/.claude/skills/",