npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@mylesiyabor/mddb

v1.8.0

Published

Multiplayer markdown database — SQLite-backed, real-time, agent-ready

Readme

mddb

Multiplayer markdown database — SQLite-backed, real-time, and agent-ready. Every write broadcasts over WebSocket to all connected browsers.

npx @mylesiyabor/mddb start

Open http://localhost:7778 in your browser.

Install

npm install -g @mylesiyabor/mddb

Requires Node.js 18.14.1+.

Usage

mddb start                        # default port 7778, default DB path
mddb start ./team.db              # custom SQLite file
mddb start --port 8080            # custom port
mddb users create alice           # create a user and print their token
mddb users list
mddb users rotate alice
mddb users delete alice
mddb users promote alice          # mark a user as admin (database flag)
mddb get roadmap ./team.db        # print a document from a specific DB
mddb set roadmap ./notes.md       # write from a file path
mddb set projects/mddb/roadmap ./notes.md
mddb set roadmap --by myles < roadmap.md
mddb delete roadmap ./team.db
mddb search "roadmap partner"       # full-text search (FTS5) across all docs
mddb search "keywords" ./team.db  # optional explicit DB path
mddb migrate ./old.db ./new.db
mddb migrate https://old.trygravity.ai ./backup.db --from-token <token>
mddb migrate ./team.db https://new.trygravity.ai --to-token <token>

For mddb get, set, list, history, delete, and search, you can pass the DB as either --db /path/to.db or a trailing path/to.db. mddb set accepts content as a literal string, a file path, or stdin.

Folders and paths

Document IDs can be slash-delimited paths like projects/mddb/roadmap.

  • The bundled browser viewer renders those IDs as a collapsible folder tree, similar to a code editor sidebar.
  • The browser URL hash keeps the structure readable, e.g. #/projects/mddb/roadmap.
  • The sidebar create button opens a visible create menu, and right-clicking folders, docs, or blank sidebar space opens context actions.
  • Creating a folder from the sidebar stores that folder explicitly in SQLite, so empty folders persist even before the first doc is added inside them.
  • Folder deletes are recursive, so removing projects/mddb also removes nested docs and subfolders after confirmation.
  • mddb prevents file/folder path collisions like notes and notes/today existing at the same time.
  • Nested folders are supported, e.g. projects/mddb/archive/notes.

Migration

Use mddb migrate to move content between mddb databases and hosted mddb servers.

  • Local DB to local DB preserves documents, folders, history, settings, and users.
  • HTTP migrations preserve documents, folders, and settings when the API allows it.
  • HTTP migrations do not preserve user token hashes, and remote imports only restore the latest document state, not full history.

Examples:

mddb migrate ./old.db ./new.db
mddb migrate https://old-mddb.trygravity.ai ./backup.db --from-token <token>
mddb migrate ./team.db https://new-mddb.trygravity.ai --to-token <token>

Search (full-text)

mddb indexes title + markdown body with SQLite FTS5 (Porter stemmer + prefix matching on each token, so road matches roadmap). This is keyword search, not semantic embeddings — good for agents to locate docs before calling mddb_get.

  • CLI: mddb search "<keywords>" (optional trailing path/to.db)
  • HTTP: GET /api/search?q=keywords&limit=20 — JSON with results[]: id, title, snippet, rank
  • MCP: mddb_search tool
  • Cap: max hits default 20, upper bound from MDDB_SEARCH_LIMIT (default 50)

Embedding-based search could be added later as an optional mode; FTS stays the default because it has no extra services and stays in sync with your SQLite file.

Slack notifications (optional)

Configure a Slack Incoming Webhook URL in either place:

  1. Web UI (admins)Settings in the top bar → Slack incoming webhookSave. Stored in SQLite (app_settings); leave the field empty to clear the override.
  2. Environment — set MDDB_SLACK_WEBHOOK_URL (alias: MDDB_SLACK_WEBHOOK) on the server process.

Precedence: a URL saved in the database from the UI overrides the environment variable. If nothing is stored in the DB, the env URL is used.

When auth_required is false (no users in the DB and no MDDB_AUTH_TOKENS / MDDB_TOKEN), the Settings button is still shown so you can set the Slack URL without signing in. GET/PUT /api/settings does not require admin in that mode — only expose mddb on networks you trust, or add users so auth is enforced.

Whenever a new document ID is created (first write to that ID), mddb POSTs a short message with doc id, title, and updated_by if present. Updates to existing docs do not notify.

Applies to writes that go through dbSet (HTTP API, Node MCP in local mode, mddb server). Raw SQLite writes from other tools bypass this hook.

Users and admins

CLI

Create accounts with mddb users create <name>, rotate tokens with mddb users rotate, remove with mddb users delete. Use mddb users promote <name> to grant admin in the database.

Web UI (admins)

In the browser viewer, Settings and Users are in the top bar (after MCP; you must be signed in with a token). They only open for admins; if you are not an admin yet, hover either button for the server command to promote yourself (mddb users promote <name> or MDDB_ADMIN_NAMES).

From Settings, admins can set the Slack incoming webhook URL (see Slack notifications).

The MCP button opens a setup panel that shows the exact claude mcp add ... command for the current server. When auth is enabled and you are signed in, that command includes your current token and a copy button.

From Users, admins can list users and create new users (optional Admin checkbox). The new user’s token is shown once — copy it for MDDB_TOKEN.

Who counts as an admin

  • Users with is_admin set in the database (mddb users promote does this), or
  • Names listed in MDDB_ADMIN_NAMES (comma-separated, case-insensitive). On startup, matching users get is_admin synced in SQLite so you can bootstrap an admin without extra migrations.

API (admins)

With a valid bearer token for an admin user:

  • GET /api/users — list users (no secrets)
  • POST /api/users — body { "name": "...", "is_admin": false } — create user; response includes the new token once
  • GET /api/settings{ "slack_webhook_url": string | null } — value stored in DB (not the env fallback); null if unset in DB
  • PUT /api/settings — body { "slack_webhook_url": "https://..." } — save webhook; empty string clears the DB value so the env var applies again

What it does

  • SQLite — markdown per document, last 10 versions kept in history
  • WebSocket — live updates across browsers and sessions
  • Viewer — EasyMDE editor, wiki links [[doc-id]], slash commands, a VS Code-style folder tree, and sidebar context menus for create/delete actions
  • HTTP API — REST for scripts and integrations
  • MCPmddb_search, mddb_get, mddb_set, mddb_append, mddb_upsert_section, mddb_delete, mddb_read_lines, mddb_history, etc., for Claude Code and other MCP clients
  • Optional auth — after the first user exists, API and WebSocket require Authorization: Bearer <token>

HTTP API

GET    /api/auth/status
GET    /api/auth/validate
GET    /api/me
GET    /api/users              (admin)
POST   /api/users              (admin)   { "name", "is_admin"? }
GET    /api/settings           (admin)
PUT    /api/settings           (admin)   { "slack_webhook_url" }
GET    /api/folders
POST   /api/folders                      { "path" }
DELETE /api/folders/:path
GET    /api/docs
GET    /api/docs/:id
POST   /api/docs/:id
POST   /api/docs/:id/append
DELETE /api/docs/:id
GET    /api/docs/:id/history
GET    /api/docs/:id/lines?start=1&end=50
GET    /api/search?q=keywords&limit=20   full-text search (FTS5)
WS     /ws

MCP (Claude Code)

Point MDDB_HOST at wherever the server is reachable (including http://localhost:7778 for local dev):

claude mcp add --scope user mddb -e MDDB_HOST=https://your-mddb-host.example.com -- npx -y @mylesiyabor/mddb mcp

If the server requires a user token:

claude mcp add --scope user mddb \
  -e MDDB_HOST=https://your-mddb-host.example.com \
  -e MDDB_TOKEN=<token> \
  -- npx -y @mylesiyabor/mddb mcp

Check registration:

claude mcp get mddb

Restart the IDE or start a new session so tools appear.

Example tool usage in an agent session:

mddb_list
mddb_get(id: "roadmap")
mddb_set(id: "sprint", content: "# Sprint\n", by: "agent")

Bounded reads use MDDB_DEFAULT_READ_LINES (default 200) unless you pass line ranges or use mddb_download.

Environment variables

| Variable | Meaning | |----------|---------| | MDDB_PATH | SQLite file path | | MDDB_PORT | Listen port (default 7778) | | MDDB_BASE_PATH | Optional URL prefix if served behind a reverse proxy subpath (e.g. /mddb) | | MDDB_TOKEN / MDDB_AUTH_TOKENS | Bootstrap bearer token(s); MDDB_AUTH_TOKENS can be label:token pairs | | MDDB_ADMIN_NAMES | Comma-separated names treated as admins (merged with DB is_admin) | | MDDB_DEFAULT_READ_LINES | Default line window for MCP reads | | MDDB_SEARCH_LIMIT | Max hits per search request (default 50) | | MDDB_SLACK_WEBHOOK_URL | Slack Incoming Webhook URL — posts when a new document is created (not on edits). Alias: MDDB_SLACK_WEBHOOK | | MDDB_HOST | Used by MCP client (mcp.js) to reach the HTTP API |

Slash commands

Type / in the editor:

| Command | Result | |--------|--------| | /h1 /h2 /h3 | Headings | | /todo | Task checkbox | | /bullet /num | Lists | | /code | Code block | | /table | Table | | /quote /bold /italic /link | Formatting |

Self-hosting (short)

  • Run behind HTTPS in production; terminate TLS at your load balancer or reverse proxy.
  • Health checks can use GET /api/auth/status (returns JSON; works without auth when no users exist yet).
  • If you expose the app only under a subpath, set MDDB_BASE_PATH to that path (e.g. /mddb) so routes and the viewer match.
  • Ensure MDDB_HOST in MCP config matches the public URL agents use (scheme + host + optional base path).

Tech

  • Node.js HTTP + ws
  • MCP stdio server: mcp.js (@modelcontextprotocol/sdk)
  • better-sqlite3
  • EasyMDE / CodeMirror in the bundled viewer