Imported from ShreyanshVaibhaw/Markzy (
AGENTS.md). Install upstream withnpx skills add ShreyanshVaibhaw/Markzy. Copyright stays with the author.
AGENTS.md - Instructions for AI agents working on Markzy
If you are an AI agent (Claude Code, Cursor, Copilot, Codex, etc.) touching this repository, read this file first, every session, before making any change. The original phase-by-phase build plan (
plan.md) has been consumed;docs/upstream-map.mdanddocs/parity-gaps.mdare now the governing references for behavior and divergences.
What this project is
Markzy is a rebuild of ColaMD - "The Agent Native Markdown Editor" - ported from Electron to Tauri 2 (Rust) + WebView2/WKWebView/WebKitGTK. The original app's headline feature is live agent sync: when an AI agent edits a .md file on disk, the editor updates in real time and a titlebar dot pulses orange while the agent writes and flashes green when it settles.
The win is footprint: ~10-30MB RAM and ~5-15MB installers instead of Electron's ~200MB+ / ~150MB.
This is a port, not a redesign. Feature parity with upstream v1.5.0 is the goal.
Stack (do not change without user approval)
- Shell: Tauri 2.x, frameless window, custom HTML titlebar with
data-tauri-drag-region. - Backend: Rust, edition 2021. Modules:
main.rs,commands.rs,watcher.rs,slides.rs,export.rs,theme.rs. - Renderer: TypeScript + Vite, reusing the upstream Milkdown WYSIWYG editor (
@milkdown/kit),remark-breaks, themes CSS, and slides HTML templates. - IPC:
@tauri-apps/apiinvoke()+listen(). There is no preload script (that was Electron-specific). - File watching:
notify+notify-debouncer-mini, 100ms debounce. - Slides server:
axumon127.0.0.1(loopback only, never external). - PDF export (v1): webview print dialog (Save as PDF). Headless PDF is a documented future enhancement, not a current goal.
Repository layout
markzy/
src-tauri/ Rust backend
src/
main.rs Tauri init, plugin registration, invoke_handler
commands.rs file open/save/new/read/write + IPC commands
watcher.rs notify watcher + agent activity state machine (CORE FEATURE)
slides.rs bundled slides template + axum slides server
export.rs HTML / PDF / slides export
theme.rs built-in + user themes, persistence
Cargo.toml
tauri.conf.json
icons/
src/ Renderer (runs in the webview)
renderer/
main.ts app entry
editor.ts Milkdown setup
ipc.ts Tauri-backed reimplementation of upstream preload API
titlebar.ts activity dot logic
styles/
themes-assets/ built-in theme CSS + slides templates + tutorial markdown
index.html Vite entry
vite.config.ts
package.json
tsconfig.json
docs/
upstream-map.md responsibility map + IPC contract (written in Phase 1)
export.md export approach + future enhancements
parity-gaps.md any remaining behavioral differences vs upstream
docs/parity-gaps.md any remaining behavioral differences vs upstream
AGENTS.md this file
README.md
../ColaMD-upstream/ reference clone of the original Electron app (sibling dir, NOT part of this repo)
The upstream reference
The original Electron source is cloned at ../ColaMD-upstream (sibling directory, outside this repo). Use it as the behavioral and visual reference. Do not copy it into the project tree. When a behavior is ambiguous, match upstream. The map from upstream responsibilities to Rust modules is in docs/upstream-map.md.
Commands to run
Run these from the project root.
| Task | Command |
|---|---|
| Dev (opens the app) | npm run tauri dev |
| Build renderer only | npm run build |
| Build Rust only (debug) | cargo build (run inside src-tauri/, or cargo build --manifest-path src-tauri/Cargo.toml) |
| Typecheck renderer | npm run build (Vite fails on TS errors) or tsc --noEmit if configured |
| Lint Rust | cargo fmt then cargo clippy -- -D warnings (in src-tauri/) |
| Format Rust | cargo fmt |
| Production bundle (installers) | npm run tauri build |
| Generate app icons | npm run tauri icon <path-to-png> |
After any implementation change, always run and fix until clean: cargo fmt, cargo clippy -- -D warnings (in src-tauri/), and npm run build. Do not mark work done with failing lint/typecheck/build.
Coding conventions
- Rust: edition 2021,
clippyclean with-D warnings,cargo fmtclean. Prefer the Tauri 2 plugin ecosystem over hand-rolling. Snake_case for commands; the renderer'sipc.tsmaps camelCase -> snake_case. Neverunwrap()in command bodies - returnResult<T, String>and surface errors to the renderer. - TypeScript: strict mode. Reuse the upstream renderer's style and structure; only the IPC layer (
ipc.ts) is new. Do not introduce frameworks the upstream app does not use. - No comments in code unless explicitly requested by the user.
- No emojis in code or commits unless the user asks.
- Keep the renderer's
ipc.tsAPI surface identical to the upstream preload API (names + signatures) so the rest of the renderer stays unchanged. Any deviation must be documented indocs/upstream-map.md.
The core feature - get this right
Live agent sync (watcher.rs) is the reason this app exists. Requirements:
- Detect external edits to the open file via
notify(ReadDirectoryChangesW on Windows). - Debounce 100ms (matching upstream); emit a
file-changedevent to the renderer with the freshly-read content on each settled change. - Maintain an activity state machine with three states:
Idle->Activeon first change ->Cooldown(3s after last change) ->Idle(2s after entering Cooldown). Emitagent-activitywith the state string ('idle','active','cooldown') - the renderer sets the dot class accordingly. - The renderer pulses the titlebar dot orange (breathing animation) while Active, green while Cooldown, and gray/dim while Idle - match upstream's exact animation timing (
agent-breathe 2s ease-in-out infinite). - Suppress watcher events during internal saves (set a flag, clear after 100ms) so saving from the editor does not trigger agent activity.
- Resolve relative image paths to
file://absolute URLs before sending content to the renderer. - Survive atomic rewrites (agents that write via temp file + rename): if
notifyreports remove-then-add on the watched path, re-acquire the watch and treat it as a change. Test this explicitly on Windows with aMove-Item -Forcescript. - The renderer must update content without stealing focus or scroll position.
What this app does NOT do (do not add these)
Per upstream's explicit scope:
- No file manager or workspace.
- No cloud sync or real-time multi-user collaboration.
- No built-in AI features - it is a viewer/editor for AI-generated content.
- No plugin system.
- One thing, done well.
Do not "improve" the app by adding these. If asked, push back and reference this section.
Security rules
- The slides server binds to 127.0.0.1 only. Never
0.0.0.0. - Never log or persist secrets. This app has no auth, but if any credential ever appears, do not write it to disk or logs.
- Keep
tauri.conf.jsonCSP as tight as the features allow. Phase 6 tightens it; re-test everything after any CSP change. - File commands must only read/write paths the user explicitly chose via dialog or dropped onto the window. Do not accept arbitrary paths from the renderer without validation.
Git and commits
- The repo is a git repo. Do not reinitialize it. Do not commit unless the user explicitly says "commit".
- Never commit unless the user explicitly says "commit". Never push unless explicitly asked.
- Never add your agent name as a co-author in commit messages.
- Never manually edit
CHANGELOG.mdor any file marked auto-generated. - When you do commit, write a concise message matching repo style, stage only intended files, and never stage secrets.
Workflow for implementation changes
- Read
docs/upstream-map.md(behavioral contract) anddocs/parity-gaps.md(documented divergences) before changing behavior. - After any implementation change, run the verification suite (
cargo fmt,cargo clippy -- -D warnings,npm run build) and fix everything until clean. - Use the
checkskill after any non-trivial implementation phase. - If a task is blocked, stop and report. Do not guess around blockers.
- If you discover a divergence from upstream mid-build, record it in
docs/parity-gaps.mdrather than silently deviating.
Known parity gaps (v1, intentional)
- PDF export uses the OS print dialog ("Save as PDF") rather than silent headless
printToPDF. Documented indocs/export.md. True one-click PDF is a future enhancement. - Any other gaps discovered during the build go in
docs/parity-gaps.md.
Pointers
- Tauri 2 docs: https://tauri.app/
- Upstream ColaMD: https://github.com/marswaveai/ColaMD
- Milkdown: https://milkdown.dev/
- Upstream responsibility map + IPC contract:
docs/upstream-map.md - Parity gaps and Markzy-specific divergences:
docs/parity-gaps.md