These instructions are for AI assistants working in this project.
Always open @/openspec/AGENTS.md when the request:
- Mentions planning or proposals (words like proposal, spec, change, plan)
- Introduces new capabilities, breaking changes, architecture shifts, or big performance/security work
- Sounds ambiguous and you need the authoritative spec before coding
Use @/openspec/AGENTS.md to learn:
- How to create and apply change proposals
- Spec format and conventions
- Project structure and guidelines
Keep this managed block so 'openspec update' can refresh the instructions.
Generated: 2026-01-05 Context: Hybrid macOS QuickLook Extension (Swift + TypeScript)
macOS QuickLook extension for Markdown files. Hybrid architecture: Native Swift app hosts a WKWebView which runs a bundled TypeScript rendering engine.
.
├── Makefile # Main build orchestrator (npm + xcodegen + xcodebuild)
├── project.yml # XcodeGen config (Generates .xcodeproj - DO NOT EDIT PROJECT DIRECTLY)
├── Sources/
│ ├── Markdown/ # Host App (SwiftUI) - Container for extension
│ └── MarkdownPreview/# Extension (AppKit) - WKWebView, QLPreviewingController
├── web-renderer/ # Rendering Engine (TypeScript/Vite) -> See web-renderer/AGENTS.md
└── scripts/ # Versioning and packaging scripts
| Task | Location | Notes |
|---|---|---|
| Project Config | project.yml |
Add files/targets here. Run make generate to apply. |
| Build Logic | Makefile |
make all builds everything. |
| Extension Logic | Sources/MarkdownPreview/PreviewViewController.swift |
Lifecycle, File I/O, JS Bridge. |
| Host UI | Sources/Markdown/MarkdownApp.swift |
Minimal SwiftUI container. |
| Rendering | web-renderer/src/index.ts |
Markdown parsing (see subdir AGENTS.md). |
| Rules | .clinerules |
TDD & Doc-first requirements. |
| Release Process | docs/release/RELEASE_PROCESS.md |
Complete PR handling and release workflow. |
| Homebrew Cask | ../homebrew-tap/Casks/flux-markdown.rb |
Update version & SHA256 after each release. |
- Hybrid Bridge: Swift loads
index.html, callswindow.renderMarkdown(content). JS logs back viawindow.webkit.messageHandlers.logger. - Ephemeral Project:
.xcodeprojis ignored. Always usexcodegen(make generate). - Versioning:
.versionfile stores full version (e.g.,1.13.149). Build number (third part) aligns with git commit count. - Sandbox: App Sandbox enabled. Read-only access to files.
- Release Flow:
- PR Merged: Run
./scripts/analyze-pr.sh <PR_NUMBER>to generate CHANGELOG entry, add to[Unreleased]section. - Release: Run
make release [major|minor|patch]→ Updates.version,CHANGELOG.md, builds DMG, creates GitHub release. - Homebrew: Run
./scripts/update-homebrew-cask.sh <VERSION>to update Homebrew Cask automatically. - See
docs/release/RELEASE_PROCESS.mdfor complete workflow.
- PR Merged: Run
- Homebrew Distribution: After release, run
./scripts/update-homebrew-cask.sh <VERSION>or manually update../homebrew-tap/Casks/flux-markdown.rb.
- TDD: Write tests/metrics before implementation (see
.clinerules). - Docs: Create
docs/debug/DEBUG_*.mdfor hard problems. - Logs: Use
os_logvia the JS bridge. Do not rely onconsole.logalone.
- Never commit .xcodeproj: It is generated.
- No manual build numbers: Use
makeor scripts. - Do not edit
dist/: It is a build artifact ofweb-renderer.
make generate # Generate Xcode project from project.yml
make build_renderer # Build TypeScript engine (npm install && build)
make app # Build macOS app
make release [major|minor|patch] # Release new version
./install.sh # Build & install locally (clears QL cache)
log stream --predicate 'subsystem == "com.markdownquicklook.app"' --level debug
./scripts/analyze-pr.sh <PR_NUM> # Analyze PR and generate CHANGELOG entry
./scripts/update-homebrew-cask.sh <VERSION> # Update Homebrew Cask