How to Use the `swarm_handoff.sh` Helper Script in Swarm-Forge
The swarm_handoff.sh helper script validates draft handoff files and converts them into machine-ready payloads for moving work between Swarm-Forge roles.
The swarm_handoff.sh script is the primary entry point for creating handoffs in the Swarm-Forge workflow system. According to the unclebob/swarm-forge source code, this thin Zsh wrapper delegates all processing to a Babashka script that enforces protocol compliance, validates recipients, and manages audit lifecycle.
What swarm_handoff.sh Actually Does
At swarmforge/scripts/swarm_handoff.sh (lines 1-6), the script is intentionally minimal:
#!/usr/bin/env zsh
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
exec bb "$SCRIPT_DIR/swarm_handoff.bb" "$@"
This wrapper pattern ensures consistent Babashka execution regardless of your current working directory. The real implementation lives in swarm_handoff.bb, which runs an 8-step pipeline for every handoff.
The Handoff Pipeline: Step by Step
Step 1: Determine Sender Role
The script identifies who is sending the handoff by reading the current worktree's role from the roles file via handoff-lib:
- Function:
sender-role(lines 88-94) - Source: reads Git configuration and role mappings
Step 2: Validate Draft Location
Draft files must reside under ./tmp/ inside the sender's worktree. This constraint prevents cross-contamination between worktrees:
- Function:
require-worktree-tmp-draft!(lines 99-102) - Fails fast if the draft path violates this rule
Step 3: Parse Draft Headers
Headers are processed line-by-line into a field map with syntax error collection:
- Function:
parse-draft(lines 111-145) - Supports required fields, optional fields, and comment lines (starting with
#)
Step 4: Enrich Missing Fields
The prepare-headers function (lines 89-95) injects defaults:
| Field | Default Source |
|---|---|
priority |
50 (hardcoded) |
commit |
Current HEAD short SHA via git rev-parse |
Step 5: Run Validation Checks
Five validation categories run in sequence (main flow, lines 274-316):
base-errors— required fields present (type,to,priority)validate-recipients— role exists, no duplicate recipientscanonical-commit— commit SHA normalized viagit rev-parsetask-state-errors— task exists on board, not already "done"duplicate-errors— no identical active handoff already queued
All errors merge into a single report; any failure aborts with structured output.
Step 6: Prepare the Payload
For git_handoff types, write-handoff! (lines 403-447):
- Computes changed files via
commit-artifacts - Builds a
.handofffile in.swarmforge/handoffs/outbox/ - Names files using pattern:
{priority}_{timestamp}_{sequence}_from_{sender}_to_{recipient}.handoff
Step 7: Handle Audit State
submit-after-audit! (lines 260-274) checks audit history:
- If audited before: immediate submission
- If new: creates pending-audit file, prompts user to run audit
Step 8: Cleanup
On success: draft deleted, "HANDOFF QUEUED" message printed.
Creating Valid Draft Files
Drafts are plain text with YAML-like headers. The type field determines processing rules.
Example: Git Handoff Draft
Create under ./tmp/ of your worktree:
cat > ./tmp/api-refactor.handoff <<'EOF'
type: git_handoff
to: reviewer
priority: 40
task: refactor-user-service
# commit auto-filled from HEAD
EOF
Execute:
$ ./swarmforge/scripts/swarm_handoff.sh ./tmp/api-refactor.handoff
HANDOFF QUEUED: .swarmforge/handoffs/outbox/40_20231128T123456Z_000001_from_dev_to_reviewer.handoff
Example: Note Handoff (Non-Code)
cat > ./tmp/deploy-notice.handoff <<'EOF'
type: note
to: ops
priority: 20
message: Production deploy scheduled for 02:00 UTC
EOF
$ ./swarmforge/scripts/swarm_handoff.sh ./tmp/deploy-notice.handoff
HANDOFF QUEUED: .swarmforge/handoffs/outbox/20_20231128T123456Z_000002_from_dev_to_ops.handoff
Error Handling Example
Missing required fields produce structured error reports:
$ ./swarmforge/scripts/swarm_handoff.sh ./tmp/incomplete.handoff
HANDOFF INVALID: ./tmp/incomplete.handoff
Errors:
- Missing required header 'type'.
- Missing required header 'to'.
- Missing required header 'priority'.
Cross-Shell Compatibility
Though the wrapper uses Zsh, it executes from any shell with Babashka installed:
# From Bash
bash -c "./swarmforge/scripts/swarm_handoff.sh ./tmp/my-feature.handoff"
# From Fish
bash ./swarmforge/scripts/swarm_handoff.sh ./tmp/my-feature.handoff
The exec bb pattern ensures the Babashka process replaces the shell entirely, eliminating subshell compatibility concerns.
Required Headers by Handoff Type
| Header | git_handoff |
note |
Description |
|---|---|---|---|
type |
Required | Required | Discriminator for processing branch |
to |
Required | Required | Recipient role(s), comma-separated |
priority |
Required¹ | Required¹ | Integer 1-99, lower = higher priority |
task |
Required | Optional | Board task identifier |
message |
Optional | Required | Human-readable content |
commit |
Auto-filled | N/A | Git SHA for code handoffs |
¹ Defaults to 50 if omitted
Key Source Files
| File | Purpose | Lines of Interest |
|---|---|---|
swarmforge/scripts/swarm_handoff.sh |
Zsh entry wrapper | 1-6 |
swarmforge/scripts/swarm_handoff.bb |
Core implementation | 74-115 (-main), 274-316 (validation) |
swarmforge/scripts/handoff_lib.bb |
Shared Git/role utilities | sender-role, git-toplevel |
swarmforge/scripts/pack_board.sh |
Post-audit board update | Triggered after successful audit |
swarmforge/scripts/done_with_current.sh |
Task completion helper | Marks in-process task done |
Summary
swarm_handoff.shis a thin wrapper that launchesswarm_handoff.bbvia Babashka- Draft files must live in
./tmp/of the sender's worktree - Validation runs 8 steps from role detection through audit handling
- Two primary handoff types:
git_handoff(code) andnote(messages) - Auto-enrichment fills
priority(default 50) andcommit(current HEAD) - Structured error reports prevent malformed handoffs from entering the system
Frequently Asked Questions
Where must I save draft handoff files?
Draft files must be saved under ./tmp/ inside your current worktree. The require-worktree-tmp-draft! function (lines 99-102) enforces this to maintain isolation between worktrees. Attempting to handoff a file from outside this directory aborts with a clear error message.
What happens if my draft has validation errors?
The script aggregates all validation failures—missing headers, invalid recipients, bad commit SHAs, duplicate handoffs—into a single error report prefixed with HANDOFF INVALID. No partial handoff is created; you must fix all errors and re-run.
Does swarm_handoff.sh work without Zsh?
Yes. While the wrapper specifies #!/usr/bin/env zsh, the exec bb pattern means any shell can invoke it provided Babashka (bb) is installed and on your PATH. The Zsh dependency is for the launcher script only, not the core Babashka implementation.
What is the difference between git_handoff and note types?
git_handoff transfers code changes: it computes file diffs from the specified commit, requires a task reference, and auto-fills the commit SHA. note sends unstructured messages without Git artifacts, requiring a message field instead. Both use the same validation pipeline but diverge during payload construction in write-handoff!.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →