Skip to main content
Team Hooks let you attach shell scripts to key team events so automation can run at the right time without changing gg source code.

Mental model

Think of Team Hooks as a thin, deterministic runtime:
  1. gg observes a canonical team event.
  2. gg resolves effective hooks (user + project config).
  3. Hooks run concurrently with JSON input over stdin.
  4. Hook outputs are aggregated in stable order.
  5. gg injects lifecycle context into target sessions and appends typed system_notice timeline rows.
Two properties matter most:
  • Hooks do not replace core team operations; they augment them.
  • Delivery-aware events wait for real message lifecycle completion.

What hooks are good for

Practical use cases:
  • Pre-add teammate setup in the source session checkout before native worktree creation (pre_teammate_add).
  • Post-add onboarding reminders and policy injection.
  • Post-remove cleanup notices and audit signal.
  • Delivery-aware follow-ups after direct/broadcast send success.
  • Compaction recovery guidance when a member loses context.

Hooks are not worktree init

pre_teammate_add hooks and worktree init are separate runtime steps:
  • pre_teammate_add runs before native worktree creation in the source session cwd.
  • Worktree init runs after new native worktree creation in the new worktree cwd, using .agents/gg/worktree-init.sh.
  • The Add Agent pre-hook checkbox controls hooks only; it does not disable worktree init.
For the worktree-init contract, see Configure: Worktree Init.

Delivery-aware automation

Message hooks are not queue-time hooks. They fire on delivery success semantics:
  • Direct hooks fire only when direct delivery is fully injected.
  • Broadcast hooks can still succeed if a recipient is removed mid-flight, as long as all still-eligible recipients are injected.
  • Partial terminal failures do not fire message hooks.
This avoids false positives for workflows that depend on actual delivery completion.

Event applicability at runtime

Hook outputs apply per event as follows:
  • pre_teammate_add: after the new member session is created, injection can target the caller and explicit targets. agent_id="__new_member__" resolves to the spawned member session.
  • post_teammate_add: applies to caller/targets from hook output after canonical member-add commit.
  • post_teammate_remove: applies after canonical member-remove commit, but any injection targeting removed member session IDs is suppressed.
  • post_direct_message_send: applies only on full direct-delivery success.
  • post_broadcast_message_send: applies on full broadcast delivery, or terminal completion where every still-eligible (still-member) recipient is injected.
  • post_compaction: baseline compaction guidance is emitted for resolved recipients; post-compaction hook injection can override recipient text/kind for those recipients.

Where config lives

Team Hooks resolve from:
  • ~/.agents/gg/team-hooks.json (user)
  • <session cwd>/.agents/gg/team-hooks.json (project)
Project hooks override user hooks on (event, normalized name) collisions.

Safety and failure boundaries

Failure policy is explicit:
  • pre_teammate_add is fail-closed and can block add-member operations.
  • All post_* hooks are fail-open and do not roll back committed operations.
Compaction handling is resilient:
  • If post-compaction hook resolution/execution fails, gg still sends baseline compaction notices.

Current v1 limits

Team Hooks v1 intentionally stays narrow:
  • Shell commands only (no HTTP hook transport).
  • One JSON-in / JSON-out contract version (schema_version: 1).
  • No global “disable all hooks” toggle.
  • Post teammate/message hooks are source-filtered to tool-originated agent operations (agent_tool) to avoid automation recursion.

UI behavior to know

When pre-add hooks exist, the Add Agent dialog shows a checkbox:
  • Checked (default): run pre hooks.
  • Unchecked: skip pre hooks for that one quick-add action.
  • This checkbox does not disable worktree init for create-new native worktree adds.
Lifecycle hook notices render as typed timeline system_notice rows (team_hook_*_notice kinds plus baseline team_member_compaction_notice). Legacy non-transport wrapper parsing for team_hook_* envelopes is not a supported runtime path.

Next step

Use the full contract page for schema, merge rules, per-event payloads, and copy-paste examples: