Publish & Distribute
Bahulam supports two distribution channels — pick whichever suits your
audience. Both hit the same bahulam install code path.
Distribute via Git — the default
The primary distribution channel is a public git repo. Users install with
one command. Advantages: versioning via tags, updates via git pull,
contributions via PRs, no registry to sign up to.
Repo checklist:
plugin.yamlat the repo root (not in a subdirectory)- A
README.mdthat shows one working example per tool and one screenshot per view - A
CHANGELOG.md— plugin authors are expected to bumpmetadata.versionon breaking changes - A
LICENSE— MIT / Apache-2.0 are safest for community adoption - A
selftest.mjs(or equivalent) withnode selftest.mjsdocumented — the quickest way for a user to prove your math/logic before trusting it
Version Your Manifest
metadata.version is displayed in the workspace and used by the registry.
Follow semver:
- Major — breaking changes to tool names, parameters, or return shapes
- Minor — new tools, new views, new agents
- Patch — bug fixes, prompt tweaks, documentation
Test Locally Before Publishing
# Symlink your dev checkout into the search path
ln -s "$(pwd)" ~/.bahulam/plugins/my-plugin
# Launch a workspace against a real project
bahulam plugin my-plugin /path/to/some/project
# Iterate on handler code and reload:
# - Views: refresh the browser (plugin scan has a 5s TTL)
# - Handlers: cache-busted per-call, so edits are picked up on the next callHandler modules are dynamically imported with a timestamp cache-bust, so you can edit a handler mid-session and the next tool call will pick up the new code without restarting the CLI.
Publish via Git
Push the repo, cut a tag, and share the install command:
git tag v1.0.0 && git push --tags
# users install with:
bahulam install https://github.com/your-name/my-plugin --ref v1.0.0List in awesome-bahulam-plugins (recommended)
The community registry lives at
awesome-bahulam-plugins —
a plain, human-editable index of open-source plugins. Once your plugin is
listed there, users can install by short name:
bahulam install my-plugin
bahulam install bahulam:my-plugin # explicit prefix, same resultThe registry itself is a registry.json at the repo root. Adding your plugin
is a small PR with one entry:
{
"plugins": [
{
"name": "my-plugin",
"repository": "https://github.com/your-name/my-plugin",
"ref": "v1.0.0",
"description": "One-line summary shown in listings",
"author": "your-handle",
"tags": ["seo", "content"]
}
]
}You can also host the plugin directly inside awesome-bahulam-plugins as
a subdirectory (like manim-studio, hello-world, hello-mcp do today). The
registry entry then points repository at the community repo itself and adds
a subdir field:
{
"name": "manim-studio",
"repository": "https://github.com/BahulamAI/awesome-bahulam-plugins",
"ref": "main",
"subdir": "plugins/manim-studio",
"description": "Text-to-video via Manim scenes",
"author": "BahulamAI"
}The CLI fetches registry.json, matches name case-insensitively, and does
a shallow git clone of just the subdir when set. There is no server, no
auth, no submission fee — just PR review for quality and security.
PR checklist before submitting:
plugin.yamlis at the repo root of your plugin (root of a standalone repo, or root of thesubdirfor a monorepo entry)- A tagged release exists (
v1.0.0or later) for standalone repos — no floatingmainunless the plugin lives underawesome-bahulam-pluginsitself (wheremainIS the reviewed source) - README shows one working example per tool and a screenshot of any view
- No secrets, no
curl | sh, no credential prompts in handlers LICENSEpresent (MIT / Apache-2.0 preferred)- A
selftest.mjsor equivalent proves the core logic runs offline
Ship Privately
Not everything needs to be public. For internal plugins:
- Keep the repo private; users install with
bahulam install [email protected]:acme/internal-plugin.git(git auth uses their SSH keys) - Or ship as a tarball on an internal artifact server
- Or check the plugin into the project itself under
.bahulam/plugins/and it loads with zero install steps for anyone who clones the project
Security Notes for Authors
- Handlers run with the user’s permissions. Don’t
rm, don’tcurl | sh, don’t reach for credentials the user didn’t hand you. If you need secrets, read them from a well-known env var and document it. - Views are same-origin with the workspace. Any script in your view can
call
/api/tools/execute— includingshell. Sanitize any string you inject into the DOM withtextContent, notinnerHTML. - Never bundle credentials in the manifest or handler code. Users will copy your repo verbatim.
- Honor
options.signalon long-running tools so the CLI can cancel a runaway call. - MCP servers you bundle: if using a stdio server, spawn only trusted binaries. If pointing at a remote MCP, prefer HTTPS and env-var-based auth.
Security Notes for Users
- Read
plugin.yamlbefore installing. It lists every tool the agent will gain, every handler file that will run, and every MCP server that will be spawned. - Prefer plugins with a pinned
git taginstall, notmain. - Plugins can call any built-in tool from their view, including
shell— the workspace token is the whole authorization boundary. Don’t share workspace URLs. - MCP servers declared by a plugin are only spawned when that plugin is active. They don’t pollute your global MCP list.
Reference — Where the Pieces Live
| File / Route | Purpose |
|---|---|
~/.bahulam/plugins/<name>/plugin.yaml | Manifest — the only required file |
~/.bahulam/plugins/<name>/mcp.json | Optional Claude-Desktop-format MCP config (merged with inline mcpServers:) |
~/.bahulam/plugins/<name>/tools/*.mjs | JS handler modules |
~/.bahulam/plugins/<name>/workspace/*.html | Panel views |
~/.bahulam/data/<name>/state.db | The plugin’s Shared Blackboard (SQLite) |
~/.bahulam/plugins/<name>/.bahulam-plugin.json | Install stamp (origin + timestamp) — managed by the CLI |
bahulam plugin <name> [path] | Open a workspace scoped to a plugin |
bahulam install <source> | Install a pack (registry name, git URL, tarball, local dir, bahulam:<name>, or pi:<npm-package> to scaffold) |
bahulam pull pi:<npm-package> | Pull a raw pi ingredient (composable, not directly runnable) |
bahulam list | info | update | enable | disable | remove | validate | Management commands (moved to top level) |
POST /api/tools/execute | Local API for view → tool calls |
POST /api/plugin-state/<plugin> | Local API for view → Shared Blackboard |
GET /api/events | SSE stream (includes plugin_state_changed events) |
GET /api/plugin-views | Lists views discovered in current session |
GET /plugin-view/<plugin>/<path> | Static file serving for view assets |
awesome-bahulam-plugins | Community registry — powers install <name> |
Plugins are the community extension point. The stable contract is the manifest, the handler signature, and the local API surface above — everything else is subject to change as the system grows.