diff --git a/README.md b/README.md
index c7e55d7..2188eec 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,8 @@
# Dripnex developers
-Plugin and theme **pack SDK** for Dripnex (not a store). Fumadocs + Next.js static export on Cloudflare Pages.
+Pack SDK for **Dripnex, the hackable AI note taker** (not a store). Fumadocs + Next.js static export on Cloudflare Pages.
+
+Notes live in local SQLite. `.md` is export. First launch is AuthGate. Personal hacks are `init.js` / `styles.css` / `keybindings.json` from **Settings → Hack**. Satellite packs are `dripnex/plugin-*` / `dripnex/theme-*` plus a GitHub Release tarball.
[docs.dripnex.app](https://docs.dripnex.app) is the user manual ([`dripnex/docs-site`](https://github.com/dripnex/docs-site)). This repo is how to write satellite packs. Marketing lives in [`dripnex/marketing`](https://github.com/dripnex/marketing).
diff --git a/app/layout.tsx b/app/layout.tsx
index 62ad604..11167c7 100644
--- a/app/layout.tsx
+++ b/app/layout.tsx
@@ -19,7 +19,7 @@ export const metadata: Metadata = {
template: '%s | Dripnex Developers',
},
description:
- 'Plugin and theme API for Dripnex — extend the desktop editor with commands, CodeMirror, layout zones, and palettes.',
+ 'Pack SDK for Dripnex, the hackable AI note taker — init.js, plugins, and themes. Not a store.',
applicationName: 'Dripnex Developers',
icons: {
icon: [
@@ -53,7 +53,7 @@ export default function RootLayout({ children }: { children: ReactNode }) {
banner: (
- Desktop plugin API.{' '}
+ Desktop pack SDK for the hackable AI note taker.{' '}
/` | Scanner → `loadPluginFromSource()` → same host |
-| **Hackable files** | Data directory (`init.js`, `styles.css`, `keybindings.json`) | `init.js` loads as plugin `user-init` |
+| **Hackable files** | Data directory (`init.js`, `styles.css`, `keybindings.json`) | Open from **Settings → Hack**. `init.js` loads as plugin `user-init` |
Discovered packs always live in user data. Palettes are **not** compiled into the app (`OFFICIAL_THEMES` is `[]`).
@@ -29,6 +33,8 @@ Discovered packs always live in user data. Palettes are **not** compiled into th
Override with `DRIPNEX_DATA_DIR` or `--user-data-dir` if the CLI and the app disagree about the folder.
+That directory is for **packs**. The note store is SQLite in the same data dir. Do not treat notes as files on disk.
+
## Repo layout
`dripnex-plugin init "My Plugin"` writes:
@@ -58,7 +64,7 @@ Override with `DRIPNEX_DATA_DIR` or `--user-data-dir` if the CLI and the app dis
Theme packs add `theme.json` next to `manifest.json`. See [Create a theme](/guides/create-a-theme).
-On disk after install:
+After install:
```
userData/plugins//
@@ -138,13 +144,13 @@ Keymap chords only bind if the command was registered in `activate()`. They cann
## Plugin contract
-Keep markdown portable. These are product rules, not extra host checks:
+Notes live in SQLite. Export is Markdown. Packs should stay optional chrome and commands:
-1. **Removable without breaking `.md` files** — uninstall and notes stay valid markdown.
-2. **No new syntax** other editors cannot read.
-3. **No automatic content mutation** — never rewrite the user's markdown without an explicit command.
-4. **Not required to interpret text** — notes must be readable without the pack.
-5. **No inter-note dependencies** that break if a note is moved or deleted.
+1. **Removable** — uninstall and notes stay readable. Do not make the store depend on your pack.
+2. **No invented syntax** other tools cannot read when the user exports `.md`.
+3. **No automatic content mutation** — never rewrite a note without an explicit command.
+4. **Not required to interpret text** — a note must still make sense without the pack.
+5. **No inter-note graph the pack owns** that breaks if a note is moved or deleted.
## Official satellites (verified)
@@ -155,7 +161,7 @@ How users get a shipped pack: **Settings → Themes → Available** (themes) or
| [dripnex/plugin-stamp](https://github.com/dripnex/plugin-stamp) | `stamp` | Insert date / timestamp at the cursor |
| [dripnex/plugin-mermaid](https://github.com/dripnex/plugin-mermaid) | `mermaid` | Insert a ` ```mermaid ` fence. **No renderer.** Diagrams are the built-in `dripnex-mermaid` pack. |
| [dripnex/plugin-math](https://github.com/dripnex/plugin-math) | `math` | Insert `$$…$$`. **No KaTeX.** Math rendering is the built-in `dripnex-math` pack. |
-| [dripnex/plugin-vim](https://github.com/dripnex/plugin-vim) | `dripnex-vim-mode` | Real `@replit/codemirror-vim`. Install spec is `dripnex/plugin-vim`, not the manifest id. |
+| [dripnex/plugin-vim](https://github.com/dripnex/plugin-vim) | `dripnex-vim-mode` | Real `@replit/codemirror-vim`. Satellite, not built-in. Install spec is `dripnex/plugin-vim`, not the manifest id. |
| [dripnex/theme-parchment](https://github.com/dripnex/theme-parchment) | `theme-parchment` | Warm-paper palette. Other palettes are `dripnex/theme-*` satellites, not core. |
Built-in mermaid, math, and tables **renderers** ship in the app. Do not treat the mermaid/math satellites as those renderers.
diff --git a/content/docs/getting-started/init-file.mdx b/content/docs/getting-started/init-file.mdx
index 42136a1..3f4590a 100644
--- a/content/docs/getting-started/init-file.mdx
+++ b/content/docs/getting-started/init-file.mdx
@@ -1,32 +1,59 @@
---
title: The init file
-description: Customize Dripnex on startup with init.js — the host PluginContext, not Inkdrop’s Atom APIs
+description: Settings → Hack opens init.js. Lead with registerAiCommand “Make this sendable.”
---
# The init file
-`init.js` is a **user file** in the data directory, not a plugin repo. Open it from **Settings → Plugins**. Dripnex writes a template on first open.
+`init.js` is a **user file** in the data directory, not a plugin repo. Open it from **Settings → Hack** (Open init.js). Dripnex writes a template on first launch. Existing files are not overwritten.
-It is the same idea as Inkdrop's init file: run JavaScript at startup. The object you get is **Dripnex's** host API (`createInitApi` in `@dripnex/plugin-api`), not Inkdrop's Atom-style `inkdrop` global.
+That is the user-facing hack surface: **Settings → Hack** opens `init.js`, `styles.css`, and the keymap (`keybindings.json`). Save to apply. Reload plugins after changing `init.js`.
-## Two formats
-
-`loadInitScript()` accepts:
+The object you get is Dripnex’s host API (`createInitApi` in `@dripnex/plugin-api`), injected as the `dripnex` argument. There is no Atom-style global.
-1. **Free-form (default).** The file is wrapped as plugin `user-init` and runs at activate with a `dripnex` argument.
-2. **CommonJS `PluginManifest`.** If the file assigns `module.exports` / `exports.*` and looks like a manifest (`id`, `activate`, `name`, or `version`), it is validated and loaded as a normal pack.
+## Make this sendable
-Free-form is what the default template uses (`dripnex.menu.add`, `dripnex.commands.add`). Do not assume a browser `window.dripnex` with a `.menu` — the host injects the init API as the `dripnex` function argument.
+The default template registers an AI command. Messy notes become a document a person would actually send — not a model dump.
```js
-dripnex.commands.add('paste-as-link', 'Paste as Link', () => {
- const { from, to } = dripnex.editor.getSelection();
- const text = dripnex.editor.getContent().slice(from, to);
- dripnex.editor.replaceRange(from, to, '[' + text + '](url)');
+dripnex.registerAiCommand({
+ id: 'make-this-sendable',
+ name: 'Make this sendable',
+ description: 'Turn this note into a document a person would actually send.',
+ systemPrompt:
+ 'Turn messy notes into a document a person would actually send. ' +
+ 'Clear, specific, human. Not a model dump. Preserve facts. Cut filler. ' +
+ 'Match the implied genre (email, message, brief, post).',
+ userPromptTemplate:
+ 'Turn the following into a document a person would actually send.\n\n' +
+ 'Title: {{title}}\n\n' +
+ 'Selection (if any):\n{{selection}}\n\n' +
+ 'Full note:\n{{note}}',
+ outputTarget: 'replace',
+ category: 'writing',
});
```
-Reload plugins (**Settings → Plugins → Reload**) after saving.
+Placeholders in `userPromptTemplate`: `{{selection}}`, `{{note}}`, `{{title}}`. `outputTarget`: `'replace'` | `'insert'` | `'panel'` (default `'panel'`). The command appears in the AI panel and the command palette.
+
+A palette command that is not AI still works. It is a comment in the template — it does not lead:
+
+```js
+// dripnex.commands.add('insert-date', 'Insert Date', () => {
+// dripnex.editor.insertAtCursor(new Date().toISOString().slice(0, 10));
+// });
+```
+
+Reload after saving: **Settings → Plugins → Reload**, or the Reload Plugins command.
+
+## Two formats
+
+`loadInitScript()` accepts:
+
+1. **Free-form (default).** The file is wrapped as plugin `user-init` and runs at activate with a `dripnex` argument.
+2. **CommonJS `PluginManifest`.** If the file assigns `module.exports` / `exports.*` and looks like a manifest (`id`, `activate`, `name`, or `version`), it is validated and loaded as a normal pack.
+
+Free-form is what the default template uses. Do not assume a browser `window.dripnex` with a `.menu` — the host injects the init API as the `dripnex` function argument.
## The `dripnex` object (`InitApi`)
@@ -43,7 +70,7 @@ Reload plugins (**Settings → Plugins → Reload**) after saving.
| `vim` | `@replit/codemirror-vim` `Vim` object **when** [plugin-vim](https://github.com/dripnex/plugin-vim) is loaded; otherwise unavailable |
| `getActiveEditor()` | `{ editor, cm }` where `cm` is `editor.getView()` (live CodeMirror 6 view or `null`) |
-There is no Inkdrop `inkdrop.packages`, `CompositeDisposable`, or Atom command registry. Map keys with `dripnex.commands.add` / `registerCommand`, or with `Vim.map` after the Vim pack has called `registerVim`.
+Map keys with `dripnex.commands.add` / `registerCommand`, or with `Vim.map` after the Vim pack has called `registerVim`.
## Read-only store
@@ -60,9 +87,11 @@ const unsub = dripnex.store.subscribe(() => {
- Mutate through `dripnex.commands.dispatch`, `editor`, or `data`.
- `settings` is appearance only (theme, accent, zoom). It never includes API keys.
+Notes themselves live in local SQLite. The store is a projection, not a folder of files.
+
## Vim maps (after installing Vim)
-Vim is **not** built-in. Users install `dripnex/plugin-vim` from **Settings → Plugins → Install** / **Other package** (manifest id `dripnex-vim-mode`) and enable it. The pack exposes `dripnex.vim` via `registerVim` so init can map keys:
+Vim is **not** built-in. It is the satellite [dripnex/plugin-vim](https://github.com/dripnex/plugin-vim). Users install it from **Settings → Plugins → Install** / **Other package** (manifest id `dripnex-vim-mode`) and enable it. The pack exposes `dripnex.vim` via `registerVim` so init can map keys:
```js
const Vim = dripnex.vim;
@@ -77,6 +106,8 @@ if (Vim) {
## Also in the data directory
+Open all three from **Settings → Hack**.
+
| File | Role |
| ---- | ---- |
| `init.js` | This page |
diff --git a/content/docs/getting-started/style-tweaks.mdx b/content/docs/getting-started/style-tweaks.mdx
index 70c2b58..23503d1 100644
--- a/content/docs/getting-started/style-tweaks.mdx
+++ b/content/docs/getting-started/style-tweaks.mdx
@@ -1,11 +1,11 @@
---
title: Style tweaks
-description: Personal CSS and theme tokens without shipping a full theme pack
+description: Personal CSS from Settings → Hack — not a theme pack, not notes-as-files
---
# Style tweaks
-`styles.css` in the data directory is injected into every renderer window. Save to apply. Open it from **Settings → Plugins** (written on first open, same as `init.js`).
+`styles.css` in the data directory is injected into every renderer window. Save to apply. Open it from **Settings → Hack** (Open styles.css). Written on first launch if missing, same as `init.js` and `keybindings.json`. Existing files are not overwritten.
Use this for personal chrome. To **share** a palette, ship a [theme pack](/guides/create-a-theme).
@@ -34,9 +34,11 @@ Unknown names are rejected for **registered themes**. Your personal `styles.css`
}
```
+Enable **Development Mode** in Settings → General, then right-click → Inspect Element.
+
## From a plugin or init.js
-Packs can register variables without a `theme.json`:
+Packs (and `init.js`) can register variables without a `theme.json`:
```js
dripnex.registerCssVariables('my-tweaks', {
@@ -52,7 +54,7 @@ dripnex.registerCssVariables('my-tweaks', {
| | `styles.css` | Theme pack |
| - | ------------ | ---------- |
| Audience | You | Anyone who installs the satellite pack |
-| Activation | Always, for your user data | Settings → Themes → **Available** (one click) |
+| How you open it | Settings → Hack | Settings → Themes → **Available** (one click) |
| Token validation | Raw CSS | `CORE_THEME_TOKENS` + extension scopes |
| Example | A larger editor font | [dripnex/theme-parchment](https://github.com/dripnex/theme-parchment) |
diff --git a/content/docs/guides/create-a-plugin.mdx b/content/docs/guides/create-a-plugin.mdx
index 4e61a71..28e2d53 100644
--- a/content/docs/guides/create-a-plugin.mdx
+++ b/content/docs/guides/create-a-plugin.mdx
@@ -1,11 +1,13 @@
---
title: Create a plugin
-description: Scaffold, activate, bundle to CommonJS, and load a Dripnex plugin from disk
+description: Scaffold, activate, bundle to CommonJS, and load a Dripnex plugin
---
# Create a plugin
-This walkthrough builds a pack you can load locally. The real first-party example is [dripnex/plugin-stamp](https://github.com/dripnex/plugin-stamp): CommonJS, `menu.add`, `editor.insertAtCursor`.
+Personal AI commands belong in `init.js` (**Settings → Hack**). This walkthrough is a **satellite pack** you can load locally. The real first-party example is [dripnex/plugin-stamp](https://github.com/dripnex/plugin-stamp): CommonJS, `menu.add`, `editor.insertAtCursor`.
+
+If you only want “Make this sendable,” stop here and edit [init.js](/getting-started/init-file). You do not need a repo for that.
## 1. Scaffold
@@ -57,7 +59,7 @@ Keep `id` / `name` / `version` in sync with `manifest.json`. Return `{ dispose()
TypeScript is fine if your bundler emits CJS `module.exports`. Named ESM `export const plugin` is **not** what `loadPluginFromSource` reads.
-## 3. Commands and layout (optional)
+## 3. Commands, AI commands, and layout (optional)
Commands land in the palette as `plugin::`:
@@ -77,6 +79,8 @@ const off = context.registerCommand(
);
```
+AI commands use `context.registerAiCommand` — same options as [init.js](/getting-started/init-file#make-this-sendable). Use that when the pack’s job is “turn this note into something a person will send,” not when you are inserting a date.
+
Mount UI with `context.layout.addComponent`. Zones are listed in [Layout zones](/reference/layout-zones). Status bar example:
```js
@@ -150,8 +154,10 @@ scan manifest.json → eval main → activate(context) → apply keymaps/menus/s
## Five rules
-1. Removable without breaking `.md` files.
-2. No invented markdown other editors cannot read.
+Notes live in SQLite. `.md` is export.
+
+1. Removable — uninstall and notes stay readable.
+2. No invented markdown other tools cannot read on export.
3. No automatic content mutation.
4. Notes stay readable without the pack.
5. No brittle inter-note graph that the pack owns.
diff --git a/content/docs/guides/create-a-theme.mdx b/content/docs/guides/create-a-theme.mdx
index 35656c1..7593138 100644
--- a/content/docs/guides/create-a-theme.mdx
+++ b/content/docs/guides/create-a-theme.mdx
@@ -1,10 +1,12 @@
---
title: Create a theme
-description: Satellite theme packs — manifest.json, dist/index.js, and theme.json. Palettes are not in the core app.
+description: Satellite theme packs — Settings → Hack is personal CSS; packs are palettes you share.
---
# Create a theme
+Personal chrome is `styles.css` from **Settings → Hack**. A **theme pack** is how you share a palette.
+
Palettes do **not** live in the desktop core. `OFFICIAL_THEMES` is `[]`. Every named palette is a satellite pack: a `dripnex/theme-*` git repo plus a GitHub Release tarball.
[dripnex/theme-parchment](https://github.com/dripnex/theme-parchment) is the reference (pack id `theme-parchment`, palette id `dripnex-parchment`).
diff --git a/content/docs/guides/publishing.mdx b/content/docs/guides/publishing.mdx
index c6e8d95..034a8ab 100644
--- a/content/docs/guides/publishing.mdx
+++ b/content/docs/guides/publishing.mdx
@@ -5,7 +5,9 @@ description: A pack is a satellite git repo plus a GitHub Release tarball. Not a
# Publishing
-This site is the pack SDK. Publishing does **not** mean upload, browse, or “publish to Dripnex.” There is no public marketplace and no ipm-style registry.
+This site is the pack SDK for the hackable AI note taker. Publishing does **not** mean upload, browse, or “publish to Dripnex.” There is no public marketplace and no ipm-style registry.
+
+`init.js` / `styles.css` / `keybindings.json` are personal. They are not packs. Do not ship them as a Release.
A pack is:
@@ -66,3 +68,5 @@ CLI `install` errors if that `manifest.id` is already present. Settings can over
- Proof toys (word count, typewriter, reading time) are not satellite packs.
- Do not open a plugin PR against `dripnex/app` unless it is becoming a **built-in**.
- Do not invent a second version number besides the git tag.
+- Do not claim notes are files on disk. The store is SQLite; `.md` is export.
+- Vim is `dripnex/plugin-vim`, not built-in.
diff --git a/content/docs/index.mdx b/content/docs/index.mdx
index 377d43f..9464183 100644
--- a/content/docs/index.mdx
+++ b/content/docs/index.mdx
@@ -1,15 +1,26 @@
---
-title: Start building with the Dripnex API
-description: SDK for Dripnex satellite packs — plugins and themes, not a store
+title: Hack the AI note taker
+description: Pack SDK for Dripnex — init.js, satellite plugins, and themes. Not a store.
---
-# Start building with the Dripnex API
+# Hack the AI note taker
+
+Dripnex is **the hackable AI note taker**. Messy input becomes a document a person will send — not a model dump.
This site is the **SDK for packs**. How to write, pack, and ship a plugin or theme. It is not a store.
[docs.dripnex.app](https://docs.dripnex.app) is the **user manual**. How people use Dripnex.
-A pack is a satellite git repo (`dripnex/plugin-*` or `dripnex/theme-*`) **plus** a GitHub Release asset named `{id}-{version}.tar.gz`. A git tag alone is not enough.
+## What Dripnex is (and is not)
+
+Dripnex is not a files-first Markdown editor. Notes live in **local SQLite**. `.md` is export, not identity. Plain files are easy to romanticize.
+
+First launch is **AuthGate**. There is no “no account to open a file.”
+
+Hackable means two surfaces:
+
+1. **User files** in the data directory — `init.js`, `styles.css`, `keybindings.json`. Open them from **Settings → Hack**.
+2. **Satellite packs** — git repos named `dripnex/plugin-*` or `dripnex/theme-*`, plus a GitHub Release asset `{id}-{version}.tar.gz`. A git tag alone is not enough.
There is **no public marketplace**, no ipm-style registry, and nothing to “publish to Dripnex.” Shipping is the tarball on the repo’s GitHub Release.
@@ -17,14 +28,14 @@ Desktop only. Phone v1 has no plugin path. Current API major: `PLUGIN_API_VERSIO
## Getting started
-Before you ship a pack, learn how Dripnex loads scripts and styles from the data directory:
+Personal hacks first. Then a pack, if you want to share.
-
- Customize startup with JavaScript in `init.js`. Register commands, map Vim keys, or read the store — without a plugin repo.
+
+ Open `init.js`. The default command is `registerAiCommand` **Make this sendable**.
- Restyle the UI with `styles.css` and CSS variables. You do not need a full theme pack for a personal tweak.
+ Restyle the UI with `styles.css`. You do not need a theme pack for a personal tweak.
@@ -34,7 +45,7 @@ How a **plugin repo** is structured (manifest, `main`, package files) is in [Plu
- Scaffold, activate, bundle to CommonJS, and load a pack from disk.
+ Scaffold, activate, bundle to CommonJS, and load a pack from the data directory.
Ship a palette: `manifest.json` + `dist/index.js` + `theme.json`.
@@ -51,7 +62,7 @@ How a **plugin repo** is structured (manifest, `main`, package files) is in [Plu
Everything passed to `activate()` — commands, editor, layout, data, themes.
- `registerCommand`, `dispatchCommand`, menus, and keymaps.
+ `registerCommand`, `registerAiCommand`, `dispatchCommand`, menus, and keymaps.
CodeMirror 6, decorations, and the live `EditorView`.
diff --git a/content/docs/meta.json b/content/docs/meta.json
index 0d355ee..e492da7 100644
--- a/content/docs/meta.json
+++ b/content/docs/meta.json
@@ -1,5 +1,5 @@
{
- "title": "Dripnex API",
+ "title": "Hackable AI note taker",
"root": true,
"pages": [
"index",
diff --git a/content/docs/reference/commands.mdx b/content/docs/reference/commands.mdx
index 38bfbc6..c9889ad 100644
--- a/content/docs/reference/commands.mdx
+++ b/content/docs/reference/commands.mdx
@@ -1,6 +1,6 @@
---
title: Commands
-description: registerCommand, dispatchCommand, menus, context menus, and package keymaps
+description: registerCommand, registerAiCommand, dispatchCommand, menus, context menus, and package keymaps
---
# Commands
@@ -42,6 +42,16 @@ const off = context.registerCommand(
From `init.js`, `dripnex.commands.add(id, name, execute, options?)` is the same registration without repeating `id`/`name` in the options object.
+## `registerAiCommand`
+
+```ts
+registerAiCommand(options: PluginAiCommandOptions): () => void
+```
+
+Appears in the AI panel and the command palette. The host resolves `{{selection}}`, `{{note}}`, and `{{title}}` at execution time.
+
+The default `init.js` command is **Make this sendable** (`outputTarget: 'replace'`). See [The init file](/getting-started/init-file#make-this-sendable).
+
## `dispatchCommand`
```ts
@@ -50,7 +60,7 @@ dispatchCommand(id: string, payload?: Record): Promise
Use a **full** id: host commands such as `app:save-note`, or `plugin:stamp:…`. Init equivalent: `dripnex.commands.dispatch`.
-Vim's `:cmd {id}` (from plugin-vim) is this dispatch, not an Inkdrop command bus.
+Vim's `:cmd {id}` (from the [plugin-vim](https://github.com/dripnex/plugin-vim) satellite) is this dispatch.
## Plugins menu
@@ -83,7 +93,7 @@ context.contextMenu.add(
After `activate()`, `keymaps/*.json` and `menus/*.json` are applied.
-**Keymap** — Dripnex form `{ "say-hello": "Mod+Shift+H" }` or Inkdrop form `{ "body": { "ctrl-alt-n": "say-hello" } }`. Chords parse `Mod+Shift+K` or `ctrl-alt-n`. Only `plugin::…` commands this pack registered are bound; core `app:` / `editor:` ids are skipped.
+**Keymap** — Dripnex form `{ "say-hello": "Mod+Shift+H" }`, or the `{ "body": { "ctrl-alt-n": "say-hello" } }` form the parser also accepts. Chords parse `Mod+Shift+K` or `ctrl-alt-n`. Only `plugin::…` commands this pack registered are bound; core `app:` / `editor:` ids are skipped.
**Menus** — JSON items with `label` + `command`, optional `accelerator`, optional `submenu`. Context-menu selectors map aliases such as `note-list`, `.cm-editor`, `tag` onto the four targets above.
diff --git a/content/docs/reference/data.mdx b/content/docs/reference/data.mdx
index fa63b2e..29ec0b5 100644
--- a/content/docs/reference/data.mdx
+++ b/content/docs/reference/data.mdx
@@ -1,11 +1,11 @@
---
title: Data API
-description: Notes, notebooks, tags, links, and graph — DataAPI plus the slimmer AppAPI
+description: Notes live in local SQLite — DataAPI plus the slimmer AppAPI. .md is export.
---
# Data API
-Plugins do not talk to a local HTTP server. Reads and writes go through `context.data` (`DataAPI`) and a smaller `context.app` (`AppAPI`). Types: `packages/plugin-api/src/data/dataTypes.ts` and `createDataAPI.ts`.
+Plugins do not talk to a local HTTP server. Notes live in **local SQLite**. Reads and writes go through `context.data` (`DataAPI`) and a smaller `context.app` (`AppAPI`). `.md` is export, not the store. Types: `packages/plugin-api/src/data/dataTypes.ts` and `createDataAPI.ts`.
## `AppAPI` (`context.app`)
diff --git a/content/docs/reference/editor.mdx b/content/docs/reference/editor.mdx
index cd34f83..9ea6e49 100644
--- a/content/docs/reference/editor.mdx
+++ b/content/docs/reference/editor.mdx
@@ -59,7 +59,7 @@ const off = context.registerExtensions('hello-keymap', [
]);
```
-Anything not on the [host require whitelist](/getting-started#the-module-must-be-commonjs) (for example `@replit/codemirror-vim`) must be bundled. That is how [plugin-vim](https://github.com/dripnex/plugin-vim) works: `registerExtensions` + `registerVim` + status bar, not an Atom keymap.
+Anything not on the [host require whitelist](/getting-started#the-module-must-be-commonjs) (for example `@replit/codemirror-vim`) must be bundled. That is how the [plugin-vim](https://github.com/dripnex/plugin-vim) satellite works: `registerExtensions` + `registerVim` + status bar. Vim is not built-in.
## Decorations
diff --git a/content/docs/reference/examples.mdx b/content/docs/reference/examples.mdx
index 7528323..5db70eb 100644
--- a/content/docs/reference/examples.mdx
+++ b/content/docs/reference/examples.mdx
@@ -1,10 +1,35 @@
---
title: Examples
-description: Patterns from official satellites and valid PluginContext usage
+description: Make this sendable in init.js, then official satellite patterns
---
# Examples
+## Make this sendable (`init.js`)
+
+Personal AI commands live in the data directory. Open **Settings → Hack → Open init.js**. This is the default template — messy notes → a document a person would send, not a model dump.
+
+```js
+dripnex.registerAiCommand({
+ id: 'make-this-sendable',
+ name: 'Make this sendable',
+ description: 'Turn this note into a document a person would actually send.',
+ systemPrompt:
+ 'Turn messy notes into a document a person would actually send. ' +
+ 'Clear, specific, human. Not a model dump. Preserve facts. Cut filler. ' +
+ 'Match the implied genre (email, message, brief, post).',
+ userPromptTemplate:
+ 'Turn the following into a document a person would actually send.\n\n' +
+ 'Title: {{title}}\n\n' +
+ 'Selection (if any):\n{{selection}}\n\n' +
+ 'Full note:\n{{note}}',
+ outputTarget: 'replace',
+ category: 'writing',
+});
+```
+
+A pack that does the same uses `context.registerAiCommand` inside `activate()`. You do not need a satellite repo for a personal command.
+
## Stamp (official satellite)
[dripnex/plugin-stamp](https://github.com/dripnex/plugin-stamp) — insert date/timestamp. CommonJS, `menu.add`, `insertAtCursor`. Users install from **Settings → Plugins → Install** / **Other package** (`dripnex/plugin-stamp`). Authors iterating locally: `dripnex-plugin install .`.
@@ -141,4 +166,4 @@ Init.js equivalent: `void dripnex.commands.dispatch('app:save-note')`.
## Vim (official satellite)
-[dripnex/plugin-vim](https://github.com/dripnex/plugin-vim) — manifest id `dripnex-vim-mode`. Bundles `@replit/codemirror-vim`, calls `registerExtensions` and `registerVim`. Users install from **Settings → Plugins → Install** / **Other package** with spec `dripnex/plugin-vim`. After it is enabled, `init.js` may use `dripnex.vim` ([init file](/getting-started/init-file#vim-maps-after-installing-vim)).
+Vim is **not** built-in. [dripnex/plugin-vim](https://github.com/dripnex/plugin-vim) — manifest id `dripnex-vim-mode`. Bundles `@replit/codemirror-vim`, calls `registerExtensions` and `registerVim`. Users install from **Settings → Plugins → Install** / **Other package** with spec `dripnex/plugin-vim`. After it is enabled, `init.js` may use `dripnex.vim` ([init file](/getting-started/init-file#vim-maps-after-installing-vim)).
diff --git a/content/docs/reference/plugin-context.mdx b/content/docs/reference/plugin-context.mdx
index 939b236..04a5e6e 100644
--- a/content/docs/reference/plugin-context.mdx
+++ b/content/docs/reference/plugin-context.mdx
@@ -32,7 +32,7 @@ Return `{ dispose() }` and undo registrations. `deactivate()` on the manifest is
| `components` | `PluginComponents` | Stock `Button`, `Modal`, `Dialog` |
| `preview` | `{ on(event, handler) }` | `'a:click'` \| `'checkbox:change'` |
| `themes` | `{ list, getActive, setActive, onDidChange }` | [Themes](/reference/themes) |
-| `markdownRenderer` | `MarkdownRenderer` | Inkdrop-shaped remark/rehype/React/fence maps |
+| `markdownRenderer` | `MarkdownRenderer` | remark/rehype arrays, React element map, fenced-code map, preview events |
## Registration methods
@@ -52,7 +52,7 @@ CodeMirror 6 `Extension[]` in a compartment. See [Editor](/reference/editor).
### `registerVim(api)`
-Publish a Vim API for `dripnex.vim` in `init.js`. Call at **module load**, not only inside `activate`, so init can `Vim.map` as soon as the pack is present.
+Publish a Vim API for `dripnex.vim` in `init.js`. Call at **module load**, not only inside `activate`, so init can `Vim.map` as soon as the [plugin-vim](https://github.com/dripnex/plugin-vim) satellite is present. Vim is not built-in.
### `registerRemarkPlugin(id, plugin, options?)` / `registerRehypePlugin(id, plugin, options?)`
@@ -70,6 +70,8 @@ Fence renderer. Props: `{ code, language, meta? }` (`CodeBlockRendererProps`). B
Appears in the AI panel and the command palette. Placeholders in `userPromptTemplate`: `{{selection}}`, `{{note}}`, `{{title}}`. `outputTarget`: `'replace'` \| `'insert'` \| `'panel'` (default `'panel'`).
+The canonical personal example is **Make this sendable** in `init.js` — messy notes → a document a person will send, not a model dump. See [The init file](/getting-started/init-file#make-this-sendable).
+
### `registerCssVariables(id, variables)` / `registerTheme(theme)`
See [Themes](/reference/themes).