This guide helps contributors understand VMark's project structure, conventions, and AI-assisted development setup.
| Layer | Technology |
|---|---|
| Desktop shell | Tauri v2 (Rust) |
| Frontend | React 19, Zustand v5, Tailwind v4 |
| Editor | Tiptap / ProseMirror |
| Build | Vite v7, pnpm |
| Tests | Vitest v4 |
pnpm install
pnpm tauri:dev # Start the app in dev mode
pnpm test # Run all tests once
pnpm check:all # Full quality gate (lint + coverage + build)vmark/
├── src/ # React frontend
│ ├── components/ # UI components
│ ├── hooks/ # Custom React hooks
│ ├── plugins/ # ProseMirror / Tiptap editor plugins
│ ├── stores/ # Zustand state stores
│ ├── styles/ # Global CSS and design tokens
│ ├── utils/ # Shared utilities
│ └── test/ # Test setup and shared helpers
├── src-tauri/ # Rust backend (Tauri)
│ └── src/ # Tauri commands, menu, plugins
├── shared/ # Types shared between frontend and backend
├── website/ # VitePress documentation site
├── vmark-mcp-server/ # MCP server sidecar
├── AGENTS.md # AI instructions (shared across all tools)
├── CLAUDE.md # Claude Code entry point
├── .claude/ # Claude Code configuration
│ ├── rules/ # Auto-loaded project rules
│ ├── agents/ # Custom subagents
│ ├── skills/ # Custom skills (slash commands)
│ └── commands/ # Custom commands
├── .mcp.json # MCP server configuration
├── vitest.config.ts # Test config with coverage thresholds
└── package.json # Scripts and dependencies
These apply to all contributors, human or AI.
- Keep files under ~300 lines — split proactively.
- Zustand stores: Never destructure in components; use selectors. Prefer
useXStore.getState()inside callbacks. - Imports: Use
@/for cross-module, relative for same-module. Never use../../../chains. - Error handling: Always narrow
unknownerrors withinstanceof ErrororString(). - CSS: Never hardcode colors — use design tokens from
src/styles/index.css. See.claude/rules/31-design-tokens.mdfor the full token reference.
Coverage thresholds are enforced in vitest.config.ts. The check:all gate runs vitest run --coverage — if coverage drops below the thresholds, the build fails.
- Write a failing test first (RED), implement minimally (GREEN), refactor (REFACTOR).
- Tests go next to the source:
foo.test.tsbesidefoo.ts, or in a__tests__/subdirectory. - See
.claude/rules/10-tdd.mdfor a full pattern catalog with real file references.
Three files must stay in sync when adding or changing shortcuts:
| File | Format |
|---|---|
src-tauri/src/menu/localized.rs |
CmdOrCtrl+Shift+N |
src/stores/settingsStore/shortcuts.ts |
Mod-Shift-n |
website/guide/shortcuts.md |
Mod + Shift + N |
See .claude/rules/41-keyboard-shortcuts.md for the full procedure.
Five files must be updated together. See .claude/rules/40-version-bump.md.
Run before pushing:
pnpm check:allThis runs, in order:
eslint+ custom lints (selection styles, design tokens, em-dash spacing)vitest run --coverage(with threshold enforcement)tsc && vite build
VMark uses multiple AI coding tools. The configuration is checked into the repo so the whole team shares the same context.
Different AI tools read different files:
| Tool | Reads |
|---|---|
| Claude Code | CLAUDE.md + .claude/rules/*.md |
| Codex CLI | AGENTS.md |
| Gemini CLI | GEMINI.md |
The problem: maintaining the same instructions in three places. The solution: write once in AGENTS.md, import everywhere.
CLAUDE.mdcontains@AGENTS.md— a Claude Code directive that inlines the file.GEMINI.md(if added) would use the same@AGENTS.mdimport.- Codex CLI reads
AGENTS.mddirectly.
This means AGENTS.md is the single source of truth for all AI tools. When you update instructions, update AGENTS.md — every tool picks up the change.
AGENTS.md # Shared rules for all AI tools
CLAUDE.md # Claude Code entry point (imports AGENTS.md)
.claude/
settings.json # Team-shared Claude Code settings
rules/ # Auto-loaded into every Claude Code session
00-engineering-principles.md
10-tdd.md # TDD workflow and pattern catalog
20-logging-and-docs.md
21-website-docs.md
30-ui-consistency.md
31-design-tokens.md # Full CSS token reference
32-component-patterns.md # Popup, toolbar, context menu patterns
33-focus-indicators.md # Accessibility focus rules
34-dark-theme.md
40-version-bump.md
41-keyboard-shortcuts.md
50-codebase-conventions.md # Store, hook, plugin, test patterns
agents/ # Subagents for specialized tasks
implementer.md # Implements scoped changes with tests
auditor.md # Logic, duplication, dead-code checks
planner.md # Turns goals into work items
...
skills/ # Slash commands (e.g., /release-gate)
react-app-dev/
rust-tauri-backend/
tiptap-dev/
...
commands/ # Additional slash commands
feature-workflow.md
codex-audit.md
...
.mcp.json # MCP servers (Tauri E2E, Codex)
Rules are numbered by topic and auto-loaded into every Claude Code session. They contain project conventions that AI agents must follow — but they're also useful as references for human contributors:
10-tdd.md— When tests are required, pattern catalog with real examples31-design-tokens.md— Every CSS custom property, its purpose, and default value32-component-patterns.md— Popup, toolbar, context menu CSS patterns41-keyboard-shortcuts.md— Procedure for adding/changing shortcuts50-codebase-conventions.md— Store, hook, plugin, test, and import patterns
| File | In git? | Purpose |
|---|---|---|
AGENTS.md |
Yes | Shared AI instructions |
CLAUDE.md |
Yes | Claude Code entry point |
.claude/rules/, .claude/agents/, .claude/skills/ |
Yes | Shared config |
.claude/settings.json |
Yes | Team-shared settings |
CLAUDE.local.md |
No | Personal overrides (gitignored) |
.claude/settings.local.json |
No | Personal settings (gitignored) |
To add personal instructions that don't affect the team, create CLAUDE.local.md in the project root.
.mcp.json configures Model Context Protocol servers:
- tauri — E2E testing via
@hypothesi/tauri-mcp-server(webview interaction, screenshots) - codex — OpenAI Codex integration for audit commands
When vibe-coding this project, always prefer subscription-based auth over API keys for AI coding tools. Subscription plans are dramatically cheaper for sustained coding sessions — API billing can cost 10–30x more for the same work.
| Tool | Recommended Auth | Plan |
|---|---|---|
| Claude Code | claude login (subscription) |
Claude Max ($100–200/mo) |
| Codex CLI | codex login (subscription) |
ChatGPT Plus/Pro ($20–200/mo) |
| Gemini CLI | gemini login (Google account) |
Free tier / Google One AI Premium |
API keys still work as a fallback, but for regular development, subscription auth is the way to go.
VMark's .mcp.json registers an OpenAI Codex MCP server. This lets you ask Codex for help directly from Claude Code — useful as a second pair of eyes or for independent audits.
Prerequisite: Install the Codex CLI globally and log in with your subscription:
npm install -g @openai/codex
codex login # Log in with your ChatGPT subscription (recommended)Avoid API keys for Codex.
codex loginuses your ChatGPT Plus/Pro subscription, which is dramatically cheaper thanOPENAI_API_KEYpay-per-token billing for heavy coding sessions.
Codex must be on your PATH for the MCP server to start. Verify with codex --version.
The project provides four Codex-powered slash commands in .claude/commands/:
| Command | What it does |
|---|---|
/codex-audit |
Full 9-dimension audit (security, correctness, compliance, etc.) |
/codex-audit-mini |
Fast 5-dimension check (logic, duplication, dead code, debt, shortcuts) |
/codex-verify |
Verify fixes from a previous audit report |
/codex-commit |
Inspect changes and generate commit messages |
Audit uncommitted changes:
/codex-audit
Audit the last 3 commits:
/codex-audit commit -3
Fast check on a specific directory:
/codex-audit-mini src/plugins/search
Verify fixes after addressing audit findings:
/codex-verify
- You type a slash command in Claude Code (e.g.,
/codex-audit). - Claude reads the command definition from
.claude/commands/codex-audit.md. - The command instructs Claude to discover the Codex MCP tool via
ToolSearch. - Claude delegates per-file analysis to Codex through the MCP bridge.
- If Codex is unavailable or returns empty results, Claude falls back to manual analysis using its own Read/Grep tools — the audit still completes.
Beyond slash commands, you can ask Claude to consult Codex at any point during a conversation. For example, if Claude is stuck on a tricky bug or unsure about an approach, just say:
Summarize your trouble, and ask Codex for help.
Claude will formulate a focused question, send it to Codex via the MCP bridge, and incorporate the response. This works because the Codex MCP server is always available — no special setup needed beyond the initial codex CLI install.
| Situation | Command |
|---|---|
| Pre-push sanity check | /codex-audit-mini |
| PR review / thorough audit | /codex-audit |
| After fixing audit findings | /codex-verify |
| Quick fix with smart commit message | /codex-commit |
| General bug fix | /fix [description] |
You don't need any AI tools to contribute. The rules files in .claude/rules/ double as living documentation of project conventions — read them to understand the patterns and standards the codebase follows.
The key files to read before your first PR:
AGENTS.md— Project overview and conventions.claude/rules/10-tdd.md— Testing requirements.claude/rules/50-codebase-conventions.md— Code patterns