Plugin Development Guide
Eidos Lite plugins can provide custom editors and viewers for files, add independent pages to the sidebar navigation, or register shortcuts in the Command Palette. Plugins have access to local filesystem APIs (ctx.fs), isolated storage, network access, and host interaction interfaces.
Quickstart: Create Your First Plugin
Section titled “Quickstart: Create Your First Plugin”1. Prerequisites
Section titled “1. Prerequisites”Ensure you have Node.js 22.12 or newer and a package manager (npm, pnpm, or yarn) installed. Also download Eidos Lite to run and debug plugins locally.
2. Initialize a Project
Section titled “2. Initialize a Project”Scaffold a new plugin using the official tooling:
npx @eidos.space/plugin-tools create my-plugincd my-pluginnpm install # or pnpm installThe generated project structure is as follows:
my-plugin/├── plugin.json # Manifest declaring plugin metadata, views, and entry points├── package.json # Project dependencies and npm scripts├── tsconfig.json # Strict TypeScript configuration└── src/ ├── main.tsx # View mount entry point └── style.css # StylesheetThe scaffolding configures the official toolchain in package.json:
@eidos.space/plugin-sdk: Complete TypeScript specification and types for Plugin 1.0.npm run check: Performs static syntax, type, and manifest verification (eidos-plugin check .).npm run pack:plugin: Packages a self-contained offline distribution archive (.eidos-plugin).
3. Load and Debug Live in Eidos Lite
Section titled “3. Load and Debug Live in Eidos Lite”You do not need a build step before debugging. Eidos Lite features an on-the-fly compiler that compiles and reloads code in real time:
- Launch Eidos Lite and enter any Space.
- In the top toolbar, click the Plugins icon (located between the Search box and Space menu).
- Click Load development source… and select your project’s
plugin.json. - Review the declared permissions and enable the plugin for the current Space.
- In the Space file tree, right-click a matching file and choose Open with → Your Plugin View.
Whenever you edit and save files under src/ in your code editor, Eidos Lite will automatically recompile and hot-reload the view!
Core Capabilities Walkthrough
Section titled “Core Capabilities Walkthrough”1. Custom File Views (context: "file")
Section titled “1. Custom File Views (context: "file")”File views take over the presentation and editing of any file format (text, media, custom binary files, or .eidos SQLite database packages).
Declare the view in plugin.json:
{ "apiVersion": 1, "id": "example.file-viewer", "name": "Custom File Viewer", "version": "0.1.0", "views": [ { "id": "viewer", "title": "Custom Viewer", "entry": "./src/main.tsx", "context": "file", "access": "write" } ], "placements": [ { "location": "file/open", "view": "viewer", "extensions": [".json", ".dat", ".mp4"] } ]}Mount a React interface in src/main.tsx:
import type { ViewContext } from "@eidos.space/plugin-sdk"import React, { useEffect, useState } from "react"import { createRoot } from "react-dom/client"import "./style.css"
function App({ ctx }: { ctx: ViewContext }) { const [content, setContent] = useState<string>("") const file = ctx.file!
useEffect(() => { // Read current file text or binary using ctx.fs ctx.fs.readText(file.path).then(setContent).catch(console.error) }, [file.path])
const handleSave = async () => { await ctx.fs.writeText(file.path, content) await ctx.ui.notify("File saved successfully!") }
return ( <div className="viewer-container"> <header className="header"> <h3>{file.name} ({file.size} bytes)</h3> <button onClick={handleSave}>Save</button> </header> <textarea value={content} onChange={(e) => setContent(e.target.value)} /> </div> )}
export default function mount(ctx: ViewContext, root: HTMLElement) { const reactRoot = createRoot(root) reactRoot.render(<App ctx={ctx} />)
return { dispose() { reactRoot.unmount() }, }}2. Filesystem Operations & Companion Files (ctx.fs)
Section titled “2. Filesystem Operations & Companion Files (ctx.fs)”ctx.fs provides complete local filesystem operations to plugins. In file views, it supports reading/writing binary data, companion file discovery, and streaming media playback.
① Binary I/O & Large Files
Section titled “① Binary I/O & Large Files”ctx.fs.readBinary(path) and ctx.fs.writeBinary(path, data) support binary payloads up to 16 MiB, allowing direct handling of images, audio/video chunks, and custom binary formats:
// Read binary dataconst bytes = await ctx.fs.readBinary("assets/logo.png")
// Write binary dataconst payload = new Uint8Array([0x89, 0x50, 0x4e, 0x47])await ctx.fs.writeBinary("data/output.bin", payload)② Companion Media Detection & Streaming Playback
Section titled “② Companion Media Detection & Streaming Playback”For media files and subtitles, use ctx.fs.getUrl() and ctx.fs.list():
// 1. Get high-performance streaming URL with range request support (206 Partial Content)const streamUrl = await ctx.fs.getUrl("movie.mp4")
// 2. Discover companion subtitle files in the same directoryconst companions = await ctx.fs.list(undefined, { extensions: [".srt", ".vtt"] })
// 3. Read companion subtitle textif (companions.length > 0) { const srtText = await ctx.fs.readText(companions[0].path)}③ Real-Time File Watching (watch)
Section titled “③ Real-Time File Watching (watch)”const watcher = await ctx.fs.watch("data", () => { console.log("Directory changed; reloading data")})
// Automatically unsubscribe when the view unmountsctx.subscriptions.add(watcher)3. Commands and Shortcuts (actions)
Section titled “3. Commands and Shortcuts (actions)”Execute background operations via the Command Palette (Cmd+K) or keyboard shortcuts.
Declare the action in plugin.json:
{ "extension": "./src/extension.ts", "actions": [ { "id": "stat-workspace", "title": "Summarize Space Files", "context": "workspace" } ], "placements": [ { "location": "command-palette", "action": "stat-workspace" }, { "location": "keybinding", "action": "stat-workspace", "key": "Mod+Alt+S" } ]}Implement the action in src/extension.ts:
import type { ExtensionContext } from "@eidos.space/plugin-sdk"
export default function activate(ctx: ExtensionContext) { ctx.actions.register("stat-workspace", async ({ fs, ui }) => { const files = await fs.list() await ui.notify(`The root directory contains ${files.length} files.`) })}4. Independent Feature Pages (context: "page")
Section titled “4. Independent Feature Pages (context: "page")”Build dedicated dashboards or tool panels anchored in the Space navigation sidebar.
Declare the page in plugin.json:
{ "workspace": { "files": true }, "views": [ { "id": "dashboard", "title": "Journal Dashboard", "context": "page", "entry": "./src/dashboard.tsx" } ], "placements": [ { "location": "navigation", "view": "dashboard" } ]}Once mounted, the page appears in the Space sidebar navigation. When workspace: { "files": true } is declared, the page can use ctx.fs to index or create files across the entire Space (e.g. automatically creating daily journal entries).
5. Verification and Packaging for Distribution
Section titled “5. Verification and Packaging for Distribution”Run static type and manifest checks from the project root:
npm run checkBundle the plugin into an offline .eidos-plugin archive:
npm run pack:pluginThe resulting file is located at dist/<plugin-id>-<version>.eidos-plugin. Users can double-click it or drag and drop it directly into the Eidos Lite Plugin Manager to install.