This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
@AGENTS.md
AGENTS.md above documents the upstream doocs/md project. This repo is mdlook, a fork that adds a Tauri desktop app, a token-based theme system, and a deliberately narrowed UI. The notes below cover what AGENTS.md does not. Read README.md for the product framing.
- Tauri 2 macOS desktop app (
apps/web/src-tauri/) — opens a local folder, browses a.mdfile tree, edits, and saves back to the source file. Same Vue web app, packaged natively. - DESIGN.md token themes (
packages/shared/src/design-md/) — design-token-based themes (Claude / Linear / Vercel / Stripe / Apple / Figma / Notion) layered over the upstream CSS themes inpackages/shared/src/configs/theme-css/(now includingclaude.css, the default). - Product convergence — account login, cloud sync, share pages, AI assistant, and tipping/membership code from upstream is kept but hidden from the UI by default. Don't assume a missing surface is deleted; it's likely just not mounted. The maintained surfaces are web typesetting/publishing and the macOS local Markdown app.
Run from repo root (the web script is pnpm --filter @md/web):
pnpm web tauri:dev # run the desktop app in dev (loads the Vite dev server)
pnpm web tauri:build # bump patch version (desktop:version) then tauri build
pnpm web desktop:version patch # bump version across tauri.conf.json + Cargo.toml + Cargo.lock
pnpm desktop:release patch # build + verify DMG and generate latest.json
pnpm desktop:deploy # atomically publish and verify the public downloadscripts/bump-desktop-version.mjs keeps the Tauri version in sync across all three files — use it instead of editing versions by hand.
- Detection / state:
apps/web/src/stores/desktop.ts(useDesktopStore).isTauriis true only when__TAURI_INTERNALS__/__TAURI__exists onwindow; in the browser every desktop method is a no-op. Gate desktop-only behavior onisTauri, not on build flags. - Rust commands (
apps/web/src-tauri/src/lib.rs, called via@tauri-apps/api'sinvoke):read_md_tree— walk a folder into a file treeread_text_file/write_text_file— load/save a.mdfiletake_pending_file— pick up a file opened via Finder double-click / "Open with mdlook" (also handles.mdURL association; CJK paths supported)copy_html/copy_text— native clipboard, used to bypass WebView clipboard limits when copying to WeChat
- Web fallbacks:
apps/web/src/utils/clipboard.tsandutils/file.tsbranch between native Tauri calls and browser APIs.
When adding a desktop capability, add the #[tauri::command] in lib.rs, register it in the run() handler, allow it in apps/web/src-tauri/capabilities/, and call it through the desktop store's invoke wrapper.
pnpm installfails inapps/webpostinstall withwebidl.util.markAsUncloneable is not a function(stack goes throughwxt prepare→miniflare→undici): this is a Node version problem, not a dependency problem. The repo requires Node >= 22.22.2 (.nvmrcpinsv22.22.2);undici@8calls an internal API that only exists on Node 22+, so it crashes on Node 20. The earlierpnpm installwarningUnsupported engine: wanted {"node":">=22.22.2"}is the real cause. Fix:nvm use(ornvm install 22.22.2), confirmnode -vshows v22.22.2, then re-runpnpm install.nvm useonly affects the current terminal — make sure the IDE's integrated terminal is also on Node 22.- The frontend dev server (
pnpm start/pnpm web dev) serves at http://localhost:5173/md/ — note the/md/base path.
Issues and PRDs are tracked as local markdown files under .scratch/<feature-slug>/. See docs/agents/issue-tracker.md.
This repo uses the default mattpocock/skills triage label vocabulary. See docs/agents/triage-labels.md.
This repo uses a single-context layout: root CONTEXT.md plus root docs/adr/. See docs/agents/domain.md.