`homeboy build`
Synopsis
homeboy build <component_id>
homeboy build <component_id> --path /path/to/workspace/clone
homeboy build <component_id> --changed-since origin/main
homeboy build --json '<spec>'
homeboy build <project_id> --all --changed-since origin/mainDescription
Runs the component’s local build quality gate by resolving a build command from
the component’s linked extension and executing it in the component’s local_path.
Builds are extension-owned and currently local-only. A component links to one
build-capable extension, and Homeboy asks that extension for the command to run.
Use runner or Lab-backed commands such as test, lint, audit, review,
bench run, fuzz run, and trace for portable offload. One-off shell commands
that do not belong in a reusable extension should live in a rig command step
instead.
Path Override
Use --path to run the build against a different directory than the configured local_path:
homeboy build sample-plugin --path /var/lib/sampleplugin/workspace/sample-pluginThis is useful for:
- AI agent workflows — agents working in workspace clones
- CI/CD — running builds on a fresh checkout
- Multi-branch development — testing different branches without swapping the installed plugin
The override is transient — it does not modify the stored component config.
Build resolution checks component-owned scripts.build first. If absent, it requires exactly one linked extension with build support. Component-level build_command is not supported as configuration; the build_command field in command output is the command Homeboy resolved for this run.
Changed-Scope Builds
Use --changed-since <ref> to ask the build provider whether the changed files require a build:
homeboy build sample-plugin --changed-since origin/main
homeboy build intelligence-example --all --changed-since origin/mainHomeboy core stays language-agnostic. If the linked build provider declares build.changed_scope_script, Homeboy runs that script with HOMEBOY_CHANGED_SINCE set and expects JSON on stdout:
{ "outcome": "no-op", "reason": "changed docs only" }
{ "outcome": "scoped", "reason": "only package-a changed", "build_args": ["package-a"] }
{ "outcome": "full", "reason": "lockfile changed" }Outcomes are:
no-opskips the build and reports success.scopedruns the normal provider build command with provider-suppliedbuild_argsappended.fullruns the normal full build.
If no resolver exists, the resolver fails, or the resolver returns invalid or unknown output, Homeboy conservatively runs the full build and records that fallback in changed_scope.
Useful remediation paths when a component is not buildable:
- Link a build-capable extension:
homeboy component set <id> --extension <extension_id> - Add a component-owned shell build:
"scripts": { "build": ["npm run build"] } - Inspect installed extensions:
homeboy extension list - Use a rig
commandstep for workflows that are environment orchestration rather than component build behavior.
Pre-Build Validation
If a component’s extension defines a pre_build_script in its build configuration, that script runs before the build. If the pre-build script exits with a non-zero code, the build fails.
For WordPress components, this runs PHP syntax validation to catch errors before building.
Example extension configuration:
{
"build": {
"script_names": ["build.sh"],
"extension_script": "scripts/build.sh",
"pre_build_script": "scripts/validate-build.sh"
}
}JSON output
Note: all command output is wrapped in the global JSON envelope described in the JSON output contract. The object below is the
datapayload.
Single
{
"command": "build.run",
"component_id": "<component_id>",
"build_command": "<resolved command string>",
"changed_scope": {
"changed_since": "origin/main",
"outcome": "scoped",
"reason": "only package-a changed",
"provider": "example-extension",
"build_args": ["package-a"]
},
"stdout": "<stdout>",
"stderr": "<stderr>",
"success": true
}Note: all command output is wrapped in the global JSON envelope described in the JSON output contract. The object below is the data payload.
Bulk (--json)
{
"action": "build",
"results": [
{
"id": "<component_id>",
"command": "build.run",
"component_id": "<component_id>",
"build_command": "<extension-resolved command string>",
"stdout": "<stdout>",
"stderr": "<stderr>",
"success": true
}
],
"summary": { "total": 1, "succeeded": 1, "failed": 0 }
}Note: all command output is wrapped in the global JSON envelope described in the JSON output contract. The object below is the data payload.
{ "component_ids": ["component-a", "component-b"] }Exit code
- Single mode: exit code matches the underlying build process exit code.
- Bulk mode (
--json):0if all builds succeed;1if any build fails.