### Install and Run Development Server
Source: https://github.com/xiaochong/markbun/blob/main/README.md
Commands to install dependencies and start the development environment with or without Hot Module Replacement.
```bash
# Install dependencies
bun install
# Development without HMR (uses bundled assets)
bun run dev
# Development with HMR (recommended)
bun run dev:hmr
```
--------------------------------
### Simplified Test Imports
Source: https://github.com/xiaochong/markbun/blob/main/README.md
Example of using the setup file to simplify import paths in test files.
```typescript
// Import from setup.ts instead of long relative paths
import { isTableCell, toggleBold } from '../setup';
```
--------------------------------
### Clone and setup repository
Source: https://github.com/xiaochong/markbun/blob/main/CONTRIBUTING.md
Commands to clone the repository and navigate into the project directory.
```bash
git clone https://github.com/yourusername/markbun.git
cd markbun
```
--------------------------------
### Install dependencies
Source: https://github.com/xiaochong/markbun/blob/main/CONTRIBUTING.md
Command to install project dependencies using Bun.
```bash
bun install
```
--------------------------------
### Run Development Server
Source: https://github.com/xiaochong/markbun/blob/main/AGENTS.md
Start the development environment; logs will appear in the terminal.
```bash
# Logs appear in terminal where you run `bun dev`
bun dev
```
--------------------------------
### Basic JavaScript Example
Source: https://github.com/xiaochong/markbun/blob/main/website/index.html
A simple demonstration of logging a string to the console.
```javascript
const hello = "MarkBun World";
console.log(hello);
```
--------------------------------
### Clone and Build MarkBun
Source: https://github.com/xiaochong/markbun/blob/main/website/download.html
Commands to clone the repository, install dependencies, and build the project for production.
```bash
git clone https://github.com/xiaochong/markbun
cd markbun
# Install dependencies
bun install
# Build for production
bun run build
```
--------------------------------
### Install Turndown dependencies
Source: https://github.com/xiaochong/markbun/blob/main/docs/plans/2026-04-04-003-feat-clipboard-operations-plan.md
Command to add the Turndown library and its TypeScript definitions to the project.
```bash
bun add turndown @types/turndown
```
--------------------------------
### Commit message example
Source: https://github.com/xiaochong/markbun/blob/main/CONTRIBUTING.md
Example of a properly formatted conventional commit message.
```text
feat: Add file explorer sidebar component
- Implement folder tree navigation
- Add file open/save handlers
- Style with Tailwind CSS
```
--------------------------------
### Add Milkdown Plugins
Source: https://github.com/xiaochong/markbun/blob/main/README.md
Install additional Milkdown plugins using the Bun package manager.
```bash
bun add @milkdown/plugin-math
```
--------------------------------
### Run development mode
Source: https://github.com/xiaochong/markbun/blob/main/CONTRIBUTING.md
Commands to start the development server with or without Hot Module Replacement (HMR).
```bash
# With HMR (recommended for UI development)
bun run dev:hmr
# Without HMR
bun run dev
```
--------------------------------
### Update setupMenu in src/bun/menu.ts
Source: https://github.com/xiaochong/markbun/blob/main/docs/windows-menu.md
Modify the menu setup function to remove the Windows-specific platform check and enable native menus for all platforms.
```typescript
// Current code (using frontend menu)
export function setupMenu(state: ViewMenuState, tFn: (key: string) => string): void {
const menu: ApplicationMenuItemConfig[] = [...];
currentMenuConfig = menu;
// Windows uses frontend menu, skip native menu setup
if (!isWindows) {
ApplicationMenu.setApplicationMenu(menu);
}
}
// Change to (using native menu)
export function setupMenu(state: ViewMenuState, tFn: (key: string) => string): void {
const menu: ApplicationMenuItemConfig[] = [...];
currentMenuConfig = menu;
// All platforms use native menu
ApplicationMenu.setApplicationMenu(menu);
}
```
--------------------------------
### Git Commit Message Examples
Source: https://github.com/xiaochong/markbun/blob/main/AGENTS.md
Standardized commit message prefixes for tracking project changes.
```text
feat: Add file explorer sidebar
fix: Fix auto-save not triggering on window blur
docs: Update README with build instructions
style: Fix toolbar button alignment
refactor: Extract file operations to separate module
test: Add tests for file saving
```
--------------------------------
### Display Blob URL in Markdown
Source: https://github.com/xiaochong/markbun/blob/main/AGENTS.md
Example of the markdown format used within the editor to reference a Blob URL.
```typescript
// Editor markdown uses blob URL
const markdown = `${"`"};
```
--------------------------------
### Detect fenced code block ranges
Source: https://github.com/xiaochong/markbun/blob/main/docs/solutions/logic-errors/milkdown-html-block-code-fence-misidentification-and-chunk-splitting-2026-04-09.md
Utility function to identify the start and end line indices of all fenced code blocks within a document.
```typescript
function getFenceRanges(lines: string[]): Array<[number, number]> {
const ranges: Array<[number, number]> = [];
let inFence = false;
let fenceChar = '';
let fenceLen = 0;
let start = -1;
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
if (!inFence) {
const m = line.match(/^(\`{3,}|~{3,})/);
if (m) {
inFence = true;
fenceChar = m[1][0];
fenceLen = m[1].length;
start = i;
}
} else {
const m = line.match(/^(\`+|~+)\s*$/);
if (m && m[1][0] === fenceChar && m[1].length >= fenceLen) {
ranges.push([start, i]);
inFence = false;
}
}
}
return ranges;
}
```
--------------------------------
### Configure Electrobun Main Process
Source: https://github.com/xiaochong/markbun/blob/main/AGENTS.md
Sets up the native window and application menu for the desktop environment.
```typescript
import { BrowserWindow, ApplicationMenu } from "electrobun/bun";
// Create window
const win = new BrowserWindow({
title: "MarkBun",
url: "views://main-ui/index.html",
width: 1200,
height: 800,
});
// Set up menus
ApplicationMenu.setApplicationMenu([
{
label: "File",
submenu: [
{ label: "New", action: "file-new" },
{ label: "Open", action: "file-open" },
{ label: "Save", action: "file-save" },
],
},
]);
```
--------------------------------
### Build Project for Release
Source: https://github.com/xiaochong/markbun/blob/main/README.md
Commands to build the application for either canary or stable release channels.
```bash
# Build for canary release
bun run build:canary
# Build for stable release
bun run build:stable
```
--------------------------------
### Run Development Scripts
Source: https://github.com/xiaochong/markbun/blob/main/README.md
Use these Bun commands to manage the development lifecycle, including building, testing, and linting.
```bash
bun run dev # Start development with file watch
bun run dev:hmr # Start development with HMR (recommended)
bun run build:canary # Build canary release
bun run build:stable # Build stable release
bun run test # Run tests once
bun run test:watch # Run tests in watch mode
bun run test:coverage # Run tests with coverage
bun run lint # Run typecheck and tests
```
--------------------------------
### Configure MarkBun Settings
Source: https://github.com/xiaochong/markbun/blob/main/README.md
Settings are defined in the ~/.config/markbun/settings.json file to control general, editor, appearance, and backup behaviors.
```json
{
"__version": 1,
"general": {
"autoSave": true,
"autoSaveInterval": 2000,
"language": "en"
},
"editor": {
"fontSize": 15,
"lineHeight": 1.65
},
"appearance": {
"theme": "system",
"sidebarWidth": 280
},
"backup": {
"enabled": true,
"maxVersions": 20,
"retentionDays": 30,
"recoveryInterval": 30000
}
}
```
--------------------------------
### Initialize Milkdown Editor
Source: https://github.com/xiaochong/markbun/blob/main/AGENTS.md
Configures the editor instance with commonmark, GFM, and history plugins.
```typescript
import { Editor } from "@milkdown/kit/core";
import { commonmark } from "@milkdown/kit/preset/commonmark";
import { gfm } from "@milkdown/kit/preset/gfm";
import { history } from "@milkdown/kit/plugin/history";
Editor.make()
.use(commonmark)
.use(gfm)
.use(history)
.create();
```
--------------------------------
### Implement Electrobun Renderer Process
Source: https://github.com/xiaochong/markbun/blob/main/AGENTS.md
Handles menu actions and communicates with the main process via RPC.
```typescript
import { Electroview } from "electrobun/view";
const electrobun = new Electroview({ rpc: null });
// Listen for menu actions
electrobun.on("menu-action", (action) => {
if (action === "file-save") {
saveDocument();
}
});
// Call main process
electrobun.rpc("saveFile", { content: "..." });
```
--------------------------------
### Build and verify changes
Source: https://github.com/xiaochong/markbun/blob/main/CONTRIBUTING.md
Commands to build the project and check for TypeScript errors before submission.
```bash
bun run build:canary
```
```bash
bun run tsc --noEmit
```
--------------------------------
### Run Pre-commit Checks
Source: https://github.com/xiaochong/markbun/blob/main/AGENTS.md
Execute these commands before committing to ensure code quality and type safety.
```bash
# Quick syntax and type check
bun run typecheck
# Full check (types + tests)
bun run lint
```
--------------------------------
### Configure MarkBun UI State
Source: https://github.com/xiaochong/markbun/blob/main/README.md
UI state preferences such as window dimensions and visibility toggles are stored in ~/.config/markbun/ui-state.json.
```json
{
"showTitleBar": false,
"showToolBar": false,
"showStatusBar": false,
"showSidebar": false,
"sidebarWidth": 280,
"sidebarActiveTab": "files",
"windowX": 200,
"windowY": 200,
"windowWidth": 1200,
"windowHeight": 800
}
```
--------------------------------
### Main App File Processing Logic
Source: https://github.com/xiaochong/markbun/blob/main/docs/file-association.md
Logic for consuming the pending file path during startup, runtime, and via RPC.
```typescript
const filePath = await consumePendingFile();
if (filePath) pendingOpenFilePath = filePath;
```
```typescript
watch('/tmp/markbun', (eventType, filename) => {
if (filename !== 'pending.txt') return;
const filePath = await consumePendingFile();
if (filePath) openFileInFocusedWindow(filePath);
});
```
```typescript
// RPC: getPendingFile
getPendingFile: async () => {
if (!pendingOpenFilePath) return null;
const filePath = pendingOpenFilePath;
pendingOpenFilePath = null;
return { path: filePath, content: ... };
}
```
--------------------------------
### Enable Renderer DevTools
Source: https://github.com/xiaochong/markbun/blob/main/AGENTS.md
Configure BrowserWindow options to enable developer tools in the renderer process.
```javascript
const win = new BrowserWindow({
// ...
webPreferences: {
devTools: true,
},
});
```
--------------------------------
### Clipboard Implementation Sequence
Source: https://github.com/xiaochong/markbun/blob/main/docs/plans/2026-04-04-003-feat-clipboard-operations-plan.md
Visual representation of the dependency chain and verification points for clipboard feature development.
```text
Unit 1 (frontmatter extract + clipboardBlobConverter)
↓
Unit 2 (App.tsx: menu action + keyboard handler) ← VERIFICATION GATE HERE
↓ confirm execCommand works
Unit 3 (backend: readFromClipboard extension) ← can start parallel with Unit 2
↓
Unit 4 (insertMarkdown + turndown + smart paste) ← depends on Unit 2 + Unit 3
↓
Unit 5 (image paste) ← depends on Unit 4 paste framework
```
--------------------------------
### Run Bun Test Commands
Source: https://github.com/xiaochong/markbun/blob/main/README.md
Standard commands for executing tests, watching for changes, and generating coverage reports.
```bash
# Run all tests
bun test
# Run tests in watch mode (during development)
bun run test:watch
# Run tests with coverage report
bun run test:coverage
```
--------------------------------
### Initialize Dark Mode
Source: https://github.com/xiaochong/markbun/blob/main/website/about.html
Checks local storage for the theme preference and applies the dark class to the document element.
```javascript
if(localStorage.getItem("mb-theme")==="dark")document.documentElement.classList.add("dark");
```
--------------------------------
### Implement recommended commands fallback
Source: https://github.com/xiaochong/markbun/blob/main/docs/solutions/ui-bugs/command-palette-history-and-discovery-2026-04-01.md
Provides a default list of commands to display when the user's command history is empty.
```typescript
// src/mainview/hooks/useQuickOpen.ts
if (commandHistory.length > 0) {
// Show by recency order from history
recentCommands = commandHistory
.map(action => allCommandItems.find(c => c.type === 'command' && c.action === action))
.filter(...)
.slice(0, MAX_PER_GROUP);
} else {
// No history yet: show recommended (most useful) commands
const recommended = [
'view-quick-open',
'edit-find',
'file-save',
'format-strong',
'format-emphasis',
'view-toggle-sidebar',
'view-toggle-theme',
];
recentCommands = recommended
.map(action => allCommandItems.find(c => c.type === 'command' && c.action === action))
.filter(...)
.slice(0, MAX_PER_GROUP);
}
```
--------------------------------
### Visualize Edit Mode Flow with Mermaid
Source: https://github.com/xiaochong/markbun/blob/main/website/index.html
A flowchart demonstrating the decision process between WYSIWYG and Source editing modes.
```mermaid
graph TD
A[Open File] --> B{Edit Mode?}
B -->|WYSIWYG| C[Milkdown]
B -->|Source| D[CodeMirror]
```
--------------------------------
### Project structure overview
Source: https://github.com/xiaochong/markbun/blob/main/CONTRIBUTING.md
Visual representation of the project directory layout.
```text
markbun/
├── src/
│ ├── bun/ # Main process (Bun/Electrobun)
│ │ └── index.ts # Entry point
│ └── mainview/ # Renderer process (React)
│ ├── App.tsx # Main component
│ ├── main.tsx # React entry
│ └── index.css # Styles
├── doc/ # Documentation
├── electrobun.config.ts # Electrobun configuration
└── package.json
```
--------------------------------
### Main Process Electrobun Imports
Source: https://github.com/xiaochong/markbun/blob/main/docs/architecture.md
Essential imports for accessing system-level APIs and window management in the main process.
```typescript
import Electrobun, {
BrowserWindow,
BrowserView,
Updater,
Utils,
ApplicationMenu,
ContextMenu,
Screen
} from "electrobun/bun";
```
--------------------------------
### Generate Coverage Report
Source: https://github.com/xiaochong/markbun/blob/main/README.md
Command to execute tests and output a coverage report.
```bash
bun test --coverage
```
--------------------------------
### Perform Manual Verification
Source: https://github.com/xiaochong/markbun/blob/main/AGENTS.md
Use these commands to verify specific parts of the codebase or run tests in isolation.
```bash
# Only check our code, ignore node_modules
bun run typecheck 2>&1 | grep "src/" || echo "✓ No errors in src"
# Just run tests
bun test
```
--------------------------------
### Git Workflow for Contributing
Source: https://github.com/xiaochong/markbun/blob/main/README.md
Standard sequence of commands for submitting a feature contribution to the repository.
```bash
git checkout -b feature/amazing-feature
```
```bash
git commit -m 'Add amazing feature'
```
```bash
git push origin feature/amazing-feature
```
--------------------------------
### Configure Electrobun build settings
Source: https://github.com/xiaochong/markbun/blob/main/docs/architecture.md
Defines the application metadata and platform-specific build configurations for the Electrobun framework.
```typescript
// electrobun.config.ts
import type { ElectrobunConfig } from "electrobun";
// CEF is only needed in dev mode for debugging
const isBuild = process.argv.some(arg => arg === "build");
export default {
app: {
name: "MarkBun",
identifier: "dev.markbun.app",
version: "0.1.0",
urlSchemes: ["markbun"],
},
build: {
copy: {
"dist/index.html": "views/mainview/index.html",
"dist/assets": "views/mainview/assets",
"src/mainview/images": "views/mainview/images",
},
watchIgnore: ["dist/**"],
mac: {
bundleCEF: !isBuild,
},
linux: {
bundleCEF: true,
icon: "icon.iconset/icon_256x256.png",
},
win: {
bundleCEF: false,
icon: "icon.iconset/icon_256x256.png",
},
},
} satisfies ElectrobunConfig;
```
--------------------------------
### Importing Electrobun Modules
Source: https://github.com/xiaochong/markbun/blob/main/llms.txt
Use these import patterns to access Electrobun functionality in main and browser contexts.
```typescript
import { BrowserWindow } from "electrobun/bun"
```
```typescript
import { Electroview } from "electrobun/view"
```
--------------------------------
### Pre-commit Verification Commands
Source: https://github.com/xiaochong/markbun/blob/main/README.md
Commands to run before committing code to ensure type safety and test passing.
```bash
# Before committing
bunx tsc --noEmit # Type check
bun test # Run all tests
```
--------------------------------
### Integrate Conversion into Milkdown Editor
Source: https://github.com/xiaochong/markbun/blob/main/docs/solutions/best-practices/milkdown-frontmatter-display-workaround-2026-04-04.md
Apply conversion logic at initialization, parsing, retrieval, and change notification points to maintain data integrity.
```typescript
// useCrepeEditor.ts
// 1. Initial display conversion
const initialValueRef = useRef(convertFrontmatterToCodeBlock(defaultValue));
// 2. setMarkdown - convert before parsing
const setMarkdown = useCallback((markdown: string, options?) => {
const convertedMarkdown = convertFrontmatterToCodeBlock(markdown);
// ... parse convertedMarkdown
}, []);
// 3. getMarkdown - convert before returning
const getMarkdown = useCallback(() => {
const content = crepeRef.current?.getMarkdown() ?? '';
return convertCodeBlockToFrontmatter(content);
}, []);
// 4. onChange - convert before notifying
const changeListenerPlugin = $prose((ctx) => {
return new Plugin({
view: () => ({
update: (view, prevState) => {
if (!view.state.doc.eq(prevState.doc)) {
const serializer = ctx.get(serializerCtx);
const markdown = serializer(view.state.doc);
// Convert before notifying parent
onChangeRef.current?.(convertCodeBlockToFrontmatter(markdown));
}
},
}),
});
});
```
--------------------------------
### Define MarkBun technical stack configuration
Source: https://github.com/xiaochong/markbun/blob/main/website/about.html
Represents the core runtime, UI framework, and security configuration used in the MarkBun architecture.
```json
{
"core": {
"runtime": "Bun (1.16.0+)",
"language": "TypeScript",
"shell": "Electrobun"
},
"ui": {
"framework": "React 18",
"styling": "Tailwind CSS",
"editor": "Milkdown"
},
"security": {
"isolation": true,
"ipc_bridge": "Secure Context",
"telemetry": null
}
}
```
--------------------------------
### Agent-Browser Automation Commands
Source: https://github.com/xiaochong/markbun/blob/main/AGENTS.md
Use agent-browser for automation tasks. Always include the --cdp 9222 flag to connect to the remote debugging port.
```shell
# Connect to the running Chrome with remote debugging on port 9222
agent-browser --cdp 9222 open http://localhost:5173
agent-browser --cdp 9222 snapshot
```
```bash
agent-browser --cdp 9222 snapshot -i # Get interactive elements snapshot
agent-browser --cdp 9222 click @e1 # Click element
agent-browser --cdp 9222 screenshot # Take screenshot
```
--------------------------------
### Define UI State Interface
Source: https://github.com/xiaochong/markbun/blob/main/docs/architecture.md
Stores ephemeral window and layout configuration separate from persistent settings.
```typescript
interface UIState {
showTitleBar: boolean;
showToolBar: boolean;
showStatusBar: boolean;
showSidebar: boolean;
sourceMode: boolean;
sidebarWidth: number;
sidebarActiveTab: 'files' | 'outline' | 'search';
windowX: number;
windowY: number;
windowWidth: number;
windowHeight: number;
displayId?: number;
}
```
--------------------------------
### Run i18n validation and linting
Source: https://github.com/xiaochong/markbun/blob/main/docs/plans/2026-04-06-002-refactor-consolidated-i18n-plan.md
Commands used to verify the integrity of translation files and overall project health.
```bash
bun run lint
```
```bash
bun run scripts/validate-i18n.ts
```
--------------------------------
### Synchronous HTML preview rendering
Source: https://github.com/xiaochong/markbun/blob/main/docs/solutions/integration-issues/milkdown-html-block-rendering-with-dompurify-2026-04-07.md
Parses HTML content and mirrors 'src' attributes to 'data-src' to prevent DOMPurify from stripping them. Must return synchronously to prevent Milkdown from displaying a loading placeholder.
```typescript
if (lang === 'html' && content.trim()) {
const parser = new DOMParser();
const doc = parser.parseFromString(content.trim(), 'text/html');
// Preserve width/height against Milkdown CSS resets
doc.querySelectorAll('img').forEach((img) => {
const widthAttr = img.getAttribute('width');
const heightAttr = img.getAttribute('height');
if (widthAttr && !img.style.width) {
img.style.width = /\D/.test(widthAttr) ? widthAttr : `${widthAttr}px`;
}
if (heightAttr && !img.style.height) {
img.style.height = /\D/.test(heightAttr) ? heightAttr : `${heightAttr}px`;
}
});
// Mirror src to data-src so Milkdown's internal DOMPurify can't strip it permanently
doc.querySelectorAll('img').forEach((img) => {
const src = img.getAttribute('src');
if (src) {
img.setAttribute('data-src', src);
}
});
// MUST return synchronously to avoid Milkdown's "Loading..." placeholder
return doc.body.innerHTML;
}
```
--------------------------------
### Restore HTML preview images via MutationObserver
Source: https://github.com/xiaochong/markbun/blob/main/docs/solutions/integration-issues/milkdown-html-block-rendering-with-dompurify-2026-04-07.md
Uses a MutationObserver to detect HTML blocks and restore 'src' attributes from 'data-src', while resolving local file paths to blob URLs.
```typescript
const restoreHtmlPreviewImages = () => {
const htmlBlocks = container.querySelectorAll('.milkdown-code-block[data-lang="html"]');
htmlBlocks.forEach((block) => {
const imgs = block.querySelectorAll('.preview img[data-src]');
imgs.forEach((img) => {
if (img.hasAttribute('data-resolved')) return;
const dataSrc = img.getAttribute('data-src');
if (!dataSrc) return;
// Recover src if DOMPurify stripped it
if (!img.getAttribute('src')) {
img.setAttribute('src', dataSrc);
}
// Resolve local file paths to blob URLs (WebView cannot access file://)
if (!/^(https?:|data:|blob:)/i.test(dataSrc)) {
const resolvedPath = workspaceManager.resolvePath(dataSrc);
loadLocalImage(resolvedPath, dataSrc)
.then((blobUrl) => {
if (blobUrl) {
img.setAttribute('src', blobUrl);
img.setAttribute('data-src', blobUrl);
}
})
.catch((e) => {
console.error('[HTML Preview] Failed to load local image:', dataSrc, e);
});
}
img.setAttribute('data-resolved', 'true');
});
});
};
const observer = new MutationObserver(() => {
updateLatexCodeBlocks();
restoreHtmlPreviewImages();
});
observer.observe(container, {
childList: true,
subtree: true,
characterData: true,
});
```
--------------------------------
### Apply Tailwind Styling
Source: https://github.com/xiaochong/markbun/blob/main/AGENTS.md
Use semantic tokens and the cn() utility instead of raw colors or manual ternaries.
```tsx
// ❌ Don't: Raw colors, manual ternaries