Skip to content

EpicenterHQ/epicenter

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

13,112 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Epicenter

Epicenter

Local-first, open-source apps

One folder of plain text and SQLite on your machine, synced across all your devices.
Grep it, query it, host it wherever you want.

GitHub stars License Discord macOS Windows Linux

AppsArchitecturePackagesFor DevelopersQuick StartContributingDiscord


What is Epicenter?

Epicenter is an ecosystem of open-source, local-first apps. All your data—notes, transcripts, chat histories—lives in a single folder of plain text and SQLite on your machine. Every tool we build reads and writes to the same place. It's open, tweakable, and yours. Grep it, open it in Obsidian, version it with Git, host it wherever you want.

Under the hood, Yjs CRDTs are the single source of truth. They materialize down to SQLite (for fast queries) and markdown (for human-readable files). Sync happens over the Yjs protocol; the server is a relay, not an authority—it never sees your content.

The library that powers this, @epicenter/workspace, is something other developers can build on too. Define a typed schema, get CRDT-backed tables with multi-device sync handled for you.

Architecture

                              ┌──────────────────────────────────┐
                              │         @epicenter/api           │
                              │   Cloudflare Workers + DO hub    │
                              │   auth · sync relay · AI chat    │
                              └──────────┬───────────────────────┘
                                         │ y-websocket protocol
                    ┌────────────────────┼──────────────────────┐
                    │                    │                      │
               ┌────▼──────┐      ┌─────▼───────┐      ┌──────▼──────┐
               │ Whispering│      │  Opensidian  │      │ Tab Manager │
               │  (Tauri)  │      │ (SvelteKit)  │      │  (WXT ext)  │
               └────┬──────┘      └─────┬────────┘      └──────┬──────┘
                    │                    │                      │
          ┌─────────┴────────────────────┴──────────────────────┘
          │              All apps share these layers:
          │
    ┌─────▼───────────────────────────────────────────────────────────┐
    │                     MIDDLEWARE / ADAPTERS                        │
    │  @epicenter/svelte    — Svelte integration, auth, persistence   │
    │  @epicenter/filesystem — POSIX file layer over Yjs              │
    │  @epicenter/skills    — skill/reference tables                  │
    │  @epicenter/ai        — LLM tool bridging                      │
    └─────────────────────────────┬───────────────────────────────────┘
                                  │
    ┌──────────────────────────────▼───────────────────────────────────┐
    │                           CORE                                   │
    │  @epicenter/workspace — typed schemas, Yjs CRDTs, extensions,   │
    │                         E2E encryption, lifecycle, materializers │
    │  @epicenter/sync      — protocol encoding/decoding, V2 updates  │
    │  @epicenter/constants — app URLs, versions, shared config       │
    │  @epicenter/ui        — shadcn-svelte component library         │
    │  @epicenter/cli       — TypeBox→yargs CLI, auth/session APIs    │
    └─────────────────────────────────────────────────────────────────┘

The dependency flow is strict: core has zero upward dependencies, middleware only reaches into core, and apps compose both. @epicenter/workspace is the gravitational center—every middleware package and most apps depend on it. The sync server is a relay, not an authority; it never sees your content because encryption happens client-side before anything leaves the device.

Full architecture walkthrough → · Encryption design →

Apps

Press shortcut, speak, get text. Desktop transcription that cuts out the middleman. Bring your own API key or run locally with Whisper C++.

Source · Install

Local-first note-taking with a built-in bash terminal, end-to-end encryption, and real-time sync. Your notes live in a CRDT-backed virtual filesystem.

Source · Try it

Browser extension side panel for managing tabs with workspace sync and AI chat that can call workspace tools with inline approval.

Source

Apple Notes-style local-first notes app. Folders, rich-text editing with ProseMirror, and collaborative sync via Yjs.

Source

The hub server. Auth, real-time sync via Durable Objects, and AI inference. Everything that needs a single authority across devices.

Source

Build your own

The @epicenter/workspace library makes it straightforward to build apps that share the same CRDT-backed data. Define a schema, get tables, add sync.

Also in the repo: Fuji (personal CMS), Zhongwen (Mandarin learning chat), Skills Editor (agent skill manager), Dashboard (billing UI), and Landing (public site).

Packages

Package Description License
@epicenter/workspace Core library. Typed schemas, Yjs CRDTs, extension builder, E2E encryption, materializers. Everything builds on this. MIT
@epicenter/sync Yjs sync protocol encoding/decoding. Dumb server, smart client—protocol framing is separate from transport. AGPL-3.0
@epicenter/ui shadcn-svelte component library shared across all apps. MIT
@epicenter/svelte Svelte 5 integration—persisted state, auth, workspace gate, TanStack Query helpers. MIT
@epicenter/filesystem POSIX-style virtual filesystem over Yjs workspace tables. mkdir, mv, rm, stat. MIT
@epicenter/skills Skill and reference tables for AI-enhanced workspace apps. MIT
@epicenter/ai Bridges workspace actions with LLM tool calling. MIT
@epicenter/cli The epicenter command. TypeBox schemas become CLI flags automatically. MIT
@epicenter/constants Shared URLs, ports, and version info across the monorepo. MIT

For Developers

The hard problem with local-first apps is synchronization. If each device has its own SQLite file, how do you keep them in sync? If each device has its own markdown folder, same question. We ended up using Yjs CRDTs as the single source of truth, then materializing that data down to SQLite (for fast SQL reads) and markdown (for human-readable files). Yjs handles the sync; SQLite and markdown handle the reads.

The @epicenter/workspace package wraps this into a single API. Define a schema, get CRDT-backed tables, attach providers to materialize to SQLite or markdown, and add sync when you're ready.

import { type } from 'arktype';
import { createWorkspace, defineTable, defineWorkspace } from '@epicenter/workspace';
import { indexeddbPersistence } from '@epicenter/workspace/extensions/persistence/indexeddb';
  import { createSyncExtension } from '@epicenter/workspace/extensions/sync/websocket';

    const posts = defineTable(
  type({ id: 'string', title: 'string', published: 'boolean', _v: '1' }),
      );

      const definition = defineWorkspace({
  id: 'epicenter.blog',
  tables: { posts },
  });

const workspace = createWorkspace(definition)
  .withExtension('persistence', indexeddbPersistence)
  .withExtension('sync', createSyncExtension({
    url: (docId) => `ws://localhost:3913/rooms/${docId}`,
  }));

await workspace.whenReady;
workspace.tables.posts.set({ id: '1', title: 'Hello', published: false, _v: 1 });

Each user gets their own database. Schema definitions are plain JSON, so they work with MCP and OpenAPI out of the box. Write to Yjs and SQLite updates; edit a markdown file and the CRDT merges it in.

Read the full workspace docs →

Where We're Headed

More apps are in progress—each one shares the same workspace, so data flows between them without import/export. The @epicenter/workspace library handles the hard parts (schemas, CRDT sync, materialization), so each new app is mostly UI.

Epicenter Cloud will provide hosted sync for people who don't want to run their own server. Same model as Supabase selling hosted Postgres or Liveblocks selling hosted collaboration. Self-hosting is and will remain first-class—the sync server is open source under AGPL, and when you run it yourself, you control the encryption keys and trust boundary.

Quick Start

Install Whispering

brew install --cask whispering

Or download directly from GitHub Releases for macOS (.dmg), Windows (.msi), or Linux (.AppImage, .deb, .rpm).

Full installation guide →

Build from Source

# Prerequisites: Bun (https://bun.sh) and Rust (https://rustup.rs)
git clone https://github.com/EpicenterHQ/epicenter.git
cd epicenter
bun install
cd apps/whispering
bun dev

Troubleshooting

If things break after switching branches or pulling changes:

bun clean    # Clears caches and node_modules
bun install  # Reinstall dependencies

For a full reset including Rust build artifacts (~10GB, takes longer to rebuild):

bun nuke     # Clears everything including Rust target
bun install

You rarely need bun nuke—Cargo handles incremental builds well. Use bun clean first.

Contributing

We're looking for contributors who are passionate about open source, local-first software, or just want to build with Svelte and TypeScript.

Read the Contributing Guide →

Contributors coordinate in our Discord.

Tech Stack

Svelte 5 Tauri TypeScript Rust Yjs Cloudflare Workers Tailwind CSS

Design Decisions

We publish our implementation specs. These are the reasoning behind non-obvious architectural choices—alternatives considered, trade-offs made, and why we landed where we did.

Spec What it decided
Encrypted Workspace Storage XChaCha20-Poly1305 at the CRDT value level; server-managed keys with self-hosting as the trust boundary
Y-Sweet Persistence Architecture How Yjs documents persist and compact in Durable Objects
Simple Definition-First Workspace API The defineTablecreateWorkspace.withExtension() builder pattern
Resilient Client Architecture How workspace clients handle offline, reconnect, and extension failures
Migrate to @epicenter/sync Custom sync protocol replacing Y-Sweet with our own framing layer

All 112 implemented specs live in specs/.

License

Most packages and all apps are MIT—use them however you want, no strings attached. The sync server (apps/api) and sync protocol (packages/sync) are AGPL-3.0, which means anyone hosting a modified version shares their changes. This follows the same pattern as Yjs (MIT core, AGPL y-redis), Liveblocks (Apache clients, AGPL server), and Bitwarden (GPL clients, AGPL server).

See FINANCIAL_SUSTAINABILITY.md for the full reasoning behind the split.


Contact: github@bradenwong.com | Discord | @braden_wong_

Local-first · CRDT · Own your data · Open source