@myndra/plugin-sdk
v0.1.0
Published
SDK for building Myndra plugins
Readme
@myndra/plugin-sdk
SDK for building Myndra plugins.
Installation
npm install @myndra/plugin-sdkUsage
import type { MyndraPluginModule, PluginContext } from '@myndra/plugin-sdk'
const plugin: MyndraPluginModule = {
activate(ctx: PluginContext) {
// Register commands
ctx.commands.register({
id: 'my-plugin.hello',
label: 'Say Hello',
run: () => {
ctx.ui.notify('Hello from my plugin!')
},
})
// Listen to events
ctx.events.on('node:selected', ({ nodeKey }) => {
console.log('Selected:', nodeKey)
})
// Access graph
const nodes = ctx.graph.selection.getSelectedNodes()
console.log('Currently selected:', nodes)
},
deactivate() {
// Cleanup
},
}
export default pluginAPI Reference
PluginContext
The context object passed to your plugin's activate function.
graph- Graph operations façadecommands- Command registryevents- Event bus for subscribing to app eventsui- UI utilities (notifications, modals)views- View registration for UI slotsSchemas- Zod schemas and inferred types for Myndlet/Myndlink nodes
GraphAPI
Safe façade for graph operations, organized into explicit mutation lanes so plugin authors know which changes survive a restart.
Mutation Lanes
| Lane | Namespace | Persisted Where | Survives Restart |
| ----------- | --------------------- | ----------------------------------------------------- | ------------------------- |
| Durable | ctx.graph.durable.* | myndspace.json (workspace graph) | Yes |
| Derived | ctx.graph.derived.* | Global graph, but rebuilt on load | No — adapters re-derive |
| Session | ctx.graph.session.* | sessions.json if restoreWithSession: true, else RAM | Only with flag + same tab |
Read Methods (lane-agnostic, on ctx.graph)
getNode(key)- Get node data (checks global graph, then session)getNodeAttribute(key, attribute)- Get a specific attribute (global graph)getFilePosition(key)- Get file position for a nodegetNodeEdges(nodeKey)- Get all edges connected to a nodehasNode(key)- Check if a node existsgetChildren(nodeKey)- Get child node keys via hierarchy edgesgetParent(nodeKey)- Get hierarchy parentfindNodes(predicate)- Find nodes matching a predicatebatch(fn, options?)- Execute multiple changes atomically with optional layout
Durable Mutations (ctx.graph.durable)
Changes persisted to the workspace graph (myndspace.json):
addNode(attributes)- Add a new nodeaddDomNode(input)- Add a DOM-backed node with defaultsupdateNode(key, patch)- Update node attributesremoveNode(key)- Remove a nodeaddReferenceLink(source, target, attributes?)- Add a reference edgeaddHierarchyLink(source, target, attributes?)- Add a hierarchy edge (replaces existing parent)removeLink(edgeKey)- Remove an edge
Derived Mutations (ctx.graph.derived)
Metadata rebuilt on load from source files:
addTreeSitterNode(treeSitterNode, attributes)- Add a node from a tree-sitter syntax nodesetFilePosition(key, position)- Set file position for a nodesyncFilePositions(positions)- Batch-update file positions after re-parse
Selection (ctx.graph.selection)
getSelectedNodes()- Get selected node keyssetSelectedNodes(keys)- Set selected nodesgetHoveredNode()- Get the hovered node key
SessionGraphAPI
Session-only injection via ctx.graph.session. Session data never modifies
the durable workspace graph (myndspace.json).
inject(payload)- Inject session-only nodes/edges into a session graph- Set
restoreWithSession: trueto save the layer to sessions.json for tab restore - Default: volatile, cleared on restart
- Set
clear(sessionId?)- Clear previously injected session-only data
Which API to use?
- Adding user-authored structural data? →
ctx.graph.durable.* - Tracking file positions or tree-sitter nodes? →
ctx.graph.derived.* - Injecting transient render nodes (previews, overlays)? →
ctx.graph.session.inject() - Reading data regardless of origin? →
ctx.graph.getNode(), etc.
EventBus
Subscribe to application events:
on(event, handler)- Subscribe to an eventoff(event, handler)- Unsubscribe from an event
Events:
graph:loadedgraph:mountedgraph:unmountednode:selectednode:creatednode:deletednode:expandednode:collapsednode:preview-requestednode:children-loadingnode:children-loadednode:children-load-errorsession:filters-changedsession:depth-changedfile:openedfile:closedfile:changedgraph:plugin-scopecontextmenu:opencommand:invokedfilesystem:before-syncfilesystem:after-syncmyndspace:opened
Schemas
The SDK re-exports the app's Zod schemas and inferred types so plugins can validate payloads without duplicating shapes. Import from the Schemas namespace or from the @myndra/plugin-sdk/schemas subpath:
import { Schemas } from '@myndra/plugin-sdk'
// or: import { MyndletAttributesSchema } from '@myndra/plugin-sdk/schemas'
const validNode = Schemas.MyndletAttributesSchema.parse({ label: 'Hello', kind: 'note' })License
MIT
