Beyoneer Programming Interface

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.

26 API Modules 5 Lifecycle Hooks Sandboxed Zero build step Mobile-first IDB + localStorage Header · Footer · Dialogs

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 Function scope
  • 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

  • _beyoLastSel preserves 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

1

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.

2

Create New Plugin

Click + New Plugin. Give it a name. The editor opens with a starter template.

3

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' });
});
4

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 FormatExampleNotes
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

MethodReturnsDescription
getValue()stringFull editor content
setValue(str)voidReplace entire editor content
getSelectedText()stringCurrently selected text
insertAtCursor(str)voidInsert text at cursor position (mobile-safe)
getCursorLine()number1-based line number of cursor
getActivePath()stringPath of the open file (e.g. 'index.html')
getActiveExt()stringExtension without dot (e.g. 'js')
replaceSelection(str)voidReplace selected text with str
getLineCount()numberTotal line count
focus()voidRe-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

MethodDescription
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

MethodDescription
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

BPI.FS / BeyoFS

Virtual filesystem — read/write project files stored in IndexedDB.

readFile(path)writeFile(path, content)deleteFile(path)listFiles(ext?)readJson(path)writeJson(path, obj)appendFile(path, str)moveFile(from, to)getStats(path)readAll()listByExt(ext)
BeyoFS.writeFile('output.txt', 'hello world');
var src = BeyoFS.readFile('index.html');
var jsFiles = BeyoFS.listByExt('js'); // → ['app.js', 'utils.js']
BPI.Execute / BeyoExecute_

Run JS code, current file, or schedule/benchmark tasks.

run(code)runFile(path)runCurrentFile()runAsync(fn)schedule(fn, ms)benchmark(fn, n)interval(fn, ms)retry(fn, n)debounce(fn, ms)throttle(fn, ms)
BeyoExecute_.benchmark(function() {
  // heavy operation
}, 100); // runs 100x, logs avg time

var search = BeyoExecute_.debounce(myFn, 300);
BPI.Project / BeyoProject_

Manage IDE projects — list, switch, create, duplicate, get stats.

info()list()switchTo(idOrName)create(name)stats()duplicate(id)
var info = BeyoProject_.info();
// → { name, id, files, created, modified }
var s = BeyoProject_.stats();
// → { files: 4, bytes: 12048, lines: 380 }
BPI.Env / BeyoEnv_

In-memory environment variable store for plugins — like .env but in JS.

get(key)set(key, val)has(key)delete(key)toggle(key)all()keys()dump()clear()
BeyoEnv_.set('API_KEY', 'abc123');
BeyoEnv_.get('API_KEY'); // → 'abc123'
BeyoEnv_.toggle('DEBUG'); // true ↔ false
BeyoEnv_.dump(); // logs all vars to console
BPI.Clipboard / BeyoClipboard_

Clipboard read/write — copy editor content, selection, or file.

copy(text)copyEditor()copySelection()pasteToEditor()read()copyFile(path)
BeyoClipboard_.copyEditor();    // copy full file
BeyoClipboard_.copySelection();  // copy selected text
BeyoClipboard_.pasteToEditor();  // paste from clipboard
BPI.Format / BeyoFormat_

Code formatting, case transforms, and text utilities.

formatCurrent()minify()tabsToSpaces()camelToSnake(str)toBase64(str)wordCount(str)toPascalCase(str)toKebabCase(str)htmlEncode(str)truncate(str,n)toTable(arr)stripHtml(str)
BeyoFormat_.formatCurrent();  // Prettier on active file
BeyoFormat_.minify();          // minify in place
BeyoFormat_.camelToSnake('myVar'); // → 'my_var'
BPI.Search / BeyoSearch_

Find, count, and replace in the active file or across the project.

findAll(query, flags?)count(query)replaceAll(query, replacement)findInProject(query)
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' }]
BPI.Diff / BeyoDiff_

Compute diffs between strings, files, or editor vs saved file.

diff(a, b, labelA?, labelB?)diffFiles(pathA, pathB)diffEditorVsFile(path)
BeyoDiff_.diffEditorVsFile('index.html');
// logs +added -removed ~changed to console
BPI.Lint / BeyoLint_

Basic syntax checking and code quality linting.

checkSyntax(code, ext)lintCurrent()lintProject()
BeyoLint_.lintCurrent(); // lint active file → console
BeyoLint_.lintProject();  // scan all project files
var issues = BeyoLint_.checkSyntax('var x = ;', 'js');
BPI.Http / BeyoHttp_

Fetch wrapper with method helpers and asset loader.

get(url, headers?)post(url, body, headers?)put(url, body)patch(url, body)delete(url)loadScript(url)loadCSS(url)getJSON(url)
var data = await BeyoHttp_.getJSON('https://api.github.com/users/octocat');
await BeyoHttp_.loadScript('https://cdn.jsdelivr.net/npm/marked/marked.min.js');
BPI.Git / BeyoGit_

Lightweight Git-style version control for project files (snapshot based).

commit(path, message)log(path)checkout(path, index)diffHead(path)reset(path)status()
BeyoGit_.commit('app.js', 'before refactor');
var log = BeyoGit_.log('app.js'); // → array of snapshots
BeyoGit_.checkout('app.js', 0); // restore latest snapshot
BPI.Task / BeyoTask_

Background task queue — register, run, monitor, and cancel named tasks.

register(name, fn)run(name)isRunning(name)list()unregister(name)
BeyoTask_.register('autoSave', async function() {
  await DB.save();
});
BeyoTask_.run('autoSave');
BeyoTask_.isRunning('autoSave'); // → true | false
BPI.Event / BeyoEvent_

Pub/sub event bus — let plugins communicate with each other.

on(channel, fn)once(channel, fn)off(channel, fn)emit(channel, data)channels()clear(channel)
BeyoEvent_.on('my:event', function(data) {
  Toast_notification_({ message: data.msg, type: 'info' });
});
BeyoEvent_.emit('my:event', { msg: 'Hello from plugin A' });
BPI.Config / BeyoConfig_

Persistent per-plugin configuration store (backed by localStorage).

get(key)set(key, val)read()write(obj)reset()list()
BeyoConfig_.set('myplugin.theme', 'dark');
var theme = BeyoConfig_.get('myplugin.theme');
BPI.Bench / BeyoBench_

Performance benchmarking utilities.

start(label)end(label)run(fn, n?)runAsync(fn, n?)memory()
BeyoBench_.start('parse');
parseCode();
BeyoBench_.end('parse'); // logs ms to console

BeyoBench_.memory(); // logs heap usage
BPI.Snippets / BeyoSnippetLib_

Save, retrieve, and insert code snippets from/into the editor.

save(trigger, code, lang?)get(trigger)insert(trigger)list()search(query)delete(trigger)dump()
// Register a snippet (also: BeyoSnippet_ shorthand)
BeyoSnippet_({ trigger: 'clg', code: 'console.log($1)', lang: 'js' });
BeyoInsertSnippet_('clg'); // insert at cursor
BPI.Notify / BeyoNotify_

Rich notifications — toasts, desktop alerts, haptics, progress.

success(msg, ms?)error(msg, ms?)warn(msg, ms?)info(msg, ms?)confirm(msg, fn)prompt(label, fn)vibrate(pattern)progress(id, pct, msg)desktop(title, body)queue(msgs)
BPI.UI / BeyoUI_

Dynamic UI builder — panels, chips, tooltips, overlays, context menus.

floatingPanel(opts)closePanel(id)statusChip(id, label, color)removeChip(id)tooltip(el, text)contextMenu(items, x, y)badgeCount(el, n)highlight(sel)loadingOverlay(bool)
BPI.KeyMap / BeyoKeyMap_

Custom keyboard shortcut registry separate from BeyoCommand_.

bind(key, fn)unbind(key)list()

★ NEW New in v1.15

BPI.Theme / BeyoTheme_
NEW

Live CSS variable overrides — change colors, fonts, and save named themes.

setVar(key, val)getVar(key)save(name)apply(name)reset()patch(obj)current()list()isDark()defaults()
// 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
BPI.Color / BeyoColor_
NEW

Color math utilities — conversions, mixing, accessibility checks.

hexToRgb(hex)rgbToHex(r,g,b)mix(a,b,t)lighten(hex,pct)darken(hex,pct)luminance(hex)contrast(a,b)isAccessible(fg,bg)toRgba(hex,a)invert(hex)readable(hex)randomHex()
BeyoColor_.contrast('#3b82f6', '#09090b'); // → 7.42
BeyoColor_.readable('#3b82f6'); // → '#ffffff'
BeyoColor_.randomHex(); // → '#a3e4d7'
BPI.Storage / BeyoStorage_
NEW

Unified storage — IndexedDB async, sessionStorage, and localStorage.

setIDB(key, val)getIDB(key)delIDB(key)keysIDB()clearIDB()session.set/get/dellocal.set/get/delexportLocal()importLocal(json)
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.

BPI.Worker / BeyoWorker_
NEW

Web Worker pool manager — run heavy tasks off the main thread.

spawn(id, code)post(id, data)onMessage(id, fn)terminate(id)terminateAll()list()run(fn, data)
// 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' });
});
BPI.Template / BeyoTemplate_
NEW

Code template manager — save, apply, insert, and manage reusable templates.

save(name, code, meta?)get(name)apply(name)insert(name)saveFromEditor(name)list()delete(name)rename(old, new)export()import(json)clear()
BeyoTemplate_.saveFromEditor('MyBoilerplate');
BeyoTemplate_.apply('MyBoilerplate'); // replaces editor
BeyoTemplate_.insert('MyBoilerplate'); // inserts at cursor
BPI.I18n / BeyoI18n_
NEW

Internationalization — register locale strings and translate in-plugin text.

register(lang, dict)t(key)setLang(lang)getLang()available()keys()has(key)dump()
BeyoI18n_.register('hi', { hello: 'नमस्ते', save: 'सहेजें' });
BeyoI18n_.setLang('hi');
BeyoI18n_.t('hello'); // → 'नमस्ते'

Terminal: bpi Commands

Access BPI tools directly from the Beyoneer terminal

$bpi help BPI API v1.15 — Available Modules: (lists all 26 modules)
$bpi env ── BeyoEnv_ vars ── (lists all set variables)
$bpi lint Lint complete — check console
$bpi stats files: 4 bytes: 12048 lines: 380
$bpi exec BeyoColor_.randomHex() → #a3e4d7
$bpi theme current: { primary: '#6366f1', bg: '#09090b', ... }
$bpi color BPI.Color.contrast("#3b82f6","#09090b") → 7.42
$bpi storage BPI.Storage local keys: bpi_myplugin, beyoneer_v5_data ...

Sandbox & Security

How BPI isolates and protects against unsafe plugin code

Isolated Function scope
document.write() blocked
Storage triggers trust dialog
eval() not used — new Function()
Trusted IDs persisted
// ── 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

JSON Validator & Formatter
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' });
});
Auto-Save Every 30s
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);
});
TODO / FIXME Finder
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' });
});
Fetch API Tester (with BeyoPanel_)
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

Auto-Savecore

Saves the active file every 30 seconds if content changed. Zero UI footprint.

Word Count

Updates the browser tab title with live line/word count on file open.

Theme Cycler

Adds a toolbar button + Ctrl+T to cycle through Default, Pro Black, Synthwave, and Forest themes.

Focus Mode

Hides sidebar, header, footer, dock. Ctrl+F11 or double-tap editor to toggle. Dbl-tap exits on mobile.

TODO Finder

Scans the editor for TODO, FIXME, HACK, NOTE, BUG tags and logs them to the console.

File Stats

Logs line and word count to the console each time a file is opened via the onFileOpen hook.

Font Size

Click cycles sizes. Scroll wheel fine-tunes. Long-press opens a size picker. Mobile dock has +/- buttons.

Color Picker

24-color swatch palette + RGB sliders + hex input. Inserts color at cursor. Mobile-safe with line picker.

JSON Tool

Validates and pretty-formats JSON in the active file. Shows key count on success.

Regex Tester

Floating panel with live regex match highlighting. Preloads selected text from editor.

Duplicate Line

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

GoalUse
Add toolbar buttonadd_header(name, fn, { icon, tooltip })
Add footer chipadd_footer(name, fn, { icon, color })
Register keyboard shortcutBeyoCommand_({ name, shortcut, action })
Show toastToast_notification_({ message, type })
Log to consoleBeyoConsole_.log(msg)
Open modalBeyoDialog_({ title, content, actions })
Open floating panelBeyoPanel_({ id, title, html, position })
Read editorBeyoEditor_.getValue()
Write editorBeyoEditor_.setValue(str)
Insert at cursorBeyoEditor_.insertAtCursor(str)
Read project fileBeyoFS.readFile(path)
Write project fileBeyoFS.writeFile(path, content)
HTTP GET JSONawait BeyoHttp_.getJSON(url)
Change theme colorsBeyoTheme_({ primary, bg, font })
Persist data (IDB)await BeyoStorage_.setIDB(key, val)
Cross-plugin eventsBeyoEvent_.on(ch, fn) / .emit(ch, data)
Run in backgroundBeyoWorker_.run(fn, data).then(...)
React to file openOnThe_Function('onFileOpen', fn)
Format codeBeyoFormat_.formatCurrent()
Find in fileBeyoSearch_.findAll(query)