PluginsPublish & Distribute

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.yaml at the repo root (not in a subdirectory)
  • A README.md that shows one working example per tool and one screenshot per view
  • A CHANGELOG.md — plugin authors are expected to bump metadata.version on breaking changes
  • A LICENSE — MIT / Apache-2.0 are safest for community adoption
  • A selftest.mjs (or equivalent) with node selftest.mjs documented — 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 call

Handler 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.0

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 result

The 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.yaml is at the repo root of your plugin (root of a standalone repo, or root of the subdir for a monorepo entry)
  • A tagged release exists (v1.0.0 or later) for standalone repos — no floating main unless the plugin lives under awesome-bahulam-plugins itself (where main IS 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
  • LICENSE present (MIT / Apache-2.0 preferred)
  • A selftest.mjs or 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’t curl | 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 — including shell. Sanitize any string you inject into the DOM with textContent, not innerHTML.
  • Never bundle credentials in the manifest or handler code. Users will copy your repo verbatim.
  • Honor options.signal on 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.yaml before 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 tag install, not main.
  • 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 / RoutePurpose
~/.bahulam/plugins/<name>/plugin.yamlManifest — the only required file
~/.bahulam/plugins/<name>/mcp.jsonOptional Claude-Desktop-format MCP config (merged with inline mcpServers:)
~/.bahulam/plugins/<name>/tools/*.mjsJS handler modules
~/.bahulam/plugins/<name>/workspace/*.htmlPanel views
~/.bahulam/data/<name>/state.dbThe plugin’s Shared Blackboard (SQLite)
~/.bahulam/plugins/<name>/.bahulam-plugin.jsonInstall 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 | validateManagement commands (moved to top level)
POST /api/tools/executeLocal API for view → tool calls
POST /api/plugin-state/<plugin>Local API for view → Shared Blackboard
GET /api/eventsSSE stream (includes plugin_state_changed events)
GET /api/plugin-viewsLists views discovered in current session
GET /plugin-view/<plugin>/<path>Static file serving for view assets
awesome-bahulam-pluginsCommunity 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.