macOS desktop app
The free beta expires on 11 August 2026 at 22:00 UTC. A silent browser security check creates a protected link that expires after five minutes. Report bugs through the in-app feedback button.
Programmable API client
BuildAPlugin is a desktop API client where JavaScript plugins can change the workspace, automate requests, and call app-managed native bridges for Bluetooth, camera, microphone, network, files, clipboard, SMS, phone, Android, and Windows diagnostics.
Download
All four builds are delivered through private, rate-limited CloudFront links. No account, email address, or checkout is required.
The free beta expires on 11 August 2026 at 22:00 UTC. A silent browser security check creates a protected link that expires after five minutes. Report bugs through the in-app feedback button.
Version 1.0.0 for 64-bit Windows. The guided setup installs the complete app, adds Start Menu shortcuts, and includes a standard uninstaller. It is not yet code-signed, so SmartScreen may show a warning.
Version 1.0.0 for 64-bit Debian and Ubuntu systems, packaged as a tested .deb with an application launcher and icon.
Version 1.0.0 for Android 7.0 and newer. This release-compiled beta APK is development-key signed and installed directly, outside the Play Store.
Create requests, save collections, edit headers and bodies, inspect responses, then let plugins add the workflow-specific tools your team normally builds as scripts or internal dashboards.
Build requests with methods, URLs, headers, bodies, variables, saved names, and a response viewer designed for repeated API work.
Bring in Postman-style collections with folders, then export organized workflows back out when teams need portable API assets.
Plugins can store settings, add controls, update the current request, and persist state without changing the Flutter app.
Plugin-first architecture
The app renders a JSON-defined UI. JavaScript plugins can transform that UI, add buttons and panels, run commands, intercept requests, inspect responses, and use a Postman-style pm API.
Native plugin bridges
BuildAPlugin is not limited to HTTP screens. Plugins can request camera and microphone access, record and transcribe voice instructions, test Bluetooth and BLE devices, inspect network interfaces, use OS launchers, work with files, and write native results back into plugin UI.
Use bluetooth.run actions for permission checks, adapter status, scans, connect/disconnect, service discovery, characteristic reads, and writes. A bundled Bluetooth Test plugin shows live availability, scan counts, devices, RSSI, and raw JSON.
Use media actions to request native permissions, render camera preview nodes, start audio recording, stop recording, and store the captured audio result in plugin data.
Use platform.run for system info, locale, paths, network diagnostics, DNS, HTTP probes, clipboard, secure storage, preferences, file picking, file metadata, text file read/write, Android snapshots, and Windows diagnostics.
Open OS handlers for email drafts, SMS drafts, phone dialer screens, portable calendar .ics files, and contact .vcf files. The bridge opens user-controlled drafts; it does not silently send messages or place calls.
Record spoken workflow instructions, transcribe them through the AI bridge, and turn repeatable request interactions into reusable plugin commands. The internal frontend test driver is disabled in public builds.
Developer documentation
BuildAPlugin plugins are CommonJS JavaScript files that can add UI, run commands, mutate the live workspace, inspect app values, chain requests, and pass data between plugins through the plugin bus. Use this as the quick-start reference for building reliable plugins by hand or with the AI builder.
Every plugin exports a `manifest`, optional `transformApp`, command handlers, and optional request/response hooks. Use stable IDs for every UI node so Inspect, Recorder, and other plugins can target your components.
module.exports = {
manifest: {
id: "hello-plugin",
name: "Hello Plugin",
version: "1.0.0",
priority: 100,
permissions: ["ui.transform", "plugin.storage"]
},
transformApp: function(app, api) {
api.ui.remove(app, "helloPluginCard");
api.ui.append(app, "rightPanel", {
type: "card",
id: "helloPluginCard",
children: [
{ type: "text", id: "helloPluginTitle", value: "Hello Plugin" },
{ type: "button", id: "helloPluginRun", text: "Run", command: "helloPlugin.run" }
]
});
return app;
},
commands: {
"helloPlugin.run": function(ctx) {
return { __action: "showMessage", title: "Hello", message: "Plugin ran." };
}
}
};
Use `api.ui.append`, `api.ui.prepend`, `api.ui.insertBefore`, `api.ui.insertAfter`, and `api.ui.remove` to place plugin UI in the workspace. Common targets include `rightPanel`, `mainPanel`, `pluginList`, `requestTopBar`, `headersEditor`, `bodyEditor`, `responseViewer`, `urlInput`, and `sendButton`.
Commands return action objects. Use `multi` when you need several operations in order.
return {
__action: "multi",
actions: [
{ __action: "ui.setValue", targetId: "urlInput", value: "https://api.example.com/users" },
{ __action: "setFields", fields: { "activeRequest.method": "GET" } },
{ __action: "triggerTarget", targetId: "core.request.sendButton" }
]
};
Long-press a visible element in the app and choose Inspect. Copy the exact selector or command body from the inspect panel into your plugin or into the AI builder. Recorder uses the same target model, so recorded workflows can be replayed as plugin commands.
var url = ctx.dollar("#urlInput").val();
ctx.dollar("#requestNameInput").val("Copied from URL");
ctx.dollar("#bodyEditor").val("url=" + url);
return ctx.dollar("#bodyEditor");
Supported selectors are `#id`, `.className`, type names, role names, exact `id` or `targetId`, and exact label text. Prefer Inspect-provided IDs such as `#urlInput`, `#bodyEditor`, `#response.body.line.2`, `#kvTable.Headers.add.key`, and `#core.headers.addButton`.
Use hooks to prepare requests, validate data, store results, or chain follow-up requests. Hooks can return a request, a response, or an action.
module.exports = {
manifest: { id: "response-tools", name: "Response Tools", version: "1.0.0" },
hooks: {
beforeRequest: function(ctx) {
ctx.request.headers["X-From-Plugin"] = "yes";
return ctx.request;
},
afterResponse: function(ctx) {
return {
__action: "multi",
actions: [
{ __action: "setPluginData", key: "responseTools.lastBody", value: ctx.responseBody },
{ __action: "pluginBus.output", name: "response.lastBody", value: ctx.responseBody }
]
};
}
}
};
To send and then show the response, call `core.request.send` with an explicit `afterSendCommand`, then read `ctx.responseBody`, `ctx.response`, or `ctx.payload.response` in that command.
The plugin bus is the shared lane for plugin-to-plugin data. Use it when another plugin, request interpolation, or the inspector should be able to see an output.
commands: {
"authTools.publishToken": function(ctx) {
return {
__action: "multi",
actions: [
{ __action: "pluginBus.output", name: "auth.token", value: "abc123" },
{ __action: "pluginBus.publish", channel: "auth.token.changed", data: { source: "authTools" } }
]
};
},
"authTools.useToken": function(ctx) {
var token = ctx.bus.input("auth.token", "");
return { __action: "setFields", fields: { "activeRequest.headers": { "Authorization": "Bearer " + token } } };
}
}
Private bus names start with `_` or contain `.private.`, `:private:`, or `/private/`. Use clear public names like `auth.token`, `customer.selected`, `response.cleaned`, or `pluginId.outputName`.
The request tabs became dramatically faster by moving the hot path out of plugin storage and full app rebuilds. Normal tab clicks now update request/tab state in RAM, repaint a tiny native tab strip, and avoid JavaScript execution, disk saves, and app-definition rebuilds.
Plugin authors should use this principle too: use full `transformApp` rebuilds for structure, and lightweight runtime mutations for frequent interactions like tab switching, accordions, typing, selection, filters, hover state, and temporary workflow state.
// Good for frequent UI changes:
return { __action: "ui.setValue", targetId: "requestNameInput", value: "Fast update" };
// Good for durable settings:
return { __action: "setPluginData", key: "myPlugin.settings", value: { enabled: true } };
// Avoid this for every click or keystroke:
return { __action: "refresh" };
Rule of thumb: persist what must survive restart; keep temporary UI state in runtime memory; use `ui.*` mutations and `ctx.dollar` for immediate effects; rebuild only when the plugin’s structure actually changes.
These screenshots are from the current desktop app: a request editor, plugin manager, variable tools, live theme controls, modal editors, and upgrade activation flow.
Use the WooCommerce store for Pro access, license activation, and account management. The download page is now the public entry point; shop and account stay available for purchases and activation.