-
Notifications
You must be signed in to change notification settings - Fork 15
Developer Guide Plugin System
github-actions[bot] edited this page Jun 1, 2026
·
1 revision
YourSSH supports two types of plugins that coexist at runtime.
Compiled into the app binary. Registered in app/lib/plugins/plugin_registry.dart (kRegisteredPlugins).
- Add the package to
app/pubspec.yamldependencies anddependency_overrides(if local). - Import and instantiate in
plugin_registry.dart.
abstract class YourSSHPlugin {
Widget buildUI(BuildContext context, YourSSHPluginContext ctx);
Future<void> onActivate(YourSSHPluginContext ctx);
Future<void> onDeactivate();
int get minApiVersion;
}YourSSHPluginContext exposes:
-
activeSessions— list of active SSH session IDs -
execCommand(sessionId, cmd)— run a command on a session -
savePreference(key, value)/getPreference(key)— namespaced storage
| Package | Features |
|---|---|
yourssh_devops |
Containers, Network Tools, Cloudflare Tunnel, MCP Server, Mail Catcher, S3 Browser |
yourssh_web_tools |
In-app HTTP browser over port-forwarded connection |
yourssh_snippets |
Command snippet library |
Loaded at runtime from ~/.yourssh/plugins/. No app rebuild required.
App (Dart/Flutter)
└── PluginLoader — scans ~/.yourssh/plugins/, hot-reloads on file change
└── QuickJsRuntime (FFI) — isolated JS context per plugin
├── JsRuntimeRegistrar — registers bridge APIs
├── HookBus — typed event routing
└── PermissionGuard — enforces manifest permissions
| Hook type | Behavior |
|---|---|
transform |
Handler can modify the data (e.g., rewrite terminal output) |
intercept |
Handler can block the event entirely |
observe |
Side-effect only; cannot modify data |
| Event | Fires when |
|---|---|
terminal.output |
Data arrives from the SSH server |
terminal.input |
User types in the terminal |
session.connect |
Session is fully established |
session.disconnect |
Session closes |
| Bridge | Available calls |
|---|---|
ssh |
ssh.exec(sessionId, cmd), ssh.write(sessionId, data)
|
sftp |
sftp.list(sessionId, path), sftp.readFile, sftp.writeFile
|
storage |
storage.get(key), storage.set(key, value), storage.delete(key)
|
ui |
ui.showNotification(msg), ui.register(id, spec)
|
PluginErrorTracker counts consecutive errors per plugin. If the threshold is exceeded, the plugin is automatically disabled. The user sees the error in the Plugin Console.
- Plugin Authoring — write your first JS plugin
- Architecture — where plugin loading fits in the app