Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 19 additions & 19 deletions DEVELOPMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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.

Expand Down Expand Up @@ -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 |

---

Expand All @@ -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

Expand Down
25 changes: 13 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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) │
└───────────────────────────────────────────────────────────┘
Expand Down Expand Up @@ -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
Expand All @@ -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

Expand Down
17 changes: 17 additions & 0 deletions __tests__/platform.test.ts
Original file line number Diff line number Diff line change
@@ -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')
})
})
3 changes: 2 additions & 1 deletion app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,26 +9,27 @@
import { useEditor, detectFileKind, getMimeType } from '@/context/editor-context'
import { useLocal } from '@/context/local-context'
import { useView, type ViewId } from '@/context/view-context'
import { useLayout, usePanelResize } from '@/context/layout-context'

Check warning on line 12 in app/page.tsx

View workflow job for this annotation

GitHub Actions / Lint, Typecheck & Test

'usePanelResize' is defined but never used. Allowed unused vars must match /^_/u
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,
commitFilesByName as commitFiles,
} from '@/lib/github-api'
import { usePlugins } from '@/context/plugin-context'

Check warning on line 23 in app/page.tsx

View workflow job for this annotation

GitHub Actions / Lint, Typecheck & Test

'usePlugins' is defined but never used. Allowed unused vars must match /^_/u
import { SpotifyPlugin } from '@/components/plugins/spotify/spotify-plugin'
import { YouTubePlugin } from '@/components/plugins/youtube/youtube-plugin'
import { isOnboardingComplete } from '@/components/onboarding-tour'
import { PreviewProvider } from '@/context/preview-context'

Check warning on line 27 in app/page.tsx

View workflow job for this annotation

GitHub Actions / Lint, Typecheck & Test

'PreviewProvider' is defined but never used. Allowed unused vars must match /^_/u
import { ViewRouter } from '@/components/view-router'
import { StatusBar } from '@/components/status-bar'
import { useKeyboardShortcuts } from '@/components/keyboard-handler'
import { emit, on } from '@/lib/events'
import { KnotLogo } from '@/components/knot-logo'

Check warning on line 32 in app/page.tsx

View workflow job for this annotation

GitHub Actions / Lint, Typecheck & Test

'KnotLogo' is defined but never used. Allowed unused vars must match /^_/u
import type { AppMode } from '@/lib/mode-registry'
import { openNewEditorInstance } from '@/lib/tauri'

Expand Down Expand Up @@ -105,7 +106,7 @@
const { status } = useGateway()
const { repo, setRepo } = useRepo()
const local = useLocal()
const { files, activeFile, openFile, setActiveFile, markClean, updateFileContent } = useEditor()

Check warning on line 109 in app/page.tsx

View workflow job for this annotation

GitHub Actions / Lint, Typecheck & Test

'updateFileContent' is assigned a value but never used. Allowed unused vars must match /^_/u
const {
localMode,
readFile: localReadFile,
Expand All @@ -117,7 +118,7 @@
setRootPath: localSetRootPath,
commitFiles: localCommitFiles,
} = local
const { activeView, setView, direction } = useView()

Check warning on line 121 in app/page.tsx

View workflow job for this annotation

GitHub Actions / Lint, Typecheck & Test

'direction' is assigned a value but never used. Allowed unused vars must match /^_/u
const { mode, spec: modeSpec, setMode } = useAppMode()
const layout = useLayout()
const visibleViews = modeSpec.visibleViews
Expand All @@ -137,7 +138,7 @@
if (!mobile.includes('terminal')) mobile.push('terminal')
return mobile.slice(0, 5)
}, [visibleViews])
const activeViewMeta = VIEW_ICONS[activeView] ?? {

Check warning on line 141 in app/page.tsx

View workflow job for this annotation

GitHub Actions / Lint, Typecheck & Test

'activeViewMeta' is assigned a value but never used. Allowed unused vars must match /^_/u
icon: 'lucide:layout-panel-top',
label: 'Workspace',
}
Expand All @@ -156,7 +157,7 @@
const [isTauriDesktop, setIsTauriDesktop] = useState(false)
const [isMacTauri, setIsMacTauri] = useState(false)
const [flashedTab, setFlashedTab] = useState<ViewId | null>(null)
const [connectionAnim, setConnectionAnim] = useState<'pop' | 'pulse' | null>(null)

Check warning on line 160 in app/page.tsx

View workflow job for this annotation

GitHub Actions / Lint, Typecheck & Test

'connectionAnim' is assigned a value but never used. Allowed unused vars must match /^_/u
const prevStatusRef = useRef(status)
const tabRefs = useRef<(HTMLButtonElement | null)[]>([])
const tabContainerRef = useRef<HTMLDivElement>(null)
Expand Down Expand Up @@ -668,7 +669,7 @@
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}`)})`}
>
<Icon icon={m.icon} width={13} height={13} />
</button>
Expand Down
Loading
Loading