{"owner":"siyuan-note","repo":"siyuan","hasSkills":true,"hasMcp":false,"mcpConfig":null,"found":["AGENTS.md"],"files":{"AGENTS.md":"# AGENTS.md\n\nSiYuan repository guide. Module path `github.com/siyuan-note/siyuan`, license AGPL-3.0.\n\n---\n\n## 1. Non-negotiable constraints\n\n### Do not hand-edit\n\n- `app/stage/protyle/js/lute/lute.min.js` (built from upstream `88250/lute`)\n- `app/stage/build/**`, `app/src/types/dist/**`\n- `app/changelogs/**` (generated by separate tooling)\n- `app/kernel/SiYuan-Kernel*`, `*.syso`, `kernel/kernel.aar`\n- `app/pandoc/*`\n\n### Verification and prohibited operations\n\n1. **Frontend verification:** Do not use `npx webpack` or `pnpm dev` to verify changes; after changes, run `pnpm run lint` with `app/` as the working directory to check code style\n2. **Frontend build:** Do NOT run `pnpm build` — the developer runs `pnpm dev` manually, and `pnpm build` will conflict with it, producing broken bundles\n3. **Kernel development:** After modifying Go code, run `gofmt`, but do not compile the kernel binary or restart a running kernel; the developer handles both manually\n4. **Git:** **NEVER** run `git commit` / `git push` unless explicitly asked — no exceptions\n\n---\n\n## 2. Project-specific rules\n\n1. **i18n:**\n   - New keys go at the **top** of each `langs/*.json` object; add to every language file (reference `en.json`)\n   - Indent `langs/*.json` with tabs, using one tab per nesting level; do not use spaces for indentation\n   - Exception: inside the `_kernel` object, append new entries at the **end** using the next incremental numeric key\n   - Each language must be properly translated — do NOT copy the same text across all language files\n   - Use three ASCII periods (`...`) for ellipses in all localized strings; do not use Unicode ellipsis characters (`…` or `……`)\n   - Setting description tip strings must not end with a period or equivalent sentence-ending mark (for example `.`, `。`, or `।`)\n   - Domains: `ld246.com` only in `zh-CN.json`; use `liuyun.io` in all other languages\n   - In `zh-TW` localization and the Traditional Chinese user guide, translate SiYuan's content-model term Block as `區塊`; never abbreviate it as `塊`\n   - Use `區塊` consistently in compound terms, for example `內容區塊`, `子區塊`, `父區塊`, `嵌入區塊`, `程式碼區塊`, `區塊 ID`, `區塊標`, and `區塊級`\n   - Translate Block Reference as `區塊引用` and Blockquote as `引述區塊`; do not confuse them or reverse the word order\n   - When counting content blocks, use `個區塊` rather than using `塊` as a classifier or abbreviation\n   - Do not mechanically replace `塊` in ordinary words with `區塊`; preserve non-content-block terms such as `分塊` for data chunks and `覈取方塊` for Checkbox\n   - Keep block terminology consistent between the Traditional Chinese interface and user guide\n   - After modifying i18n files, run `python scripts/check-lang-keys.py` to verify key completeness across all language files\n2. **Cross-platform scripting:**\n   - Do not assume the current shell is Bash, zsh, or PowerShell. Confirm the shell before using shell-specific syntax; otherwise avoid constructs such as `&&`, heredocs, and `/dev/null`\n   - For simple sequences, use separate command calls and set the command working directory instead of chaining `cd` with another command\n   - For multi-step logic, write and run a temporary Node.js or Python script. On Windows, avoid PowerShell unless necessary\n   - Do not pass non-ASCII text through shell pipelines, PowerShell here-strings, `python -c`, or `node -e`; write the text to a UTF-8 file with a file-editing tool and consume that file instead\n3. **Icons:** Do not hand-write SVG; use existing icons from `app/appearance/icons/litheness/icon.js` when possible\n4. **User guide:** When editing the user guide, follow `docs/SY-FORMAT.md`\n   - When a feature adds or changes shortcuts, update the shortcut documentation in the user guide in the same change; if the appropriate section is unclear, ask the user where it should be placed\n   - Represent in-app UI navigation paths as segmented `kbd` text marks: use one `NodeTextMark` with `TextMarkType: \"kbd\"` per navigation level, and place a plain `NodeText` containing ` - ` between adjacent levels\n   - When a `kbd` path is embedded in prose, use exactly one ASCII space outside the path on each side when adjacent ordinary text exists; do not add an outer space at the start or end of a block\n   - Omit the left outer space when the first `kbd` immediately follows full-width punctuation (for example, `，` or `、`); apply this rule to every language, including Chinese and Japanese, but do not apply it to half-width punctuation\n   - Omit the right outer space when `kbd` is immediately followed by punctuation, whether full-width or half-width; keep the internal ` - ` separators of segmented UI paths unchanged\n5. **Git:**\n   - When explicitly asked to commit, follow the style of recent commits (gitmoji prefix + subject, in English)\n   - Append the full issue/PR URL to the end of the commit title (e.g. `https://github.com/siyuan-note/siyuan/issues/<NNN>`, not the `#NNN` short form — it is clickable) only when a related issue exists; never put the URL in the commit body, and do not fabricate one\n6. **GitHub:** Prefer the GitHub CLI (`gh`) for all GitHub operations, including reading issues, comments, pull requests, commits, statuses, and metadata. If `gh` is unavailable or does not support the operation, fall back to the GitHub API or web interface\n   - For GitHub write operations containing non-ASCII text on Windows or when shell encoding is uncertain, use this file-based workflow:\n     1. Create the request payload as UTF-8 JSON with a file-editing tool, not an inline shell command\n     2. Store it in the operating system's temporary directory with a unique name such as `siyuan-gh-<operation>-<timestamp>.json`; do not leave temporary payloads in the repository\n     3. Call the appropriate endpoint with `gh api --method <method> \"<endpoint>\" --input \"<absolute-json-path>\"`\n     4. Inspect the returned resource and read it back with `gh api` to verify the published text exactly, including line breaks and non-ASCII characters\n     5. Delete the temporary JSON file and confirm that it no longer exists\n   - Example for an issue comment: write `{\"body\":\"<comment text>\"}` to the UTF-8 JSON file, run `gh api --method POST \"repos/{owner}/{repo}/issues/<number>/comments\" --input \"<absolute-json-path>\"`, then read the returned comment by its `id` before deleting the file\n7. **Issue titles:** Whenever the user asks to generate an issue title, provide it in English regardless of the wording of the request, and do not start it with `Fix`\n   - If the issue is labeled `Bug`, objectively describe the problem or symptom instead of writing from a bug-fix perspective\n   - If the issue is labeled `Enhancement`:\n     - For improvements to existing functionality, write the title from an improvement perspective and prefer `Improve ...`\n     - For capabilities that did not previously exist, write the title from a support perspective and prefer `Support ...`\n   - If no applicable label is available, infer the perspective from the issue content\n8. **LD246:** When accessing `ld246.com`, set the HTTP `User-Agent` header to `SiYuan-Coding-Agent`\n9. **Configurable entries:**\n   - Treat the `data-id` of a configurable desktop menu item and the `data-type` of a configurable dock entry as persisted configuration identifiers. Do not rename or reuse them unless the same change migrates existing visibility and order configuration\n   - When adding, removing, renaming, or moving a configurable desktop menu item or dock entry, or changing its `data-id` / `data-type`, update `app/src/config/entryVisibility/catalog.ts` in the same change, including its type, hierarchy, label, Simple profile default, and default position, and update the related tests\n   - Give every configurable desktop menu separator a stable `data-id` and register it in the catalog as a `separator`. Keep the catalog order aligned with the actual menu declaration order because it defines the built-in order and where new entries are merged into existing custom profiles\n   - Keep parent and child paths aligned with the actual menu hierarchy. Dock entries support visibility only and must not be included in sorting\n   - Cover catalog consistency, separator placement, order migration, and plugin-slot preservation in the related tests. Configured menus must not produce leading, trailing, or consecutive separators\n   - The menu `ignore` option controls conditional rendering and must not be used to opt an entry out of visibility or order configuration\n\n---\n\n## 3. Coding conventions\n\n1. **Comments:** Wrap code comments at 120 characters\n2. **Comments:** Describe what the code does, not what it replaced — don't reference the old implementation in comments\n3. **Comments:** Write comments in Chinese\n4. **Punctuation:** Use language-appropriate punctuation (e.g. Chinese punctuation ，。：；！？「」 for Chinese, not ASCII); do not hard-code it in code — put it in the i18n language files so each locale renders its own. Applies to comments, user guide, `.md` docs, etc.\n5. **UI paths:** In all contexts, including code comments, UI text, i18n, user guides, documentation, issue/PR content, and responses, separate navigation levels with a hyphen surrounded by spaces (for example, `设置 - 快捷键 - 通用`); do not use arrow symbols such as `→`\n6. **Markdown:** Do not hand-wrap; keep each line (paragraphs, table rows, list items, etc.) on a single line\n7. **TypeScript/JavaScript:** Semicolons required, use double quotes, indent with spaces\n8. **CSS:** Do not use the `:has()` selector because of its performance impact\n9. **Go:** Format with `gofmt` after editing\n\n---\n\n## 4. Required toolchain\n\n| Tool | Version | Source of truth |\n|---|---|---|\n| Go | see `go` directive | `kernel/go.mod` |\n| Node (+ pnpm) | see CI matrix | `.github/workflows/cd.yml`, `app/package.json` (`packageManager` field) |\n\n---\n\n## 5. Repository layout\n\n**Architecture:** Go kernel (`kernel/`) + TypeScript frontend (`app/`), plus a separate `export` bundle (global `Protyle`, entry `src/protyle/method.ts`) for rendering rich content in exported HTML / PDF preview. Read versions from `kernel/go.mod`, `app/package.json`, `kernel/util/working.go`.\n\nTop level (repo root):\n\n| Path | Contents |\n|---|---|\n| `kernel/` | Go backend — server, data engine, API, all domain logic |\n| `app/` | TypeScript frontend (Electron/web), built by webpack into `app/stage/build/` |\n| `app/appearance/` | Themes, icons, **i18n** (`appearance/langs/*.json`) |\n| `app/stage/` | Build output served by the kernel |\n| `app/changelogs/` | Per-version changelog markdown |\n| `.github/` | `CONTRIBUTING.md` (+zh-CN), `SECURITY.md`, `CODE_OF_CONDUCT.md`, `PULL_REQUEST_TEMPLATE.md`, issue templates, `workflows/` |\n| `scripts/` | Release packaging: `win-build.bat`, `darwin-build.sh`, `linux-build.sh`, `parse-changelog.py`, `check-lang-keys.py` |\n\n### Major `kernel/` packages (under `kernel/`)\n\n| Package | Responsibility |\n|---|---|\n| `main.go` (`//go:build !mobile`) | Desktop entry point → `cli/cmd` |\n| `cli/cmd/` | Cobra CLI subcommands (`serve`, `notebook`, `block`, `search`, `sql`, `export`, `repo`, `sync`, …) |\n| `model/` | **Core domain** (~70 files): blocks/trees, transactions, indexing, search, attribute views, export, history, sync, flashcards, AI, CalDAV/CardDAV, auth |\n| `treenode/` | In-memory tree over the Lute AST + `blocktree.db` (`BlockTree{ID,RootID,ParentID,BoxID,Path,HPath,Type,...}`) |\n| `av/` | **Attribute View** (database) engine: values, filters, sorts, layouts (table/kanban/gallery) |\n| `sql/` | **Embedded SQLite** (`siyuan.db`, `history.db`, `asset_content.db`) + FTS5; async index queues |\n| `search/` | FTS tokenizer helpers, CJK conversion (`hanconv.go`) |\n| `bazaar/` | Marketplace: plugins/widgets/themes/icons/templates |\n| `filesys/` | Read/write `.sy` files on disk (via `filelock`) |\n| `server/` | Gin server bootstrap (`serve.go`): middleware, TLS/cmux, WebDAV/CalDAV/CardDAV, WebSocket, MCP |\n| `api/` | HTTP route registration (`router.go::ServeAPI`, ~400 endpoints) + per-area handlers |\n| `conf/` | Configuration structs |\n| `util/` | Cross-cutting: `working.go` (workspace, `Boot()`), `lute.go`, `i18n.go`, `websocket.go` (melody push), `result.go` (API envelope) |\n| `plugin/` | Plugin subsystem (kernel side) |\n| `mcp/` | MCP (Model Context Protocol) server |\n| `agent/` | AI agent runtime |\n| `mobile/`, `harmony/` | `//go:build mobile` gomobile bindings for Android/iOS/HarmonyOS |\n\n### Frontend (`app/src/`) highlights\n\n| Dir | Purpose |\n|---|---|\n| `index.ts` | Main `App` class — boots SPA, opens main WebSocket, handles WS push events |\n| `window/` | Detached Electron window variant |\n| `protyle/` | **The block editor** — `wysiwyg/`, `toolbar/`, `gutter/`, `breadcrumb/`, `hint/`, `scroll/`, `undo/`, `preview/`, `render/` (incl. `render/av/`) |\n| `editor/`, `layout/`, `menus/`, `dialog/`, `config/`, `mobile/`, `ai/`, `sync/`, `history/`, `search/`, `card/` | Feature modules |\n| `util/fetch.ts` | `fetchGet`/`fetchPost` — all kernel calls |\n| `layout/Model.ts` | WebSocket client all UI binds to |\n| `constants.ts` | Global constants (version, IDs, storage keys) |\n\nFour webpack configs each emit a separate bundle to `app/stage/build/{app,desktop,mobile,export}/`. The kernel's `serveAppearance` picks which bundle to serve based on User-Agent. The `export` bundle is different from the other three: it is not an app UI — it is a client-side library (global `Protyle`, entry `src/protyle/method.ts`) exposing renderers for code highlighting, math (KaTeX), and diagrams (Mermaid/flowchart/graphviz/…). It is loaded by the HTML pages assembled during export (`app/src/protyle/export/index.ts`) — the desktop PDF preview window and standalone exported HTML files — so rich content renders outside the editor.\n\n---\n\n## 6. Related repositories (navigation)\n\nSiYuan spans several repos. This repo (`siyuan`) holds the kernel + Electron/web frontend; the others are separate projects with their own tooling.\n\n| Repo | Role / what to know |\n|---|---|\n| `siyuan` | **This repo** — kernel + Electron/web/tablet UI |\n| `siyuan-android` / `siyuan-ios` / `siyuan-harmony` | Native apps wrapping the gomobile kernel; build steps differ per platform — see each project's README |\n| `siyuan-chrome` | Browser extension (web clipper); talks to the running kernel over HTTP only |\n| `siyuan-testing` | Playwright end-to-end tests for a running SiYuan instance; test data belongs in the `SiYuan Testing` notebook — see that repository's `AGENTS.md` |\n| `petal` | SiYuan Plugin API declaration (the plugin system is named \"petal\"); consumed by plugins, not a kernel Go dependency |\n| `lute` | Markdown/Kramdown AST engine — the editor + `.sy` format; also the source of the bundled `lute.min.js` (a GopherJS build served to the frontend). **Lives under `$GOPATH/src/github.com/88250/lute`, not as a sibling repo** |\n| `dejavu` | Data repo / sync engine (encrypted snapshots) |\n| `riff` | Spaced-repetition (SRS) flashcard scheduler |\n| `gulu` | General Go utility library (`gulu.Ret`, `gulu.JSON`, …) |\n| `eventbus` | In-process event bus |\n| `filelock` | Cross-platform file locking (`.sy` read/write) |\n| `httpclient` | HTTP client wrapper (cloud / sync / bazaar calls) |\n| `logging` | Leveled logging used throughout the kernel |\n| `go-sqlite3` / `pdfcpu` | Maintainer's forks, pulled in via permanent `replace` in `kernel/go.mod` (keep those) |\n| `epub` / `clipboard` / `go-humanize` / `vitess-sqlparser` / `dataparser` / `encryption` | Smaller Go libraries (export / clipboard / formatting / SQL parse / data parse / crypto) |\n\nAll Go libraries above are dependencies in `kernel/go.mod`. GitHub org: `siyuan-note/*` for the `siyuan-` apps and most libs; `88250/*` for lute, gulu, and the forks (go-sqlite3 / pdfcpu).\n\n### Cross-repo notes\n\n- **Editing any Go dependency (Lute / dejavu / gulu / eventbus / riff / filelock / httpclient / logging / go-sqlite3 / pdfcpu / epub / …):** these are imported by the kernel as Go modules (`kernel/go.mod`). To test a local change, add a temporary `replace` in `kernel/go.mod` pointing at your local checkout — but **never commit that `replace`**; it breaks builds for everyone else.\n- **Rebuilding `lute.min.js`:** it's the JS build of the Go `lute` project — generated upstream and checked into `app/stage/protyle/js/lute/`. Don't edit it here; change `lute`, rebuild, and copy the artifact in.\n- **Mobile apps (`siyuan-android` / `siyuan-ios` / `siyuan-harmony`):** each is a separate native app that wraps the kernel built from this repo. For how to build, vendor the kernel binding, and wire everything up, **read each project's own README** — the toolchains and steps differ per platform and aren't documented here.\n- **`siyuan-chrome`:** independent TypeScript project; it only interacts with a running SiYuan instance through the public HTTP API documented in `docs/API.md`.\n\n---\n\n## 7. Response style\n\n1. **Language:** Match the user's language; do not mix languages mid-sentence (keep proper nouns / identifiers in their original form)\n"}}