This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
pnpm install # Install dependencies
pnpm dev # Start dev server (http://localhost:5173)
pnpm build # Production build
pnpm preview # Preview production build
pnpm format # Run Prettier on all filesThere are no tests. The pre-commit hook runs lint-staged, which auto-formats staged files with Prettier (.{ts,tsx,js,jsx,css,json,md}).
Execly is a fully client-side JS/TS playground — no backend. All compilation and execution happen in the browser tab.
App.tsx owns all state. When the user runs code:
Editor(viaeditorRef) exposes the current text throughEditorHandle.getValue()linter.tsruns diagnostics synchronously (getJSLintfor JS,getTSDiagnosticsviats.createProgramfor TS)runner.tscompiles (compileTSviats.transpileModuleortranspileJSvia Babel) then callsexecute()execute()wraps the compiled code in anasync IIFEinsidenew Function, injecting a sandboxedconsoleproxy and a whitelist of globals — the realwindowis not accessible- Console output streams line-by-line into
consoleLinesstate, rendered inOutputPanel
- CodeMirror 6 compartments:
langCompartment,linterCompartment, andthemeCompartmentinEditor.tsxare module-level singletons. Lang/theme switches useview.dispatch({ effects: compartment.reconfigure(...) })rather than re-mounting the editor — this preserves undo history. - Per-language code persistence:
savedCoderef inEditor.tsxstores the editor content for each language ({ js: string, ts: string }). Switching languages saves the current buffer and restores the saved content for the new language. - Callback refs pattern:
onRunRef,onCursorRef,onProblemsRefare kept in sync viauseEffectso the stable CM6updateListenerclosure always calls the latest React callbacks without needing the editor to remount. - Linting is dual-purpose:
getCM6Diagnosticsfeeds inline CM6 squiggles;getTSDiagnostics/getJSLintreturnProblem[]for the Problems panel and are called again at run-time. Both paths share the same diagnostic logic. - Theme: Light/dark is toggled via
data-themeon<html>(CSS custom properties inApp.css) plusthemeCompartment.reconfigure(oneDark | [])for the CM6 editor. - Layout:
layoutDir('lr'|'tb') switches between left-right and top-bottom split panes. TheResizercomponent drivesoutWidth/outHeightstate inApp.
Lang, Problem, CursorPos, ConsoleLine, EditorHandle — import from here rather than redefining locally.