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 recipients
  • canonical-commit — commit SHA normalized via git rev-parse
  • task-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):

  1. Computes changed files via commit-artifacts
  2. Builds a .handoff file in .swarmforge/handoffs/outbox/
  3. 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.sh is a thin wrapper that launches swarm_handoff.bb via 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) and note (messages)
  • Auto-enrichment fills priority (default 50) and commit (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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →