Adds the campaign stale-path banner (839f474a..d2d8104c), documents op-util, the shared host-logic module tables, the three input-ladder spines, the i18n panel-shard key workflow, block_on_anywhere, and the typed-error recipe; deletes claims the reorg made false (old file splits, 113-tool count, shell-core paths, five-file property panel). Every path named was existence-checked against the tree.
5.3 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
The TypeScript OpenPencil has been retired.
apps/web,apps/desktop,apps/cli, and thepen-*packages (pen-types/core/engine/renderer/figma/mcp/ai-skills/sdk/react/acp) are gone. The product is now implemented in Rust (crates/) with a thin wasm-backed web SDK (packages/op-web-sdk*). Historical// ported from pen-*comments in the Rust sources name the retired TS as their origin — that code no longer exists in-tree; consult git history (last TS tagv0.7.5) if you need it.
Detailed module docs load automatically in subdirectories:
crates/CLAUDE.md— Rust shell: crate layout, editor core, widgets, hosts (native/web/desktop), MCP, AI, orchestrator, codegen. The canonical architecture doc.packages/CLAUDE.md— Remaining packages (op-web-sdk web viewer SDK family).
Commands
Tooling is Cargo (Rust — the product). The root has no package.json; the JS/Bun tooling for the web SDK lives under packages/ — run SDK/JS scripts from there.
- Web dev server (Rust):
bash scripts/start-web-rust.sh - Build (Rust):
cargo build --workspace --release - Run all tests (Rust):
cargo test --workspace; single crate:cargo test -p <crate> - Type check:
cargo check --workspace; wasm:cargo check --target wasm32-unknown-unknown -p op-host-web --no-default-features --features web - Lint / format (Rust):
cargo clippy --workspace --all-targets -- -D warnings/cargo fmt --all - Lint / format (remaining TS SDK): from
packages/:bun run lint(oxlint) /bun run format(oxfmt) - Desktop app:
cargo build -p op-host-desktop→ binaryopenpencil-desktop(live MCP on127.0.0.1:<port>/mcp) - CLI:
cargo build -p op-cli→ binaryop - MCP server: built into the desktop/web host (
--mcp <path>); crateop-mcp - Iconify catalog (Rust assets): from
packages/:bun run generate-iconify-catalog - Sync all managed versions:
scripts/sync-version.shreads the canonical version from rootCargo.toml; verify without writing viatools/check-version-sync.sh
Architecture
OpenPencil is an open-source, AI-native vector design tool (Design-as-Code). The editor — canvas engine, chrome, stores, MCP, AI — is Rust, built on the vendored jian skia/widget/render/event toolkit (vendor/jian) and casement winit fork (vendor/casement). See crates/CLAUDE.md for the authoritative crate map; the essentials:
crates/
├── op-editor-core/ Canonical `.op` (PenDocument) editor state + EditorCommand + design-variable resolution
├── op-editor-ui/ Platform-free widgets + RenderBackend facade (wasm32-clean)
├── op-editor-host-core/ Transport-free host state machines shared by all hosts
├── op-host-native/ Native host lib (winit + skia-safe GL) — desktop + mobile
├── op-host-web/ Browser bundle: wasm32 cdylib, CanvasKit renderer
├── op-host-desktop/ Desktop binary `openpencil-desktop`; also the `--serve-web` daemon
├── op-host-services/ Headless serve-web / MCP daemon lib (shared by desktop + web-server)
├── op-host-web-server/ Thin GL-free web-server binary
├── op-cli/ `op` command-line tool
├── op-util/ Dependency-free leaf: hex-colour parsing + JSON / XML escaping
└── op-mcp / op-ai / op-ai-skills / op-codegen / op-orchestrator / op-figma /
op-git / op-opmerge / op-pen-loader / op-design-lint / op-i18n / op-html /
op-auth-bridge / op-smoke / …
packages/
├── op-web-sdk/ Read-only `.op` web viewer SDK (wraps the op-host-web wasm bundle)
├── op-web-sdk-react/ React 19 adapter for op-web-sdk
└── op-web-sdk-vue/ Vue 3 adapter for op-web-sdk
Data flow, canvas engine, Document/EditorCommand model, MCP layered-design workflow, design variables, and the run/debug recipe are all documented in crates/CLAUDE.md.
Code Style
- Single files must not exceed 800 lines — split into smaller modules when they grow beyond this. The workspace currently has zero violations; the convention is a spine (public surface +
moddeclarations) plus sibling files, with re-exports keeping import paths stable. - One component/widget per file, single responsibility.
.rsfilenames use snake_case;.ts/.tsx(SDK) use kebab-case.- Source comments (
.rs/.ts/.toml) in English (spec/plan markdown + test CJK fixtures may keep Chinese). - Rust widgets paint against jian's
Painter;draw_textis baseline-relative (label components center viacentered_text_baseline_y, not(h-fs)/2).
Git Commit Convention
Use Conventional Commits: <type>(<scope>): <subject>
Types: feat, fix, refactor, perf, style, docs, test, chore
Scopes: editor, canvas, panels, history, ai, codegen, store, types, variables, figma, mcp, desktop, web, renderer, sdk, cli, agent, i18n
Rules: Subject in English, lowercase start, no period, imperative mood. Body optional; explain why not what. One commit per change.
License
MIT License. See LICENSE for details.