Read Manifesto

Archive all your memoriesas markdown

Open source, local-first, and sandboxed. Run plugins to index your data, then search across everything from one CLI.

GitHub
Twitter / X
Pocket
Raindrop.io
Obsidian
Slack
RSS
iMessage
Chrome
Twitter / X
Pocket
Raindrop.io
Obsidian
Slack
RSS
iMessage
Chrome
? Where should your library live? (ENTER for ~/.dither/library)
✓ library: ~/.dither/library (created)
✓ wrote ~/.dither/config.json
→ starting dither daemon...
✓ daemon started (pid 4821)
✓ indexed 120 files
✓ embedded 980 chunks in 1m 12s

Search by qmd

Hybrid lexical + semantic search in one index, one file, built on qmd by Tobi Lütke.

Sandboxed with Deno

Permissions are explicit and transparent. Third-party plugin code is secured through Deno.

Scheduled & watched

Optional crons, folder watchers, and activity triggers keep your index current on its own.

Agent ready

Expose your index to any agent — a SKILL.md and clean CLI output are all they need.

Sandboxed plugins write markdown.

Plugins write plain markdown straight into your library. No database, no proprietary format — just files you can edit, grep, or move.

{"type":"log","msg":"fetching bookmarks since 2026-05-11"}
{"type":"log","msg":"2 new, 0 unchanged"}
~/.dither/library
├── raindrop/ # just written
│ ├── grug-brained-developer.md
│ └── deno-runtime-deep-dive.md
├── notes/ # you write these
└── vault → ~/Documents/Obsidian # indexed in place

Open source. Sandboxed. Your files stay markdown, on your disk. Nothing to lose access to.

Index your data.

Plugins pull from feeds, folders, and APIs into your collections. Each is a Deno script that runs only with the permissions you grant.

Twitter / X

Import Twitter exports & individual tweets.

pocket

Sync Pocket bookmarks to a collection.

raindrop

Pull Raindrop.io bookmarks via API.

URL Scraper

Scrape any URL into a markdown entry.

iMessage

Index local iMessage threads.

browser history

Pull Chrome / Safari / Firefox history.

slack

Index a Slack workspace via the API.

RSS

Pull any RSS / Atom feed.

Missing a source? Request a plugin

Your data has a center now.

Save the things you don't want to lose and find them again. One local index, designed to outlive any service or app you've used.

  • MIT licensed
  • Local-first
  • CLI
  • TypeScript
  • npm

plugins/bookmarks/plugin.ts
import { readInput, writeEntry } from "@dither/plugin";

const { env } = await readInput();
const res = await fetch(
  "https://api.raindrop.io/rest/v1/raindrops/0",
  { headers: { Authorization: `Bearer ${env.RAINDROP_TOKEN}` } },
);
const { items } = await res.json();

for (const b of items) {
  await writeEntry({
    collection: "bookmarks",
    body: `# ${b.title}\n\n${b.excerpt}\n\n${b.link}`,
    frontmatter: {
      id: String(b._id),
      url: b.link,
      title: b.title,
      tags: b.tags,
    },
  });
}

Plugins are simple TypeScript. Sandboxed.

The runtime denies anything not granted — Deno sandboxes each plugin process. Each plugin declares the URL access list, env, and file system scopes it needs; you approve once and the daemon enforces it on every run.


Hands-off ingest.

Run on a schedule, watch a folder, or trigger on activity. The plugin works the same way — you just don't have to think about it.

  • dither plugin run — manual one-shot ingest.
  • --every — cron or natural language like every 15min.
  • --watch — a collection or directory, runs on filesystem changes.
$ dither plugin run bookmarks --every "1h"
✓ scheduled bookmarks: every 1h
→ next run: 15:00
 
$ dither plugin run notes-inbox --watch notes
✓ watching notes-inbox: notes
→ changed: notes/meeting-notes.md
next: dither plugin list

Manifesto

Something happened to our digital memories.

They used to belong to us. Photos on hard drives. Emails in folders. Bookmarks in browsers. You knew where things were because you put them there.

Today, our memories are scattered across a thousand services. Your thoughts live in Notion's cloud. Your conversations in Slack's servers. Your inspirations on Twitter's timeline. Your discoveries buried in Reddit's endless scroll. Each platform holds a piece of your digital self hostage, locked behind their walls, searchable only by their rules, accessible only at their pleasure.

You've become a digital tenant, paying rent to access your own memories in houses you'll never own.

Dither is a tool that works for you, not the other way around. Connect your services once. Search everything instantly. Keep control always.

Frequently asked questions

Why not just use qmd?
You can — and it's great. qmd is an excellent, agentic RAG index, and dither is honestly just a wrapper around it. I was building similar RAG applications as alternatives, decided to cut my losses, and wrapped qmd instead. dither adds the file-management layer around it: collections, plugins, scheduling, watching, and a CLI that ties it all together. The plugin runtime is where most of the work went — every plugin is a Deno subprocess started with explicit --allow-read / --allow-write / --allow-net flags derived from grants you approve at install time, scoped to the paths and hosts that plugin actually needs. Nothing in the runtime is ambient: a plugin can't read another plugin's collection, can't escape its sandbox, and can't silently broaden its grants — any change forces a reinstall and re-approval. If you don't need any of that, use qmd directly.
Does dither send telemetry?
No. The CLI runs locally, the daemon runs locally, and plugins only reach networks they're explicitly granted.
Can plugins exfiltrate my data?
Each plugin runs in a Deno subprocess started with explicit --allow-read / --allow-write / --allow-env / --allow-net flags derived from the grants accepted at install time. Grants are stored per plugin in ~/.dither/grants/<plugin>.json. Anything not in those flags is denied by the runtime; a plugin that requests new permissions has to be reinstalled and re-approved.
Can I run scheduled plugins on a headless box?
Yes. `dither daemon start` spawns a detached process that runs the scheduler and watcher loops; `dither daemon stop` and `dither daemon status` manage it. For auto-start on boot, wrap it in systemd / launchd in the usual way.
Will I get rugpulled?
No backend, no account, no telemetry. The CLI is MIT-licensed and the index is just markdown files on your disk — you can read them with anything, including without dither. The core stays free and open source forever. If paid addons ever happen (e.g. a sync service to your phone), they'll be optional and base dither won't change.
Does it play nice with Obsidian (or my existing markdown folder)?
Yes. dither operates on plain markdown files on disk; it never moves or deletes them. Point a collection at your Obsidian vault (or any folder) and it indexes in place. Plugins can update entries if you wire them to existing files, but you can also set them up against a separate collection so nothing in your vault is ever touched.
Try it out now

Read the source code. Open issues, ship PRs.

github.com/janniks/dither