Flash’s browser help combines feature guides with the state of the running
resident. flash help_show opens its homepage; :help works after opening
the command line with flash enter_command_mode or a user-defined shortcut.
The default NORMAL ? mapping opens
the effective mapping table, as does :mappings; the mapping syntax guide
remains available through :help mappings.
:help <topic> opens a guide directly:
:help plugins
:help normal-mode
:help widgets
:help config
The homepage is one checklist for this Mac. It marks permissions, the config file, shortcuts, plugins, and the status bar from the resident’s state, and it remembers which guides this browser has opened. Guides cover hints, grid/pointer control, modes, flashlight, mappings, configuration, status formats, the status bar, widgets, popups, plugins, privacy, troubleshooting and development. Items in “What is missing” open their linked guide or page when they have one; otherwise they jump to their checklist step. Plugin manifests add their own topics.
| Page | What it describes |
|---|---|
| Mappings | Effective bindings after defaults, plugin contributions and user overrides, grouped by mode. A blank search stays alphabetical by command. The search ranks what a binding does, including typos. Each row has a small copy control for a TOML snippet that changes the binding; the Source column links plugin origins to their details and config origins to the live editor |
| Keyboard | The [keyboard] layout drawn as keys, each showing what it does in the mode Flash is in: the bindings of that mode and all, the hint alphabet with each key’s ease while labels are up, the grid block while the grid is up, the adjust, pointer and search keys in their sessions, and the zone of label_order = "zones". Follows the resident’s mode and hint session over the event stream, or a mode picked by hand. Selecting a key lists its bindings. Nothing typed is shown, only what Flash is ready for |
| Commands | Built-in and installed plugin command definitions, sorted alphabetically |
| Plugins | Loaded manifests, process health, errors and capabilities. Selecting Inspect details opens a dialog; Escape or its close button dismisses it |
| Runtime | Current mode, app, configuration diagnostics, permissions, input capture, hints and window state. Resolved configuration is JSON: default values keep the base colour, and an override is marked with the layer that set it. Config provenance links jump to the editor on the same page; Purge defaults removes bundled values in the editor and Save writes the file |
| Logs | Recent structured diagnostics and interaction traces |
| Clipboard | Live text registers (unnamed, latest yank and named buffers) above recent text, images, formatted copies, and files from core history. The page requests history directly on opening, loads it in pages, and can copy back or delete each entry |
The browser follows the resident’s event stream: Flash pushes a snapshot when something it shows changes, never on a timer, and the page derives uptimes from the start times it carries. Plugin CPU time and memory change without an event, so they read as of the last snapshot; Refresh on the runtime page and Resample on a plugin’s details ask for a fresh one. A disconnected browser keeps its last snapshot and marks the connection state with a small warning icon in the top bar. The icon’s title explains that the snapshot may be stale; the page must not present that snapshot as current. Runtime state can include private app or clipboard data; see privacy before sharing it.
The inspector listens on loopback (port 4242 by default), starting when one of
the browser commands needs it, or at launch with
[debug] http_inspector_enabled = true. It stays available until Flash quits.
| Path | Destination |
|---|---|
/ |
Help homepage: a live onboarding checklist |
/docs, /docs/<topic> |
Guide index; documentation topic, including aliases |
/mappings, /commands |
Key mappings: your keyboard with what each key does in the mode picked under it (NORMAL, HOLD, HYPER, INSERT, COMMAND, TERMINAL or all), tinted by purpose, with free keys dashed and NORMAL’s counts marked. Modifier buttons show the Shift, Control, Option and Command layers; a key that starts longer bindings opens what can follow it; picking a key lists its bindings, and a free key offers the TOML to map it. The list below follows the mode and key, groups bindings by purpose, leads with what each does, and copies the TOML that rebinds or removes it. A search ranks the whole mode and lights the keys it matches. The page also shows how each action resolves in the focused app, and never follows the live mode. Command catalog. Opening mappings focuses its search. ?q=<text> starts the list filtered |
/plugins, /plugins/<id> |
Plugin list; a direct plugin link opens that plugin’s details in a dialog |
/state, /clipboard |
Runtime and clipboard pages |
/logs |
Live logs. The record list fills the page height, and its search field is focused when the page opens |
/search?q=<text> |
Results across guide sections, commands, mappings and plugins. Typing in the top bar rewrites the query in place, so a search reloads and can be shared; ↓ ↑ ↩ pick a result |
/api/state, /api/logs, /api/traces, /api/events |
JSON snapshots and the server-sent event stream the pages read; /api/state?refresh=1 takes a fresh snapshot |
/api/clipboard/<id> |
GET returns one history image. DELETE removes that entry. The id is 32 lowercase hex characters |
/api/clipboard/history?offset=<n> |
Up to 100 history entries from newest to oldest, plus the next offset or null at the end |
The page routes itself with the History API: same-origin page links navigate
in place, back/forward restore each page’s scroll position, and modified,
middle or new-window clicks keep the browser’s behavior. The top bar shows
the path as a breadcrumb (page › group › guide), hidden on Home, and the tab title
names the guide. After a navigation focus moves to the main region and the
new title is announced to assistive technology. Shortcuts outside a text
field: / or ⌘K search, [ and ] previous and next guide, g then a
letter jumps to a page, ? opens the shortcut sheet. Escape blurs a focused
field so these page shortcuts work again. The server answers
a direct load or reload of any page with the app, an unknown path with the
app’s not-found page and a 404 status, and an unknown /api/ path with a
plain 404. DebugServer.Page and Inspector/src/lib/routes.ts hold the same
page table; change them together.
Fragments are in-page anchors. Guide headings take GitHub-style slugs, so
/docs/normal-mode#input-capture-and-latency opens a guide at a section, and a
guide’s #heading links and other-guide.md#heading references resolve.
HelpDocs.allTopics merges built-in and manifest topics in reading order:
HelpDocs.groups names each built-in topic’s section and position, and
plugin topics follow under one group. The snapshot carries group and
manual with each topic; the browser groups the sidebar and index from
them and derives previous/next links, so a new built-in guide only joins
groups (a test rejects one left out). The browser also remembers, in its
own localStorage, a hash of each guide it has shown: a guide whose body
changed since is marked updated and an unknown one new, until opened, and
the guide index lists them with a link to the release notes. A name or alias
may identify only one accepted topic: built-ins take precedence, then the
first plugin topic claiming the name wins. The browser’s navigation and search use
that installed inventory. Links between guides use /docs/<topic>; links to
runtime companions use their page paths, such as /mappings or /state.
Long-form references link to the published manual through
HelpDocs.manual("<page>"), which is docs/ built by mkdocs at
https://aymericbeaumet.github.io/flash/ from main; the manual topic
(:help manual, aliases docs, reference, alternatives) is its table
of contents. Source files that are not manual pages, such as AGENTS.md,
keep absolute repository links pinned to the bundle’s FlashGitCommit.
Built-in prose lives in HelpDocs.swift or beside the feature that owns it
(Config.helpTopic, NormalModeDispatcher.helpTopic,
URLEventHandler.helpTopic, PluginManager.helpTopic). Command and mapping
inventories derive from the effective runtime definitions; do not maintain
parallel hard-coded reference tables. The full engineering contracts stay
in docs/ and are linked from the concise browser guides.
When adding a feature, update its owning topic or add a topic to HelpDocs,
link its live companion when available, and keep routes unique. The help
tests cover core workflow discoverability, alias resolution, plugin collisions,
internal guide links, mapping resolution, browser URL construction and the
server’s page, endpoint and not-found routing.
Every page prints in full: print styles release the app shell’s fixed-height scroll container, drop the navigation, search, filters and connection status, repeat table headers across pages and keep rows whole. The log list prints every filtered record rather than its visible window. Printing the mappings page gives a complete reference of the effective bindings; filter it first to print a subset.
Inspector/ is a Svelte app. Run pnpm check there, then run
Scripts/build-inspector.sh --release from the repository root to update the
committed Sources/flash/Resources/inspector.html. Plain SwiftPM builds serve
that resource; CI checks that it matches the frontend source. A dev install
builds a separate unminified page and stages it into the app at
Contents/Resources/Flash_flash.bundle/inspector.html. The resident reads
that copy. The generated Bundle.module path does not, so leaving the new
page only in .build does not change what the installed app serves.
Check browser routes (direct loads, back/forward, heading anchors), search,
guide links, live/disconnected states, narrow layouts and print preview after
UI changes. Below 1300 px the outline folds into a disclosure above the
article; below 1000 px the guide list becomes a drawer under a toggle; below
700 px the sidebar becomes a scrimmed drawer and the breadcrumb keeps its
last crumb. Nothing is set below 12 px and interactive targets are at least
40 px tall. node --test Inspector/*.test.ts runs the pure tests (search,
reading state, onboarding, mapping search, keyboard). The page must remain self-contained and must render
plugin-authored Markdown as untrusted content.