# `homeboy git`
## Synopsis
```sh
homeboy git <COMMAND>
```
Output is always JSON-wrapped (see [JSON output contract](../architecture/output-system.md)).
Note: some subcommands accept a `--json` flag for bulk operations.
## Subcommands
### Single Component Mode
- `status <component_id>`
- `commit <component_id> [message-or-spec] [--json <spec>] [-m <message>] [--staged-only] [--files <paths>...] [--include <paths>...] [--exclude <paths>...]`
- `push <component_id> [--tags]`
- `pull <component_id>`
- `tag <component_id> [tag_name] [-m <message>]`
- If `tag_name` is omitted, Homeboy tags `v<component version>` (from `homeboy version show`).
### Commit Options
By default, `commit` stages all changes before committing. Use these flags for granular control:
- `-m, --message <msg>`: Commit message (required in CLI mode, or in JSON body)
- `--staged-only`: Commit only changes that are already staged. Skips the automatic `git add .` step.
- `--files <paths>...`: Stage and commit only the specified files.
- `--include <paths>...`: Alias for `--files` (repeatable).
- `--exclude <paths>...`: Stage all files except the specified paths.
### JSON Spec Mode (commit)
`homeboy git commit` accepts a **JSON spec** for single or bulk commits.
- You can pass the spec positionally: `homeboy git commit <component_id> '<json>'` (auto-detected as JSON)
- Or pass a plain message positionally: `homeboy git commit <component_id> 'Update docs'`
- Or explicitly: `homeboy git commit <component_id> --json '<json>'` (forces JSON mode)
- The JSON spec value supports:
- an inline JSON string
- `-` to read from stdin
- `@file.json` to read from a file
Homeboy auto-detects **single vs bulk** by checking for a top-level `components` array.
### Bulk Mode (--json)
All subcommands except `tag` support a `--json` flag for bulk operations across multiple components.
- `status --json '<bulk_ids_input>'`
- `commit --json '<bulk_commit_input>'` (or positional spec)
- `push --json '<bulk_ids_input>'`
- `pull --json '<bulk_ids_input>'`
`BulkIdsInput` uses `component_ids` (snake_case).
## Bulk JSON Input Schemas
### SingleCommitSpec (for commit JSON spec)
```json
{
"id": "extra-chill-multisite",
"message": "Update multisite docs",
"staged_only": false,
"include_files": ["README.md", "docs/index.md"]
}
```
Notes:
- `id` is optional when you also provide a `<component_id>` positional argument.
- `staged_only` defaults to `false`.
- `include_files` is optional; when present, Homeboy runs `git add -- <files...>` instead of `git add .`.
- `exclude_files` is optional; when present, Homeboy stages all changes and then unstages the excluded paths.
### BulkCommitInput (for commit)
```json
{
"components": [
{ "id": "extra-chill-multisite", "message": "Update multisite docs" },
{ "id": "extra-chill-api", "message": "Update API docs" }
]
}
```
### BulkIdsInput (for status, push, pull)
```json
{
"component_ids": ["extra-chill-multisite", "extra-chill-api"],
"tags": true
}
```
Notes:
- `tags` field is optional (defaults to false), only used for `push`
## JSON Output
> Note: all command output is wrapped in the global JSON envelope described in the [JSON output contract](../architecture/output-system.md). The object below is the `data` payload.
### Single Component Output
```json
{
"component_id": "<component_id>",
"path": "<local path>",
"exit_code": 0,
"stdout": "<stdout>",
"stderr": "<stderr>"
}
```
### Bulk Output
```json
{
{
"component_id": "extra-chill-multisite",
"path": "/path/to/component",
"action": "commit",
"success": true,
"exit_code": 0,
"stdout": "[main abc1234] Update multisite docs\n 2 files changed",
"stderr": ""
},
{
"component_id": "extra-chill-api",
"path": "/path/to/component",
"action": "commit",
"success": false,
"exit_code": 1,
"stdout": "",
"stderr": "error: nothing to commit"
}
],
"summary": {
"total": 2,
"succeeded": 1,
"failed": 1
}
}
```
Notes:
- `commit` returns a successful result with `stdout` set to `Nothing to commit, working tree clean` when there are no changes.
- Bulk operations continue processing all components even if some fail; the summary reports total/succeeded/failed counts.
- Bulk outputs are `BulkGitOutput { action, results, summary }` where `results` is a list of `GitOutput` objects (not the generic bulk envelope used by some other commands).
## Exit code
- Single mode: exit code matches the underlying `git` command.
- Bulk mode (`--json`): `0` if all components succeeded; `1` if any failed.
## Examples
### Single Component
```sh
homeboy git status extra-chill-multisite
# CLI mode
homeboy git commit extra-chill-multisite -m "Update docs"
# Commit only staged changes
homeboy git commit extra-chill-multisite -m "Release notes" --staged-only
# Commit only specific files
homeboy git commit extra-chill-multisite -m "Update docs" --files README.md docs/index.md
# Commit all but exclude paths
homeboy git commit extra-chill-multisite -m "Update docs" --exclude Cargo.lock
# JSON spec mode (single)
homeboy git commit extra-chill-multisite '{"message":"Update docs","files":["README.md"]}'
homeboy git push extra-chill-multisite --tags
homeboy git pull extra-chill-multisite
homeboy git tag extra-chill-multisite v1.0.0 -m "Release 1.0.0"
```
### Bulk Operations
```sh
# Bulk commit with per-component messages
homeboy git commit --json '{"components":[{"id":"extra-chill-multisite","message":"Update multisite docs"},{"id":"extra-chill-api","message":"Update API docs"}]}'
# Bulk commit with staged-only per component
homeboy git commit --json '{"components":[{"id":"extra-chill-multisite","message":"Release prep","staged_only":true}]}'
# Bulk status check
homeboy git status --json '{"component_ids":["extra-chill-multisite","extra-chill-api","extra-chill-users"]}'
# Bulk push with tags
homeboy git push --json '{"component_ids":["extra-chill-multisite","extra-chill-api"],"tags":true}'
# Bulk pull
homeboy git pull --json '{"component_ids":["extra-chill-multisite","extra-chill-api"]}'
```
## Related
- [version](version.md)