Skip to content
Agentmart
Submit a tool

AGENTS.md · zsviczian/obsidian-excalidraw-plugin

AGENTS.md from zsviczian/obsidian-excalidraw-plugin: 808 lines covering Purpose, Product And Deployment Model, Core Mental Model, Project Overview And Tooling…

Template by zsviczian

IndexedAGPL-3.0★ 7,776
Write a review

Install

Works with Codex, Cursor, GitHub Copilot, Gemini CLI, OpenCode, Claude Code. Read the repository before you give any tool access to your data.

curl -fsSL https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/AGENTS.md -o AGENTS.md

Read it and adapt it to your project before use.

Get the weekly diff

The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.

We use your email only for this newsletter. Privacy

About

The AGENTS.md file that zsviczian/obsidian-excalidraw-plugin (7,776 stars) keeps for coding agents. It has 808 lines in 20 sections: Purpose; Product And Deployment Model; Core Mental Model; Project Overview And Tooling; Security, privacy, and compliance; UX & copy guidelines (for UI text, commands, settings); DOM Styling And Visibility; Performance; Coding conventions; Mobile; Agent do/don't; Issue Investigation And Resolution Templates; References; Repository Map; Startup And Lifecycle Rules; Build And Packaging Rules; Architectural Conventions; Naming And Placement Conventions; Documentation Standard; Backward Compatibility Requirements. Use it as a model for your own project's instructions.

Use cases: prompt-engineering

No reviews yet. Installed it? Reviews come from verified installers only. How reviews work

What's in it

An AGENTS.md file: instructions coding agents (Codex, Cursor, Copilot, Gemini CLI and others) read before working in a repo.

For
Codex, Cursor, GitHub Copilot, Gemini CLI, OpenCode, Claude Code
Length
808 lines
File
AGENTS.md

Sections

  1. Purpose
  2. Product And Deployment Model
  3. Core Mental Model
  4. Project Overview And Tooling
  5. Security, privacy, and compliance
  6. UX & copy guidelines (for UI text, commands, settings)
  7. DOM Styling And Visibility
  8. Performance
  9. Coding conventions
  10. Mobile
  11. Agent do/don't
  12. Issue Investigation And Resolution Templates
  13. References
  14. Repository Map
  15. Startup And Lifecycle Rules
  16. Build And Packaging Rules
  17. Architectural Conventions
  18. Naming And Placement Conventions
  19. Documentation Standard
  20. Backward Compatibility Requirements

First lines (shown under the repo's AGPL-3.0 license)

# Obsidian Excalidraw Plugin Agent Guide

## Purpose

This repository contains the Obsidian Excalidraw plugin: an Obsidian.md plugin that integrates a heavily customized Excalidraw fork into Obsidian.

This is not a generic React canvas app. Many implementation choices are driven by:

- Obsidian plugin lifecycle constraints
- Electron desktop and mobile compatibility
- popout window support
- startup time and bundle size
- compatibility with a customized upstream Excalidraw fork
- advanced plugin-specific features such as scripts, automation, custom pens, custom fonts, markdown embeds, PDF export, OCR, AI features, and deep vault integration

When working in this repo, optimize for correctness inside Obsidian and for preserving existing behavior. Do not assume that a simpler-looking web-app pattern is safe here.

Use https://github.com/obsidian-typings/obsidian-typings as a reference when dealing with Obsidian APIs, especially undocumented or weakly documented ones.

## Product And Deployment Model

- The shipped plugin is effectively three files: `main.js`, `styles.css`, and `manifest.json`.
- The production build emits these into `dist/`.
- The bundle is intentionally assembled as a single CommonJS `main.js` with embedded runtime payloads.
- `package.json` is primarily the library/package manifest. Its version is not the canonical plugin release version.
- Plugin release versions live in `manifest.json` and `manifest-beta.json`.
- `package.json` `main` and `types` point to the library build in `lib/`, not the Obsidian runtime bundle.

## Core Mental Model

- `src/core/main.ts` owns plugin startup, lifecycle, settings loading, migration, and manager initialization.
- `src/view/ExcalidrawView.ts` is the main runtime surface for the editor/view experience.
- `src/core/managers/` contains most lifecycle-adjacent coordination logic.
- `src/shared/` contains major reusable subsystems such as Excalidraw Automate, dialogs, data handling, script engine support, LaTeX, workers, and SVG conversion.
- `src/utils/` contains lower-level helpers for Obsidian integration, export, files, PDF, AI, dynamic styling, and scene manipulation.
- `rollup.config.mjs` is a critical part of the runtime architecture, not just a packaging detail.

Treat build code and runtime code as one system.

## Project Overview And Tooling

- Target: Obsidian Community Plugin (TypeScript → bundled JavaScript).
- Runtime entry point: `src/core/main.ts`, compiled by `rollup.config.mjs` to `dist/main.js`.
- Required release artifacts: `main.js`, `manifest.json`, and `styles.css`.
- Node.js: use Node 22 or newer. Check `node --version` before diagnosing build-tool failures; mixed Node/Corepack installations can produce misleading errors.
- Package manager: npm. Use `npm install` and the scripts in this repository's `package.json`.
- Runtime bundler: Rollup. Do not replace this build with a sample-plugin esbuild setup; Rollup also assembles compressed runtime payloads and merged CSS.
- Primary lint command: `npm run code`. `npm run lint` is broader and may expose unrelated repository backlog.
- Types: Obsidian type definitions plus conservative declarations for intentionally used unpublished APIs.

## Security, privacy, and compliance

Follow Obsidian's **Developer Policies** and **Plugin Guidelines**. In particular:

- Default to local/offline operation. Only make network requests when essential to the feature.
- No hidden telemetry. If you collect optional analytics or call third-party services, require explicit opt-in and document clearly in `README.md` and in settings.
- Keep every external origin and every fully static URL as a literal `https://...` string in source so reviewers and security scanners can identify the destination without executing the code. A dynamic resource path may be appended only to a literal base URL, and each untrusted path segment must be validated or encoded.
- Never conceal a network destination or evade a scanner finding by splitting or joining domain labels, deriving an origin from Git state, environment variables, runtime configuration, or character codes, or by encoding, compressing, encrypting, or otherwise transforming a URL. Do not weaken, suppress, or work around a scanner by making an endpoint less statically visible; fix the underlying behavior or document a genuine false positive transparently.
- Never execute remote code, fetch and eval scripts, or auto-update plugin code outside of normal releases.
- Minimize scope: read/write only what's necessary inside the vault. Do not access files outside the vault.
- Clearly disclose any external services used, data sent, and risks.
- Respect user privacy. Do not collect vault contents, filenames, or personal information unless absolutely necessary and explicitly consented.
- Avoid deceptive patterns, ads, or spammy notifications.
- Register and clean up all DOM, app, and interval listeners using the provided `register*` helpers so the plugin unloads safely.

## UX & copy guidelines (for UI text, commands, settings)

- Prefer sentence case for headings, buttons, and titles.
- Use clear, action-oriented imperatives in step-by-step copy.
- Use **bold** to indicate literal UI labels. Prefer "select" for interactions.
- Use arrow notation for navigation: **Settings → Community plugins**.
- Keep in-app strings short, consistent, and free of jargon.

## DOM Styling And Visibility

- Prefer Obsidian's established classes such as `mod-warning` before adding plugin-specific CSS. Consult the Obsidian CSS variables and component conventions when styling settings or dialogs.
- Never use `document.createElement()`, `Document.createElement()`, or `Document.createDocumentFragment()`. Prefer Obsidian's `createEl()`, `createDiv()`, `createSpan()`, `createSvg()`, and `createFragment()` helpers, following these established patterns:
  - Create detached typed rendering elements whose owning document is irrelevant through a fragment, for example `const canvas = createFragment().createEl("canvas")` or `const image = createFragment().createEl("img")`.
  - Before creating a temporary wrapper solely for serialization, check whether the consumer accepts a `DocumentFragment` or DOM node directly. For example, `htmlToMarkdown()` accepts a fragment; clone and transform that detached tree before passing it to the consumer. Do not substitute `XMLSerializer` without verifying that its XML serialization is equivalent to the required HTML representation.
  - Register known runtime font sources through document-scoped `FontFace` objects and `document.fonts.add()`/`delete()`. Preserve descriptors such as `unicodeRange`, retain each face for replacement and cleanup, and do not build a generic CSS parser merely to translate arbitrary stylesheet text into `FontFace` objects.
  - `setCssProps()`/`setCssStyles()` are suitable for dynamic declarations on one element, not for CSS requiring selectors, pseudo-elements, at-rules, or arbitrary rule text. Creating the same `<style>` through `createEl("style")` does not resolve the separate CodeScanner policy finding for dynamic style elements.
- `deliberateCreateElement`, injected by `rollup.config.mjs`, is restricted to the remaining reviewed `<style>` cases: document-scoped runtime stylesheets that cannot be represented as element declarations, and styles that must belong to an iframe's `contentDocument`, where Obsidian's DOM helpers are not installed. Do not broaden this exception without first exhausting the patterns above and documenting why document-specific native creation is intrinsic. Track the upstream policy discussion in [obsidianmd/eslint-plugin#196](https://github.com/obsidianmd/eslint-plugin/issues/196).
- Use semantic interactive elements and Obsidian's event helpers. Link-like navigation should use a real anchor, not a button merely styled as a link; use `onClickEvent` when applying custom navigation behavior. Validate touch interactions on a physical mobile device because desktop mobile emulation proves layout, not native touch activation.
- When a control already has a styled tooltip, do not also set an HTML `title` attribute. Keep its accessible name in `aria-label`; `title` produces a second native Chromium/Electron tooltip and must not replace accessible labeling.
- Do not write an element's `style` attribute directly. Use `setStyle` and `removeStyle` from `src/utils/styleUtils.ts` when a dynamic inline style is genuinely necessary.
- Use the existing visibility helpers instead of the native `hidden` property or attribute, which is not reliable in Obsidian's styled UI. Choose `hideElement`/`showElement` or `setComponentVisibility` from `src/utils/styleUtils.ts`, or `setElementHidden`/`setElementDisplay` from `src/utils/htmlUtils.ts` when a boolean/display-oriented API is clearer.
- Search `src/utils/styleUtils.ts` and `src/utils/htmlUtils.ts` before introducing new DOM styling helpers or display classes.
- Run Obsidian CodeScanner after CSS changes. Preserve compatibility with the declared minimum Obsidian version and prefer a widely supported property when it provides the same result; for example, a basic underline is preferable to optional underline-thickness/offset styling.
- For a known vault path, use the most specific synchronous lookup: `app.vault.getFolderByPath()` for folders and `app.vault.getFileByPath()` for files. Use `getAbstractFileByPath()` only when either type is intentionally accepted, and avoid adapter-level existence checks when the Vault API already models the target.
- Radix content in the customized Excalidraw package may be rendered through `ObsidianRadixPortal` directly under the owning document's body. A body portal escapes component ancestor selectors and modal stacking contexts. When a trigger is visible but its menu or popover is not, first inspect whether the content mounted behind a modal or lost ancestor-scoped styles. Use a class on the portaled content, a portal-safe selector, and an explicit stacking level when required; validate main-window, popout, click-outside, and Escape behavior.

## Performance

- Keep startup light. Defer heavy work until needed.
- Avoid long-running tasks during `onload`; use lazy initialization.
- Batch disk access and avoid excessive vault scans.
- Debounce/throttle expensive operations in response to file system events.
- For temporary performance diagnostics, use a unique searchable prefix and
  emit one copyable string per event rather than logging expandable objects.
  Keep timing-only callbacks and state isolated from production behavior.
- Distinguish synchronous API duration, queue completion, browser-task yields,
  animation-frame callbacks, and actual paint; none is a substitute for the
  others when explaining perceived latency.
- Temporary diagnostics are not product observability. Do not log vault
  contents, and include filenames only when the maintainer explicitly needs
  per-file attribution. Remove the diagnostics before commit and search both
  `src/` and the built `dist/main.js` for their prefix.

## Coding conventions

- TypeScript with `"strict": true` preferred.
- **Keep `main.ts` minimal**: Focus only on plugin lifecycle (onload, onunload, addCommand calls). Delegate all feature logic to separate modules.
- **Split large files**: If any file exceeds ~200-300 lines, consider breaking it into smaller, focused modules.
- **Use clear module boundaries**: Each file should have a single, well-defined responsibility.
- Bundle everything into `main.js` (no unbundled runtime deps).
- Avoid Node/Electron APIs if you want mobile compatibility; set `isDesktopOnly` accordingly.
- Prefer `async/await` over promise chains; handle errors gracefully.

## Mobile

- Don't assume desktop-only behavior unless `isDesktopOnly` is `true`.
- Avoid using desktop only objects and functions such as Node Buffer, SharedArrayBuffer, etc. For the special case when this is required, make proper mobile safe guards.
- Avoid large in-memory structures; be mindful of memory and storage constraints.
- Treat a physical phone or tablet as a separate validation environment for touch targets, synthesized clicks, scrolling gestures, focus, and the mobile WebView. Desktop mobile emulation is useful for responsive layout checks but is not a substitute for real touch testing.

## Agent do/don't

**Do**

- Add commands with stable IDs (don't rename once released).
- Provide defaults and validation in settings.
- Write idempotent code paths so reload/unload doesn't leak listeners or intervals.
- Use `this.register*` helpers for everything that needs cleanup.

**Don't**

- Introduce network calls without an obvious user-facing reason and documentation.
- Ship features that require cloud services without clear disclosure and explicit opt-in.
- Store or transmit vault contents unless essential and consented.

## Issue Investigation And Resolution Templates

When triaging or updating issues across the plugin, Excalidraw fork, Extras, and EA Scripts, use the central [plugin issue tracker and label guidelines](.github/ISSUE_LABELS.md); this plugin repository is the default issue hub for all four projects.



- For source-based issue investigations, GitHub issue comments, and a prioritized shortlist, use [issue assessment](docs/agent-workflows/issue-assessment.md).
- Only after maintainer approval of specific issues, use [issue implementation handoff and resolution](docs/agent-workflows/issue-resolution.md) to prepare a dedicated branch and plan-only draft PR for the local implementation agent.
- The issue owns the technical assessment; the draft PR owns the implementation plan; the branch owns the code. Keep draft PRs open through implementation, link cross-repository dependencies, and do not merge without authorization.

## References

- Obsidian sample plugin: https://github.com/obsidianmd/obsidian-sample-plugin
- API documentation: https://docs.obsidian.md
- Developer policies: https://docs.obsidian.md/Developer+policies
- Plugin guidelines: https://docs.obsidian.md/Plugins/Releasing/Plugin+guidelines
- Style guide: https://help.obsidian.md/style-guide

## Repository Map

Signals

Stars
7,776
Forks
522
Open issues
871
Last commit (this folder)
Oct 13, 2026 (16 days ago)
Last release
Oct 12, 2026 (16 days ago)

From GitHub (fetched Oct 24, 2026).

Details

License
AGPL-3.0
First seen
Oct 24, 2026
Last checked
Oct 24, 2026
Cite this page

AGENTS.md · zsviczian/obsidian-excalidraw-plugin. Agent Mart. https://agentmart.dev/templates/zsviczian-obsidian-excalidraw-plugin-agents-md (last updated 2026-10-24)