Plugins
A Bahulam plugin is a single directory that bundles tools, agents, and
a workspace view for one use case — installed by dropping a folder into
~/.bahulam/plugins/, invoked from the CLI with bahulam plugin <name>.
Nothing else ships together this way:
| Primitive | What it is | Where it lives |
|---|---|---|
| Tool | One callable function | Backend @tool registry, or a plugin handler |
| Sub-agent | System prompt + tool whitelist | .bahulam/agents/, or inside a plugin |
| Workspace view | HTML panel in the local browser | Plugin only (config.views) |
| Plugin | All three, purpose-built for one domain | ~/.bahulam/plugins/<name>/ |
Plugins run entirely client-side. Handlers execute in your CLI process; the
backend only sees the tool schemas (via the client_tools field on
/api/execute) and never runs plugin code. This is the same trust model as
the shell tool — you consented by installing.
Runtime modes and plugin execution
The plugin contract is the same in all four CLI modes:
| Mode | Who owns planning and delegation? | How plugin tools run |
|---|---|---|
--remote | Hosted backend | Tool call is returned to npm and executed locally |
--bundled | Bundled backend-compatible runtime | Tool call is returned to npm and executed locally |
--local | npm | npm executes the handler, MCP client, or state tool |
--direct | npm | npm executes the handler, MCP client, or state tool |
Remote and bundled runs advertise plugin schemas to the runtime. Local and direct runs give the npm-owned agent loop the same schemas directly. In both cases the handler, MCP process, workspace view, and plugin state remain local; the model does not receive permission to execute plugin code by itself.
The model transport is the only intended difference between the two npm-owned
modes: --local sends model requests to Bahulam Gateway, while --direct
sends them to the configured Anthropic or OpenRouter provider.
Agents, sub-agents, tools, and references
A plugin can contain all four layers:
config/workspace.yamldeclares the workspace or entry agent.config/agents/*.yamlcontains delegated agents. Declare the directory withconfig.agents_from; every YAML file in it is loaded and merged into the plugin agent registry.- Each agent’s
toolslist is an allowlist. The names resolve to the plugin’s handlers, MCP tools, composed tools, or generated state tools. An agent withcan_delegate: truemay invoke another allowed agent through the bounded delegation path; it does not create an unrestricted second agent loop. config/reference/files are ordinary plugin files for prompts, authoring guidance, or domain conventions. They are not automatically injected into model context. An agent must read an available file through a tool such asread_file, or a plugin tool must load it explicitly.
The entry agent and delegated agents are available to the runtime as agent
schemas. A plugin agent can be run explicitly with /run <slug> when enabled,
while autonomous delegation remains subject to the agent allowlist and
workspace policy. See Create a Plugin and Agents
for the complete manifest and delegation examples.
Where to go from here
- Create a Plugin — manifest, tool handlers, workspace views, sub-agents
- Bring your own tools via MCP — Python, Go, Rust, remote services as first-class plugin tools; the Plugin = MCP + UX pattern
- Shared Blackboard — persistent state that the agent and the human both write to, with a live reactive UI
- Install & Manage —
install,list,info,update,enable,disable,remove,validate - Publish & Distribute — git distribution, the
awesome-bahulam-pluginsregistry, private shipping, security notes
Reference plugins
Two plugins ship as copy-paste starters in the community registry:
hello-world— three JS tools, one sub-agent, one workspace view. Covers the Shared Blackboard end-to-end.hello-mcp— one bundled MCP server, one JS state tool, one sub-agent that composes both, a live workspace view. Covers the MCP integration end-to-end.
Everything below reflects what ships in the CLI today. Where a piece of the experience is not yet wired, it is called out explicitly rather than hidden behind future syntax.