Files.md vs Obsidian for Local-First Markdown Notes: 2025 Comparison

Quick Summary: Files.md vs Obsidian at a Glance

Both Files.md and Obsidian share the same philosophical core: your notes live in plain .md files on your own disk, and no proprietary format locks you in. The similarities stop there. Files.md is a zero-install, browser-based PWA with an intentionally minimal codebase you can hold in your head. Obsidian is a polished Electron desktop app with 1,000+ community plugins and a mature graph view. Switching between them costs almost nothing—your files stay put—so the choice comes down to what you value more: radical simplicity or ecosystem depth.

Side-by-side feature comparison table

| Dimension | Files.md | Obsidian | |---|---|---| | Installation required | ✗ Browser PWA | ✓ Electron desktop app (~200 MB) | | File format | Plain .md | Plain .md | | Offline support | ✓ Full offline via PWA | ✓ Full offline | | Sync options | iCloud / Dropbox / self-hosted binary | Obsidian Sync ($10/mo) or Git plugin | | Plugin ecosystem | Minimal; LLM-extensible | 1,000+ community plugins | | Privacy model | Zero server communication (File System API) | Local by default; optional Obsidian Sync (E2EE) | | LLM-friendly codebase | ✓ Single index.html, no build step | ✗ Complex Electron + plugin API | | Mobile / on-the-go | Telegram bot | Official iOS & Android apps | | Price | Free & open source | Free personal; $10/mo Sync; $8/mo Publish |

Who should read this comparison

Developers who are evaluating local-first tools for a personal knowledge base, technical journal, or Zettelkasten. If you're already deep in Obsidian and happy, this comparison will either confirm your choice or show you a lighter path. If you're new to both, start here.

TL;DR verdict

Choose Files.md if you want zero installation, absolute privacy, and a hackable single-file codebase. Choose Obsidian if you need a rich plugin ecosystem, polished mobile apps, and an interactive graph view you can click around for an hour. Both bet on plain .md files, so you can try one, switch to the other, and lose nothing.


Privacy and Data Ownership Model

How Files.md keeps data strictly on-device

Files.md's privacy guarantee is architectural, not just a policy. The app is a static web page that uses the browser's File System Access API to read and write .md files directly on your local disk. No HTTP request to a remote server is ever made for your note content. There is no account, no telemetry endpoint, and no background sync daemon. The guarantee is enforced by the runtime itself: the browser's sandbox only allows window.showDirectoryPicker() to open a directory, and all subsequent reads and writes go through FileSystemDirectoryHandle—none of it touches a network socket.

Here is exactly how Files.md opens a local directory and reads markdown files:

// Invoked when the user clicks "Open Folder"
async function openLocalVault() {
  // Prompts the OS folder picker — no server involved
  const dirHandle = await window.showDirectoryPicker({
    mode: 'readwrite'
  });

  // Persist the handle across sessions (IndexedDB)
  await saveHandleToIndexedDB(dirHandle);

  const notes = [];
  for await (const [name, handle] of dirHandle.entries()) {
    if (handle.kind === 'file' && name.endsWith('.md')) {
      const file = await handle.getFile();
      const text = await file.text();
      notes.push({ name, text });
    }
  }
  return notes;
  // Zero network requests. Zero.
}

This approach means Files.md works identically when your machine is fully offline. There is no "sync paused" state—the files are always the source of truth.

Obsidian's privacy stance and optional cloud sync

Obsidian is also local-first by default. The application binary reads your vault from disk without sending anything to Obsidian's servers. Where things diverge is the optional Obsidian Sync add-on ($10/month): it transmits your notes to Obsidian's servers using end-to-end encryption, meaning Obsidian the company cannot read your content. That's a credible claim, but it still means encrypted blobs travel over the internet and live on third-party infrastructure.

For most developers, Obsidian's default local mode is perfectly private. The concern is third-party plugins—some community plugins phone home or load remote resources, and you need to audit each one.

What 'local-first' really means for developers

"Local-first" means the local copy is the authoritative copy, not a cache. Both tools satisfy this definition. Files.md enforces it at the API level; Obsidian does so by design but leaves an escape hatch for sync. If you work in an air-gapped environment, on a machine where installing software is restricted, or simply distrust anything touching a cloud endpoint, Files.md's architecture is the stricter guarantee.


Installation, Setup, and Portability

Files.md: zero-install PWA running from a browser

Navigate to app.files.md, click the install icon in the browser address bar, and you have a desktop shortcut that opens the PWA in its own window. No .dmg, no apt install, no admin rights required. The entire codebase lives in web/index.html—no build step, no node_modules, no Webpack config. On a machine where you can't install software (corporate laptop, shared workstation), this is the difference between having a tool and not having one.

One caveat: full File System Access API support requires a Chromium-based browser—Chrome, Edge, or Brave. Firefox does not yet support showDirectoryPicker() with readwrite mode. Check caniuse.com/native-filesystem-api for the current compatibility matrix.

Obsidian: Electron desktop app requiring installation

Obsidian ships as an Electron bundle. On macOS the .dmg weighs roughly 200 MB; on Windows the installer is comparable. Installation is straightforward and Obsidian updates silently in the background. The Electron foundation gives Obsidian native OS integration—system notifications, menu bar access, deep mobile app parity—but it also means you're running a bundled Chromium instance and a Node.js runtime for every session.

Opening a local folder in Files.md via the File System Access API

See the code in the Privacy section above for the full folder-opening flow. The key point is that FileSystemDirectoryHandle can be serialized to IndexedDB and restored on the next session without re-prompting the user, so the experience on second launch is instant—click the PWA icon, your vault is already open.

Portable self-hosting: running Files.md from a single binary

Files.md ships an optional Go server binary for teams or developers who want to access their notes over a local network. No Docker, no Node, no configuration file required:

# Download the latest release binary for your platform
curl -L https://github.com/zakirullin/files.md/releases/latest/download/filesmd-linux-amd64 \
  -o filesmd && chmod +x filesmd

# Serve your notes directory on port 8080
./filesmd --dir /home/user/notes --port 8080

# The web UI is now available at http://localhost:8080
# All reads/writes go directly to /home/user/notes/*.md

The binary is self-contained—it serves the static web/ assets and provides a thin file-read/write API over HTTP, scoped to the directory you specify. There is no database, no authentication layer beyond your network boundary, and no persistent state outside the .md files themselves.


Note-Taking Workflow and Capture Speed

Files.md chat-like flow for instant thought capture

The fastest path from thought to file in Files.md is the chat interface: open the app, type your thought, hit Enter, then pick a destination file (or skip and save to an inbox file to triage later). This mirrors the UX pattern of a messaging app, which has a low enough cognitive overhead that you'll actually use it mid-flow. There's no modal dialog asking you to name a new note, no YAML frontmatter to fill in, no template to invoke.

Obsidian Quick Capture with the QuickAdd plugin

Obsidian's equivalent is the QuickAdd community plugin, which binds a hotkey to a capture prompt. It's highly configurable—you can define templates, target specific files, and run Obsidian commands after capture. The tradeoff is setup time. You need to install QuickAdd, configure a macro, and assign a hotkey. Once configured, it's fast; getting there takes 20 minutes and a trip to the documentation.

Telegram bot integration in Files.md for mobile capture

Files.md ships a Telegram bot (@FilesMDBot) that accepts a message and appends it as a timestamped .md file in your notes folder. This is the mobile capture story for Files.md—no iOS/Android app to install, just a Telegram chat. Here is the webhook payload format the server handler processes:

{
  "update_id": 123456789,
  "message": {
    "message_id": 42,
    "from": { "id": 987654321, "username": "yourhandle" },
    "date": 1718000000,
    "text": "Idea: use exponential backoff in the retry loop of the data pipeline"
  }
}

The Files.md server receives this webhook, extracts message.text and message.date, and writes a file like notes/2024-06-10-idea-exponential-backoff.md with the content prepended by a timestamp header. The result is a plain .md file in your local vault, indistinguishable from a note you typed in the app itself.

Zettelkasten and Second Brain patterns in both tools

Both tools support atomic notes with wikilinks, which is the mechanical core of Zettelkasten. Files.md's opinionated folder structure (brain/, dev/, journal/) maps cleanly to a Second Brain PARA setup. Obsidian's Dataview plugin adds query-driven views across your notes—genuinely useful for surfacing connections you'd otherwise miss. For pure capture-and-link workflows, Files.md is faster. For querying and aggregating notes at scale, Obsidian + Dataview is more powerful.


Linking, Knowledge Graph, and Connected Notes

Wikilink syntax [[...]] in both tools

Both Files.md and Obsidian use the [[note-name]] wikilink syntax. Type [[ and an autocomplete dropdown appears. In Files.md, the trigger is typing [ in the editor—it opens a lightweight in-editor link completion menu. In Obsidian, [[ triggers a fuzzy-search picker across your entire vault.

Here is a sample note file that uses wikilinks to connect ideas across brain/ and dev/ folders in a Zettelkasten structure:

---
title: Exponential Backoff
folder: dev
tags: [resilience, distributed-systems]
---

# Exponential Backoff

When a request fails, wait before retrying. Double the wait each time.
Cap the maximum wait to avoid infinite delays.

## Why it works
See [[brain/how-humans-handle-failure]] — we naturally slow down
after repeated mistakes to avoid wasted energy.

## Implementation pattern
- Base delay: 100ms
- Max delay: 30s
- Jitter: add random ±20% to prevent thundering herd

Related: [[dev/circuit-breaker-pattern]], [[dev/retry-budgets]]
Inspiration: [[brain/compounding-small-improvements]]

This file lives at dev/exponential-backoff.md. The links to brain/ notes cross the folder boundary, which is exactly the compounding effect both tools are designed to support.

Obsidian's interactive graph view

Obsidian renders your wikilinks as an interactive force-directed graph. You can zoom, filter by tag, highlight clusters, and click nodes to open notes. It's genuinely impressive for a vault of 500+ notes—visual clusters emerge that reveal how your thinking is organized. The downside: the graph becomes slow and visually noisy past ~1,000 nodes, and on lower-end hardware it can stutter.

Files.md's lightweight in-editor link completion

Files.md takes the opposite stance. Typing [ shows a simple dropdown of your existing files. There is no visual graph. This is a deliberate constraint—the project's philosophy is that restrictions foster creativity, and that a link you follow in your head while writing is more valuable than a rendered graph you click around passively.

LLM-assisted knowledge growth in Files.md

Because the entire Files.md codebase is a single readable HTML file, you can paste it into Claude or GPT-4 and ask it to add graph rendering, backlink panels, or any other feature. The "graph view" Obsidian took years to build can be prototyped in an afternoon with an LLM that can see your whole codebase at once. This is the extensibility story Files.md is betting on.


Sync Options: iCloud, Dropbox, Self-Hosted Server

Sync method comparison

| Method | Cost | Setup complexity | Server required | E2E encrypted | |---|---|---|---|---| | Files.md + iCloud / Dropbox / Google Drive | Free (within existing plan) | Low — point app at synced folder | ✗ | Depends on provider | | Files.md self-hosted binary | Free | Medium — run Go binary on a server | ✓ self-owned | ✓ over HTTPS | | Obsidian Sync | $10/month | Low — toggle in settings | ✓ Obsidian's servers | ✓ E2EE | | Obsidian Git plugin | Free | Medium — configure Git remote | ✓ Git host | ✓ with private repo |

Files.md sync via iCloud, Dropbox, or Google Drive folder

The simplest Files.md sync strategy: put your notes folder inside a Dropbox, iCloud Drive, or Google Drive directory. Open that folder with window.showDirectoryPicker(). The cloud client syncs files in the background at the OS level, invisible to Files.md. No Files.md configuration needed. The limitation is conflict resolution—if you edit the same file on two devices simultaneously, you get a duplicate file with a conflict suffix, same as any Dropbox conflict.

Files.md optional self-hosted binary server

# Run the Files.md server on a home server or VPS
# Expose only over Tailscale or behind an nginx reverse proxy
./filesmd --dir /mnt/data/notes --port 3000

# With a systemd unit for persistence
# /etc/systemd/system/filesmd.service
[Unit]
Description=Files.md note server
After=network.target

[Service]
ExecStart=/usr/local/bin/filesmd --dir /mnt/data/notes --port 3000
Restart=on-failure

[Install]
WantedBy=multi-user.target

Pair this with Tailscale and you have a private, zero-trust note server accessible from any device without opening a port to the public internet.

Obsidian Sync vs Obsidian Git plugin

Obsidian Sync is the lowest-friction paid option: enable it, authenticate, and your vault syncs across devices with version history. At $10/month it's priced for individuals, not teams. The Git plugin is free and gives you full version history, conflict resolution via standard Git tooling, and the ability to host on any Git provider. The tradeoff is that you're managing a Git workflow, including dealing with merge conflicts in your markdown notes.


Plugin Ecosystem and Extensibility

Obsidian's 1000+ community plugins

Obsidian's plugin marketplace is its strongest differentiator. Dataview turns your vault into a queryable database using an SQL-like syntax. Templater inserts dynamic templates with JavaScript expressions. Kanban renders .md files as drag-and-drop boards. Excalidraw embeds a whiteboard. These are mature, well-maintained plugins with thousands of users. If a workflow exists in the knowledge management space, there's probably an Obsidian plugin for it.

The cost: plugins interact with a complex internal API that changes across Obsidian versions. Breaking changes are common during major releases. You're dependent on volunteer maintainers keeping their plugins current.

Files.md's LLM-driven extensibility philosophy

Files.md takes a different bet: instead of a plugin API, the codebase is so small that you can add features directly by editing index.html with LLM assistance. The claim "one person or an LLM can hold the whole codebase in their head" isn't marketing—the core logic genuinely fits in a single file with no build toolchain.

Here is a concrete example: adding a live word count display to the editor with a snippet you could ask an LLM to generate and then paste directly into index.html:

// Add this inside the <script> block in Files.md's index.html
// Hook into the existing editor's input event

function initWordCount() {
  const editor = document.querySelector('.editor-textarea');
  const counter = document.createElement('div');
  counter.id = 'word-count';
  counter.style.cssText = 
    'position:fixed;bottom:12px;right:16px;font-size:11px;opacity:0.5;pointer-events:none';
  document.body.appendChild(counter);

  function update() {
    const words = editor.value
      .trim()
      .split(/\s+/)
      .filter(w => w.length > 0).length;
    counter.textContent = `${words} words`;
  }

  editor.addEventListener('input', update);
  update();
}

// Call after the editor is mounted
document.addEventListener('DOMContentLoaded', initWordCount);

No npm, no build step, no plugin API docs to read. Paste it in, force-refresh (Cmd+Shift+R), done. The equivalent Obsidian plugin requires scaffolding a TypeScript project, understanding the Plugin class API, building with esbuild, and placing the output in .obsidian/plugins/.

When a minimal codebase beats a plugin marketplace

When your customization needs are specific and narrow—word count, a custom shortcut, a different syntax highlight color—editing a single HTML file with LLM help is faster and more maintainable than learning a plugin API. When your needs are broad and standard—Kanban boards, SQL-like queries, flashcard review—a plugin marketplace wins.


When to Choose Files.md

  • You need zero installation. You're on a corporate machine, a borrowed laptop, or an environment where installing Electron apps requires IT approval. Files.md runs in any Chromium browser with no footprint.
  • You want provable privacy. The File System Access API makes network exfiltration of your notes structurally impossible. No policy document required—the architecture enforces it.
  • You want to hack your tool with an LLM. Your entire note app fits in a single file. You can describe a feature to Claude, get a JavaScript snippet back, paste it in, and ship it in under 10 minutes. No plugin API, no build pipeline.
  • You need Telegram-based mobile capture. You're already in Telegram all day. Sending a note to @FilesMDBot and having it appear as a .md file in your vault is faster than switching to a native app.
  • You distrust Electron. Files.md has no bundled Node.js runtime, no native modules, and no auto-updater running in the background. It's a web page.
  • You want a minimal, distraction-free interface. The chat-like capture flow reduces friction to the point where you'll actually use it during a debugging session rather than switching apps and losing focus.

When to Choose Obsidian

  • You rely on Dataview or Templater. If your workflow involves querying metadata across hundreds of notes, or running JavaScript in templates, these plugins are irreplaceable and have no equivalent in Files.md.
  • You need a polished graph view. The interactive, filterable graph is genuinely useful for discovering hidden connections in a large vault. If visual knowledge exploration is part of your review process, Obsidian delivers and Files.md doesn't.
  • You want official mobile apps. Obsidian's iOS and Android apps are mature, support all core features, and sync via Obsidian Sync or Git. If you take notes on your phone daily and want a full editing experience, the mobile apps are the right answer.
  • You rely on community extensions. Kanban, Excalidraw, Spaced Repetition, Footnote Shortcut, Git—the community has built tooling for nearly every knowledge management use case. Betting on that ecosystem is rational.
  • You want Obsidian Publish. Publishing a subset of your vault as a public website with backlinks and graph view is a one-click operation with Obsidian Publish ($8/month). No equivalent exists in Files.md.
  • You want a larger support community. Obsidian has an active forum, Discord, subreddit, and YouTube tutorial ecosystem. Files.md is a smaller open-source project—support is GitHub issues and reading the source.

Verdict: Files.md or Obsidian for Your Dev Workflow in 2025

Both tools prove the same thesis: plain .md files outlast any app. Your switching cost is effectively zero because the files are always yours, always readable, always portable. That's the most important thing to take away from this comparison.

Summary recommendation matrix by developer persona

| Developer persona | Recommended tool | Primary reason | |---|---|---| | Privacy-first developer | Files.md | Zero server communication; File System API enforces it architecturally | | Minimal-tool advocate | Files.md | Single-file codebase, no Electron, no build step | | Plugin power user | Obsidian | Dataview, Templater, Kanban, 1,000+ plugins | | Team knowledge base | Obsidian + Git | Mature conflict resolution, shared plugin configs, Obsidian Publish | | Mobile-heavy workflow | Obsidian | Polished native iOS/Android apps with full sync |

The plain-files principle: a bet both tools agree on

The most durable decision you can make in 2025 is to keep your notes in plain .md files regardless of which app you choose. Both Files.md and Obsidian honor that contract. If Files.md disappears tomorrow, open your folder in Obsidian. If Obsidian changes its pricing, open your vault in Files.md. The files work in VS Code, Vim, Typora, or cat in a terminal. The tool is secondary; the files are primary.

For the most common developer use case—a personal technical journal and knowledge base on a single machine—Files.md is the better default in 2025 precisely because it has less surface area to fail, update, break, or demand your attention. Obsidian is the better tool the moment you need its ecosystem.