Packaging and distribution
When you build custom tools, channel plugins, or workflow-specific skills on top of Bub, or even want to ship a branded CLI of your own, you can package them as standard Python distributions (wheels) and publish them to PyPI or a private index for your team and users to install.
In Bub, packaging and distribution usually falls into one of three shapes:
| Shape | Deliverable | When to use it |
|---|---|---|
| Capability extension | Plugin entry point + skill namespace | Contribute custom tools, long-running services, or specialized skills to the existing Bub ecosystem |
| Dedicated business CLI | Your own command script (for example my-bub) |
Wrap Bub as an agent for one business scenario, pinning the workspace or baking in default settings |
| All-in-one suite | Own commands + plugins + skills | Deliver a complete vertical-domain agent that works as soon as users install it |
Publish your own command
Section titled “Publish your own command”A distribution can provide its own command name and call Bub’s CLI entry point internally. This lets you give the agent its own brand or fix its default behavior:
# src/my_bub/cli.py
from pathlib import Path
import os
from bub.__main__ import main as bub_main
def main() -> None:
# Optional: pin a default workspace. Bub's workspace defaults to the current
# directory and has no BUB_* environment variable, so change directory before
# calling bub_main(); a user-supplied --workspace still overrides it.
if workspace := os.getenv("MY_BUB_WORKSPACE"):
os.chdir(Path(workspace).expanduser())
# Call Bub's CLI dispatcher; chat, run, gateway, and the other subcommands work unchanged
bub_main()
Register the command in pyproject.toml with [project.scripts]:
[project.scripts]
my-bub = "my_bub.cli:main"
After installation, users can run my-bub chat, my-bub gateway, or my-bub run directly. Bub’s Typer CLI mounts every native subcommand, and standard arguments such as --workspace keep working.
Distribute plugins and skills
Section titled “Distribute plugins and skills”A single wheel can provide plugin entry points, a standard skill namespace package, and custom CLI commands together:
Directorymy-bub/
- pyproject.toml
Directorysrc/
Directorymy_bub/
- __init__.py
- cli.py # Your CLI entry point
- plugin.py # Plugin and hook implementations
- tools.py # Custom tools
Directoryskills/ # Skill namespace package (never add __init__.py)
Directoryrepo-reviewer/
- SKILL.md
Directoryreferences/
- guidelines.md
Configure pyproject.toml
Section titled “Configure pyproject.toml”Set up the entry points and Hatch build includes in pyproject.toml:
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[project]
name = "my-bub"
version = "0.1.0"
description = "My Custom Bub Agent Distribution"
requires-python = ">=3.12"
dependencies = [
"bub[app]>=0.6.0", # Required for the CLI, plugin loading, and the skill runtime
]
[project.scripts]
my-bub = "my_bub.cli:main"
[project.entry-points."bub"]
my_plugin = "my_bub.plugin:plugin"
[tool.hatch.build.targets.wheel]
packages = ["src/my_bub", "src/skills"]
Key settings
Section titled “Key settings”- Dependencies: Always declare
bub[app]. Since 0.6.0 the corebubpackage holds only the lightweight kernel; the CLI, plugin loading, and the skill runtime all come from theappextra, following the package restructuring described in the 0.6 migration notes. Declare third-party libraries your plugins depend on (such ashttpxorpydantic) in the distribution’sdependenciesas well. - Entry point format: The entry point group must be
"bub". See the plugin registration rules for the exact syntax. - Packaging scope: Explicitly include
"src/skills"inpackagesunder[tool.hatch.build.targets.wheel]so skill assets ship in the wheel and install intosite-packages/skills/.
Build and distribute
Section titled “Build and distribute”uv builds a standard wheel and source distribution quickly:
uv build
The artifacts land in dist/ (for example my_bub-0.1.0-py3-none-any.whl). Publish them to PyPI, or distribute them inside your organization through a private index.
For downstream users:
- Install as a global CLI:
uv tool install my-bub. - Install as a managed plugin: to install the package into the separate project or container environment that Bub manages, use
bub install.
Verify before release
Section titled “Verify before release”Before publishing publicly or releasing to production, always verify the package in a fresh virtual environment.
-
Create an isolated environment and install the wheel:
uv venv .test-env && source .test-env/bin/activate uv pip install dist/*.whlAlways install from the built wheel rather than running from the development source directory.
-
Verify plugin and hook loading:
my-bub hooksCheck that the output lists your plugin identifier, confirming the entry point loaded with no deprecation warnings or import errors.
-
Verify skill discovery:
my-bub run ",skill"Confirm that the distributed skill (such as
repo-reviewer) appears in the discovered list, then runmy-bub run ",skill name=repo-reviewer"to check that variable interpolation and body expansion work. -
Verify your command and the interaction path:
my-bub run "Test model and custom tool calls" my-bub chatConfirm model interaction, custom tool execution, internal command dispatch, and session history persistence.
-
Verify the gateway and host integration (if applicable): If the distribution provides channel extensions or is embedded in a host system, follow Deploy and Reuse the Bub app to wire it into the host service, and verify concurrency, stream closure, and shutdown cleanup.