v1 contract lock (hard cut-over)
These contracts are current and authoritative for v1:post_teammate_removefires foroperation_source=agent_toolandoperation_source=ui_command.- Native worktree mode is first-class when
worktree_nameis provided ongg_team_manage(add). gg_team_manage(add)supports both create-new and existing-worktree reuse (use_existing_worktree=true) whenworktree_nameis set.- In native worktree mode, runtime owns branch/worktree/cwd derivation; hook
spawn_template_mutation.cwddoes not override final native spawn cwd. pre_teammate_addscripts execute with process cwd set topre_teammate_add.template_source_session_cwd.- Native planning metadata fields in
pre_teammate_addinput are readable context only, not a control plane for native branch/cwd selection. - Worktree init (
.agents/gg/worktree-init.sh) is a separate runtime contract from Team Hooks and is documented at Configure: Worktree Init.
Team Hooks vs worktree init
Keep these boundaries explicit:pre_teammate_addruns before native worktree creation in the source session cwd (pre_teammate_add.template_source_session_cwd).- Worktree init runs after new native worktree creation in the new worktree cwd.
run_pre_teammate_add_hooks=false(Add Agent pre-hook checkbox off) bypasses hooks only; it does not disable worktree init.
Supported events
Team Hooks v1 supports exactly six events:pre_teammate_addpost_teammate_addpost_teammate_removepost_direct_message_sendpost_broadcast_message_sendpost_compaction
Config file locations
gg resolves hooks from two files:- User-level:
~/.agents/gg/team-hooks.json - Project-level:
<workspace-or-session-cwd>/.agents/gg/team-hooks.json
Merge and override rules
Effective hooks are merged per event using normalized hook name:- Load user hooks.
- Load project hooks.
- If
(event, name)collides, project entry overrides user entry. - Unique names are unioned.
- Missing files are treated as no-op.
_) before duplicate/override matching.
Config schema
versionmust be1.nameandcommandare required.timeout_msis optional (default15000).timeout_msmust be between100and120000.- Unknown keys are rejected.
- Duplicate hook names within the same event are rejected after normalization.
Execution model
Each hook runs as a shell command:- macOS/Linux:
sh -lc "<command>" - Windows:
cmd /C "<command>"
- Input payload is written as JSON to
stdin. - Hook must write JSON to
stdout. - Non-zero exit is a failure.
- Empty or invalid JSON
stdoutis a failure. - Hooks for the same event run concurrently.
- Aggregation is deterministic in effective hook order.
Trust boundary
Team hooks are trusted local shell execution:- Project and user hook scripts run as the desktop app user on the local machine.
- No hook sandboxing or separate hook permission gate is added in v1.
- Treat hook config and scripts as trusted code, not untrusted input.
Lifecycle delivery lanes
When hook output is applied, gg uses two coordinated lanes:- Model-context lane: text is injected with automation projection semantics (not a user message lane).
- UI lane: gg appends typed timeline
system_noticerows for lifecycle visibility.
team_hook_pre_teammate_add_noticeteam_hook_post_teammate_add_noticeteam_hook_post_teammate_remove_noticeteam_hook_post_direct_message_send_noticeteam_hook_post_broadcast_message_send_noticeteam_hook_post_compaction_noticeteam_member_compaction_notice(baseline compaction notice kind used when no post-compaction override applies per recipient)
Event firing semantics
| Event | Fires when | Notes |
|---|---|---|
pre_teammate_add | Before native worktree creation and session creation | Blocking (fail-closed). Runs in source session cwd (pre_teammate_add.template_source_session_cwd). Can request spawn cwd mutation for non-native adds, append onboarding text, and apply inject after spawn with team_hook_pre_teammate_add_notice. In native mode (worktree_name set), runtime-derived branch/worktree/cwd is authoritative and hook cwd mutation is ignored. |
post_teammate_add | After canonical member-add commit | Only for agent_tool source. Applies caller/target injection via typed team_hook_post_teammate_add_notice. |
post_teammate_remove | After canonical member-remove commit | For agent_tool and ui_command sources. Injection to removed member is suppressed; surviving recipients use team_hook_post_teammate_remove_notice. |
post_direct_message_send | After direct message reaches delivery-complete success | Only for agent_tool source. No fire on partial failure/terminal failure. Typed notice kind: team_hook_post_direct_message_send_notice. |
post_broadcast_message_send | After broadcast success by delivery rules | Only for agent_tool source. Remove-race success is supported. Typed notice kind: team_hook_post_broadcast_message_send_notice. |
post_compaction | During compaction runtime handling | Runtime-source hook. Hook injection recipients use team_hook_post_compaction_notice. Baseline fallback recipients depend on runtime status (executed, no_hooks, resolution_failed, execution_failed) described below. |
Source filtering rules
Source eligibility is event-specific:- Allowed for
post_teammate_add,post_direct_message_send,post_broadcast_message_send:operation_source = agent_toolonly. - Allowed for
post_teammate_remove:operation_source = agent_toolandoperation_source = ui_command. pre_teammate_addandpost_compactionare source-agnostic at runtime.
- Automation/system DMs (
tool_automation) are excluded from message hooks. - UI command-originated member removes do trigger
post_teammate_remove. - UI command-originated post-add/message operations remain filtered.
Delivery-complete behavior (direct and broadcast)
post_direct_message_send fires only when the message is fully delivered.
post_broadcast_message_send fires on either:
- full delivery, or
- terminal completion where every recipient still currently in the team has been injected.
- If recipient B is removed mid-flight, recipient B no longer blocks hook success.
- If an active remaining recipient fails delivery, hook does not fire.
Failure behavior
pre_teammate_add: fail-closed (operation is blocked on hook failure).- All
post_*: fail-open (core operation already committed and does not roll back).
- Hook failures are logged and recorded in diagnostics.
- Successful hook outputs can still be applied when other hooks fail.
post_compaction runtime status branches
Compaction fallback logic is intentionally branch-specific and should not be treated as one combined “no hook” behavior.
executed: effective hooks resolved and ran. Hook output can override recipients/message text. Override notices useteam_hook_post_compaction_notice.no_hooks: no effectivepost_compactionhooks were configured for the compacted member context. Runtime switches tocreator_and_subscribers_onlyfallback targeting by default (the compacted member is excluded).resolution_failed: hook resolution failed (for example, config load/parse issues). Runtime falls back to the canonical baseline target contract.execution_failed: hooks resolved but execution failed. Runtime falls back to the canonical baseline target contract.
resolution_failed and execution_failed) is not the same as no_hooks: it keeps standard baseline targeting semantics and baseline notice kind team_member_compaction_notice unless hook-produced overrides exist.
Input contract
Every hook receives this base envelope:Event-specific input examples
pre_teammate_add
post_teammate_add
post_teammate_remove
post_direct_message_send
post_broadcast_message_send
post_compaction
Output contract
Base output shape:pre_teammate_add output extension
pre_teammate_addextension is valid only for thepre_teammate_addevent.inject.caller.textis applied to the caller session context after the new member session exists.inject.targets[].agent_id = "__new_member__"is a reserved token forpre_teammate_addthat resolves to the spawned member session after creation.- For
pre_teammate_add, target IDs other than__new_member__are treated as concrete session IDs. - If multiple pre hooks return conflicting
spawn_template_mutation.cwdvalues, pre-hook execution fails. - If
native_worktree_requested=true, runtime-derived native branch/worktree/cwd remains authoritative and hook-providedspawn_template_mutation.cwdis ignored for final spawn cwd selection. - Native planning metadata fields (
requested_worktree_name,planned_branch_name,planned_worktree_cwd,planned_worktree_root,planned_unified_workspace_path) are readable by hooks but are not a control plane for native branch/cwd selection. pre_teammate_addhooks execute with process cwd set topre_teammate_add.template_source_session_cwd.run_pre_teammate_add_hooks=falsehard-bypasses all pre-hook side effects (cwd mutation, onboarding append text, and inject output) but does not disable worktree init for create-new native worktree adds.- For
post_teammate_remove, runtime suppresses any injection targeted at removed member session IDs.
Applicability and suppression rules
- Message-hook applicability is delivery-aware:
post_direct_message_sendrequires full delivery;post_broadcast_message_sendalso permits terminal success when all still-eligible recipients were injected. - Post hook execution is source-filtered by event:
post_teammate_add,post_direct_message_send,post_broadcast_message_send:operation_source=agent_tool.post_teammate_remove:operation_source=agent_toolandoperation_source=ui_command.pre_teammate_addandpost_compactionare source-agnostic.- Recipient applicability is delivery-aware and membership-aware: recipients no longer in the team are excluded from broadcast terminal-success evaluation and post-remove target injection.
Example scripts for all six events
These are minimal shell examples. Replace paths and logic for your workflow.1) pre_teammate_add
2) post_teammate_add
3) post_teammate_remove
4) post_direct_message_send
5) post_broadcast_message_send
6) post_compaction
Timeline rendering contract
Lifecycle hook notices are rendered from typed timelinesystem_notice rows, not from non-transport wrapper parsing.
Legacy non-transport team_hook_* wrapper notices are not a supported runtime path.

