| author | |
| committer | |
| log | 3e2370fbbf1efacb341a68e6f28efb06b695e148 |
| tree | 62880092d34d532e01138b247a1f3ac4fe21ca2c |
| parent | 91e53e501c9e7eb03f0ea4a5b72221d08eff9c5c |
| signature | Signed by PGP key B5690EEEBB952194 |
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: Julius Marminge <julius0216@outlook.com>6 files changed, 24 insertions(+), 0 deletions(-)
apps/web/src/components/CommandPalette.tsx+11| ... | @@ -469,6 +469,7 @@ function overlayModeForCommand(command: string | null): SearchOverlayMode | null | ... | @@ -469,6 +469,7 @@ function overlayModeForCommand(command: string | null): SearchOverlayMode | null |
| 469 | } | 469 | } |
| 470 | 470 | ||
| 471 | export function CommandPalette({ children }: { children: ReactNode }) { | 471 | export function CommandPalette({ children }: { children: ReactNode }) { |
| 472 | const navigate = useNavigate(); | ||
| 472 | const [state, dispatch] = useReducer(reduceCommandPaletteUiState, { | 473 | const [state, dispatch] = useReducer(reduceCommandPaletteUiState, { |
| 473 | open: false, | 474 | open: false, |
| 474 | mode: "command", | 475 | mode: "command", |
| ... | @@ -561,6 +562,13 @@ export function CommandPalette({ children }: { children: ReactNode }) { | ... | @@ -561,6 +562,13 @@ export function CommandPalette({ children }: { children: ReactNode }) { |
| 561 | }); | 562 | }); |
| 562 | return; | 563 | return; |
| 563 | } | 564 | } |
| 565 | if (command === "usage.open") { | ||
| 566 | event.preventDefault(); | ||
| 567 | event.stopPropagation(); | ||
| 568 | setOpen(false); | ||
| 569 | void navigate({ to: "/usage" }); | ||
| 570 | return; | ||
| 571 | } | ||
| 564 | const mode = overlayModeForCommand(command); | 572 | const mode = overlayModeForCommand(command); |
| 565 | if (mode === null) { | 573 | if (mode === null) { |
| 566 | return; | 574 | return; |
| ... | @@ -574,9 +582,11 @@ export function CommandPalette({ children }: { children: ReactNode }) { | ... | @@ -574,9 +582,11 @@ export function CommandPalette({ children }: { children: ReactNode }) { |
| 574 | }, [ | 582 | }, [ |
| 575 | appearanceMode, | 583 | appearanceMode, |
| 576 | keybindings, | 584 | keybindings, |
| 585 | navigate, | ||
| 577 | previewOpen, | 586 | previewOpen, |
| 578 | resolvedTheme, | 587 | resolvedTheme, |
| 579 | setAppearanceMode, | 588 | setAppearanceMode, |
| 589 | setOpen, | ||
| 580 | terminalOpen, | 590 | terminalOpen, |
| 581 | theme, | 591 | theme, |
| 582 | themeHalves, | 592 | themeHalves, |
| ... | @@ -2023,6 +2033,7 @@ function OpenCommandPaletteDialog(props: { | ... | @@ -2023,6 +2033,7 @@ function OpenCommandPaletteDialog(props: { |
| 2023 | searchTerms: ["usage", "use", "tokens", "cost", "spend", "limits", "stats", "analytics"], | 2033 | searchTerms: ["usage", "use", "tokens", "cost", "spend", "limits", "stats", "analytics"], |
| 2024 | title: "Open usage", | 2034 | title: "Open usage", |
| 2025 | icon: <ChartNoAxesColumnIcon className={ITEM_ICON_CLASS} />, | 2035 | icon: <ChartNoAxesColumnIcon className={ITEM_ICON_CLASS} />, |
| 2036 | shortcutCommand: "usage.open", | ||
| 2026 | run: async () => { | 2037 | run: async () => { |
| 2027 | await navigate({ to: "/usage" }); | 2038 | await navigate({ to: "/usage" }); |
| 2028 | }, | 2039 | }, |
apps/web/src/components/settings/KeybindingsSettings.logic.test.ts+1| ... | @@ -243,6 +243,7 @@ describe("KeybindingsSettings.logic", () => { | ... | @@ -243,6 +243,7 @@ describe("KeybindingsSettings.logic", () => { |
| 243 | "chat.new", | 243 | "chat.new", |
| 244 | "rightPanel.toggleMaximized", | 244 | "rightPanel.toggleMaximized", |
| 245 | "thread.stop", | 245 | "thread.stop", |
| 246 | "usage.open", | ||
| 246 | "script.setup-db.run", | 247 | "script.setup-db.run", |
| 247 | ]), | 248 | ]), |
| 248 | ); | 249 | ); |
docs/user/usage.md+4| ... | @@ -1,5 +1,9 @@ | ... | @@ -1,5 +1,9 @@ |
| 1 | # Usage and limits | 1 | # Usage and limits |
| 2 | 2 | ||
| 3 | Open **Usage** from the sidebar or the command palette, or press `mod+u` on web and | ||
| 4 | desktop when the terminal is not focused. Customize `usage.open` in | ||
| 5 | **Settings → Keybindings**. | ||
| 6 | |||
| 3 | ## Understand your usage | 7 | ## Understand your usage |
| 4 | 8 | ||
| 5 | **Usage** combines Codex, Claude Code, and Grok Build session history from your connected | 9 | **Usage** combines Codex, Claude Code, and Grok Build session history from your connected |
packages/contracts/src/keybindings.test.ts+6| ... | @@ -78,6 +78,12 @@ it.effect("parses keybinding rules", () => | ... | @@ -78,6 +78,12 @@ it.effect("parses keybinding rules", () => |
| 78 | }); | 78 | }); |
| 79 | assert.strictEqual(parsedProjectSearch.command, "projectSearch.toggle"); | 79 | assert.strictEqual(parsedProjectSearch.command, "projectSearch.toggle"); |
| 80 | 80 | ||
| 81 | const parsedUsageOpen = yield* decode(KeybindingRule, { | ||
| 82 | key: "mod+u", | ||
| 83 | command: "usage.open", | ||
| 84 | }); | ||
| 85 | assert.strictEqual(parsedUsageOpen.command, "usage.open"); | ||
| 86 | |||
| 81 | const parsedThemeEditor = yield* decode(KeybindingRule, { | 87 | const parsedThemeEditor = yield* decode(KeybindingRule, { |
| 82 | key: "mod+alt+shift+t", | 88 | key: "mod+alt+shift+t", |
| 83 | command: "themeEditor.toggle", | 89 | command: "themeEditor.toggle", |
packages/contracts/src/keybindings.ts+1| ... | @@ -78,6 +78,7 @@ export const STATIC_KEYBINDING_COMMANDS = [ | ... | @@ -78,6 +78,7 @@ export const STATIC_KEYBINDING_COMMANDS = [ |
| 78 | "commandPalette.toggle", | 78 | "commandPalette.toggle", |
| 79 | "filePicker.toggle", | 79 | "filePicker.toggle", |
| 80 | "projectSearch.toggle", | 80 | "projectSearch.toggle", |
| 81 | "usage.open", | ||
| 81 | "theme.select", | 82 | "theme.select", |
| 82 | "appearance.cycle", | 83 | "appearance.cycle", |
| 83 | "themeEditor.toggle", | 84 | "themeEditor.toggle", |
packages/shared/src/keybindings.ts+1| ... | @@ -40,6 +40,7 @@ export const DEFAULT_KEYBINDINGS: ReadonlyArray<KeybindingRule> = [ | ... | @@ -40,6 +40,7 @@ export const DEFAULT_KEYBINDINGS: ReadonlyArray<KeybindingRule> = [ |
| 40 | { key: "mod+k", command: "commandPalette.toggle", when: "!terminalFocus" }, | 40 | { key: "mod+k", command: "commandPalette.toggle", when: "!terminalFocus" }, |
| 41 | { key: "mod+p", command: "filePicker.toggle", when: "!terminalFocus" }, | 41 | { key: "mod+p", command: "filePicker.toggle", when: "!terminalFocus" }, |
| 42 | { key: "mod+shift+f", command: "projectSearch.toggle", when: "!terminalFocus" }, | 42 | { key: "mod+shift+f", command: "projectSearch.toggle", when: "!terminalFocus" }, |
| 43 | { key: "mod+u", command: "usage.open", when: "!terminalFocus" }, | ||
| 43 | { key: "mod+alt+a", command: "theme.select", when: "!terminalFocus" }, | 44 | { key: "mod+alt+a", command: "theme.select", when: "!terminalFocus" }, |
| 44 | { key: "mod+alt+shift+a", command: "appearance.cycle", when: "!terminalFocus" }, | 45 | { key: "mod+alt+shift+a", command: "appearance.cycle", when: "!terminalFocus" }, |
| 45 | { key: "mod+alt+shift+t", command: "themeEditor.toggle" }, | 46 | { key: "mod+alt+shift+t", command: "themeEditor.toggle" }, |