diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md
index 5e1d69e..df247d3 100644
--- a/DEVELOPMENT.md
+++ b/DEVELOPMENT.md
@@ -35,7 +35,7 @@ code-editor/
│ │ ├── device-carousel # Multi-device preview
│ │ ├── pip-window # Picture-in-Picture floating preview
│ │ ├── agent-annotations # AI change highlights
-│ │ └── component-isolator # Component isolation (⌘⇧I)
+│ │ └── component-isolator # Component isolation (Cmd/Ctrl+Shift+I)
│ ├── workspace-sidebar # Chat list + navigation
│ ├── agent-panel # Chat/agent interface
│ ├── settings-panel # Settings (themes, GitHub, editor)
@@ -101,9 +101,9 @@ Launches a native macOS window with the web app inside. Both the web frontend an
Copy `.env.example` → `.env` and fill in:
-| Variable | Required | Description |
-| ------------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `NEXT_PUBLIC_SPOTIFY_CLIENT_ID` | Optional | Spotify PKCE OAuth Client ID for the music plugin. Create at [developer.spotify.com/dashboard](https://developer.spotify.com/dashboard). |
+| Variable | Required | Description |
+| ------------------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
+| `NEXT_PUBLIC_SPOTIFY_CLIENT_ID` | Optional | Spotify PKCE OAuth Client ID for the music plugin. Create at [developer.spotify.com/dashboard](https://developer.spotify.com/dashboard). |
> **Note:** `NEXT_PUBLIC_` variables are embedded in the client bundle. Only put public client IDs here, never secrets.
@@ -198,19 +198,19 @@ The `release.yml` workflow:
## Keyboard Shortcuts
-| Shortcut | Action |
-| -------- | --------------------------- |
-| `⌘B` | Toggle file explorer |
-| `⌘J` | Toggle terminal |
-| `⌘\` | Toggle sidebar |
-| `⌘P` | Quick open file |
-| `⌘⇧I` | Isolate component (preview) |
-| `⌘K` | Inline edit |
-| `⌘L` | Send selection to chat |
-| `⌘S` | Save file |
-| `⌘⇧F` | Global search |
-| `⌘⇧P` | Command palette |
-| `Esc` | Close overlays |
+| Shortcut | Action |
+| ------------------ | --------------------------- |
+| `Cmd/Ctrl+B` | Toggle file explorer |
+| `Cmd/Ctrl+J` | Toggle terminal |
+| `Cmd/Ctrl+\` | Toggle sidebar |
+| `Cmd/Ctrl+P` | Quick open file |
+| `Cmd/Ctrl+Shift+I` | Isolate component (preview) |
+| `Cmd/Ctrl+K` | Inline edit |
+| `Cmd/Ctrl+L` | Send selection to chat |
+| `Cmd/Ctrl+S` | Save file |
+| `Cmd/Ctrl+Shift+F` | Global search |
+| `Cmd/Ctrl+Shift+P` | Command palette |
+| `Esc` | Close overlays |
---
@@ -236,11 +236,11 @@ To add a new theme:
## Preview System
-The preview panel (`⌘3` or click Preview tab) connects to any local dev server:
+The preview panel (`Cmd/Ctrl+3` or click Preview tab) connects to any local dev server:
- **URL bar** — type `localhost:5173` or any dev server URL
- **Device Carousel** — see your app on iPhone, Pixel, iPad, MacBook, Desktop simultaneously
-- **Component Isolation** (`⌘⇧I`) — isolate a React component from the active file
+- **Component Isolation** (`Cmd/Ctrl+Shift+I`) — isolate a React component from the active file
- **Picture-in-Picture** — float the preview over your code while editing
- **Agent Annotations** — when the AI makes changes, glowing highlights show what changed
diff --git a/README.md b/README.md
index 7f12591..6858d69 100644
--- a/README.md
+++ b/README.md
@@ -8,8 +8,9 @@ A lightweight, AI-native code editor powered by [OpenClaw](https://github.com/op
┌──────────────┬──────────────────────────┬─────────────────┐
│ File Tree │ Monaco Editor │ Agent Panel │
│ │ (multi-tab, vim mode) │ (chat + diff) │
-│ ⌘B toggle │ ⌘K inline edit │ ⌘J toggle │
-│ │ ⌘P quick open │ │
+│ Cmd/Ctrl+B │ Cmd/Ctrl+K │ Cmd/Ctrl+J │
+│ toggle │ inline edit │ toggle │
+│ │ Cmd/Ctrl+P quick open │ │
├──────────────┴──────────────────────────┴─────────────────┤
│ Terminal (xterm.js) │
└───────────────────────────────────────────────────────────┘
@@ -81,7 +82,7 @@ Copy `.env.example` to `.env` and configure. All variables are optional — the
- **Agent Builder** — Choose a persona, customize your system prompt, configure behaviors
- **Inline Edits** — Agent proposes changes, you review diffs and accept/reject per-hunk
- **7 Themes** — Obsidian, Bone, Neon, Catppuccin, VooDoo, CyberNord, PrettyPink
-- **Monaco Editor** — Multi-tab, Vim mode, syntax highlighting, ⌘P quick open
+- **Monaco Editor** — Multi-tab, Vim mode, syntax highlighting, Cmd/Ctrl+P quick open
- **GitHub Integration** — Token-based auth, commit, push, branch switching
- **Terminal** — Integrated xterm.js with gateway slash commands
- **Spotify + YouTube** — Built-in music and video plugins
@@ -108,15 +109,15 @@ See [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) for the technical architecture,
## Keyboard Shortcuts
-| Shortcut | Action |
-| -------- | ------------------------------ |
-| `⌘P` | Quick file open (fuzzy search) |
-| `⌘K` | Inline edit at selection |
-| `⌘B` | Toggle file explorer |
-| `⌘I` | Toggle agent panel |
-| `⌘J` | Toggle terminal |
-| `Enter` | Send message / Start chat |
-| `Esc` | Close overlays |
+| Shortcut | Action |
+| ------------ | ------------------------------ |
+| `Cmd/Ctrl+P` | Quick file open (fuzzy search) |
+| `Cmd/Ctrl+K` | Inline edit at selection |
+| `Cmd/Ctrl+B` | Toggle file explorer |
+| `Cmd/Ctrl+I` | Toggle agent panel |
+| `Cmd/Ctrl+J` | Toggle terminal |
+| `Enter` | Send message / Start chat |
+| `Esc` | Close overlays |
## Tech Stack
diff --git a/__tests__/platform.test.ts b/__tests__/platform.test.ts
new file mode 100644
index 0000000..4141d58
--- /dev/null
+++ b/__tests__/platform.test.ts
@@ -0,0 +1,17 @@
+import { describe, expect, it } from 'vitest'
+import { formatShortcut, formatShortcutKeys } from '@/lib/platform'
+
+describe('shortcut labels', () => {
+ it('renders generic modifiers for display text', () => {
+ expect(formatShortcut('meta+shift+p')).toBe('Cmd/Ctrl+Shift+P')
+ })
+
+ it('renders generic modifier keys for kbd chips', () => {
+ expect(formatShortcutKeys('meta+alt+1')).toEqual(['Cmd/Ctrl', 'Alt/Option', '1'])
+ })
+
+ it('handles special keys', () => {
+ expect(formatShortcut('meta+enter')).toBe('Cmd/Ctrl+Enter')
+ expect(formatShortcut('escape')).toBe('Esc')
+ })
+})
diff --git a/app/page.tsx b/app/page.tsx
index 44ecea3..0270026 100644
--- a/app/page.tsx
+++ b/app/page.tsx
@@ -14,6 +14,7 @@ import { useAppMode } from '@/context/app-mode-context'
import { WorkspaceSidebar } from '@/components/workspace-sidebar'
import { FloatingPanel } from '@/components/floating-panel'
import { EditorTabs } from '@/components/editor-tabs'
+import { formatShortcut } from '@/lib/platform'
import { isTauri } from '@/lib/tauri'
import {
fetchFileContentsByName as fetchFileContents,
@@ -668,7 +669,7 @@ export default function EditorLayout() {
key={m.id}
onClick={() => setMode(m.id)}
className={`shell-mode-button ${mode === m.id ? 'shell-mode-button--active' : ''}`}
- title={`${m.label} mode (⌘⇧${index + 1})`}
+ title={`${m.label} mode (${formatShortcut(`meta+shift+${index + 1}`)})`}
>
Looking for your gateway
> ) : ( @@ -387,7 +386,9 @@ export function AgentPanel() { const [sending, setSending] = useState(false) const [isStreaming, setIsStreaming] = useState(false) const [thinkingTrail, setThinkingTrail] = useState{error}
} + {error &&{error}
} ) : ( <> diff --git a/components/plugins/spotify/spotify-settings.tsx b/components/plugins/spotify/spotify-settings.tsx index 3affe64..d14b227 100644 --- a/components/plugins/spotify/spotify-settings.tsx +++ b/components/plugins/spotify/spotify-settings.tsx @@ -45,11 +45,20 @@ export function SpotifySettings() { Spotify
- Set NEXT_PUBLIC_SPOTIFY_CLIENT_ID in your environment to enable Spotify integration.
+ Set{' '}
+
+ NEXT_PUBLIC_SPOTIFY_CLIENT_ID
+ {' '}
+ in your environment to enable Spotify integration.
Create an app at{' '} - + developer.spotify.com . No client secret needed — uses PKCE flow. @@ -68,8 +77,15 @@ export function SpotifySettings() { {authenticated ? (
{error}
} + {error &&{error}
} {/* Curated playlists */} {!current && ( diff --git a/components/preview/preview-panel.tsx b/components/preview/preview-panel.tsx index cd3e387..cd3183d 100644 --- a/components/preview/preview-panel.tsx +++ b/components/preview/preview-panel.tsx @@ -13,6 +13,7 @@ import { import { useEditor } from '@/context/editor-context' import { useView } from '@/context/view-context' import { useLocal } from '@/context/local-context' +import { formatShortcut } from '@/lib/platform' import { isTauri, tauriInvoke } from '@/lib/tauri' import { emit } from '@/lib/events' @@ -705,7 +706,7 @@ function SingleDeviceZoomBar({- Open a folder{!isDesktop ? ' or connect a GitHub repo' : ''} to start editing, browsing files, and using the agent. + Open a folder{!isDesktop ? ' or connect a GitHub repo' : ''} to start editing, browsing + files, and using the agent.