`homeboy runner`
Synopsis
homeboy runner <COMMAND>runner manages durable execution backends. SSH runners are a capability on a homeboy server record, so the common Lab flow uses one ID for the machine and its runner. Local runners remain standalone because they describe this machine rather than an SSH server.
Subcommands
add
homeboy runner add <id> --workspace-root <path>
homeboy runner add <server-id> --server <server-id> --workspace-root <path>
homeboy runner add --json <spec>Options:
--kind local|ssh: explicit runner kind. Defaults tosshwhen--serveris set, otherwiselocal.--server <server-id>: existinghomeboy serverrecord for SSH runners. For SSH runners,<id>must match<server-id>.--workspace-root <path>: workspace root on the runner machine.--homeboy-path <path>: Homeboy binary path on the runner machine.--daemon: marks the runner as daemon-preferred for future commands.--concurrency-limit <n>: maximum concurrent workflows this runner should accept.--artifact-policy <label>: artifact policy label reserved for future execution commands.
enable
homeboy runner enable <server-id> --workspace-root <path>
homeboy runner enable <server-id> --workspace-root <path> --concurrency-limit 4 --artifact-policy copyEnables runner capability on an existing SSH server. This is the recommended Homeboy Lab onboarding path:
homeboy server create homeboy-lab --host 192.168.86.63 --user chubes --port 22
homeboy runner enable homeboy-lab --workspace-root /home/chubes/Developer --concurrency-limit 4 --artifact-policy copy
homeboy runner connect homeboy-labAfter this, homeboy-lab is both the server ID and the runner ID.
list
homeboy runner listshow
homeboy runner show <id>set
homeboy runner set <id> --json <JSON>
homeboy runner set <id> workspace_root=/srv/homeboy
homeboy runner set <id> -- --concurrency_limit 4Updates a runner by merging a JSON object into the runner config. SSH runner settings live under servers/<id>.json as the server’s runner capability; local runners live under runners/<id>.json.
remove
homeboy runner remove <id>exec
homeboy runner exec <runner-id> -- <command...>
homeboy runner exec <runner-id> --cwd /runner/workspace/project -- <command...>
homeboy runner exec <runner-id> --ssh --cwd /runner/workspace/project -- <command...>exec submits the command to the connected runner daemon when homeboy runner connect <runner-id> has established a live loopback tunnel. If no daemon session is connected, local runners execute directly and SSH runners require explicit --ssh.
Path rules:
- SSH runners require
workspace_rootso local paths are not silently reused remotely. - SSH
--cwdmust be an absolute path under the configuredworkspace_root. - Omitting
--cwdon an SSH runner uses the runnerworkspace_root. --sshis an MVP/diagnostic fallback; daemon execution is preferred because it records job metadata and supports artifact-oriented workflows.
workspace sync
homeboy runner workspace sync <runner-id> --path <local-worktree>
homeboy runner workspace sync <runner-id> --path <local-worktree> --mode snapshot
homeboy runner workspace sync <runner-id> --path <local-worktree> --mode gitworkspace sync materializes a laptop worktree under the runner’s configured workspace_root so Lab execution can run against an explicit remote path while Git operations and canonical edits stay local.
Modes:
snapshotcopies the current local tree, including dirty edits, through a tar stream.gitrequires a clean local tree, then clones or refreshesremote.origin.urlon the runner and checks out localHEADdetached.
Safety rules:
- The remote path is deterministic and lives under
<workspace_root>/_lab_workspaces/. - Snapshot sync excludes dependency directories, build outputs, caches,
.git, and common secret file patterns such as.env*,*.pem, and*.key. - Output includes
local_path,remote_path,sync_mode,snapshot_identity, and snapshotfiles/byteswhen available. - The runner workspace is execution-only; this command does not push branches, commit, or make the runner authoritative for source changes.
workspace apply
homeboy runner workspace apply <lab-apply.json>
homeboy runner workspace apply <lab-apply.json> --forceworkspace apply brings a Lab-generated fix artifact back to the local source worktree recorded in the artifact’s source_snapshot.local_path. It is local-only: it does not commit, push, or make the Lab runner canonical. Reviewability stays in normal local Git via git status and git diff.
Safety rules:
- The artifact must identify the local source worktree through
source_snapshot.local_path. - Homeboy recalculates the current local
source_snapshot.snapshot_hashbefore applying. - If the local source worktree drifted since the Lab snapshot, apply is refused unless
--forceis explicit. - Unified diffs are checked with
git apply --checkbefore mutation, so conflicts do not partially apply. - Delta paths must be relative and stay inside the source worktree.
- Output includes
apply_status,modified_files,expected_snapshot_hash, andcurrent_snapshot_hash.
Temporary Wave 4 adapter contract, until the Lab fix-capture contract settles:
{
"source_snapshot": {
"runner_id": "lab-a",
"local_path": "/Users/chubes/Developer/project@branch",
"remote_path": "/srv/homeboy/_lab_workspaces/project-abc123",
"git_sha": "...",
"dirty": false,
"sync_mode": "snapshot",
"snapshot_hash": "sha256:...",
"synced_at": "2026-05-16T00:00:00Z",
"sync_excludes": [".git/", "node_modules/"]
},
"patch": {
"format": "unified_diff",
"content": "diff --git a/file.txt b/file.txtn..."
}
}Delta form is also accepted for explicit file replacement/deletion:
{
"source_snapshot": { "...": "..." },
"delta": {
"files": [
{ "path": "src/file.txt", "content_base64": "Li4u" },
{ "path": "obsolete.txt", "delete": true }
]
}
}Runner Shape
SSH runner records are stored on their server as runner capability config under ~/.config/homeboy/servers/<id>.json.
{
"id": "homeboy-lab",
"host": "192.168.86.63",
"user": "chubes",
"port": 22,
"runner": {
"workspace_root": "/home/chubes/Developer",
"homeboy_path": "/usr/local/bin/homeboy",
"daemon": false,
"concurrency_limit": 4,
"artifact_policy": "copy",
"env": {},
"resources": {}
}
}Standalone local runner records are still stored under ~/.config/homeboy/runners/.
{
"id": "lab-local",
"kind": "local",
"server_id": null,
"workspace_root": "/Users/chubes/Developer",
"homeboy_path": "/usr/local/bin/homeboy",
"daemon": false,
"concurrency_limit": 2,
"artifact_policy": "copy",
"env": {},
"resources": {}
}Rules:
kindislocalorssh.sshrunner IDs are server IDs; a single SSH machine does not need a separate runner ID.concurrency_limit, when set, must be greater than zero.envandresourcesare metadata maps for futureconnect,doctor,exec, and Desktop workflows.
JSON Output
All command output is wrapped in the global JSON envelope described in the JSON output contract. The data payload uses the generic entity CRUD shape:
command: action identifier such asrunner.add,runner.list,runner.show,runner.set,runner.remove,runner.exec,runner.workspace.sync, orrunner.workspace.applyid: present for single-runner actionsentity: runner configuration for single-runner read/write actionsentities: list forlistupdated_fields: list of updated field names for writesdeleted: list of removed runner IDs