From 08caf7b9fc50890a2f99b410051f1df9aee22b70 Mon Sep 17 00:00:00 2001 From: LK Date: Thu, 8 Jan 2026 13:41:32 +0100 Subject: [PATCH 1/2] feat(commands): add /usage alias for /status --- docs/cli/index.md | 2 +- docs/tools/slash-commands.md | 23 ++--------------------- src/auto-reply/command-detection.test.ts | 2 ++ src/auto-reply/commands-registry.test.ts | 2 ++ src/auto-reply/commands-registry.ts | 2 +- 5 files changed, 8 insertions(+), 23 deletions(-) diff --git a/docs/cli/index.md b/docs/cli/index.md index 272a3a64f..5abfdf62c 100644 --- a/docs/cli/index.md +++ b/docs/cli/index.md @@ -377,7 +377,7 @@ Options: Clawdbot can surface provider usage/quota when OAuth/API creds are available. Surfaces: -- `/status` (adds a short usage line when available) +- `/status` (alias: `/usage`; adds a short usage line when available) - `clawdbot status --usage` (prints full provider breakdown) - macOS menu bar (Usage section under Context) diff --git a/docs/tools/slash-commands.md b/docs/tools/slash-commands.md index f35c0db70..d8e29444f 100644 --- a/docs/tools/slash-commands.md +++ b/docs/tools/slash-commands.md @@ -35,8 +35,7 @@ Directives (`/think`, `/verbose`, `/reasoning`, `/elevated`) are parsed even whe Text + native (when enabled): - `/help` -- `/status` -- `/debug show|set|unset|reset` (runtime overrides, owner-only) +- `/status` (alias: `/usage`) - `/cost on|off` (toggle per-response usage line) - `/stop` - `/restart` @@ -47,7 +46,7 @@ Text + native (when enabled): - `/verbose on|off` (alias: `/v`) - `/reasoning on|off|stream` (alias: `/reason`; `stream` = Telegram draft only) - `/elevated on|off` (alias: `/elev`) -- `/model ` (or `/` from `agents.defaults.models.*.alias`) +- `/model ` (or `/` from `agent.models.*.alias`) - `/queue ` (plus options like `debounce:2s cap:25 drop:summarize`; send `/queue` to see current settings) Text-only: @@ -60,24 +59,6 @@ Notes: - `/verbose` is meant for debugging and extra visibility; keep it **off** in normal use. - `/reasoning` (and `/verbose`) are risky in group settings: they may reveal internal reasoning or tool output you did not intend to expose. Prefer leaving them off, especially in group chats. -## Debug overrides - -`/debug` lets you set **runtime-only** config overrides (memory, not disk). Owner-only. - -Examples: - -``` -/debug show -/debug set messages.responsePrefix="[clawdbot]" -/debug set whatsapp.allowFrom=["+1555","+4477"] -/debug unset messages.responsePrefix -/debug reset -``` - -Notes: -- Overrides apply immediately to new config reads, but do **not** write to `clawdbot.json`. -- Use `/debug reset` to clear all overrides and return to the on-disk config. - ## Surface notes - **Text commands** run in the normal chat session (DMs share `main`, groups have their own session). diff --git a/src/auto-reply/command-detection.test.ts b/src/auto-reply/command-detection.test.ts index e8a14a898..fe8ec2f92 100644 --- a/src/auto-reply/command-detection.test.ts +++ b/src/auto-reply/command-detection.test.ts @@ -44,6 +44,8 @@ describe("control command parsing", () => { expect(hasControlCommand("help")).toBe(false); expect(hasControlCommand("/status")).toBe(true); expect(hasControlCommand("/status:")).toBe(true); + expect(hasControlCommand("/usage")).toBe(true); + expect(hasControlCommand("/usage:")).toBe(true); expect(hasControlCommand("status")).toBe(false); }); diff --git a/src/auto-reply/commands-registry.test.ts b/src/auto-reply/commands-registry.test.ts index fc270ab08..3d0a8eae6 100644 --- a/src/auto-reply/commands-registry.test.ts +++ b/src/auto-reply/commands-registry.test.ts @@ -24,6 +24,8 @@ describe("commands registry", () => { expect(detection.exact.has("/help")).toBe(true); expect(detection.regex.test("/status")).toBe(true); expect(detection.regex.test("/status:")).toBe(true); + expect(detection.regex.test("/usage")).toBe(true); + expect(detection.regex.test("/usage:")).toBe(true); expect(detection.regex.test("/stop")).toBe(true); expect(detection.regex.test("/send:")).toBe(true); expect(detection.regex.test("/debug set foo=bar")).toBe(true); diff --git a/src/auto-reply/commands-registry.ts b/src/auto-reply/commands-registry.ts index 4f3ec4ef4..bbdda249f 100644 --- a/src/auto-reply/commands-registry.ts +++ b/src/auto-reply/commands-registry.ts @@ -25,7 +25,7 @@ const CHAT_COMMANDS: ChatCommandDefinition[] = [ key: "status", nativeName: "status", description: "Show current status.", - textAliases: ["/status"], + textAliases: ["/status", "/usage"], }, { key: "debug", From 68ad27e31c9b0bc66f1091eeffb84a6d6a475863 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Fri, 9 Jan 2026 17:10:53 +0100 Subject: [PATCH 2/2] fix(commands): wire /usage to status (#492) (thanks @lc0rp) --- CHANGELOG.md | 1 + docs/tools/slash-commands.md | 21 +++++++++++++++++++- src/auto-reply/reply.directive.parse.test.ts | 6 ++++++ src/auto-reply/reply.triggers.test.ts | 17 ++++++++++++++++ src/auto-reply/reply/commands.ts | 3 ++- src/auto-reply/reply/directives.ts | 2 +- 6 files changed, 47 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 783575b69..3318ae020 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ - Providers: add Microsoft Teams provider with polling, attachments, and CLI send support. (#404) — thanks @onutc - Slack: honor reply tags + replyToMode while keeping threaded replies in-thread. (#574) — thanks @bolismauro - Commands: accept /models as an alias for /model. +- Commands: add `/usage` as an alias for `/status`. (#492) — thanks @lc0rp - Models/Auth: show per-agent auth candidates in `/model status`, and add `clawdbot models auth order {get,set,clear}` (per-agent auth rotation overrides). — thanks @steipete - Debugging: add raw model stream logging flags and document gateway watch mode. - Gateway: decode dns-sd escaped UTF-8 in discovery output and show scan progress immediately. — thanks @steipete diff --git a/docs/tools/slash-commands.md b/docs/tools/slash-commands.md index d8e29444f..33e3fff6b 100644 --- a/docs/tools/slash-commands.md +++ b/docs/tools/slash-commands.md @@ -36,6 +36,7 @@ Directives (`/think`, `/verbose`, `/reasoning`, `/elevated`) are parsed even whe Text + native (when enabled): - `/help` - `/status` (alias: `/usage`) +- `/debug show|set|unset|reset` (runtime overrides, owner-only) - `/cost on|off` (toggle per-response usage line) - `/stop` - `/restart` @@ -46,7 +47,7 @@ Text + native (when enabled): - `/verbose on|off` (alias: `/v`) - `/reasoning on|off|stream` (alias: `/reason`; `stream` = Telegram draft only) - `/elevated on|off` (alias: `/elev`) -- `/model ` (or `/` from `agent.models.*.alias`) +- `/model ` (or `/` from `agents.defaults.models.*.alias`) - `/queue ` (plus options like `debounce:2s cap:25 drop:summarize`; send `/queue` to see current settings) Text-only: @@ -59,6 +60,24 @@ Notes: - `/verbose` is meant for debugging and extra visibility; keep it **off** in normal use. - `/reasoning` (and `/verbose`) are risky in group settings: they may reveal internal reasoning or tool output you did not intend to expose. Prefer leaving them off, especially in group chats. +## Debug overrides + +`/debug` lets you set **runtime-only** config overrides (memory, not disk). Owner-only. + +Examples: + +``` +/debug show +/debug set messages.responsePrefix="[clawdbot]" +/debug set whatsapp.allowFrom=["+1555","+4477"] +/debug unset messages.responsePrefix +/debug reset +``` + +Notes: +- Overrides apply immediately to new config reads, but do **not** write to `clawdbot.json`. +- Use `/debug reset` to clear all overrides and return to the on-disk config. + ## Surface notes - **Text commands** run in the normal chat session (DMs share `main`, groups have their own session). diff --git a/src/auto-reply/reply.directive.parse.test.ts b/src/auto-reply/reply.directive.parse.test.ts index e3a2fecfb..09785796e 100644 --- a/src/auto-reply/reply.directive.parse.test.ts +++ b/src/auto-reply/reply.directive.parse.test.ts @@ -144,6 +144,12 @@ describe("directive parsing", () => { expect(res.cleaned).toBe("thats not /tmp/hello"); }); + it("preserves spacing when stripping usage directives before paths", () => { + const res = extractStatusDirective("thats not /usage:/tmp/hello"); + expect(res.hasDirective).toBe(true); + expect(res.cleaned).toBe("thats not /tmp/hello"); + }); + it("parses queue options and modes", () => { const res = extractQueueDirective( "please /queue steer+backlog debounce:2s cap:5 drop:summarize now", diff --git a/src/auto-reply/reply.triggers.test.ts b/src/auto-reply/reply.triggers.test.ts index 38f60125d..ae8154278 100644 --- a/src/auto-reply/reply.triggers.test.ts +++ b/src/auto-reply/reply.triggers.test.ts @@ -242,6 +242,23 @@ describe("trigger handling", () => { }); }); + it("reports status via /usage without invoking the agent", async () => { + await withTempHome(async (home) => { + const res = await getReplyFromConfig( + { + Body: "/usage", + From: "+1002", + To: "+2000", + }, + {}, + makeCfg(home), + ); + const text = Array.isArray(res) ? res[0]?.text : res?.text; + expect(text).toContain("ClawdBot"); + expect(runEmbeddedPiAgent).not.toHaveBeenCalled(); + }); + }); + it("reports active auth profile and key snippet in status", async () => { await withTempHome(async (home) => { const cfg = makeCfg(home); diff --git a/src/auto-reply/reply/commands.ts b/src/auto-reply/reply/commands.ts index 7299a846d..1d2ba748b 100644 --- a/src/auto-reply/reply/commands.ts +++ b/src/auto-reply/reply/commands.ts @@ -594,7 +594,8 @@ export async function handleCommands(params: { const statusRequested = directives.hasStatusDirective || - command.commandBodyNormalized === "/status"; + command.commandBodyNormalized === "/status" || + command.commandBodyNormalized === "/usage"; if (allowTextCommands && statusRequested) { const reply = await buildStatusReply({ cfg, diff --git a/src/auto-reply/reply/directives.ts b/src/auto-reply/reply/directives.ts index d04180411..c6f431b30 100644 --- a/src/auto-reply/reply/directives.ts +++ b/src/auto-reply/reply/directives.ts @@ -170,7 +170,7 @@ export function extractStatusDirective(body?: string): { hasDirective: boolean; } { if (!body) return { cleaned: "", hasDirective: false }; - return extractSimpleDirective(body, ["status"]); + return extractSimpleDirective(body, ["status", "usage"]); } export type { ElevatedLevel, ReasoningLevel, ThinkLevel, VerboseLevel };