Published: 03/06/2026
If you just unboxed an M4 MacBook Pro and restored it from an Intel Time Machine backup, your terminal is probably a lie. You’re running a beast of a machine in an “Intel bubble,” and it’s killing your performance.
I spent the afternoon nuking the “Rosetta Ghost” and building a fully local, semantic AI content pipeline. No OpenAI credits. No SaaS subscriptions. Just raw M4 power and slick automation.
Here is exactly how to build it.
1. Purge the “Rosetta Ghost”
Before you install a single AI library, you must ensure your environment is native ARM64. If your uv or python is living in /Library/Frameworks/, it’s likely an Intel-tainted relic.
The Fix:
Use Homebrew (ensure it’s in /opt/homebrew) to grab a clean, native stack.
# Check if you're translated (0 = Native)
sysctl -n sysctl.proc_translated
# Install native ARM64 Python and uv
brew install python@3.12 uv
2. The Storage Layer: LanceDB
Forget Docker or heavy database background processes. For a local knowledge brain, you want LanceDB. It’s a serverless, file-based vector store that lives right in your project folder.
import lancedb
from pathlib import Path
DB_DIR = Path("./.lancedb").resolve()
db = lancedb.connect(DB_DIR)
table = db.create_table("my_memory", data=[{"vector": [...], "text": "...", "file": "..."}])
3. Local Embeddings: FastEmbed
Don’t rent your brain from OpenAI. Use FastEmbed from the Qdrant team. It’s lightweight, runs on your CPU, and is optimized for Apple Silicon.
uv add fastembed
The Implementation:
from fastembed import TextEmbedding
model = TextEmbedding()
# This turns text into coordinates locally
embeddings = list(model.embed(["My technical thought here"]))
4. The Real-Time Indexer (The Watcher)
I don’t want to manually index my notes. I want my AI to “hear” me as I write. We built a Python watcher using watchdog that monitors my Markdown folder and updates the LanceDB index the moment I hit save.
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
class ChangeHandler(FileSystemEventHandler):
def on_modified(self, event):
if event.src_path.endswith(".md"):
index_file(event.src_path) # Your indexing logic here
observer = Observer()
observer.schedule(ChangeHandler(), path="./blog-posts", recursive=True)
observer.start()
5. The Multi-Platform Dispatch
Writing the post is only half the battle. Distribution is the “grind.” Our pipeline automates:
- Jekyll Formatting: Automatically injects YAML frontmatter.
- Substack Readiness: Uses
pandocto convert Markdown to RTF for easy pasting. - Scheduled Release: Moves posts to a
_queue/folder in Git, where a GitHub Action releases them with a 3-day buffer.
The Verdict
In the “Software 3.0” era, we should be building systems that we own. My content pipeline is now faster, cheaper, and completely sovereign.
Time is short. Stop fighting web editors and start architecting your voice.
Ramblings from an ADHD brain that finally has a pipeline that moves as fast as I do.