The BPI Plugin System
BPI is Beyoneer IDE's native extension layer — a full JavaScript API that lets you attach code, UI, commands, hooks, and automation directly into the IDE at runtime. No build step. No config file. Just a function call and your plugin is live.
Why Plugins?
What makes BPI worth using over raw script injection
Native Integration
- Buttons appear directly in the IDE header toolbar
- Footer chips live beside the editor at all times
- Keyboard shortcuts registered with one line
- Hooks fire at real IDE lifecycle events
Safe by Default
- Sandboxed via isolated
Functionscope document.write()is blocked- Storage access prompts user confirmation
- Trusted plugin IDs stored in
localStorage
Full IDE Access
- Read/write any project file via
BeyoFS - Get/set editor content, cursor, selection
- Run code, diffs, lints, HTTP requests
- Listen to and emit on the IDE event bus
Mobile-First Design
_beyoLastSelpreserves cursor on blur- Mobile dock injection via
mobileDock - Line picker for touch-safe insert position
- Long-press, vibration, touch gesture APIs
Quick Start
Your first plugin in 4 lines
Open Plugin Manager
Click the Plugins button in the IDE header, or press the plugin icon in the toolbar. The modal shows built-in and custom plugins.
Create New Plugin
Click + New Plugin. Give it a name. The editor opens with a starter template.
Write Your Code
// Minimal plugin — adds a toolbar button OnThe_Function('afterBoot', function() { add_header('Hello', function() { Toast_notification_({ message: 'Hello from BPI!', type: 'success' }); }, { icon: 'ri-hand-heart-line', tooltip: 'My first plugin' }); });
Save & Toggle Active
Save the plugin, then flip its toggle to Active. Your button appears in the toolbar immediately.
Plugin Structure
Every plugin is vanilla JavaScript — no imports, no bundler
// ── PLUGIN ANATOMY ───────────────────────────────────────────── // // 1. Wrap everything in a lifecycle hook // 2. Use BPI globals — no import needed, all pre-exposed // 3. Register UI, commands, snippets, event listeners here // OnThe_Function('afterBoot', function() { // ── UI ────────────────────────────────────────────────────── add_header('MyPlugin', function() { /* click handler */ }, { icon: 'ri-plug-line', // RemixIcon class tooltip: 'My Plugin', // hover tooltip color: '#6366f1' // optional icon tint }); // ── COMMAND ───────────────────────────────────────────────── BeyoCommand_({ name: 'My Action', shortcut: 'ctrl+shift+m', icon: 'ri-plug-line', action: function() { /* run action */ } }); // ── STORAGE (triggers trust dialog on first run) ───────────── var data = localStorage.getItem('myplugin_key'); // ── NOTIFICATIONS ─────────────────────────────────────────── BeyoConsole_.log('Plugin loaded!'); });
All BPI globals (BeyoFS, BeyoEditor_, BeyoHttp_, etc.) are available in plugin scope — they are pre-exposed on window before plugins execute.
Lifecycle Hooks
Register callbacks that fire at key IDE moments
OnThe_Function('hookName', function(...args) { // your code });
| Hook Name | When it fires | Arguments |
|---|---|---|
'afterBoot' |
After all plugins are loaded and the editor is fully ready. Primary entry point. | none |
'onFileOpen' |
Each time a file is opened or switched in the editor | path, content |
'beforeSave' |
Just before a project save is committed to IndexedDB | activeId, projectObj |
// onFileOpen example — show file stats on every open OnThe_Function('onFileOpen', function(path, content) { var lines = (content || '').split('\n').length; BeyoConsole_.log('📄 ' + path + ' — ' + lines + ' lines'); }); // You can register multiple callbacks for the same hook OnThe_Function('afterBoot', function() { /* plugin A */ }); OnThe_Function('afterBoot', function() { /* plugin B */ });
Re-entrancy guard: afterBoot has a re-entrancy guard — calling DB.save() or triggerHook() from within a hook callback will not re-fire the same hook recursively.
UI Injection
Inject buttons, chips, and panels directly into the IDE chrome
add_header( ) — Toolbar Button
add_header(name, fn, opts) // Parameters: // name string Label / dedup key (unique per plugin) // fn function Click handler, receives button element // opts object { icon, tooltip, color, w, h, t } add_header('Minify', function() { BeyoFormat_.minify(); Toast_notification_({ message: 'Minified!', type: 'success' }); }, { icon: 'ri-compress-line', tooltip: 'Minify current file', color: '#f472b6' });
Dedup: If you call add_header with the same name twice (e.g., hot-reload), the old button is removed first. No duplicate buttons.
add_footer( ) — Footer Chip
add_footer(name, fn, opts) // opts: { icon, color, tooltip, id } // Chips appear in the plugin footer bar below the editor add_footer('Stats', function() { var s = BeyoProject_.stats(); Toast_notification_({ message: s.files + ' files, ' + s.bytes + ' bytes', type: 'info' }); }, { icon: 'ri-bar-chart-line', color: '#22d3ee', tooltip: 'Project Stats' }); // Alternative: BeyoFooterChip_ (full config object) BeyoFooterChip_({ id: 'my-chip', name: 'Stats', icon: 'ri-bar-chart-line', action: fn });
Mobile Dock Injection
// Add buttons to the mobile bottom dock var dock = document.getElementById('mobileDock'); if (dock) { var btn = document.createElement('button'); btn.setAttribute('data-plugin-dock', '1'); // mark as plugin button btn.innerHTML = '<i class="ri-magic-line"></i>'; btn.onclick = myAction; dock.appendChild(btn); }
Commands & Keyboard Shortcuts
Register named actions with keyboard shortcuts
BeyoCommand_({ name: 'string', // displayed in command list shortcut: 'string', // 'ctrl+shift+x', 'alt+f', 'ctrl+F11' icon: 'string', // RemixIcon class (optional) action: function() {} // called when shortcut fires });
| Shortcut Format | Example | Notes |
|---|---|---|
ctrl+key | 'ctrl+d' | Works desktop & mobile keyboard |
ctrl+shift+key | 'ctrl+shift+f' | Three-modifier combos |
alt+key | 'alt+p' | Alt combos |
ctrl+F11 | 'ctrl+F11' | Function keys supported |
// Register a shortcut + toolbar button together OnThe_Function('afterBoot', function() { function dupLine() { var state = editorView.state; var line = state.doc.lineAt(state.selection.main.head); editorView.dispatch({ changes: { from: line.to, insert: '\n' + line.text } }); } BeyoCommand_({ name: 'Duplicate Line', shortcut: 'ctrl+d', action: dupLine }); add_header('DupLine', dupLine, { icon: 'ri-file-copy-line' }); });
Shortcut strings must be lowercase (except function keys). 'ctrl+D' will not match — use 'ctrl+d'.
BeyoKeyMap_ — Advanced Key Binding
BeyoKeyMap_.bind('ctrl+alt+t', function() { /* action */ }); BeyoKeyMap_.unbind('ctrl+alt+t'); BeyoKeyMap_.list(); // → array of { key, fn } objects
Editor Access — BeyoEditor_
Read and manipulate the active CodeMirror editor
| Method | Returns | Description |
|---|---|---|
getValue() | string | Full editor content |
setValue(str) | void | Replace entire editor content |
getSelectedText() | string | Currently selected text |
insertAtCursor(str) | void | Insert text at cursor position (mobile-safe) |
getCursorLine() | number | 1-based line number of cursor |
getActivePath() | string | Path of the open file (e.g. 'index.html') |
getActiveExt() | string | Extension without dot (e.g. 'js') |
replaceSelection(str) | void | Replace selected text with str |
getLineCount() | number | Total line count |
focus() | void | Re-focus the editor |
// Common pattern: read → transform → write var code = BeyoEditor_.getValue(); var upper = code.toUpperCase(); BeyoEditor_.setValue(upper); // Mobile-safe insert — reads window._beyoLastSel internally BeyoEditor_.insertAtCursor('// inserted by plugin\n');
Mobile note: On mobile, tapping a plugin button blurs the editor. Use window._beyoLastSel (the cursor position saved on blur) instead of reading editorView.state.selection.main after a tap — it will be stale. BeyoEditor_.insertAtCursor() handles this automatically.
Direct editorView Access
For advanced CodeMirror 6 operations, access the view directly:
// window.editorView is the live CodeMirror EditorView var state = editorView.state; var pos = state.selection.main.head; var line = state.doc.lineAt(pos); editorView.dispatch({ changes: { from: line.from, to: line.to, insert: 'replacement' }, selection: { anchor: line.from + 11 } });
Notifications & Console
Toast alerts, console output, and rich notify system
Toast_notification_( ) — Quick Toast
Toast_notification_({ message: 'Done!', type: 'success' }); Toast_notification_({ message: 'Oops', type: 'error', duration: 5000 }); // type: 'success' | 'error' | 'warn' | 'info'
BeyoConsole_ — IDE Console Output
BeyoConsole_.log('Plugin loaded'); BeyoConsole_.warn('Missing dependency'); BeyoConsole_.error('Something failed'); BeyoConsole_.dim('Verbose debug info');
BeyoNotify_ — Rich Notification System
| Method | Description |
|---|---|
BeyoNotify_.success(msg, ms) | ✅ green toast, default 3000ms |
BeyoNotify_.error(msg, ms) | ❌ red toast, default 4000ms |
BeyoNotify_.warn(msg, ms) | ⚠️ yellow toast |
BeyoNotify_.info(msg, ms) | ℹ️ blue toast, default 2500ms |
BeyoNotify_.vibrate(pattern) | Haptic feedback array e.g. [50, 30, 50] |
BeyoNotify_.desktop(title, body) | Browser Notification API (requires permission) |
BeyoNotify_.progress(id, pct, msg) | Progress indicator toast |
BeyoNotify_.queue([msgs]) | Show messages sequentially with delay |
BeyoLogger_ — Structured Logging
BeyoLogger_.info('Plugin start'); BeyoLogger_.debug('detail', { key: 'val' }); BeyoLogger_.groupStart('Batch Op'); BeyoLogger_.groupAdd('Step 1 done'); BeyoLogger_.groupEnd(); BeyoLogger_.table([{ file: 'a.js', size: 1200 }]); BeyoLogger_.query('error'); // search logs BeyoLogger_.export(); // download as JSON BeyoLogger_.summary(); // count by level
Dialogs & Floating Panels
Native IDE modal dialogs and draggable panels
BeyoDialog_( ) — Modal Dialog
BeyoDialog_({ title: 'My Dialog', icon: 'ri-question-line', content: '<p>HTML content here</p>', actions: [ { label: 'Cancel', action: 'Dlg.close()' }, { label: 'Confirm', primary: true, action: 'window.myHandler()' } ] }); // Close programmatically: Dlg.close();
Action strings in the actions array are evaluated — use window.myFn() pattern. Set handlers on window before calling BeyoDialog_.
BeyoPanel_( ) — Draggable Floating Panel
BeyoPanel_({ id: 'my-panel', // unique — toggle on/off title: 'My Tool', icon: 'ri-tools-line', position: 'bottom-right', // 'bottom-right' | 'bottom-left' | 'top-right' width: 360, height: 280, html: '<div>Panel content</div>' }); // Calling BeyoPanel_ with same id again toggles it off
BeyoUI_ — Dynamic UI Builder
| Method | Description |
|---|---|
floatingPanel(opts) | Create a floating panel (lower-level than BeyoPanel_) |
closePanel(id) | Close panel by id |
statusChip(id, label, color) | Add a status indicator chip |
removeChip(id) | Remove a status chip |
tooltip(el, text) | Attach tooltip to any element |
contextMenu(items, x, y) | Show a context menu at coordinates |
badgeCount(el, n) | Add a numeric badge to an element |
highlight(selector) | Temporarily highlight an element |
loadingOverlay(show) | Show/hide a global loading overlay |
Mobile Helpers — BeyoMobile_
Touch-safe APIs for mobile-first plugin development
// Check cursor position (saved on editor blur — mobile-safe) var pos = window._beyoLastSel; // { head, anchor } | null // Show a line picker so users can choose where to insert BeyoMobile_.showLinePicker({ title: 'Insert After Line', multi: false, onSelect: function(lineNum) { // insert after chosen line } }); // Select a range of lines BeyoMobile_.selectLines(3, 7); // Change editor font size BeyoMobile_.fontScale(16); // Open/close sidebar BeyoMobile_.openSidebar(); BeyoMobile_.closeSidebar();
Pattern for mobile insert: Always check window._beyoLastSel first. If null, call BeyoMobile_.showLinePicker() to prompt the user. If set, use it as the insert position and call editorView.focus() after dispatch.
All 26 BPI Modules
Click any module to expand its methods
Virtual filesystem — read/write project files stored in IndexedDB.
BeyoFS.writeFile('output.txt', 'hello world'); var src = BeyoFS.readFile('index.html'); var jsFiles = BeyoFS.listByExt('js'); // → ['app.js', 'utils.js']
Run JS code, current file, or schedule/benchmark tasks.
BeyoExecute_.benchmark(function() { // heavy operation }, 100); // runs 100x, logs avg time var search = BeyoExecute_.debounce(myFn, 300);
Manage IDE projects — list, switch, create, duplicate, get stats.
var info = BeyoProject_.info(); // → { name, id, files, created, modified } var s = BeyoProject_.stats(); // → { files: 4, bytes: 12048, lines: 380 }
In-memory environment variable store for plugins — like .env but in JS.
BeyoEnv_.set('API_KEY', 'abc123'); BeyoEnv_.get('API_KEY'); // → 'abc123' BeyoEnv_.toggle('DEBUG'); // true ↔ false BeyoEnv_.dump(); // logs all vars to console
Clipboard read/write — copy editor content, selection, or file.
BeyoClipboard_.copyEditor(); // copy full file BeyoClipboard_.copySelection(); // copy selected text BeyoClipboard_.pasteToEditor(); // paste from clipboard
Code formatting, case transforms, and text utilities.
BeyoFormat_.formatCurrent(); // Prettier on active file BeyoFormat_.minify(); // minify in place BeyoFormat_.camelToSnake('myVar'); // → 'my_var'
Find, count, and replace in the active file or across the project.
var hits = BeyoSearch_.findAll('console.log'); // → [{ line: 4, text: ' console.log(x)' }, ...] BeyoSearch_.replaceAll('var ', 'let '); var proj = BeyoSearch_.findInProject('TODO'); // → [{ file: 'app.js', line: 7, text: '// TODO: fix' }]
Compute diffs between strings, files, or editor vs saved file.
BeyoDiff_.diffEditorVsFile('index.html'); // logs +added -removed ~changed to console
Basic syntax checking and code quality linting.
BeyoLint_.lintCurrent(); // lint active file → console BeyoLint_.lintProject(); // scan all project files var issues = BeyoLint_.checkSyntax('var x = ;', 'js');
Fetch wrapper with method helpers and asset loader.
var data = await BeyoHttp_.getJSON('https://api.github.com/users/octocat'); await BeyoHttp_.loadScript('https://cdn.jsdelivr.net/npm/marked/marked.min.js');
Lightweight Git-style version control for project files (snapshot based).
BeyoGit_.commit('app.js', 'before refactor'); var log = BeyoGit_.log('app.js'); // → array of snapshots BeyoGit_.checkout('app.js', 0); // restore latest snapshot
Background task queue — register, run, monitor, and cancel named tasks.
BeyoTask_.register('autoSave', async function() { await DB.save(); }); BeyoTask_.run('autoSave'); BeyoTask_.isRunning('autoSave'); // → true | false
Pub/sub event bus — let plugins communicate with each other.
BeyoEvent_.on('my:event', function(data) { Toast_notification_({ message: data.msg, type: 'info' }); }); BeyoEvent_.emit('my:event', { msg: 'Hello from plugin A' });
Persistent per-plugin configuration store (backed by localStorage).
BeyoConfig_.set('myplugin.theme', 'dark'); var theme = BeyoConfig_.get('myplugin.theme');
Performance benchmarking utilities.
BeyoBench_.start('parse'); parseCode(); BeyoBench_.end('parse'); // logs ms to console BeyoBench_.memory(); // logs heap usage
Save, retrieve, and insert code snippets from/into the editor.
// Register a snippet (also: BeyoSnippet_ shorthand) BeyoSnippet_({ trigger: 'clg', code: 'console.log($1)', lang: 'js' }); BeyoInsertSnippet_('clg'); // insert at cursor
Rich notifications — toasts, desktop alerts, haptics, progress.
Dynamic UI builder — panels, chips, tooltips, overlays, context menus.
Custom keyboard shortcut registry separate from BeyoCommand_.
★ NEW New in v1.15
Live CSS variable overrides — change colors, fonts, and save named themes.
// Quick theme patch (shim available at boot) BeyoTheme_({ primary: '#e879f9', bg: '#0d0221', font: 15 }); // Full API BeyoTheme_.setVar('--primary', '#6366f1'); BeyoTheme_.save('MyTheme'); BeyoTheme_.isDark(); // → true
Color math utilities — conversions, mixing, accessibility checks.
BeyoColor_.contrast('#3b82f6', '#09090b'); // → 7.42 BeyoColor_.readable('#3b82f6'); // → '#ffffff' BeyoColor_.randomHex(); // → '#a3e4d7'
Unified storage — IndexedDB async, sessionStorage, and localStorage.
await BeyoStorage_.setIDB('myplugin_prefs', { theme: 'dark' }); var prefs = await BeyoStorage_.getIDB('myplugin_prefs'); BeyoStorage_.local.set('flag', '1'); BeyoStorage_.session.set('temp', 'abc');
Using BeyoStorage_ or raw localStorage / sessionStorage / indexedDB triggers the storage trust dialog for untrusted plugins.
Web Worker pool manager — run heavy tasks off the main thread.
// run(fn, data) — quick one-shot worker BeyoWorker_.run(function(data) { return data.reduce(function(a, b) { return a + b; }, 0); }, [1,2,3,4,5]).then(function(result) { Toast_notification_({ message: 'Sum: ' + result, type: 'info' }); });
Code template manager — save, apply, insert, and manage reusable templates.
BeyoTemplate_.saveFromEditor('MyBoilerplate'); BeyoTemplate_.apply('MyBoilerplate'); // replaces editor BeyoTemplate_.insert('MyBoilerplate'); // inserts at cursor
Internationalization — register locale strings and translate in-plugin text.
BeyoI18n_.register('hi', { hello: 'नमस्ते', save: 'सहेजें' }); BeyoI18n_.setLang('hi'); BeyoI18n_.t('hello'); // → 'नमस्ते'
Terminal: bpi Commands
Access BPI tools directly from the Beyoneer terminal
Sandbox & Security
How BPI isolates and protects against unsafe plugin code
// ── HOW SANDBOX WORKS (simplified) ───────────────────────────── const safeDocWrite = () => { /* blocked */ }; (new Function('BPI', 'document', pluginCode))( window.BPI || {}, // BPI API injected { ...document, write: safeDocWrite } // document.write() shadowed );
Storage Trust Dialog
If a custom (non-built-in) plugin's code contains any of these strings, a one-time trust dialog appears before activation:
localStorage
sessionStorage
indexedDB
BeyoStorage_
IDBKeyRange
openDatabase
Once a user clicks Trust & Activate, the plugin's ID is stored in beyoneer_trusted_plugins_v1 — they won't be prompted again. Built-in plugins bypass this dialog entirely.
Full Plugin Examples
Copy-paste ready — activate in Plugin Manager
OnThe_Function('afterBoot', function() { add_header('JSON', function() { var code = BeyoEditor_.getValue(); if (!code.trim()) { Toast_notification_({ message: 'Editor is empty', type: 'warn' }); return; } try { var obj = JSON.parse(code); BeyoEditor_.setValue(JSON.stringify(obj, null, 2)); Toast_notification_({ message: '✓ Valid JSON — formatted!', type: 'success' }); } catch(e) { Toast_notification_({ message: 'Invalid JSON: ' + e.message, type: 'error' }); BeyoConsole_.error('JSON Error: ' + e.message); } }, { icon: 'ri-braces-line', color: '#fbbf24', tooltip: 'Validate & format JSON' }); });
OnThe_Function('afterBoot', function() { var _last = ''; setInterval(function() { if (!Session.activeFile || !window.editorView) return; var content = editorView.state.doc.toString(); if (content === _last) return; // no change, skip _last = content; var proj = DB.projects[DB.activeId]; if (proj?.files?.[Session.activeFile]) { proj.files[Session.activeFile].content = content; DB.save(); } }, 30000); });
OnThe_Function('afterBoot', function() { add_header('TODOs', function() { var code = BeyoEditor_.getValue(); var lines = code.split('\n'); var tags = ['TODO', 'FIXME', 'HACK', 'BUG', 'NOTE']; var found = []; lines.forEach(function(l, i) { tags.forEach(function(t) { if (l.toUpperCase().indexOf(t) !== -1) found.push({ line: i + 1, text: l.trim() }); }); }); if (!found.length) { Toast_notification_({ message: 'No TODOs found 🎉', type: 'success' }); return; } UI.openConsole(); found.forEach(function(f) { UI.appendConsole('warn', 'L' + f.line + ': ' + f.text); }); Toast_notification_({ message: found.length + ' TODO(s)', type: 'warn' }); }, { icon: 'ri-checkbox-indeterminate-line', tooltip: 'Find TODO/FIXME/BUG tags' }); });
OnThe_Function('afterBoot', function() { add_header('Fetch', function() { BeyoPanel_({ id: 'fetch-tester', title: 'Fetch Tester', icon: 'ri-send-plane-line', position: 'bottom-right', width: 400, height: 260, html: '<input id="ftUrl" placeholder="https://..." style="width:100%;padding:7px;background:var(--bg-dark);border:1px solid var(--border);border-radius:6px;color:var(--text-main);margin-bottom:8px">' + '<button onclick="window.__ftRun()" style="width:100%;padding:8px;background:var(--primary);border:none;border-radius:6px;color:#fff;cursor:pointer">Send GET</button>' + '<pre id="ftOut" style="margin-top:8px;padding:8px;background:var(--bg-dark);border-radius:6px;font-size:0.75rem;overflow:auto;max-height:100px">…</pre>' }); window.__ftRun = async function() { var url = document.getElementById('ftUrl')?.value; var out = document.getElementById('ftOut'); if (!url || !out) return; try { var data = await BeyoHttp_.getJSON(url); out.textContent = JSON.stringify(data, null, 2).slice(0, 500); } catch(e) { out.textContent = 'Error: ' + e.message; } }; }, { icon: 'ri-send-plane-line', tooltip: 'API Fetch Tester' }); });
Built-in Plugins
Shipped with Beyoneer IDE — enable/disable in Plugin Manager
Saves the active file every 30 seconds if content changed. Zero UI footprint.
Updates the browser tab title with live line/word count on file open.
Adds a toolbar button + Ctrl+T to cycle through Default, Pro Black, Synthwave, and Forest themes.
Hides sidebar, header, footer, dock. Ctrl+F11 or double-tap editor to toggle. Dbl-tap exits on mobile.
Scans the editor for TODO, FIXME, HACK, NOTE, BUG tags and logs them to the console.
Logs line and word count to the console each time a file is opened via the onFileOpen hook.
Click cycles sizes. Scroll wheel fine-tunes. Long-press opens a size picker. Mobile dock has +/- buttons.
24-color swatch palette + RGB sliders + hex input. Inserts color at cursor. Mobile-safe with line picker.
Validates and pretty-formats JSON in the active file. Shows key count on success.
Floating panel with live regex match highlighting. Preloads selected text from editor.
Duplicates current line. Registered as Ctrl+D and toolbar button. Mobile line-picker fallback.
Tips & Best Practices
Write better plugins faster
Always wrap in OnThe_Function('afterBoot', ...). Code at the top level runs during plugin parsing before the IDE is ready. DOM elements like mobileDock and editorView won't exist yet.
Unique names for add_header. The name param is the dedup key. Two plugins using 'Stats' as name will fight — use a namespaced name like 'MyPlugin:Stats'.
Don't use eval() — it won't help and is blocked in strict sandboxes. Use BeyoExecute_.run(code) for dynamic execution.
For any insert on mobile: use BeyoEditor_.insertAtCursor() — not editorView.dispatch() directly. It reads window._beyoLastSel automatically. If the cursor has never been set, fall back to BeyoMobile_.showLinePicker().
Use setTimeout(() => ..., 60) inside BeyoDialog_ callbacks to query injected DOM elements — the dialog HTML is inserted asynchronously.
Persist plugin state with BeyoConfig_ for simple key/value, or BeyoStorage_.setIDB() for large structured data. Avoid raw localStorage unless necessary — it triggers a trust dialog and pollutes the global namespace.
Hot-reload is safe. When you re-save and re-activate a plugin, afterBoot fires again but add_header deduplicates buttons by name. Still — avoid setInterval without cleanup, or you'll spawn multiple intervals on reload.
Quick Reference Card
| Goal | Use |
|---|---|
| Add toolbar button | add_header(name, fn, { icon, tooltip }) |
| Add footer chip | add_footer(name, fn, { icon, color }) |
| Register keyboard shortcut | BeyoCommand_({ name, shortcut, action }) |
| Show toast | Toast_notification_({ message, type }) |
| Log to console | BeyoConsole_.log(msg) |
| Open modal | BeyoDialog_({ title, content, actions }) |
| Open floating panel | BeyoPanel_({ id, title, html, position }) |
| Read editor | BeyoEditor_.getValue() |
| Write editor | BeyoEditor_.setValue(str) |
| Insert at cursor | BeyoEditor_.insertAtCursor(str) |
| Read project file | BeyoFS.readFile(path) |
| Write project file | BeyoFS.writeFile(path, content) |
| HTTP GET JSON | await BeyoHttp_.getJSON(url) |
| Change theme colors | BeyoTheme_({ primary, bg, font }) |
| Persist data (IDB) | await BeyoStorage_.setIDB(key, val) |
| Cross-plugin events | BeyoEvent_.on(ch, fn) / .emit(ch, data) |
| Run in background | BeyoWorker_.run(fn, data).then(...) |
| React to file open | OnThe_Function('onFileOpen', fn) |
| Format code | BeyoFormat_.formatCurrent() |
| Find in file | BeyoSearch_.findAll(query) |