Repository: emacs-apps/appkit.el.
Appkit is the runtime and presentation library behind the Emacs clients in this repository (QQ, Disco, Slackit, Zulip, Matrix, Chirp, Bili, Verse and others). It owns application and buffer lifecycle, the order in which state changes and presentation commit, asynchronous work, and reusable buffer UI: projections, chat buffers, composers, markup and media.
Clients own their protocol: data models, transport, validation, persistence, identity, faces and branding. Appkit defines no channel, message or account model.
- Emacs 32.0 or newer, graphical for images and video
plz0.8+video.el0.1+ with its native module built- Optional: Evil (bindings load after it), the Markdown Tree-sitter grammars (Markdown codec), Respond (default translation backend)
(require 'appkit) loads every module. Appkit keeps no compatibility aliases;
use the public appkit-* names directly.
(use-package appkit
:straight (:host github :repo "emacs-apps/appkit.el"))Inside the monorepo, packages and their load paths are registered in emacs-dev/dev-registry.el.
| Chapter | Covers |
|---|---|
| Runtime | Apps, Surfaces, transitions, commands, publish/subscribe, Effects, Sources, Renderers, Resources |
| Design | how to divide an application: state ownership, messages, work, App–Surface traffic, review checklist |
| Presentation | positions, actions, prefixes and cards, rows, directories, discussions, scrolling, selection, bindings |
| Chat buffers | chat buffer and composer, timeline, history windows, read state, message leaves, completion |
| Media | resources, images, inline occurrences, tracks, video sessions, audio |
| Compose | compose sessions and operations, child editors, chat compose |
| Markup | semantic documents, native rendering, codecs, structured objects |
Read the runtime chapter first, then design. The chapters explain models and the rules that are easy to break; argument details live in docstrings.
| Area | Modules |
|---|---|
| Runtime | loop app surface command effect source topic resource context routing core cleanup transaction task-queue |
| Projection | projection position ewoc geometry scroll selection |
| Presentation | ui presentation directory discussion name-color mode-line fontify translate translate-respond bindings evil |
| Chat | chatbuf chat-timeline chat-history chat-read chat-ins chat-avatar chat-completion chat-emoji |
| Compose | compose compose-edit chat-compose markup-compose |
| Markup | markup markup-ui markup-codec markup-codecs markup-markdown-ts |
| Media | media media-resource media-effect media-image media-inline media-track media-grid media-playback media-video media-player media-card |
Each name is appkit-NAME.el.
Tests live in test/. Run them in an Emacs daemon with
emacs-dev/dev.el loaded, preferably a fresh
emacs -Q daemon whose load-path comes from the package registry:
(dev-run-test-files
(directory-files "~/Projects/dev-monorepo/appkit-apps/appkit.el/test"
t "-test\\.el\\'"))dev-run-test-files runs only the tests declared in those files and returns
counts plus unexpected results. Wrap loading in dev-with-source-loads (or set
load-prefer-newer) so stale .elc files in the tree cannot hide source edits.
Canvas geometry, real playback and touch input need a graphical frame. Tests that skip in batch prove nothing about them. Smoke-test those paths in a running client.