Developers
aibutler is open source (Apache-2.0); the code is on GitHub. The architecture and memory engine design are covered in detail in the repo's README.
Building from source
Needs Node.js 20, 22, or 24 — 22 is recommended (the repo ships an .nvmrc). Node 26 isn't supported yet.
git clone https://github.com/fantasyxxj/aibutler.git
cd aibutler
npm install
npm run build:agent-sdk # build the bundled inference layer
npm start # start in dev modeTo package:
npm run dist:mac # → release/*.dmg (native architecture)
npm run dist:mac:intel # → release/*-x64-intel.dmg
npm run dist:win # → release/*.exeWriting plugins
A plugin is a JSON bundle: its own interface (html / css / js), command declarations, and local state. The minimal example is the built-in counter that ships with the app: core/config/plugins/counter.json.
- Where it lives:
packages.local/in the data directory, one.jsonfile per plugin — drop it in and it hot-installs immediately; plugins you write yourself don't need a signature. - Two shapes: a single-screen widget (
ui), or a multi-step guided flow (workflow). - Sandbox: the interface runs in a sandbox with no
require/fetch/eval/localStorage— only abutlerUIobject (onInit·onPush·call·setState·resize). - Primitives: commands can only touch a fixed set of primitives:
speaksave_filestatemessagedbmailai_accesswebsecretrecordpronassetbus. - Network access: use the
webprimitive, with anetdomain allowlist declared at the top level of the package; store secrets with thesecretprimitive, which keeps them in the local vault. - Working with the persona: buttons can send structured results back to the persona; commands marked as AI-usable can be called by the persona directly.
Fixed-height interfaces
For things like canvas-based games where the height is fixed from the start, call butlerUI.resize(document.body.scrollHeight + 16) once in onInit, then again a couple more times shortly after, to make sure the window expands properly.
Local API: waking a persona
With the local API turned on in the Personas window, aibutler listens only on 127.0.0.1 (port 8787 by default). Scripts, cron jobs, or monitoring alerts can wake a given persona with a single POST:
curl -X POST http://127.0.0.1:8787/v1/poke \
-H 'Content-Type: application/json' \
-d '{"persona": "Researcher", "text": "The CI nightly build failed, please look into why", "from": "ci-bot"}'| Field | Required | Description |
|---|---|---|
persona | Yes | Name of the persona to wake |
text | Yes | The message to hand it |
from | No | A source tag |
idempotency_key | No | Repeated delivery with the same key only takes effect once |
The Butler engine (agent-sdk)
agent-sdk/ is the bundled, multi-model agent engine. Its exported query() / tool() / createSdkMcpServer() share the same names and signatures as the Claude Agent SDK. The chain of search engines for web search lives in agent-sdk/src/tools/search-engines.ts; adding a new search engine just means registering a function there and adding an entry to TYPES in core/search-keys.js.
