Changelog

Every release of Skrive, newest first.

  1. v1.13.1

    Pictures and emoji, and a handful of fixes underneath them.

    Insert an image

    You can now add an image from inside the editor. Reach for it from the Insert menu, the slash menu, or the command palette — a file picker opens and the image lands where your cursor was.

    Dragging an image in and pasting one already worked; this closes the gap for the times you have a file on disk and nothing on the clipboard. Whichever way it arrives, the picture is copied into an assets folder beside your note and written as a plain Markdown link, so the file stays yours and stays readable in any other editor.

    Insert emoji

    Type : followed by a name — :wave, :coffee — and a picker opens inline. Keep typing to narrow it, or pick from the grid. There is also an Emoji entry in the Insert menu if you would rather browse the full set by category.

    The trigger stays out of your way. Times like 3:30, a colon after a word, and URLs never open it, and typing a colon on its own does nothing until you follow it with a letter. An emoji is written as an ordinary character, so it travels anywhere text travels.

    Fixes

    Deleting an emoji takes one press. Backspace used to remove only half of one, leaving a broken character behind — and a family emoji took eleven presses to clear. Emoji, skin tones, flags, and accented letters now delete as the single character they look like.

    Tag suggestions keep up with you. Backspacing while writing a #tag left the suggestion list showing what you had typed a moment earlier. It now follows every keystroke, forwards and back.

    View release on GitHub →
  2. v1.13.0

    This release is about the small things you touch a hundred times a day — finding your place in a long piece, moving a paragraph, catching a typo — and making each of them feel deliberate.

    Find your way around a long document

    Every document now has a live outline down the right edge of the page. Hover it and a card opens listing every heading, with the section you are currently reading marked as you scroll. Click an entry to jump straight there, or drag the rail to scrub through the whole piece.

    Sections with headings under them fold, so you can collapse the parts you are not working in and keep the shape of the rest in view. The strip itself never changes when you fold — it stays an honest map of the whole document.

    Turn it on or off from the command palette, the View menu, or Settings.

    Spelling that respects your words

    The writing surface now checks spelling as you type, using the system dictionary. Right-click a flagged word for corrections, or teach Skrive a word once and it stops asking — either just for you, or for everyone working in the project.

    Code blocks are left alone entirely. Code is code, and checking stops at the fence.

    Move blocks without aiming

    Every block now has a handle in the left margin. Grab it to drag the block somewhere else, or use the + to insert above it. The whole gutter follows you down the page, so reordering a document is a matter of grabbing and dropping rather than selecting exactly the right range first.

    Fixed

    Find now highlights the right words. In documents with formatting or special characters, matches could land a few characters away from where the text actually sat.

    Skrive quits immediately again — under some conditions the app could hang on quit instead of closing.

    Undo after splitting a paragraph mid-sentence now repaints the block correctly.

    The interface also got a consistency pass: shared corner radii, spacing, and controls that had drifted apart across screens.

    As always, your writing stays in plain, portable files you own.

    View release on GitHub →
  3. v1.12.0

    Skrive 1.12.0 — Writing environment

    Everything in this release is about the space around the words: the width of the column, the face it is set in, what stays on screen while you work, and having somewhere to land each day.

    A library of writing faces

    Skrive now ships ten typefaces, so the face you write in is the same on every machine instead of depending on what the operating system happens to have installed.

    Serif — Literata, Newsreader, Source Serif 4, EB Garamond, Alegreya Sans — Inter, Source Sans 3, Atkinson Hyperlegible Monospace — JetBrains Mono, Monaspace Neon

    Each one does a different job: Literata is built for long reading on screen, EB Garamond is classical, Alegreya was drawn for literature, and Atkinson Hyperlegible has letterforms designed to be hard to confuse. The picker in Settings › Appearance groups them by kind and shows a specimen, so you can choose by reading rather than by name.

    Every face is bundled with the app. Nothing is fetched from the network, the picker works offline, and your choice of font is not visible to anyone but you. All ten are openly licensed, and each ships its license alongside it — the full credits are in Settings › About.

    Your own fonts still work: the Custom option takes any family installed on your system, and the system presets are unchanged.

    Focus mode

    ⌘⇧D clears everything but the writing. The chrome steps back, and paragraphs other than the one you are working in dim so your eye stays where the words are. Esc brings it all back.

    A writing column you can set

    The measure — how wide a line of text runs before it wraps — is now set in characters rather than pixels, so it means the same thing at any text size. Narrow, Normal, and Wide presets are there, along with Custom for a specific width and Full to lift the cap entirely.

    A single document can override the setting when it wants a different shape, and the palette has nudge commands for widening and narrowing without opening Settings.

    Daily notes

    ⌘⇧T opens today's note, creating it if it does not exist yet. Also available as "Open today's note" in the command palette.

    You choose the folder, how the file is named, and what a new note starts with. The name is a date pattern, so YYYY-MM-DD files as 2026-03-08 and YYYY/MM/DD files by year and month. Settings shows you the path today resolves to as you type it.

    Notes can be plain Markdown or native Folio documents, and Skrive never rewrites a note you have already written in.

    Fixed

    Preferences added in recent versions could be dropped when the app restarted, so a setting you changed would quietly revert. Settings now survive a restart as they should.

    As always, your writing stays in plain, portable files you own.

    View release on GitHub →
  4. v1.11.0

    Tables you can actually edit

    This release makes tables first-class to edit. Hover any table and grips appear around it — no menus to hunt through, no markup to hand-edit.

    • Add rows and columns from the + rails along the table's edges.
    • Select a whole row or column from its grip, then delete it — or open its menu to insert a row/column above, below, or to either side.
    • Set column alignment — left, center, or right — from the column menu.
    • Resize a column by dragging its border. The neighbouring column gives way, so the table always stays within your writing width instead of sprawling off the page.
    • Reorder rows and columns by dragging a grip, with a clear marker showing exactly where the slice will land.

    As always, your writing stays in plain, portable files you own: Markdown tables round-trip byte-for-byte, and Skrive's native format quietly keeps the extras Markdown has no place for, like column widths.

    View release on GitHub →
  5. v1.10.0

    Skrive v1.10.0 — Rich blocks

    Richer blocks, still in plain files you own. This release brings footnotes, table editing, syntax-highlighted code, and properly nested lists.

    Footnotes

    Add a footnote from the Insert menu or by typing /footnote. References render as superscripts with a hover peek at the definition, all definitions gather into a footer at the end of the document, and you can jump between a reference and its definition. Everything round-trips to plain Markdown ([^1]), so nothing is locked in.

    Table editing

    Shape a table from the keyboard: ⌥⌘ + the arrow keys insert a row or column in that direction, and you can delete a whole table as a single unit. Tables stay valid, portable Markdown throughout — ragged rows and all.

    Code blocks

    Code blocks now render with syntax highlighting and a per-block language picker, so a snippet reads the way it would in your editor.

    Nested lists

    Nested numbered lists now count the way Docs and Word do — 1., then a., then i. by depth — instead of 1. at every level. Purely how they look; your Markdown is unchanged.

    View release on GitHub →
  6. v1.9.1

    Skrive v1.9.1

    Writing polish across tags, in-document search, and inline formatting.

    Inline tags

    Type #tag anywhere in a document to file it by topic. Tags render as calm, color-coded chips, with autocomplete as you type — drawn from every tag across your project. The sidebar gains a tag facet, so a click filters your files down to a topic. Tags stay plain text in your files and round-trip cleanly; nothing proprietary is added.

    Find & replace in a document

    ⌘F opens an in-document find bar — keyboard-first, with matches highlighted in place and replace-one or replace-all. It works the same whether you are writing in rendered or Markdown mode.

    Inline formatting parity

    • The selection toolbar is now the familiar writer's set: Bold · Italic · Underline · Strikethrough. Underline and strikethrough are new; inline code moves into the selection bubble alongside links.
    • Clear formatting strips styling from a selection while keeping your links — in the bubble and the command palette.
    • Undo / Redo now appear in the command palette, not just on the keyboard.

    Rendered writing in plain files you own. No accounts, no AI.

    View release on GitHub →
  7. v1.9.0

    Skrive v1.9.0 — The writer's desk

    This release reimagines the app's chrome. Tabs are gone, the sidebar becomes a place to write from, and the toolbar stops growing — three surfaces reworked into one coherent idea of where your documents, your navigation, and your tools live.

    Tabs are retired

    No more strip of tabs across the top. The document you're in is named right in the header. Click the title (or use quick-open) to summon your working set — a recency stack of what you've been in — and jump. Switching is faster, and Skrive no longer has to remember an ever-growing pile of open documents.

    The sidebar is now a writer's desk

    The sidebar answers what am I working on first and where is everything else second:

    • Pinned — the documents you keep close, held at the top.
    • Recent — what you've touched lately, roomy and easy to scan.
    • Folders as filters — narrow the library to a folder or sort it however you like, with a clean shelf-tree view, instead of digging through a rigid file tree.
    • Quick-open + New always within reach at the top.

    A calmer toolbar

    The toolbar is now fixed — it holds a small, permanent set and won't sprawl as new features arrive. Formatting lives in the selection bubble, insertion in the slash menu and a single Insert catalog, and everything else in the command palette. A fresh monochrome icon family ties it together.

    View release on GitHub →
  8. v1.8.7

    Skrive 1.8.7 — Audit P4: posture & polish

    This release closes out the editor-quality audit that has driven the last three releases. It is all polish and posture — no new surfaces, no changed workflows, just an editor that holds up better under weight.

    Big documents feel light

    Selecting text by dragging in very large documents used to stall badly — at ten thousand blocks, each frame of the drag could take over two seconds. It now tracks instantly. Formatting a huge selection (select all, then bold) went from about twelve seconds to about one. Typing latency in large documents improved too, and a stricter automated performance gate now watches both numbers so they cannot quietly regress.

    Right-to-left writing works

    Every paragraph, heading, list item, quote, and table cell now lays itself out in its own text's direction. Hebrew and Arabic read right-aligned with quote rules and list markers on the correct side, mixed-direction lines behave, and a single document can hold both directions comfortably.

    Decisions, written down

    The audit's last open questions each got a deliberate answer rather than a shrug: spellcheck stays off for now — the investigation found the reliable path and the groundwork shipped in this release — and the remaining performance headroom is mapped and tracked rather than forgotten.

    As always: your writing lives in plain files you own, and Skrive contains no AI.

    View release on GitHub →
  9. v1.8.6

    Skrive 1.8.6 adds nothing. That is the point.

    Twenty-four fixes, no new features. This release is the end of a long audit of the editor — every gesture, every seam, every place the app quietly did the wrong thing and hoped you would not notice. Most of what follows you will experience as an absence: things that used to catch, no longer catching.

    Selecting text works

    Dragging a selection across two paragraphs used to collapse it the instant you let go. Selecting two paragraphs to copy them was, in plain terms, impossible — the highlight vanished on release. It survives now, whether you finish the drag in another block, out in the margin, or below the last line.

    The window can also be dragged by its top bar again on macOS. It could not be moved at all.

    Your place in the document is kept

    Undo now behaves the way you expect: one keystroke of typing is not one undo step, a gesture undoes as a gesture, and your history survives switching between tabs instead of being thrown away.

    Switching a Markdown file between source, split, and preview keeps your caret on the same sentence and your scroll where you left it. Before, the pane came up unfocused at the top of the file and your typing went nowhere until you clicked.

    Shift+Enter inserts a line break instead of splitting the block. Bold and italic can be armed before you type rather than only applied after. ⌘K opens a link on the selection.

    Lists, tables, code, quotes

    A numbered list keeps its starting number when you split it. Toggling a list off with only some items selected no longer takes the whole list with it. Arrow keys inside a table or a code block move by word with Alt, extend a selection with Shift, and jump to the document's edge with ⌘ — instead of being swallowed. Links work inside table cells. Tab indents inside a list or a quote rather than throwing focus out of the editor.

    Enter behaves the same inside a blockquote or a list item as it does anywhere else: it deletes the text you had selected, it keeps a heading a heading, and pressing it on a blank line in the middle of a quote splits the quote where you are, rather than dropping you below the whole thing.

    Pasting

    Paste from Word, Google Docs, Notion, or VS Code and the result is the document you copied, not its debris — no orphaned list markers, no paragraphs fused into one, no code block flattened into prose. Paste-as-plain-text is now genuinely literal: a blank line is a paragraph break and a single newline is a line break, every time.

    Skrive now refuses to follow javascript:, data:, and file: links found in pasted content or in a document's rendered preview. Previously, a document could carry a link that ran code when clicked. If you open documents you did not write, this one matters.

    Your files stay your files

    Files with Windows line endings survive a round trip intact. Tables with a ragged row keep the cells that used to be silently dropped. The rules by which Skrive writes Markdown back to disk are now written down and enforced by tests, so a file you open and close is the file you had.

    Under the hood

    Both desktop builds now compile the same way, and correctly. The macOS build had been shipping an unoptimized core; the Windows build had been shipping one with its runtime safety checks switched off. Neither was intentional, and the two were opposites. Both now build optimized with every check retained — so on Windows, a bug that would once have quietly corrupted memory instead stops and says so.


    Skrive is a writing app. Rendered writing, plain files you own, no AI. Nothing you write here leaves your machine.

    View release on GitHub →
  10. v1.8.5

    A smoother, more trustworthy editor

    This release is almost entirely fixes to the editing experience — a long list of gestures that used to quietly do nothing, or do the wrong thing, now behave the way you'd expect.

    Fixed

    • Selections that touch a code block, table, or divider act on what they can instead of swallowing the gesture.
    • Cut works everywhere — it no longer degrades to a copy near code blocks and tables.
    • Dividers, code blocks, and tables delete like anything else, and can be selected and removed as a unit.
    • Word delete (Option+Backspace), line delete (Cmd+Backspace), and text drag-and-drop now work.
    • Keyboard shortcuts no longer double-fire.
    • The slash menu can't trap you when nothing matches, and it works inside lists and quotes.
    • Turning blocks into other blocks works inside lists, quotes, and across multi-block selections.
    • Toolbar and menu commands work on a collapsed caret and no longer lose your selection along the way.
    • Pasting keeps its structure over selections, inside containers, and at the start of headings.
    • Pasted screenshots render in place, are saved next to your document, and survive reopening it.

    New

    • Live word count: a quiet counter in the corner of the editor that ticks as you type. Switch it between words, reading time, and characters; select some text and it counts the selection instead. Toggleable in Settings.
    • The document outline rail now works in rich mode — ticks, hover popover, and drag-scrub.
    • Copy page on .folio documents, with copy as Markdown, HTML, or plain text.
    • Tab in a table's last cell adds a new row.
    • Hover tooltips on the toolbar and controls, a restored inline-code button, and a round of visual polish.
    View release on GitHub →
  11. v1.8.4

    Skrive 1.8.4 is a polish release: one visual language across every menu, dialog, and control in the app, plus a set of new illustrated icons.

    New illustrated icons

    The insert menu, formatting toolbar, and block controls wear a new duotone icon set — headings, lists, quote, code, table, divider, and link, each drawn as a small illustration. They follow your theme: structural linework adapts to light and dark, and the accent color runs through the whole family.

    A better insert menu

    Type / and the insert menu now reads the way you'd hope: items grouped by kind with clean separators, icons aligned in a column, and keyboard shortcuts shown right on the row — so the menu teaches you the faster path while you use it.

    Tidier toolbar

    Code blocks are now one click on the toolbar (click again to turn back into text). The "Turn into" control shows the icon of the block you're in, and its menu is down to the essentials: text and headings.

    One look for dialogs and menus

    Every dialog and palette — rename, delete, new project, search, the command palette — now shares the same soft rounded surface as Skrive's toasts, with one calm shadow language. Context menus, dropdowns, and the command palette share consistent rows, hover fills, and shortcut hints. Destructive actions sit behind a separator where they belong.

    Calmer controls

    Buttons, text fields, toggles, and dropdowns are unified across the app — including Settings, which now matches the rest of Skrive instead of doing its own thing. Text fields focus with a gentle glow, the same everywhere.

    Also in this release

    • .html files open in a rendered read-only viewer.
    • Removed the redundant floating copy button in the Markdown preview.

    As always: your writing stays in plain files you own, on your machine.

    View release on GitHub →
  12. v1.8.3

    Skrive 1.8.3 — Dual mode

    This is a foundational release. Skrive has always been about rendered writing in plain files you own — but living up to both halves of that at once created a quiet tension. To give you rich, formatted writing while keeping every document as Markdown, Skrive had to translate your document back into Markdown text on every save. That translation fought the rich features, and it meant your file could shift under you in small ways you never asked for.

    Dual mode resolves it. From now on, the file type decides how you write — and each type does one job honestly.

    Two ways to write

    Markdown (.md) — source mode. .md files are now exactly what they look like: plain Markdown text you edit directly, with a live rendered preview beside it (source, split, or preview — your choice). Skrive shows you the preview but never rewrites the file. What you typed is what's on disk, byte for byte. If you keep your notes in Markdown, this is the trustworthy plain-text editor you wanted — nothing translated, nothing lost.

    Skrive documents (.folio) — rich mode. .folio is Skrive's own document format, and it's what powers full rendered, WYSIWYG writing. When you want formatting to just be formatting — not ## and ** you're constantly re-parsing — a .folio holds it natively. One file per document, formatting preserved as itself instead of being squeezed back into Markdown text on every keystroke. This is where Skrive's rich writing lives and grows.

    What .folio means — and why it isn't a trap

    A native format usually means lock-in. This one doesn't, on purpose.

    • Its schema is documented and open.
    • Every .folio exports in one click to Markdown, HTML, plain text, or RTF.
    • You can convert existing files in — Markdown, HTML, or text become a rich Skrive document, and your original is left untouched.
    • Skrive collects nothing.

    Open in, open out, guaranteed export. Proprietary doesn't have to mean predatory — the deal is simple: you can always leave with everything.

    Plain text, treated as plain text

    .txt files now open in a real plain-text mode — no guessed formatting, no misleading preview — and show up in the sidebar with their own icon. Create one from New text file, or just open the ones you already have.

    Take your writing anywhere

    • Export any Skrive document to Markdown, HTML, plain text, or RTF, straight into your project folder. Faithful where the format allows, honest where it can't be.
    • Convert to Skrive document brings a Markdown, HTML, or text file into rich mode — the original stays put.

    Also in this release

    • A refined text cursor, sized to the type rather than the line height.

    The bigger picture: this release frees rich writing to grow without fighting the file underneath it, while keeping the promise that made Skrive worth using — your writing lives in plain files you own, and it goes wherever you do.

    View release on GitHub →
  13. v1.8.2

    Skrive 1.8.2

    The editor's biggest reliability release yet. It closes the whole "nothing is lost" class of bugs and turns code blocks and tables from one-way traps into normal, navigable blocks.

    Your work stays put

    • Nothing is dropped on save, quit, or tab switch — the last thing you typed is always written, even a split second after you stop.
    • Paste from Google Docs and Word keeps its formatting — bold and italic survive instead of arriving as flat text.
    • CJK / IME text sticks when composed inside a code block or table cell.
    • Copy grabs exactly what you selected — no unselected code block or table sneaks onto the clipboard, and the copy keeps its own style instead of the document's first block's.
    • Inline images and line breaks behave when you split, delete, or type around them.

    Code blocks and tables are no longer traps

    • Leave a code block with the arrow keys, and delete an empty one with Backspace.
    • Click below the last block to start a new paragraph — even under a trailing code block or table.
    • Turn a code block into text (or a heading, list, or quote) from the block menu.
    • Enter in a table cell moves down a row, and drops you below the table from the last row.
    • Pasting into a code block keeps its line breaks instead of collapsing to one line.

    Writing niceties

    • Task lists and strikethrough- [ ] and ~~text~~.
    • Smarter paste: hard-wrapped prose flows correctly, and plain-text paste follows standard Markdown rules.
    • Enter at the end of a heading starts a normal paragraph, not another heading.

    App

    • Redesigned sidebar — Favorites, Recents, and All, with manual pins and sorting, plus smoother resize and click-to-collapse.
    • In-app bug reporting — report an issue without leaving the app.

    Install

    • macOS (Apple Silicon): Skrive-1.8.2-arm64.dmg — signed and notarized.
    • Windows: Skrive-1.8.2-Setup.exe (x64/arm64 portable zips also attached).

    Installed copies update themselves automatically.

    View release on GitHub →
  14. v1.8.1

    Skrive 1.8.1 — Clipboard, end to end

    This release makes getting text in and out of Skrive feel effortless — paste cleanly, copy your whole page, and undo anything.

    Paste that lands clean

    Paste from a web page, Notion, or an Obsidian note and it arrives as real formatted content — headings, lists, quotes, code blocks, bold/italic, and links — instead of a wall of literal symbols. Notion callouts become quote blocks. Need the raw characters instead? Cmd+Shift+V pastes as plain text.

    Copy your whole page

    A new Copy page button in the editor toolbar copies the entire document to your clipboard — as formatted text, or as stripped plain text. Your choice from the dropdown.

    Undo, redo, and cut

    Full undo/redo history — Cmd+Z / Cmd+Shift+Z — with smart grouping, so a burst of typing undoes in a single step instead of character by character. Cut and copy now carry clean, formatted content that pastes perfectly back into Skrive or anywhere else.

    A calmer editor

    The toolbar was tidied up: a quiet "Saved" confirmation that appears and fades rather than a permanent indicator, the Copy action tucked to the right, and the rendered/source switch moved into the command palette.

    Install polish

    Opening the macOS DMG now shows a branded install window.

    Plus smaller fixes to toasts and the update notice.


    Install: macOS (Apple Silicon) — Skrive-1.8.1-arm64.dmg · Windows — Skrive-1.8.1-Setup.exe

    View release on GitHub →
  15. v1.8.0

    Skrive's biggest change since 1.0: a brand-new editor.

    A new editing engine

    The editor has been rebuilt from the ground up on a block-canonical engine — your document is a tree of blocks, with Markdown as the file on disk. It is now the default and only editor; the two engines that came before it (CodeMirror and ProseMirror) have been retired. The payoff: typing stays instant even in very large documents, and the app is meaningfully leaner.

    What's new

    • Rendered and Source views — a Rendered | Source toggle in the toolbar (or ⌘⇧E) flips any document between the rich rendered view and its raw Markdown, over the same file. Markdown stays first-class — never hidden behind the editor.
    • Lists that feel right — start a list by typing - or 1. , nest and outdent with Tab / Shift-Tab, toggle bullet and numbered lists with keyboard shortcuts, and Enter / Backspace behave correctly at every nesting level.
    • Tables — insert a table, edit cells, Tab between them, move out with the arrow keys, and delete a whole table by selecting across it.
    • Document-wide selection — select and edit across block boundaries: cross-block delete, type or paste over a selection, multi-block paste, and select-all-delete all work as you'd expect.
    • Inline formatting — bold, italic, inline code, and links via a selection bubble, a slash insert menu, and the command palette.

    Under the hood

    • The renderer JavaScript bundle is more than 50% smaller (~647 KB to ~305 KB gzipped) now that the two old editor engines are gone.
    • Constant-time keystroke-to-paint is enforced by an automated performance gate at 10,000 blocks, so the editor stays responsive at scale.
    • The legacy Electron shell and its build pipeline have been removed; Skrive now builds entirely on its native shell.

    Install

    • macOS (Apple Silicon): Skrive-1.8.0-arm64.dmg
    • Windows: Skrive-1.8.0-Setup.exe (x64), or the portable .zip for x64 / arm64

    The Windows builds are not yet code-signed, so Windows may show a SmartScreen warning on first run.

    Full changelog: https://github.com/brueshi/Skrive/compare/v1.7.2...v1.8.0

    View release on GitHub →
  16. v1.7.2

    A polish release for the macOS app: calmer window behavior, a faster exit, and a redesigned in-app update experience.

    What's new

    • Instant quit. Cmd-Q now closes Skrive immediately, with no pause on the way out.
    • Close the window without quitting. Closing the window no longer quits Skrive — it keeps running in the dock. Click the dock icon (or open a new window) to bring it right back, exactly where you left off. Cmd-Q still quits completely.
    • A natural install window. The drag-to-install window now places Skrive on the left and the Applications folder on the right, so the drag goes the way you expect.
    • A redesigned update experience. Updates now arrive as one of Skrive's own notifications, with a tidy download-progress card in Settings, instead of a generic system dialog. You'll see it on your first update after 1.7.2.

    Notes

    • These changes are macOS-focused. Windows builds are published at 1.7.2 for parity.
    • Existing macOS users are offered 1.7.2 automatically; updates remain signed and notarized.
    View release on GitHub →
  17. v1.7.1

    Skrive 1.7.1

    Skrive 1.7.1

    A small cleanup release on the native foundation introduced in 1.7.0.

    • The app is now simply Skrive — the build-suffix label from the migration is gone.
    • Refreshed some in-app copy to match what Skrive is: a writing app for notes, drafts, and documents, not a "Markdown editor."

    Same files, same native build — it updates automatically from 1.7.0.

    View release on GitHub →
  18. v1.7.0

    Skrive 1.7.0 — Skrive is now a native app

    Skrive 1.7.0 — Skrive is now a native app

    For most of its life, Skrive ran on Electron — the framework behind most desktop apps. It worked, but it came with a tax: every Electron app bundles its own full copy of a web browser and a runtime, so a small writing app becomes a 130+ MB download that sits heavy in memory and takes its time to open. We never loved that. Writing software should feel light.

    So we rebuilt the foundation. 1.7.0 is the same Skrive you know — the same editor, the same files, the same calm — running on a new native core instead of Electron.

    The short version

    • The download went from ~132 MB to ~3.4 MB — roughly 39× smaller.
    • It's lighter on memory and quicker to open: it uses your operating system's own web engine instead of carrying a second browser inside the app.
    • Updates are now tiny and native — a few MB, delivered through each platform's own updater (signed and notarized on macOS).
    • Your writing is untouched. The same plain-text files you own, the same editor, nothing to migrate.

    Why we rebuilt it

    Skrive's whole point is rendered, joyful writing in plain files that are yours — not a heavy IDE, not a cloud silo. The Electron foundation quietly worked against that: shipping an entire Chromium browser per app is the single biggest reason desktop software feels bloated.

    The new architecture is the opposite shape: one small core, a thin native shell for each platform, and the operating system's own webview running the exact same interface. No bundled browser. The result is an app that's a few megabytes instead of a few hundred — without changing a single thing about how it feels to write.

    Under the hood

    For the curious (Skrive is source-available): the new foundation is a small set of deliberately lean, fast pieces.

    • A shared core written in Zig, exposed through a plain C interface — the part that reads and writes your files, tracks projects, and watches the disk for changes.
    • A thin native shell for each platform, each hosting the OS's own web engine: Swift on macOS (over WebKit), and Zig on Windows (over Microsoft Edge's WebView2). The Windows shell is pure Zig — no second language — sitting on the same Zig core the Mac uses.
    • The editor you actually write in — the React and TypeScript app — is the same one that ran under Electron. We replaced only the Electron-specific plumbing beneath it; the bulk of the TypeScript runs and behaves exactly as it always has.

    That last point is the whole trick: keep the entire writing experience as-is, and swap only the heavy machinery underneath it.

    How we got here

    Skrive has worn a few foundations. It started on Tauri, then moved to Electron — and the whole way, two things kept pulling at us: we wanted a small footprint, and we wanted to own as much of the stack as possible, rather than build inside someone else's framework. Neither tool gave us both. Tauri keeps apps small by using the system's webview, but you live inside Tauri's world and its abstractions. Electron hands you a consistent, fully-controlled engine — but bundles an entire browser to do it, and you're still inside Electron's app model.

    So this time we built the foundation ourselves. It moved out from under the app in careful steps — the Zig core first, then a native macOS shell, then a native Windows shell — and at every step we held the writing experience byte-for-byte identical to the old build, verified automatically against the original. The payoff is the combination Tauri and Electron each only half-delivered: a few-megabyte footprint and a shell that's entirely Skrive's own code, in the languages we chose, with nothing between us and the operating system.

    What this means for what's next

    This release is, on purpose, almost invisible: same Skrive, far lighter. But it's the foundation everything after it is built on. A few-megabyte native core opens doors a bundled browser kept shut — a genuine path to Skrive on iPad, and the groundwork for the features we most want to build next, like a real version history and effortless sync across your devices.

    And the things that make Skrive Skrive don't change: plain files you own, no AI, no telemetry (crash logs stay on your machine; you send them only if you choose to).

    Notes

    • macOS: signed and notarized — opens cleanly.
    • Windows: not yet code-signed, so Windows SmartScreen may warn on first run. Click More info → Run anyway. The installer is per-user (no admin) and sets up the Edge WebView2 runtime automatically if it's missing.
    • Existing Electron users: your current app will show a one-time notice pointing you here. Download once, and you're on the native build with automatic updates from now on.
    View release on GitHub →
  19. v1.3.0

    1.3.0

    A fresh coat of icons.

    Skrive's iconography got a modern redraw. The formatting tools, folders, and document marks are all new — heavier, cleaner, and more characterful, without losing the Skrive feel. Everything adapts to your theme automatically, with tones hand-tuned for both light and dark.

    What's new

    • Formatting toolbar — bold, italic, code, lists, quote, table, link, divider, heading, and the rest are now solid, confident glyphs. They still light up with your accent color when active, exactly as before.
    • Folders — redrawn open and closed folders that cross-fade gently as you expand and collapse them in the sidebar.
    • Documents — a refreshed Markdown page icon, tuned to stay crisp on both the light and dark sidebars.

    Notes

    • Purely visual — no changes to behavior, files, or shortcuts.
    • macOS build is signed; Windows build is unsigned (as usual).

    Full changelog: https://github.com/brueshi/Skrive/compare/v1.2.1...v1.3.0

    View release on GitHub →
  20. v1.2.1

    Skrive 1.2.1

    Minor fixes and housekeeping.

    • Share feedback directly from Settings → About, plus a gentle one-time in-app prompt
    • Persistent notifications (updates, feedback) can now be dismissed with a corner control or a swipe
    • Internal cleanup and added test coverage
    View release on GitHub →
  21. v1.2.0

    Skrive 1.2.0

    A visual refresh. This release reworks the app chrome end to end: a new light theme, a cleaner dark, a quieter sidebar, and a settings page that finally matches the editor.

    A new Light theme

    The light theme is now a clean white editor on a soft grey shell, brighter and more neutral than before. It replaces the previous warm light palette as the default.

    A refined Dark theme

    Dark has been retuned to a cooler, more even neutral, and its panels now carry a defined edge so the editor reads as its own surface instead of blending into the background. Error and destructive text is legible on dark now, too.

    A quieter sidebar

    The file sidebar is no longer a floating card. It sits flush as a calm rail alongside the editor, which now sits closer to your files. Folder names and the tree guides read more clearly across every theme.

    A redesigned Settings page

    Settings now mirrors the editor: a flush navigation rail beside a rounded content card. Switching sections fades and rises into place, the surface toggle slides between options, and the redundant Done button is gone (Back already takes you home).

    Took care of some minor bugs as well.

    View release on GitHub →
  22. v1.1.0

    Skrive 1.1.0

    Skrive 1.1.0 is a foundation release. It is the largest re-architecture of the app's internals since the move to React, and it deliberately changes nothing about how Skrive looks or feels — every editor behavior is at parity with 1.0.3. The visible change is a single security hardening; the rest is groundwork.

    If you are upgrading from 1.0.3: nothing in your workflow changes, your projects and settings are untouched, and there is nothing you need to do.

    What changed for you

    • Symlink-aware path containment. Skrive now resolves every file path against the real project root: a symbolic link inside a project that points outside it can no longer be followed out of the project folder, for reads, writes, or image serving. The impact is low for a local, single-user editor where you chose the folder yourself — but it is the correct boundary, and it is now enforced and covered by tests.
    • Everything else behaves exactly as before. Backlinks, project search, dead-link and orphan detection, rename-with-references, autosave, external-change detection, image paste, and history all work identically to 1.0.3. This release changes no editor behavior by design.

    Under the hood

    The work behind this release re-draws the line between the editor and the system layer so the editor is no longer tied to any one host.

    • One typed contract. Every message between the editor and the system now flows through a single versioned envelope with a closed set of error codes and a tested transport boundary, replacing a scatter of ad-hoc channels. This is the groundwork that lets the same editor run in other environments, including a future web embed.
    • Text analysis moved into the editor. The link graph, project search, and frontmatter schema inference now run in a dedicated background worker off one batched project snapshot, rather than in the system process. The system layer no longer parses Markdown at all — it is reduced to filesystem, project, history, and OS primitives.
    • Clipboard through the OS. Rich copy from the preview now goes through the operating-system clipboard instead of a browser API, so it keeps working across more environments.
    • Housekeeping. Removed the dead Tauri and Svelte code carried over from the original prototype stack, and added a cross-implementation parity corpus that pins the system contract command-by-command.

    Verification

    • 326 editor tests, 68 system-layer tests (including a new symlink-containment suite covering five distinct escape attempts), 65 shared-contract tests, and a 26-case parity corpus that replays green.
    • Validated on a signed, notarized packaged build before tagging.
    • No changes to the on-disk file format. Upgrading is safe and reversible.
    View release on GitHub →
  23. v1.0.3

    Skrive 1.0.3

    Skrive 1.0.3 is a correctness and performance release focused on the projection editor — the layer that keeps the Rich surface and the Markdown on disk telling the same story.

    This release came out of a deep fidelity and performance audit of the projection architecture, conducted and implemented end to end with Claude (Fable 5), Anthropic's frontier model — the audit found the bugs, multi-agent sessions fixed them in parallel, and a new corpus-wide test gate now stands guard over the dirty path.

    Round-trip fidelity fixes

    The projection editor's promise is that editing one block never rewrites the rest of your file. The untouched-block path was already byte-identical; this release fixes a set of bugs that fired when a block was edited:

    • Inline images are no longer silently deleted from the file when the paragraph around them is edited. Images now appear in the Rich surface as real inline elements and serialize faithfully (alt text, URL, and title preserved).
    • Pressing Enter in the middle of a paragraph no longer risks losing the paragraph break on save. Split blocks now correctly forget the verbatim source they inherited, on every split path (Enter, list splits, input rules), with undo still restoring the original bytes exactly.
    • The canonical serializer now escapes properly. Backslash escapes survive edits, text that happens to start with Markdown syntax ("> ", "# ", "1. ") can no longer change block structure on save, and inline code containing backticks round-trips correctly.
    • Code fences keep their character and length: a ~~~ fence whose body contains ``` lines no longer corrupts when edited, and fence info strings (language plus meta) are preserved.
    • Reference-style links and images, inline HTML, and footnote references now freeze their containing block rather than degrading to plain text when touched.
    • Link titles survive edits. Hard breaks can no longer be smuggled into headings, where they produce invalid Markdown.
    • Loose lists containing tight items keep their rhythm when edited.

    A new acceptance gate backs all of this: every block of every document in the test corpus is dirtied, serialized, and re-parsed, asserting the result is structurally identical to the original.

    Editor performance

    • Moving the cursor within a line no longer re-walks the visible syntax tree to rebuild decorations — rebuilds happen only when the cursor changes lines, the document changes, or the viewport moves. This removes the dominant per-keystroke cost in the Text surface on large documents.
    • The preview outline rail no longer re-measures every heading on every keystroke. It now invalidates on heading structure, caches heading elements, and coalesces resize bursts — an image-heavy document measures a handful of times while loading instead of dozens.
    • Typing-to-preview latency dropped by ~150ms: the preview's debounce sat downstream of the editor's store sync and coalesced nothing, so it was removed. Preview, word count, and outline now read the same snapshot.
    • Word count is memoized instead of re-scanning the document on every state emission.

    Verification

    297 tests pass, including the new dirty-corpus fidelity gate, a split-block editing matrix driven through the production plugin stack, and unit coverage for the new invalidation logic.

    View release on GitHub →
  24. v1.0.2

    Skrive 1.0.2

    Skrive 1.0.2 adds two focused improvements on top of 1.0.1.

    Git history toggle

    Settings → General → Version history now has a Use Git for version history switch (on by default). Turn it off and Skrive stops reading your project's Git repository for the History panel and uses its own checkpoint history instead — no git log or git show runs when you open a document or switch tabs. This removes the Git activity that came from simply opening or browsing documents in a repo-backed project. Flip it back on and Git history returns immediately, no reopen needed. The setting persists across restarts and applies to every project.

    macOS dock icon follows system dark mode

    The dock tile now matches your system appearance — the dark Skrive mark under dark mode, the light mark otherwise — and swaps the moment you toggle System Settings → Appearance. macOS only.

    Builds

    • macOS: Apple Silicon .dmg, signed and notarized.
    • Windows: NSIS .exe installer, unsigned (SmartScreen warns on first run — More info → Run anyway).
    View release on GitHub →
  25. v1.0.1

    1.0.1

    Small QOL changes to the Rich Editor as well as some UI fixes Install macOS (Apple Silicon): signed and notarized .dmg — installs with no warnings. Intel Macs run under Rosetta 2. Windows: .exe installer. It is unsigned for now, so SmartScreen will warn on first run — choose More info -> Run anyway.

    View release on GitHub →
  26. v1.0.0

    Skrive 1.0.0 — Overcast

    Skrive 1.0 is two reimaginings landing at once: the editor has been rebuilt from the ground up, and the entire interface has a new visual language we call Overcast. Under both is a single conviction — Skrive should be a document you write in, not a code editor with a preview bolted on.

    The editor, reimagined

    For years the Markdown editor has been a cliche: a split pane, monospace on the left, a preview on the right, syntax permanently in your face. Skrive 1.0 replaces that with a projection editor — one Markdown file, two ways to work in it:

    • Rich — a no-syntax writing surface for everyone. You write the document, and bold, headings, lists, quotes, dividers, tables, and links appear as the real thing — never as raw ** or #. Structure is created through a toolbar, a selection bubble, and a slash menu, so you build a document without ever typing a fence.
    • Text — an honest source surface for people who know Markdown and want it plain, with a choice of how present the syntax is: Raw, Recessed, or Concealed.

    Both surfaces edit the same file. Switch between them with Cmd-Shift-E and your content carries over untouched. New documents open in Rich by default; the Text surface is one keystroke away.

    The commitment that makes this honest: your file on disk is always canonical, plain Markdown. Everything richer is a projection of that text, never a container that owns it — so there is no proprietary format, no lossy export, and the bytes you would write by hand are the bytes Skrive saves. (And no AI anywhere — Skrive is a tool for your words, not a generator of them.)

    Overcast — a calmer, more crafted interface

    The whole app was re-skinned and restructured around a warm near-white page on a cooler dove-grey desk, a slate-indigo accent, rounder corners, and custom iconography:

    • Settings is now a full page, with grouped cards, instead of a cramped modal.
    • Side panels dock as cards beside a narrowing editor rather than floating over it.
    • A reworked topbar — window controls and the sidebar toggle grouped on the left, lifted tabs, a surface toggle, and a quiet save indicator.
    • Project-wide search now shows a live context preview of the highlighted match beside the results.
    • Backlinks is bidirectional — both what links to this document and what it links out to, grouped by file with folder tags.
    • New editor controls that actually do something: line measure (column width), smart typography (curly quotes, em dashes, ellipses), format on save, and a configurable autosave delay.
    • The command palette, search, every dialog, and the right-click menus were all brought into the Overcast language.

    Under the hood

    For the curious, the foundation that makes the two surfaces trustworthy:

    • Byte-faithful round-trip. A source-mapped parser tags every block with its verbatim source; the serializer splices untouched blocks back byte-for-byte and only re-writes what you actually changed. Open and edit a real document and the parts you did not touch are identical to the byte.
    • Durable saves. Writes are atomic (temp file, fsync, rename — a crash cannot corrupt a document), the app detects changes made on disk outside Skrive and asks before overwriting, autosaves on a debounce, and flushes any pending edit before the app quits.
    • Smooth at scale. Project linting runs in a background worker, so typing stays fluid no matter how large the project gets.
    • One parser, not three. Preview, the projection, and linting all run off a single Markdown authority.

    What's next

    1.0 is the foundation, not the finish line. Already in motion:

    • Marginalia — margin notes anchored to ranges of your text, with bilateral sidenotes and connectors.
    • Typed blocks — callouts, profiles, and richer blocks you author inline but that save as honest, plain-text fences.
    • PDF export with margins — beautifully typeset export with bilateral margins, connectors, and footnotes.

    Install

    • macOS (Apple Silicon): signed and notarized .dmg — installs with no warnings. Intel Macs run under Rosetta 2.
    • Windows: .exe installer. It is unsigned for now, so SmartScreen will warn on first run — choose More info -> Run anyway.
    View release on GitHub →
  27. v0.3.0

    v0.3.0 — Clipboard paste-in & copy-out, with images

    Bidirectional clipboard handling for the editor:

    • Paste in — rich HTML from web pages, Google Docs, or Word is converted to clean, canonical Markdown in Skrive's house style. Plain text pastes verbatim.
    • Copy / cut out — writes both the raw Markdown (text/plain) and the rendered HTML (text/html), so a selection pastes cleanly into code editors and as formatting into Gmail/Docs/Word.
    • Preview copy button — copies the whole document cleanly from the rendered view (no background bleed).
    • Image paste — a screenshot or copied image is saved into a sibling assets/ folder and rendered inline in the editor and preview, via a custom protocol confined to the project root.

    Prerelease build for testing. macOS is signed + notarized; Windows is unsigned (SmartScreen: "More info → Run anyway").

    View release on GitHub →
  28. v0.2.4

    Skrive v0.2.4 — Document outline rail

    The outline rail: a fast way to see a document's shape and move around inside it, right where you read it.

    What's new

    Outline rail

    In Preview (⌘3), any document with two or more headings gets a slim rail of section ticks down the right edge:

    • It tracks where you are. The tick for the section you're currently reading stays highlighted as you scroll.
    • Click a tick to jump to that heading.
    • Hover or focus the rail to expand a labeled outline — every heading, indented by level, the current one marked. Click a row to jump.
    • Drag the rail to scrub the whole document, like a scrollbar that knows your structure.
    • Tick width tapers by heading depth, so the shape of the rail echoes the shape of the document.

    Toggle it in Settings → General → Outline rail (on by default). The rail lives on the rendered preview — a reading-and-navigating aid — so the writing canvas stays clean.

    In-document links

    Headings now carry anchor ids, so [jump to a section](#heading-name) links resolve inside the preview. Ids use the same GitHub-style slug rule a published copy would (lowercase, spaces to hyphens, punctuation dropped), and repeats disambiguate the way GitHub does (-1, -2). A bare # link scrolls back to the top.

    Under the hood

    • Keyboard-complete: Tab to the rail, then ↑/↓/Home/End to move, Enter to jump, Esc to close. The rail is a single focus stop (a listbox with aria-activedescendant), and motion respects prefers-reduced-motion.
    • The rail reads heading positions from the rendered output, so it stays accurate through line wrapping, images, and reflow.
    • Slugging and active-section logic are unit-tested — 23 new tests.

    Notes

    • The rail is preview-only: it navigates the rendered document, not the editor, and it's deliberately an ambient affordance rather than another docked panel. It's hidden in raw and split layouts, and on documents with fewer than two headings.

    Install

    • macOS arm64Skrive-0.2.4-arm64.dmg, drag Skrive to Applications. Signed and notarized. Already on v0.2.3? The in-app updater will offer this one automatically.
    • WindowsSkrive-0.2.4-Setup.exe. SmartScreen warns (unsigned); click "More info" → "Run anyway."
    View release on GitHub →
  29. v0.2.3

    Skrive v0.2.3 — Fix macOS auto-updater

    🩹 Hotfix for the macOS auto-updater. v0.2.0 → v0.2.2 shipped only a .dmg artifact for macOS, which broke in-place updates with ZIP file not provided. v0.2.3 also ships a .zip — the format Squirrel.Mac (the underlying macOS update engine) actually consumes.

    What you need to do

    • macOS, currently on v0.2.0 / 0.2.1 / 0.2.2: the auto-updater can't get you to v0.2.3 — it's blocked on the missing zip in the older releases' manifest. Download the v0.2.3 DMG below and drag-to-Applications once. From v0.2.3 onward, the in-app auto-updater works again.
    • macOS, fresh install: just grab the DMG as usual.
    • Windows: unaffected; updates worked.

    What changed in code

    One line of electron-builder.yml:

    mac:
      target:
        - target: dmg
        - target: zip   # ← new
    

    The DMG is for install (drag-to-Applications); the ZIP is what the autoUpdater downloads and unpacks in place. v0.2.2 and earlier listed only the DMG in latest-mac.yml, so Squirrel.Mac rejected every update attempt.

    No other changes

    This is a release-engineering fix only — no UI or feature changes from v0.2.2. If you're already on v0.2.2 (light theme, inset design, etc.) the app looks identical; the only difference is the updater will actually work next time.

    View release on GitHub →
  30. v0.2.2

    Skrive v0.2.2 — Light theme + Electron stops forcing dark

    Light mode + a proper theme system. After v0.2.1 locked the inset design, this release adds back the light theme that had been deferred and stops Electron from forcing dark mode on light-mode machines.

    What's new

    Light mode

    • New Theme picker in Settings → General → Appearance: System (matches the OS automatically), Light, or Dark.
    • New installs default to Light. A warm paper-like palette: #fefcf7 page, #1f1d1a ink, soft warm rules. Existing dark-mode users are migrated to Dark on upgrade so nothing changes for you without consent.
    • Theme switching is live — flip in Settings and the whole workspace fades to the new palette (no relaunch needed).

    Electron stops forcing dark

    • The BrowserWindow's pre-paint background no longer hardcodes #1a1a1a. It now follows nativeTheme.shouldUseDarkColors so a light-mode OS gets a light flash on launch and a dark-mode OS gets a dark one. No more "the app is dark even though my system is light."

    Under the hood

    • All palette tokens (--skrive-bg, --skrive-fg, --skrive-muted, --skrive-rule, --skrive-link, --skrive-selection, --skrive-focus-ring) now use CSS light-dark(). The browser resolves them against the active color-scheme, which data-theme on <html> pins (or follows the OS when absent).
    • light-dark() is also wired through the three shell-tone variants. Their values stay distinct in dark mode; in light mode they all resolve to the same fixed light palette.

    Known limitation

    The Shell tone toggle is dark-mode only for v0.2.2 — picking different tones in light mode has no visible effect. Light-mode shell-tone variants are a follow-up release if the single fixed palette doesn't cover real use.

    Upgrade behavior

    • First-time installs: start in Light.
    • Existing v0.2.1 (or earlier) users: migrated to Dark to preserve your current experience. Switch to Light or System anytime in Settings → Appearance.
    View release on GitHub →
  31. v0.2.1

    Skrive v0.2.1 — Inset Design Stabilization

    A visual overhaul. The editor now floats as a rounded card inside a soft shell frame, with the sidebar as its own floating card alongside. After A/B-testing several layout forks during v0.2.0, this release locks the winning combination and commits to it.

    What you'll notice

    A new page-on-desk look

    • Full 4-side inset — the editor card has shell margin on all sides, with rounded corners and a subtle shadow.
    • Sidebar is now a floating card too, separated from the editor by a deliberate gap rather than a 1px divider line.
    • Shell tone is configurable — Light, Same, or Dark. Default is "light shell, darker page" (paper-on-inked-desk). Switch from Settings → General → Appearance.

    Topbar streamlined

    • Just three controls on the right: a panels popover (Frontmatter / Backlinks / History as checkboxes) and the Raw / Split / Preview mode toggle.
    • The sidebar toggle button got a Notion-style refresh — larger icon, clear breathing room from the traffic lights, aligned with the tab strip.
    • The project name dropdown (Open project / Close project) moved from the topbar to the sidebar's section header. The "FILES" label is replaced with your current project name + caret.

    Settings is now a modal

    • Press ⌘, and Settings opens as a centered Dialog over the editor instead of replacing the workspace. The editor stays visible behind it — useful when you're previewing appearance changes against an actual document.

    New behaviors

    • Drag-to-collapse the sidebar — pull the resize handle below ~100px and the sidebar snaps fully closed. ⌘[ reopens it at its previous width.
    • Side panel push behavior (Settings → Appearance) — when on, opening a panel narrows the editor card to make room. Switch to "Float" if you'd rather have it overlay.

    Under the hood

    • Settings rewritten as a Radix Dialog modal to eliminate the layout-shift issues the workspace-view approach kept producing.
    • Workspace + sidebar wrapped in contain: paint for paint isolation — CodeMirror scroll no longer re-rasterizes the card's rounded mask + box-shadow on every line virtualization frame.
    • Animation curve token `--skrive-easing-out` added; entrance animations use the snappier ease-out curve. Baseline durations tightened (quick 120→110ms, standard 160→150ms, slow 180→160ms).
    • Card shadow lightened in the "Same tone" palette — the old 0 8px 24px blur was costly on inner scroll.

    Removed

    The following experimental layouts and components no longer exist: Classic topbar (full FM/BL/HI cluster), Collapsed-bottom rail, Top+bottom inset, Embedded sidebar, Tabs-on-card, DocumentToolRail / CollapsedBottomRail / SettingsView. If you had any of these selected in v0.2.0, you'll be migrated to the locked behavior on next launch.


    Note: v0.2.1 ships dark-mode only. v0.2.2 immediately follows with light mode and theme switching — see that release for details.

    View release on GitHub →
  32. v0.2.0

    Skrive v0.2.0 — Same Skrive, new foundation

    v0.2.0 — Same Skrive, new foundation

    This release is a rebuild, not a redesign. Skrive's writing surface, project model, rename-with-references, and structural diff are all at v0.1.6 parity. What changed is everything underneath.

    Skrive moves off Tauri + SvelteKit onto Electron + React + napi-rs. The reason is maintainability: React + Electron is one of the most heavily traveled paths in desktop software, with a single TypeScript codebase across the renderer and the shell, and a vastly larger ecosystem of accessible primitives (Radix), command runners (Cmdk), and animation libraries (Framer Motion) to pull from when design and feature work need to scale. Tauri + Svelte was lean and fast, but every meaningful feature was a custom-build job; the foundation needed to be one we can iterate on instead of fight.

    The honest tradeoff is package size. Tauri ships a ~10MB binary by reusing the system webview; Electron bundles its own Chromium and lands in the 150-200MB range. There isn't really a best-of-both-worlds option for desktop apps right now — system webview comes with platform fragmentation, bundled Chromium comes with size. We picked the side that lets a solo project move faster without trading off correctness.

    What's new

    • Keyboard shortcut cheat sheet. ⌘/ opens a modal listing every binding the app responds to, grouped by area. First answer to "wait, what does ⌘⇧B do?"
    • Accessibility baseline. Keyboard navigation reaches every primary action. ARIA labels on custom controls. Modal focus-trap via Radix. prefers-reduced-motion respected on every transition. Not a feature flag — just how the app is built now.
    • Signed + notarized macOS installer. Skrive opens cleanly on a fresh Mac without the Gatekeeper warning, on first launch and forever after.
    • Auto-update wired in. "Update on launch" toggle in Settings → Updates, plus a manual "Check for updates" button. Background download, restart-to-apply.
    • Sidebar moves to ⌘[. v0.1.6 used ⌘B, the VS Code convention. ⌘[ feels closer to "open the rail" than "make this bold," which matters when you're not coding.

    Under the hood

    • Stack: Electron 33 + React 19 + CodeMirror 6 + Radix UI + Cmdk + Framer Motion. Replaces Tauri 2 + SvelteKit + CodeMirror 6.
    • Native diff core preserved. The Rust crate that powers version history is unchanged at the algorithm level — exposed through napi-rs as @skrive/diff instead of through Tauri commands. Same fixtures, same parity tests.
    • Typed IPC. Renderer and shell communicate through a type-checked contract instead of Tauri's runtime-typed invoke(). Adding a handler is a type + an implementation, not a refactoring spelunk.
    • Performance budgets verified. Cold-open <1.5s on a 100-file project. File switch <50ms. Lint refresh <500ms on a 200-file project. Measured by an instrumented fixture in the repo.
    • Central shortcut registry. Every keyboard binding lives in one TypeScript module — the same source the cheat sheet renders from, the same source the dispatcher reads. Adding a binding is one edit.
    • Token-coherent chrome. Radius, z-index, and motion timing live as CSS custom properties at :root. The next polish pass touches one place instead of fifty.
    • Voice consistency. Error toasts say "Couldn't" instead of "Failed to." Empty-state messages teach instead of just stating absence.

    Coming next

    A lot of great things are planned — typed blocks, exports, faster diff, cloud sync — and the new foundation is what lets those land in months instead of quarters.

    Install

    Pre-alpha build.

    Existing v0.1.6 users: uninstall v0.1.6 before installing v0.2.0. The two versions use different installer formats and updaters, and we haven't validated sharing app data between them. After uninstalling, install v0.2.0 from the assets below; v0.2.0+ will auto-update from here on.

    • macOS arm64 — download Skrive-0.2.0-arm64.dmg, drag Skrive to Applications. Signed and notarized.
    • Windows — download Skrive-0.2.0-Setup.exe. SmartScreen will warn (unsigned); click "More info" → "Run anyway." Code signing is on the roadmap.

    Skrive is solo work. If something in v0.2.0 doesn't feel like Skrive, open an issue — that's the most useful thing you can do.

    View release on GitHub →
  33. v0.1.6

    Skrive v0.1.6

    v0.1.6 — Top-bar redesign

    The chrome at the top of the workspace was reading as a separator strip — a white macOS title bar above a cream Skrive header above the editor, with rules between each layer. This release pulls the cream all the way up to the traffic lights, redoes the open-document tabs as cards that flow into the editor below, and lightens the right-side panel toggles.

    What's new

    • Cream extends to the very top. The window now uses macOS overlay title bar mode, so the warm cream surface continues up under the traffic lights instead of stopping at a white strip. No more color seam at the top of the window.
    • Tabs are document cards. Each open tab gets the Markdown doc icon, browser-style sizing (tabs hug their content width, cap at 14rem for long filenames, and shrink uniformly to 36px icon-only when many are open), and an active state that lifts to the editor cream with rounded top corners — the active tab's bottom edge meets the editor edge, so the open document visually flows out of its tab.
    • Right-side panel toggles, lightened. The FM / BL / Aa / HI text pills in the top-right are replaced with four small icon-only buttons (frontmatter, backlinks, personal dictionary, history). Counts moved into each panel's own header where they're more useful, so the chrome stops carrying content metadata.
    • Four new panel icons. IconFrontmatter, IconBacklinks, IconDictionary, and IconHistory join the existing IconDocMarkdown / IconFolder family — same hand-drawn voice, same 16/24 sizing pattern.

    Under the hood

    • New --skrive-chrome CSS variable (light: #efece5, dark: #1a1a1a) gives the chrome strip a subtle tint so the active tab — which matches editor cream — reads as lifted out of the strip and connected to the writing surface below. Tab strip uses align-items: stretch plus container padding-top so the active tab extends from above the text down to the chrome's bottom edge; tabs themselves use flex: 0 1 auto for the hug-content sizing.
    • macOS overlay title bar requires the chrome to clear the traffic-light cluster — 78px left-padding applied via a navigator.platform check at mount, so Windows / Linux builds don't get phantom whitespace. Header carries data-tauri-drag-region so window dragging still works in the empty zones of the chrome.
    • Panel click-outside escape hatch refactored: each side panel's "ignore clicks on my own toggle" check now matches a data-panel-toggle="X" attribute instead of the (deleted) per-pill class names. ~190 lines of dead pill CSS removed from Header.svelte in the same pass.

    Coming next

    • Sort order options for the sidebar tree with per-project persistence
    • Inline metadata in the sidebar (relative time, optional word count, tag chips)
    • Pinned section above the sidebar tree
    • Drag-to-reorganize with link rewriting
    • Smooth expand/collapse animation in the sidebar
    View release on GitHub →
  34. v0.1.5

    Skrive v0.1.5

    v0.1.5 — Sidebar tree redesign

    The sidebar is the workspace's most-touched surface. This release rethinks it from a writer's perspective: titles instead of filenames, custom-drawn iconography, and a tree-spine treatment that respects each subtree's structure.

    What's new

    • Title-as-primary rendering. File rows now show the document's frontmatter title: as the main label, with the filename rendered as a muted secondary line below. Docs without a title: field still show the filename, no regression.
    • Real recursive tree. The previous flat-grouped view (each subfolder rendered as a separate top-level group) is gone. Folders nest naturally, with click-to-collapse on every folder header. Expand/collapse state is in-memory for now; per-project persistence lands in a later pass.
    • Custom folder + doc icons. Two new hand-drawn icons in Skrive's visual voice: IconFolder (a single component whose pocket-line morphs between open and closed states with a subtle CSS d animation) and IconDocMarkdown (a doc silhouette with an inline Markdown wordmark). Replaces the generic chevron + filename rendering.
    • Indent guides with L-elbows. Each row gets a connector to its parent — a half-height vertical with a horizontal stub bending into the row's icon. Ancestor spines stack across the tree to make depth legible at a glance.
    • Subtree-respecting spine rule. A spine line at column d on row R draws only if R's ancestor at depth d+1 is not a last child. Each subtree's spine is contained to its own siblings — when a folder is the last in its parent, its column-line stops at its elbow rather than extending through descendants. Cleaner termination, no lines pointing to nothing.

    Under the hood

    • Indent step bumped from 0.75rem to 1.25rem so L-elbows have geometric room to read as connectors rather than tick marks.
    • File rows use a flex-row layout (icon column + flex-column label stack) so titles ellipsize independently from filenames, and the active-state accent uses an inset box-shadow instead of a transparent border — no more 2px alignment jog between folder and file rows.
    • Spine geometry is computed in the snippet and inline-styled per row, not via static CSS. Each row knows its own ancestor-lastness chain and builds its own multi-layer background-image from that.

    Coming next

    • Sort order options (modified, created, name) with per-project persistence
    • Inline metadata (relative time, optional word count, tag chips)
    • Pinned section above the tree
    • Drag-to-reorganize with link rewriting
    • Smooth expand/collapse animation
    • Backlinks panel revamp with shared visual language

    Install

    Pre-alpha build. See install instructions for each platform.

    View release on GitHub →
  35. v0.1.1

    Skrive v0.1.1

    The first post-alpha release. Four dogfood-driven additions to make daily writing flow smoother, plus the supporting plumbing each one needed.

    Drag-and-drop image import

    Drop an image onto the editor and Skrive copies it into a project-relative attachments/ folder, inserts a Markdown image at your cursor, and renders it inline. Filenames are preserved; collisions get a -1 / -2 suffix.

    • A subtle dashed outline appears on drag-enter so the drop target is unambiguous.
    • Source paths are written source-file-relative (e.g. ../attachments/foo.png from a file in chapters/), so the markdown renders correctly in Skrive, GitHub, and any other reader.
    • Filenames with spaces (screenshot defaults like Screenshot 2026-04-29 at 6.25.48 PM.png) are URL-encoded automatically.
    • When a drag source doesn't include a real file path — common for browser, Slack, and Photos.app drags that carry URLs instead — Skrive surfaces a quiet notice instead of failing silently.

    Tab indents and outdents list items

    Tab and Shift-Tab inside a -, *, +, 1., or 1) list now nest and unnest the item — what writers expect from Word, Notion, Bear. The gesture is gated on list context so Tab on a prose line falls through to default (which matters: a 4-space prose indent silently becomes a CommonMark code block).

    Multi-line selections nest as a group when every line is a list line.

    Rename-as-path

    In the rename modal (F2 on a tab or Rename… in the sidebar), typing a path with / separators now moves the file into that subdirectory. Intermediate folders are created if missing.

    • docs/foo.md → moves the file into a docs/ subfolder of its current location.
    • A "Moves to: …" hint appears under the input so typos surface before commit.
    • Inbound link rewriting reuses the same machinery as in-place renames; references update across the project automatically.

    Inline image preview

    ![alt](path) now renders as the actual image both in the editor (inline thumbnail) and in the preview pane (full size). Image URLs are resolved against the source file's directory, normalized for . and .., URL-decoded, and converted into asset-protocol URLs the webview can fetch.

    A console warning surfaces the resolved URL on load failure, so when an image doesn't render the path it tried is one click away.


    Upgrade notes: existing image markdown that you typed by hand with literal spaces in URLs won't render until the spaces are encoded as %20. Re-dropping the image is the fastest fix.

    View release on GitHub →
  36. v0.1.0

    Skrive v0.1.0

    Skrive v0.1.0 — alpha

    This is the first alpha release of Skrive — a Markdown IDE for people who write seriously and ship to the web.

    The product is intentionally narrow. Skrive is not a notes app, not a knowledge graph, not an AI editor. It is a fast, opinionated workspace for real Markdown writing — projects of files on disk, structured frontmatter, a surface that renders inline, a diff that reads like prose, and a rename that updates every reference for you.

    If you've been waiting for a tool that takes Markdown writing seriously without trying to become Notion, this is it.


    What's in the alpha

    The writing surface

    • Inline preview decorations. **bold** collapses to bold when your cursor leaves the line and reverts when it returns. Images render in place. Links display as styled text without the URL clutter.
    • Three layout modes — raw, split, preview — toggleable per file with ⌘1 / ⌘2 / ⌘3. Layout state is remembered per file across sessions.
    • A real editor surface. CodeMirror 6 underneath, an opinionated default theme on top (Iowan Old Style, 17px, 1.7 line-height), and now a curated typography picker if those defaults aren't yours.

    Project model

    • Projects are folders of .md files, not vault databases. Open them, write in them, version them with Git like any other code project.
    • Structured frontmatter. ⌘⇧F opens a typed-field panel; the project's schema is inferred at open time so autocomplete and known-value suggestions work immediately.
    • Personal dictionary layered on top of the OS spellchecker — words you've taught Skrive don't get flagged across any project.

    The Unique features

    • Rename with references. Right-click any file → Rename, and every link to it across every other file in the project updates atomically. The single feature that separates Skrive from every other Markdown tool.
    • Backlinks. ⌘⇧B shows everything in the project that links to the current file, with byte-precise jump targets.
    • Structural diff. ⌘⇧H opens version history (Git or checkpoint-based, whichever your project has). Diff between any two versions, or any version against current.

    New in v0.1.0

    • Settings page — opens with ⌘, as a workspace tab (VS Code-style). Sections: General, Editor, Personal Dictionary, Updates
    • Editor typography — five curated presets (Editorial / Classic / Screen / Sans / Mono) plus a Custom font field that uses any typeface you have installed system-wide. Stepped size (14–22) and line-height (1.5 / 1.7 / 2.0) controls.
    • Command palette⌘⇧P opens a real command runner with fuzzy search, separate from the file switcher (⌘P, unchanged). Every binding in the app discoverable from one keystroke.
    • Reveal preferences in Finder — Settings → About → Reveal in Finder. Useful for sharing your config when reporting issues.
    • Auto-update on launch toggle — Settings → Updates. Default on; opt out if you want full control over update timing.

    Installation

    • macOS — download the .dmg, drag Skrive to Applications. Signed and notarized.
    • Windows — download the .msi installer. Currently unsigned (SmartScreen will warn on first run; click More infoRun anyway).
    • Linux.deb and .AppImage both attached.

    Auto-update is enabled by default; subsequent releases install in place.


    Alpha caveats

    This is alpha. It works — but rough edges exist and your dogfood feedback is the input shape that v0.2 will be built around. Expect:

    • Visual quirks under specific font/size combinations (typography is brand new in this release).
    • Per-platform polish gaps. The macOS experience is the most mature; Windows and Linux are functional but less hardened.
    • Features you might miss. Drag-and-drop image import, hover previews, sidebar folder hierarchy — all on the post-alpha track.

    Found something broken? Settings → About → Reveal in Finder, share your app.json, and open an issue. The faster I see real-world setups, the faster v0.2 happens.


    Philosophy

    Skrive is local-first — your files live on your disk, in your folders, in plain .md. No server, no sync (yet), no AI. No phone-home. The writing is yours.

    It's source-available under PolyForm Noncommercial 1.0.0 — free for personal use; commercial rights reserved for a future paid tier.

    View release on GitHub →
  37. v0.0.9

    Skrive v0.0.9

    v0.0.9 — Structural diff: algorithm picked, backend shipped

    This release lands the research and backend work for Phase 3.3b (structural diff). The Svelte-side renderer upgrade was attempted and reverted — the diff UI users see is still the Phase 3.3a line-diff, which works cleanly. The algorithm work and Rust backend are in place so the next renderer attempt doesn't start from zero.

    What's in

    Algorithm decision (T1 resolved). Block-hash matching with Hungarian assignment. Chosen over Zhang-Shasha tree-edit-distance and block-Myers

    Full transcripts and reasoning live in docs/3.3-algorithm-memo.md.

    Production compute_diff in src-tauri/src/diff.rs. New Block, BlockKind, DiffOp (Kept/Added/Deleted/Moved/Reworded), and WordOp types. Fence-aware block splitter (code blocks with blank lines stay intact). Word-level intra-block diff for reworded paragraphs via similar::TextDiff::from_words. Exposed as a Tauri command. Covered by 10 new tests; full Rust suite at 147 passing.

    TypeScript mirror. src/lib/diff/structural-diff.ts carries the frontend-side type definitions and a thin computeDiff invoke wrapper, ready for whenever the renderer gets picked back up.

    What's deferred

    The renderer. The Svelte preview-mode upgrade (moved banners, reworded inline word-level diff, sage/slate/brass palette) landed and was reverted after a reactivity bug that couldn't be reproduced or diagnosed remotely. The 3.3a line-diff renderer stays as the diff UI. When the structural renderer is picked back up, the approach is: build it as a standalone demo page with hardcoded DiffOp[] fixtures first, then wire into DiffView as a second render path alongside the line-diff, not a replacement. No date.

    Upgrade notes

    • No user-visible changes. The diff view looks identical to v0.0.8.
    • No migration; no data format changes.

    Under the hood

    • New: src-tauri/src/diff.rs (structural diff), src/lib/diff/structural-diff.ts
    • Updated: docs/3.3-algorithm-memo.md (decision + prototype transcripts), src-tauri/src/diff_memo.rs (P2 + P3 prototypes)
    • Tests: 10 new Rust, 147 total passing; frontend typecheck clean
    View release on GitHub →
  38. v0.0.8

    Skrive v0.0.8

    v0.0.8 — Version history

    Skrive gets a full version-history surface this release. Open any Markdown file, hit ⌘⇧H, and see every version behind it — whether from git commits or Skrive's own checkpoint store for plain folders.

    See what you've changed

    • History panel (⌘⇧H) — newest-first list of every version of the active file. Single-click a row to diff it against the current file; shift-click a second row to pair-compare two historical versions.
    • Two history sources, auto-selected per project:
      • Git projects — commits that touched the file, with subject, short sha, and relative time.
      • Plain folders — Skrive-managed checkpoints: auto-snapshots every five minutes of active editing (content-hash dedup'd), plus a manual "Pin version…" command for milestones.
    • Side-by-side diff view with two modes:
      • Raw — source vs source, gutter markers for added / removed / kept lines, placeholder rows keeping panes aligned.
      • Preview — rendered Markdown on both sides with sage-tinted added paragraphs and struck-through deletions. Reads as revised prose, not code review.

    Navigate a diff like a long document

    • n / j — next change; p / k — previous; Home / End — first / last. N of M counter in the chrome so you always know where you are.
    • Sync scroll in two modes:
      • Matched (default) keeps paired blocks aligned across panes even when they render at different heights.
      • Linear is a simple scroll-height ratio — useful when the diff is small or matching isn't helpful.
    • Esc exits diff mode and returns the tab to whatever you had open before.

    Configure per-project

    .skrive.toml parsing lands this release. First live consumers:

    • [checkpoints].auto_cap — cap on auto-snapshot count per file. Default 50 (~4 hours of active editing at the 5-minute cadence).
    • [checkpoints].manual_cap — cap on pinned versions. Default 0 = unbounded; set to a positive integer to keep a rolling window.

    Future sections ([lint], [dictionary], [export.*]) parse against the committed schema so you can populate them today; their consumers ship in later phases. Edit and reopen the project to apply changes — live reload via the watcher is tracked as a follow-up.

    Full schema reference: docs/skrive-toml-reference.md.

    Under the hood

    • Search highlights now land correctly on astral-plane input (emoji, some math symbols) — column and matchLength are reported in UTF-16 code units, matching the backlinks / outgoing-link convention already used elsewhere.
    • Structural-lint phase renumbered 3.2 → 3.4 in the roadmap to match execution order (3.1 → 3.3 → lint). Phase 3.2 is an open slot for a future deliverable.
    • 134 Rust unit tests passing; frontend svelte-check clean.

    Tracked for later

    • Structural diff — moves and reworded paragraphs rendered as first-class operations rather than as line noise. Phase 3.3b, gated on dogfooding v0.0.8 to confirm whether the line-level view reads well enough.
    • Live reload of .skrive.toml — watcher extension so saves apply immediately without reopening.

    Full changelog: v0.0.7...v0.0.8

    View release on GitHub →
  39. v0.0.7

    Skrive v0.0.7

    What's new

    Bracket-family shortcuts — three ergonomic keybinds that share one pair of keys.

    • ⌘[ toggles the sidebar (was ⌘B). Moving off ⌘B keeps the universal "bold" slot free for when editor formatting shortcuts land.
    • ⌘⇧[ / ⌘⇧] cycle through your open tabs. Same convention as Safari, Chrome, and Terminal — already muscle memory if you're on macOS.

    Drag-to-resize sidebar — grab the right edge of the file list and drag; double-click the handle snaps back to the default width. Width clamps between 180 and 500 pixels and is remembered per project, so each place you write keeps its own layout.

    Fix

    Sidebar width was being written to project state on save but never read back on restore — every session opened at 260px regardless of what you'd set it to. Now it sticks.

    Install

    Download the .dmg (macOS, universal) or .msi (Windows) below. Existing installs will see the update offer inside the app via the built-in updater.

    View release on GitHub →
  40. v0.0.6

    Skrive v0.0.6

    Skrive's first "project intelligence" release. The link graph the Rust core has been building since Phase 1 finally has a UI and the commands behind it.

    New

    • Rename-with-references. Rename any Markdown file in your project and every inbound link updates automatically. Invoke with F2 on the active tab (or fn+F2 on a Mac that hasn't flipped the function-key setting) or right-click → Rename… in the sidebar. A confirmation modal previews exactly what will change — N references across M files, each row showing path, line, and a snippet — before anything is written. Inline links [text](url), wiki links [[Name]], and reference-style [label]: target definitions are all rewritten; relative paths recompute correctly from each source file's directory.
    • Backlinks panel. Press ⌘⇧B on any open file to see every other file that links to it. Click a row to jump there. The header shows a live BL · N count. Panel re-queries on tab switch and on external file changes.
    • .skrive.toml schema documented. docs/skrive-toml-reference.md defines the full schema — [project], [lint], [lint.required_frontmatter], [dictionary], [export.*] — that Phase 3.2's lint engine and Phase 5's exporters will consume. A missing file is valid; parse errors show a toast and fall back to defaults without blocking project open. No parser yet — that's Phase 3.2.

    Fixed

    • Preview-pane link clicks no longer throw a 404. Rendered markdown links route internally through the tab store for .md targets and open externals in your default browser via the Tauri opener plugin.
    • Custom error page. If any navigation does slip past the in-app handlers, you land on a Skrive-styled page with a Return to editor button instead of SvelteKit's raw 404.
    • Sidebar hides common noise directories. node_modules, target, dist, build, __pycache__, and venv no longer clutter the file tree when you point Skrive at a code repo that happens to contain Markdown. .gitignore-aware walking is a follow-up.

    Under the hood

    • Link graph edges now carry byte ranges, line, column, and link kind — the foundation the rename rewriter uses to edit source bodies back-to-front without shifting offsets.
    • Graph updates incrementally on write, create, delete, directory delete, and external-edit reload.
    • New Tauri commands: get_backlinks, get_outgoing_links, get_dead_links (data-only; the lint UI lands in Phase 3.2), preview_rename, rename_with_references.
    • 77 Rust tests, 0 Svelte-check warnings.

    Known limitations

    • Rename doesn't refresh open tabs that have unsaved edits. If a rewritten file is dirty when you rename something that references it, we keep your buffer as-is and warn you by name — save or discard on your own terms.
    • Rename target paths with spaces emit bare (no angle brackets); fine for the common case, may need bracketing if this comes up.
    • Wiki link rename is filename-stem based and case-insensitive. A case-collision with another file's stem would resolve ambiguously — flag if dogfood hits this.
    • F2 on macOS requires fn+F2 unless you've turned on "Use F1, F2, etc. keys as standard function keys" in System Settings. The sidebar's right-click Rename… menu is the Mac-idiomatic fallback.

    What's next

    Phase 3.3 — structural diff — is the next bet. Phase 3.2's lint engine will surface the dead-link data this release already emits.

    View release on GitHub →
  41. v0.0.3

    Skrive v0.0.3

    Pre-alpha build. See install instructions for each platform.

    Small bug squash

    View release on GitHub →
  42. v0.0.2

    Skrive v0.0.2

    Pre-alpha build. See install instructions for each platform.

    View release on GitHub →