`homeboy deploy`
Synopsis
homeboy deploy <project_id> [<component_ids...>] [-c|--component <id>]... [--all] [--outdated] [--check] [--dry-run] [--json '<spec>']
# If no component IDs are provided, you must use --all, --outdated, or --check.
# Multi-project deployment
homeboy deploy --projects <project1>,<project2> <component_ids...>
# Fleet deployment
homeboy deploy <component_id> --fleet <fleet_id>
# Shared component deployment (auto-detect projects)
homeboy deploy <component_id> --sharedArguments and flags
project_id: project ID<component_ids...>(optional): component IDs to deploy (positional, trailing)
Options:
-c,--component: component ID to deploy (can be repeated, alternative to positional)--all: deploy all configured components--outdated: deploy only outdated components- Determined from the first version target for each component.
--check: check component status without building or deploying- Shows all components for the project with version comparison status.
- Combines with
--outdatedor component IDs to filter results.
--dry-run: preview what would be deployed without executing (no build, no upload)--json: JSON input spec for bulk operations ({"component_ids": ["component-id", ...]})--projects: deploy to multiple projects (comma-separated). When using this flag, all positional arguments are treated as component IDs. The build artifact is reused across projects.-f,--fleet: deploy to all projects in a fleet. Resolves fleet to project IDs, then runs multi-project deployment.-s,--shared: deploy to all projects using the specified component(s). Auto-detects which projects have the component configured and deploys to all of them.
Bulk JSON input uses component_ids (snake_case):
{ "component_ids": ["component-a", "component-b"] }Positional and flag component IDs can be mixed; both are merged into the deployment list.
If no component IDs are provided and neither --all nor --outdated is set, Homeboy returns an error. If --outdated finds no outdated components, Homeboy returns an error.
JSON output
Note: all command output is wrapped in the global JSON envelope described in the JSON output contract. The object below is
data.
{
"command": "deploy.run",
"project_id": "<project_id>",
"all": false,
"outdated": false,
"check": false,
"dry_run": false,
"results": [
{
"id": "<component_id>",
"name": "<name>",
"status": "deployed|failed|skipped|planned|checked",
"deploy_reason": "explicitly_selected|all_selected|version_mismatch|unknown_local_version|unknown_remote_version",
"component_status": "up_to_date|needs_update|behind_remote|unknown",
"local_version": "<v>|null",
"remote_version": "<v>|null",
"error": "<string>|null",
"artifact_path": "<path>|null",
"remote_path": "<path>|null",
"build_command": "<cmd>|null",
"build_exit_code": "<int>|null",
"deploy_exit_code": "<int>|null",
"release_state": {
"commits_since_version": 5,
"has_uncommitted_changes": false,
"baseline_ref": "v0.9.15"
}
}
],
"summary": { "succeeded": 0, "failed": 0, "skipped": 0 }
}Note: all command output is wrapped in the global JSON envelope described in the JSON output contract. The object below is data.
- Determined from the first version target for each component.
Note: all command output is wrapped in the global JSON envelope described in the JSON output contract. The object below is data.
Component status values
Notes:
- Shows all components for the project with version comparison status.
- Combines with
--outdatedor component IDs to filter results.
Release state
Note: build_exit_code/deploy_exit_code are numbers when present (not strings).
- Determined from the first version target for each component.
When using --check, each component result includes a component_status field:
When using --check, each component result includes a release_state field that tracks unreleased changes:
Exit code
- Shows all components for the project with version comparison status.
- Combines with
--outdatedor component IDs to filter results.
Multi-Project Deployment
This helps identify components where component_status is up_to_date but work has been done since the last version bump (commits_since_version > 0), indicating a version bump may be needed before deployment.
# Deploy data-machine to both extra-chill and sarai-chinwag projects
homeboy deploy --projects extra-chill,sarai-chinwag data-machine
# Deploy multiple components to multiple projects
homeboy deploy --projects extra-chill,sarai-chinwag data-machine extrachill-api
# Preview multi-project deployment
homeboy deploy --projects extra-chill,sarai-chinwag data-machine --dry-runExit code is 0 when summary.failed == 0, otherwise 1.
Multi-project JSON output
When a component belongs to multiple projects, use --projects to deploy to all of them in a single command:
{
"command": "deploy.run_multi",
"component_ids": ["data-machine"],
"dry_run": false,
"check": false,
"force": false,
"projects": [
{
"project_id": "extra-chill",
"status": "deployed|failed",
"error": "<string>|null",
"results": [...],
"summary": { "total": 1, "succeeded": 1, "skipped": 0, "failed": 0 }
},
{
"project_id": "sarai-chinwag",
"status": "deployed|failed",
"error": "<string>|null",
"results": [...],
"summary": { "total": 1, "succeeded": 1, "skipped": 0, "failed": 0 }
}
],
"summary": { "total_projects": 2, "succeeded": 2, "failed": 0 }
}The component is built once and the artifact is reused for all subsequent project deployments.
Fleet Deployment
When using --projects, the output structure differs:
# Deploy my-plugin to all projects in the production fleet
homeboy deploy my-plugin --fleet production
# Preview fleet deployment
homeboy deploy my-plugin --fleet production --dry-run
# Check status across fleet before deploying
homeboy fleet check productionExit code is 1 if any project deployment fails.
Fleet vs Shared: When to Use Which
Deploy to all projects in a named fleet:
deploy_reasonis omitted when not applicable.component_statusis only present when using--checkor--check --dry-run.artifact_pathis the component build artifact path as configured; it may be relative but must include a filename.
See fleet for fleet management commands.
--fleet and --shared often produce the same result, especially in smaller setups where a fleet’s projects are exactly the set of projects that use a given component. The difference is in how they resolve targets:
Shared Component Deployment
Rule of thumb: Use --shared for "update this component everywhere." Use --fleet for "update this fleet specifically."
# Deploy my-plugin to every project that uses it
homeboy deploy my-plugin --shared
# See which projects would be affected
homeboy component shared my-plugin
# Preview shared deployment
homeboy deploy my-plugin --shared --dry-runIn practice, if your fleet membership mirrors your component usage, they’re interchangeable — but as your fleet grows (staging vs production, multi-site networks), the distinction becomes meaningful.
Preview Before Deploying
Deploy to all projects using a component, auto-detected:
homeboy deploy myproject --outdated --dry-runCheck Component Status
This is useful when you don’t have a named fleet but want to update a component everywhere it’s used.
# Check all components for a project
homeboy deploy myproject --check
# Check only outdated components
homeboy deploy myproject --check --outdated
# Check specific components
homeboy deploy myproject --check component-a component-bUse --dry-run to see what would be deployed without executing:
# Show changes for all project components
homeboy changes --project myproject
# Show changes with git diffs included
homeboy changes --project myproject --git-diffsPost-Deploy Hooks
Use --check to view version status for all components without building or deploying:
To see detailed git changes (commits, diffs) before deploying, use the changes command:
| Variable | Description |
|---|---|
{{component_id}} | The component ID |
{{install_dir}} | Remote install directory |
{{base_path}} | Project base path on the remote server |
Extension-level hooks
After a successful deploy, Homeboy runs post:deploy hooks remotely via SSH on the deployment target. Hooks are resolved from extensions and components (see hooks).
{
"hooks": {
"post:deploy": [
"wp plugin is-installed {{component_id}} --path={{base_path}} --allow-root 2>/dev/null && wp plugin activate {{component_id}} --path={{base_path}} --allow-root 2>/dev/null || true",
"wp cache flush --path={{base_path}} --allow-root 2>/dev/null || true"
]
}
}Component-level hooks
Template variables available:
{
"hooks": {
"post:deploy": ["systemctl restart my-service"]
}
}Extensions like WordPress define post:deploy hooks in their manifest. These run for every component using that extension:
Related
up_to_date: local and remote versions matchneeds_update: local version ahead of remote (needs deployment)behind_remote: remote version ahead of local (local is behind)unknown: cannot determine status (missing version information)