Plugin API Reference
This document provides a comprehensive reference for @eidos.space/plugin-sdk types, interfaces, and host capabilities.
Install the TypeScript types in your plugin project:
pnpm add -D @eidos.space/plugin-sdkPlugin Manifest (PluginManifest)
Section titled “Plugin Manifest (PluginManifest)”Every plugin declares its metadata, permissions, and extension points in plugin.json (or exports a manifest object from a standalone .ts / .js file).
export interface PluginManifest { apiVersion: 1 id: string name: string version: string icon?: PluginIconDefinition requires?: { pluginApi: string }
// Contribution declarations views?: ViewDeclaration[] actions?: ActionDeclaration[] formatters?: FormatterDeclaration[] placements?: Placement[]
// Background extension entry extension?: string
// Permissions and resource configurations workspace?: { files?: boolean | { read?: boolean; write?: boolean } } settings?: Record<string, SettingDeclaration> storage?: { maxBytes: number } browser?: { workers?: boolean networkOrigins?: string[] } connections?: Record< string, { title: string; url: string; configurable?: boolean } >
// Standalone host theme kind?: "theme" theme?: ThemeDeclaration}Fields
Section titled “Fields”| Field | Type | Description |
|---|---|---|
apiVersion |
1 |
Plugin host API contract version (currently 1). |
id |
string |
Unique identifier (recommended reverse domain notation, e.g. com.example.viewer). |
name |
string |
Human-readable plugin display name. |
version |
string |
Semantic version string (e.g. 0.1.0). |
icon |
PluginIconDefinition |
Plugin brand icon (SVG paths object, relative file path, or Data URL). |
requires.pluginApi |
string |
Minimum host API contract. Current Lite executable plugins require "2.0.0"; pure "1.6.0" themes remain supported. |
extension |
string |
Background module entrypoint (e.g. "./src/extension.ts"). Required if actions or formatters are declared. |
views |
ViewDeclaration[] |
User interface view contributions. |
actions |
ActionDeclaration[] |
Command and shortcut contributions. |
formatters |
FormatterDeclaration[] |
Document formatting provider contributions. |
placements |
Placement[] |
UI entrypoint mappings for views and actions. |
workspace.files |
boolean | { read?: boolean; write?: boolean } |
Permission grant for Space-wide filesystem read/write access. |
settings |
Record<string, SettingDeclaration> |
Declarations for plugin settings rendered in the plugin configuration panel. |
storage.maxBytes |
number |
Private persistent storage quota in bytes (up to 1 GiB). |
browser.networkOrigins |
string[] |
Whitelisted HTTPS origins for anonymous network requests. |
kind / theme |
"theme" / ThemeDeclaration |
Declares a standalone Eidos Lite host theme (contains no executable code). |
Declarations & Placements
Section titled “Declarations & Placements”View Declaration (ViewDeclaration)
Section titled “View Declaration (ViewDeclaration)”export interface ViewDeclaration { id: string title: string entry: string context: "file" | "page" | "table" | "document" | "media" | "eidos" access?: "read" | "write" icon?: PluginIconDefinition configuration?: ViewConfiguration}context: Physical entity target. Standard values are"file"(opened on workspace files) and"page"(standalone panel)."document","media", and"eidos"are supported for compatibility.access: File access level ("read"or"write", defaults to"read").configuration: Used withcontext: "table", declaring view settings schema stored inview.properties.plugin.
Action Declaration (ActionDeclaration)
Section titled “Action Declaration (ActionDeclaration)”export interface ActionDeclaration { id: string title: string context: "workspace" | "file" | "document" | "table" access?: "read" | "write" extensions?: string[] icon?: PluginIconDefinition}context: Target scope."workspace"for global Space commands;"file"for file-targeted context actions.extensions: File extensions filter when the action is targeted at specific formats.
Placements (Placement)
Section titled “Placements (Placement)”export type Placement = | { location: "command-palette"; action: string } | { location: "file/open"; view: string; extensions: string[] } | { location: "navigation"; view: string } | { location: "table/view"; view: string } | { location: "file/context"; action: string } | { location: "table/context"; action: string } | { location: "view/toolbar"; view: string; action: string } | { location: "keybinding"; action: string; key: string; mac?: string; linux?: string } | { location: "plugin/settings"; view: string }| Location | Target | Description |
|---|---|---|
"command-palette" |
Action | Injected into the global Command Palette (Cmd+K / Ctrl+K). |
"file/open" |
View | Injected into file right-click menu Open with, claiming matching extensions. |
"navigation" |
View | Mounted as a primary item in the Space left navigation sidebar. |
"table/view" |
View | Mounted in the table view switcher menu (New View). |
"file/context" |
Action | Injected into the file list right-click context menu. |
"table/context" |
Action | Injected into the table row/selection context menu (supports dynamic providers). |
"view/toolbar" |
Action | Displayed on the top toolbar of a specific view. |
"keybinding" |
Action | Binds a global or scoped keyboard shortcut (e.g. "Mod+Alt+F"). |
"plugin/settings" |
View | Embedded inside the plugin’s configuration detail panel. |
First-Class Primitives (CommonContext)
Section titled “First-Class Primitives (CommonContext)”Both ViewContext and ActionContext inherit the complete set of first-class capabilities via CommonContext:
export interface CommonContext extends Lifetime { readonly fs: PluginFileSystem readonly storage: PluginStorage readonly network: PluginNetwork readonly settings: Settings readonly ui: HostUI}
export interface Lifetime { readonly signal: AbortSignal readonly subscriptions: { add<T extends Disposable>(value: T): T }}Complete Filesystem Operations (ctx.fs)
Section titled “Complete Filesystem Operations (ctx.fs)”Plugins run locally in isolated sandboxes. ctx.fs provides complete local filesystem primitives:
export interface PluginFileSystem { /** Reads the text content of a file (subject to a 2 MiB preview limit). */ readText(path: string): Promise<string>
/** Writes text to a file. Missing parent directories are created automatically. */ writeText(path: string, content: string): Promise<void>
/** Reads binary data from a file (supports up to 16 MiB images, media, models, etc.). */ readBinary(path: string): Promise<Uint8Array>
/** Writes binary data to a file (up to 16 MiB). Missing parent directories are created automatically. */ writeBinary(path: string, content: Uint8Array): Promise<void>
/** Deletes a file within the Space. */ delete(path: string): Promise<void>
/** Renames or moves a regular file within the Space; rejects existing targets with ALREADY_EXISTS. */ rename(oldPath: string, newPath: string): Promise<void>
/** * Lists files in a directory. * If folder is omitted in a file view, defaults to the directory of the opened file. * Optionally filtered by options.extensions. */ list(folder?: string, options?: { extensions?: string[] }): Promise<FileStat[]>
/** Inspects file or directory metadata. Returns null if missing or inaccessible. */ stat(path: string): Promise<FileStat | null>
/** * Returns a privileged native streaming protocol URL (eidos-space-media:). * Supports HTTP Range requests and instantaneous seek. If path is omitted, defaults to the current file. */ getUrl(path?: string): Promise<string>
/** Watches a file or directory for live change events. Disposed automatically on unmount. */ watch(pathOrFolder: string, listener: () => void): Promise<Disposable>}Security and Scoping Rules
Section titled “Security and Scoping Rules”- Companion File Scope: In file views or actions without
workspace.files: true,ctx.fsoperations are strictly confined to the directory of the opened file and companion files (e.g.movie.srtnext tomovie.mp4). - Space-Wide Access: Declaring
workspace.files: truegrants permission to read and write anywhere within the active Space. - Sandbox Isolation: Traversal outside the Space (
..) and access to internal directories (such as.graft) are strictly rejected.
Host User Interface (ctx.ui)
Section titled “Host User Interface (ctx.ui)”export interface HostUI { /** Displays a toast notification in the host interface. */ notify(message: string): Promise<void>
/** Displays a modal selection dialog. */ select(options: { title: string options: Array<{ id: string; label: string }> }): Promise<{ status: "selected"; id: string } | { status: "cancelled" }>
/** Displays a modal confirmation dialog. */ confirm(options: { title: string message: string }): Promise<{ status: "confirmed" | "cancelled" }>
/** Requests the host to open a relative file path in its default or associated editor. */ openFile(relativePath: string): Promise<void>
/** Navigates internally between declared page views of this plugin. */ navigate(viewId: string, route?: string): Promise<void>}Plugin Storage (ctx.storage)
Section titled “Plugin Storage (ctx.storage)”Private binary key-value persistence on the local device, shared across Spaces for the same plugin:
export interface PluginStorage { write(key: string, value: Uint8Array): Promise<void> read(key: string): Promise<Uint8Array | null> list(prefix?: string): Promise<Array<{ key: string; size: number }>> remove(key: string): Promise<void>}Network Requests (ctx.network)
Section titled “Network Requests (ctx.network)”Performs restricted HTTPS requests to whitelisted domains declared in browser.networkOrigins:
export interface PluginNetwork { read(request: { url: string range?: { offset: number; length: number } }): Promise<{ data: Uint8Array; status: number; etag?: string }>}Settings (ctx.settings)
Section titled “Settings (ctx.settings)”Manages plugin settings declared in manifest.settings (persisted per Space):
export interface Settings { get(key: string): Promise<SettingValue> update(key: string, value: SettingValue): Promise<void> reset(key: string): Promise<void> observe( listener: (values: Record<string, SettingValue>) => void, onError?: ObserverErrorHandler ): Promise<{ values: Record<string, SettingValue>; subscription: Disposable }>}Views (ViewContext & mount)
Section titled “Views (ViewContext & mount)”Each view entrypoint exports a default mount function:
import type { ViewContext, Disposable } from "@eidos.space/plugin-sdk"
export default function mount( ctx: ViewContext, root: HTMLElement): void | Disposable | Promise<void | Disposable> { root.textContent = "Hello View" return { dispose() { root.replaceChildren() }, }}ViewContext Structure
Section titled “ViewContext Structure”export interface ViewContext extends CommonContext { readonly binding: ViewBinding
// Available according to the opened file type: readonly file?: FileContext // Available for all file views readonly editor?: TextDocument // Available when viewing text files readonly table?: TableContext // Available when viewing .eidos tables readonly eidos?: EidosFileContext // Available when viewing .eidos files}File Metadata (ctx.file)
Section titled “File Metadata (ctx.file)”Available in any view opened through file/open:
export interface FileContext { readonly path: string // Space-relative path (e.g. "notes/todo.md") readonly name: string // Full filename (e.g. "todo.md") readonly baseName: string // Filename without extension (e.g. "todo") readonly extension: string // Extension (e.g. ".md") readonly size: number // File size in bytes readonly mimeType?: string // Optional media MIME type}Text Editor Operations (ctx.editor)
Section titled “Text Editor Operations (ctx.editor)”When viewing text files, ctx.editor provides working-copy coordination:
export interface TextDocument { read(): Promise<TextSnapshot> observe(listener: (state: TextSnapshot) => void): Promise<{ snapshot: TextSnapshot; subscription: Disposable }> edit(change: { text: string; expectedVersion: string; label?: string }): Promise<{ status: "applied" | "stale"; snapshot: TextSnapshot }> save(): Promise<{ status: "saved" | "conflict"; snapshot: TextSnapshot }> undo(): Promise<TextSnapshot> redo(): Promise<TextSnapshot>}Database Tables and .eidos Context (ctx.table & ctx.eidos)
Section titled “Database Tables and .eidos Context (ctx.table & ctx.eidos)”Available when viewing .eidos SQLite database files or embedded table views:
export interface TableContext { readonly tableId: string readonly viewId: string readonly pluginConfig: TablePluginConfig read(): Promise<TableViewSnapshot> getPage(options: { offset: number; limit: number }): Promise<EidosFileRowPage> aggregate(options: TableAggregateOptions): Promise<TableAggregateResult> updateProperties(properties: Record<string, unknown>): Promise<void> openRecord(rowId: string): Promise<void> observe(listener: () => void): Disposable}
export interface EidosFileContext { listTables(): Promise<Array<{ id: string; name: string }>> readTable(tableId: string): Promise<{ fields: EidosFileFieldInfo[] }> readPluginConfig(tableId: string): Promise<TablePluginConfigSnapshot> writePluginConfig(tableId: string, input: { value: JsonObject | null; expectedVersion: string }): Promise<TablePluginConfigSnapshot>}Actions & Background Extension (activate & ActionContext)
Section titled “Actions & Background Extension (activate & ActionContext)”Plugins with actions or formatters specify an extension entry in plugin.json:
import type { ExtensionContext } from "@eidos.space/plugin-sdk"
export default function activate(ctx: ExtensionContext) { ctx.actions.register("format-markdown", async (actionCtx) => { // actionCtx provides full CommonContext })}ExtensionContext
Section titled “ExtensionContext”export interface ExtensionContext extends Lifetime { readonly actions: { register(id: string, handler: (ctx: ActionContext) => void | Promise<void>): Disposable registerTableProvider(id: string, provider: TableActionProvider): Disposable } readonly formatters: { register(id: string, provider: FormatterProvider): Disposable } readonly settings: Settings}ActionContext
Section titled “ActionContext”export interface ActionContext extends CommonContext { readonly binding: ActionBinding readonly file?: FileContext readonly editor?: TextDocument readonly table?: TableContext}Formatter Provider (FormatterProvider)
Section titled “Formatter Provider (FormatterProvider)”export interface FormatterProvider { format(input: { text: string; path: string; signal: AbortSignal }): { text: string } | Promise<{ text: string }>}Triggered automatically when the user invokes Format Document (Shift+Option+F / Shift+Alt+F).