I've sat comfily on cloud platforms for years, but with how much online data is soaked up for LLM training, I've wondered how far I can get managing my data myself. Local-first computing certainly has an appeal: everything is a file, you own your data, there's no headaches from vendor lock-in, subscriptions, changes in ToS, etc. I figured my digital brain is a good place to experiment, so after many years of using Notion, I migrated to a local Obsidian setup. This isn't a product review, both tools are excellent, it's more of a travel log. Spoiler alert, I ultimately switched back to Notion, but not for the reasons I expected, so I'm here to tell you about those surprises.

The Future is Bright

First off, why bother making a switch?

  • AI context: Local files can be fed directly to language models. No export step, no API calls to retrieve my own data. My notes become easily discovered by agentic LLMs, such as Claude Code.

  • Unix philosophy: I have nostalgia for "everything is a file," primarily for its composability. Files work with grep, with git, with shell scripts, with every tool built over the past fifty years.

  • Ownership: These are my most personal notes, ideas, reflections, half-formed plans, private thoughts. My instinct to keep them under my own roof. Is that ownership worth the trouble?

  • Colocation:. What if my project notes live in the same directory as my code and datasets? If a meeting involves writing a quick script to analyze some data, can we bundle that with our notes, instead of siloing elsewhere?

With these goals in mind, I migrated. Exported from Notion, imported into Obsidian, set up iCloud sync for cross-device access. The initial experience was positive. Obsidian's community and plugin ecosystem are impressive. I appreciated their development model enough to purchase a license. My local-first experiment seemed like a success: I had control, I had files, and my AI workflows were simpler; however, some friction began to show its face.

iClouds Getting Stormy

iCloud sync works beautifully until you touch files from the terminal. I discovered this the hard way, and the underlying problem runs deeper than I initially understood.

iCloud Drive on macOS is managed by a background process called bird. This daemon monitors your files and handles the sync between local storage and Apple's servers. When you enable "Optimize Mac Storage," files you haven't accessed recently get evicted from your local drive, leaving behind stub files. These stubs have a period prefix and an .icloud extension—so notes.md becomes .notes.md.icloud. When you access the file, bird downloads it and restores the original name.

This works fine in the Finder. But the command line sees the filesystem as it actually is: a mix of real files and .icloud stubs with different names than their logical counterparts. Scripts break. Commands fail. As Michael Tsai documented, this makes "commands and scripts inordinately complex, and in some cases impossible." The implementation treats files inconsistently at the POSIX level—it's an iOS-oriented solution that wasn't designed with Unix filesystem abstractions in mind.

The problem compounds when you delete or move files via terminal while bird is syncing. iCloud's sync database tracks file operations through Finder services. When changes happen through rm or mv, the database can lose track of what's where. Syncing hangs indefinitely—bird sits at high CPU doing nothing useful. You can kill the process (killall bird), and sometimes it respawns and recovers. But sometimes the corruption is deeper. The database itself needs rebuilding.

The Eclectic Light Company notes that "almost all problems are delays in or failure of synchronisation," and that "there are almost no tools to help diagnose or fix problems." The brctl command exists but most of its functions are undocumented. You're flying blind.

This might sound like an edge case. It isn't—at least not for my use case. My entire reason for wanting local files was to embed notes alongside scripts and data. Scripts operate through the shell, not the Finder. Build processes, git hooks, cleanup scripts—they all use rm, mv, and other standard Unix commands. The fundamental use case I'd optimized for—notes living with code—directly conflicted with how iCloud expects files to be managed.

After hitting this problem repeatedly, I eventually corrupted my sync database badly enough that the only fix was disconnecting and reconnecting my entire iCloud account. If you have significant data in iCloud Drive, you understand what a pain this is. My drive is hundreds of gigabytes. Re-syncing took the better part of a day, and I had to babysit it to make sure nothing else went wrong.

Meanwhile, if you want to access your Obsidian vault from iOS or iPadOS, there's no real alternative to iCloud. Obsidian Sync exists, but it's a separate paid service on top of the license. Dropbox and other sync solutions don't integrate with Obsidian's mobile apps in the same seamless way. For Apple device users, iCloud is the path of least resistance—which makes its command-line incompatibility particularly frustrating.

Embedding Files, Neither Here Nor There

One friction point deserves more detail: embedded files.

In Notion, when you embed an image or PDF in a note, it just exists there. It's part of the note. You don't think about where the file lives. There is no "where." The attachment is intrinsic to the page, stored in Notion's infrastructure, and rendered inline. The mental model is simple: a note contains content, and that content can include files.

In Obsidian, an embedded file is a markdown link to a file that lives somewhere else. The syntax is clean—![[diagram.png]] or ![alt text](path/to/image.png)—but the file needs a physical location in your file system. This is a necessary consequence of "everything is a file." If notes are files, and attachments are files, then attachments can't live inside notes. They live alongside notes, connected by references.

Obsidian offers several options for where attachments go. In Settings > Files & Links, you can choose: the vault root folder, a specific folder you designate, the same folder as the current note, or a subfolder relative to the current note. Each approach has trade-offs, and the Obsidian community has debated these at length.

I considered two reasonable configurations.

Option one: create a directory for each note. Inside the directory, a note.md file plus any attachments. When you embed an image in the note, the image lives right there with it. This preserves colocation—the note and its files are a self-contained unit. You can export a note to another location and know all its dependencies come with it.

But the cost is structural complexity. Every note now requires a folder. Your notes list becomes a list of folders, each containing a generically-named note.md. Navigation gets awkward. The hierarchy you're imposing doesn't reflect semantic organization—it's purely mechanical scaffolding to keep attachments colocated.

Option two: keep notes in a flat structure with descriptive filenames—2025-12-01-My-Idea.md, 2025-12-02-Meeting.md—and put all attachments in a shared files/ or attachments/ subdirectory. This keeps notes browsable. The navigation sidebar shows actual note titles, not folder names.

But the attachments directory becomes a soup of disconnected files. image.png, diagram-v2.png, meeting-notes-scan.pdf—hundreds of files with no obvious connection to their referencing notes. Which notes use image.png? Is old-screenshot.png still referenced by anything, or is it orphaned? There's no easy way to answer these questions without grepping through all your notes.

The problem gets worse when you move or reorganize notes. In Obsidian, if you move a note to a different folder, its attachments don't automatically follow. The links break unless you manually move the files and update the references. Community plugins like Consistent Attachments and Links exist to help—they can move attachments alongside notes and update links. But you need to know these plugins exist, install them, configure them, and trust them not to corrupt your vault. It's another piece of infrastructure you're responsible for.

Interestingly, even Steph Ango, Obsidian's CEO, uses a single central attachments folder for his personal vault. His reasoning: "I use very few folders. I avoid folders because many of my entries belong to more than one area of thought. My system is oriented towards speed and laziness." That's honest, and it works for him. But it also implicitly acknowledges that Obsidian's file-based model creates organizational complexity that users must actively manage.

The deeper issue is that "note with embedded content" is a different abstraction than "markdown file plus linked assets in a directory structure." The former is what I think about when taking notes. The latter is what the file system requires. Notion's cloud-based model means it can provide the first abstraction natively. Obsidian's file-based model means I have to build and maintain the machinery to approximate it.

Neither is wrong. But one requires ongoing cognitive overhead, and one doesn't.

A Vault Too Large

My idea of mixing data with notes created another problem: vault size. Once I got above 40GB, Obsidian started to choke on indexing. It has to scan the entire vault to build its link graph and search index. Launch times became unpredictable.

Once indexed, everything worked fine. But sometimes I need to capture an idea quickly—on the subway, between meetings, walking between buildings. Those moments don't wait for loading spinners. A notes app that isn't instant defeats part of its purpose.

A side annoyance: the vault must live in a specific Obsidian folder for mobile access. Not in the project directory where I want it. Not anywhere I choose. In the folder Obsidian designates.

Hitting the Wall

The collaboration gap was clearer-cut. Obsidian has no viable model for working with other people. No shared pages, no edit tracking, no access controls. Notion makes all of this trivial. If you need to collaborate—and I do, regularly—Obsidian is simply a non-starter.

Then there was the plugin treadmill. I found myself chasing Notion's UX feature by feature. Collapsible lists. Breathing room around bullet points. Emojis on pages and in navigation. Web link previews. "Mention" rendering that shows page titles inline. Each required finding a plugin, configuring it, sometimes troubleshooting compatibility issues.

I probably could have built the remaining gaps myself. Obsidian's plugin architecture is impressive, and I have the ability but not the capacity to do so.

Back Home Again

After several months, I decided to migrate back. The friction points had accumulated into a clear answer: this wasn't the right fit for my use case.

Migrating back proved its own challenge. Existing tools for Notion import didn't handle my needs: the folder hierarchy, the embedded files, the wiki-style links. So I built my own migration tool.

The script is straightforward Python using the Notion API. It walks a directory tree, creates nested pages to preserve structure, parses markdown with wiki-style links and embeds, and uploads files directly to Notion. Referenced files go inline in their notes. Orphaned files—ones in the directory but not linked from any note—get uploaded to their parent folder's page, so nothing is lost. It handles errors gracefully with retries and generates reports for verification.

I open-sourced it at notion-markdown-importer. The README covers features, usage, and limitations. If you're migrating from Obsidian or any markdown-based system, it might save you time.

Back in Notion, the friction points disappeared. Sync works reliably across all devices. There's no indexing latency regardless of content size—the database is in the cloud, already indexed. Collaboration is first-class. The UX I want works without configuration. Attachments live naturally inside pages. There is also now a nice MCP solution for connecting notes to LLMs.

Notion isn't perfect. The offline experience is weaker. You're dependent on their service continuing to exist and remain affordable. The local-file advantages I originally sought—AI context, Unix composability—are real trade-offs I'm now accepting. The load times are sometimes slow enough to disrupt my flow.

But trade-offs are exactly what this is about. Local-first computing is appealing for good reasons. "Own your data" and "everything is a file" are genuine virtues. The question is whether the implementation details hold up for your specific use case.

I've come to think of "local" as hiding complexity rather than eliminating it. Local files still need to sync somehow. That syncing depends on infrastructure—iCloud, Dropbox, Syncthing—each with its own quirks and failure modes. Local files still need to be indexed if you want fast search. That indexing takes time and computing resources. Local files give you flexibility, but exercising that flexibility means building and maintaining the features you need.

Cloud services make a different trade: control for convenience. Someone else handles sync, indexing, collaboration, and interface polish. You pay in dollars and in trust. Whether that trade is worth making depends on what you value and what problems you're solving.

For most users, Obsidian is excellent. The friction points I encountered are edge cases: unusually large vaults, terminal-based workflows that conflict with iCloud, collaboration as a core requirement, low tolerance for plugin configuration. If these don't describe you, Obsidian's local-first model might be exactly right.

For my specific situation, the edge cases accumulated into a clear answer. I like Obsidian's philosophy. I respect their development model. If the friction hadn't piled up, I'd still be there.

The file system is a beautiful abstraction. But so is a well-designed database with a good API. And sometimes, the thing that "just works" is the thing worth using.