Writing a Mode Plugin
Status: not built
Mode is declared in core and nothing implements it. The window's modes are native Rust views, and no mode-plugin package exists. This page describes the contract a third-party mode would dispatch on; the plugin-shaped surface that works today is FileType (see Writing a FileType Plugin).
A Mode is, by design, a switchable root for the collapsible nav tree. The built modes (Files, Modules, Sessions, and Hosts) are native Rust views, not Mode subtypes: Mode is declared in core and NOT BUILT. A hotkey swaps which mode's tree fills the navigation pane, and cursor position is preserved per mode across switches. A mode plugin would supply a new such root.
This page documents the mode contract. For the conceptual overview see The Dispatch ABI; for the symbol reference see API — ConceptExplorerCore.
The Mode contract
In the design (NOT BUILT), a mode is a singleton subtype of Mode plus three dispatched methods. The same three-column shape applies to every mode; the methods supply the tree and its previews:
| Method | Returns | Role |
|---|---|---|
tree_root(::Type{M}, project) | TreeNode | the mode's root node for project |
tree_children(::Type{M}, node) | Vector{TreeNode} | children of a node (lazy column fill) |
preview_for(::Type{M}, node) | PreviewPayload | preview for the selected node |
These would mirror the FileType methods (matches / preview / parse_entities) in style: a small set of generic functions, one method per mode. As the ABI page notes, core does not define the generic tree_root / tree_children / preview_for stubs, and no package defines them.
The tree IR
In the design, both mode outputs are opaque-payload structs, so the frontend renders any mode without learning its internals. (What crosses the Rust↔Julia seam today is in the serialization seam.) The two structs:
TreeNode— one node of a column. Fields:id(opaque to Rust),label,kind(aSymbollike:module,:function,:pngfile),has_children,badges(aVector{Symbol}for the cross-cutting color layer, e.g.:stale,:user_edited,:immutable), and a kind-definedpayload::Dict{String,Any}the frontend never inspects. The convenience constructor isTreeNode(id, label, kind; has_children=false, badges=Symbol[], payload=Dict()).PreviewPayload— the rendered preview for a node:mime,databytes, and anextrasdictionary. The frontend dispatches onmimeto pick a renderer, exactly as it does for file previews.
Because the payloads are opaque, a Mode plugin would need no Rust change — the frontend would draw whatever tree the kernel sends and render whatever the preview's MIME names. That is the design; it is not built, since nothing sends a mode's tree from a Mode subtype today.
How a third-party mode would dispatch
The contract is symmetrical with the FileType case. A mode package would:
Depend on
ConceptExplorerCoreandusingit.Declare a singleton subtype:
struct MyMode <: ConceptExplorerCore.Mode end.Implement
tree_rootto build the rootTreeNodefrom the project, settingkind,has_children, and any color-layerbadges.Implement
tree_childrento expand a node into the next column's nodes, reading the parent node'spayloadto know what to enumerate.Implement
preview_forto return aPreviewPayloadfor the selected node, choosing a MIME the frontend renders (see the MIME table in Writing a FileType Plugin).
Loading would follow the same route as FileType plugins, which is a kernel dependency today, not a project setting — see Discovery & Configuration.
The current core modes
For reference, the modes the window has today, each a native Rust view (the ones a hotkey switches between in the running app; the Modules tree is filled from the kernel's project scan):
| Mode | Column 1 → 2 → 3 | Preview |
|---|---|---|
| Files | parent dir → current dir → contents | file at appropriate fidelity |
| Modules (read-only) | modules → definitions (types, functions, macros, submodules) | method source + concept artifact |
| Sessions | host → workspaces | Enter switches to the session |
| Hosts | hosts (a flat list) | Enter moves the Sessions view to the host |
Types, Math, and Outputs modes are designed but not yet built; Agents mode is not built (pinned for later). The Modes page lists the full intended set and what is built.
Why modes aren't packaged yet
Extracting a mode into a standalone package is deferred, not blocked: the contract above is exactly what such a package would implement. Until the generic stubs and a third-party mode example exist, treat this page as the design of the mode seam and use the FileType path for a plugin you can ship today.
See also
The Dispatch ABI — the conceptual contract and the serialization seam.
Writing a FileType Plugin — the fully plugin-shaped surface today.
API — ConceptExplorerCore —
Mode,TreeNode,PreviewPayload.