Hook event 17 of 33

TaskCreated

Runs while the TaskCreate tool is creating a task and can cancel that creation.

Exit code veto
Exit 2 blocks
Matchers
none
if filter
Does not apply
Docs checked
2026-08-29

The task exists only if the hook lets it

You want to vet a task before it lands in the list. TaskCreated runs while the TaskCreate tool is creating a task, on every call, whenever Task tools are available. There is no matcher. The payload carries task_id, task_subject, an optional task_description, an optional teammate_name, and a deprecated optional team_name.

Two ways to cancel, and one that does nothing

Exit 2 deletes the task and returns stderr to Claude as the tool error. A top-level decision: "block" with reason cancels it and hands Claude the reason. Exit 0 and exit 1 create the task unless that JSON blocks it.

The shared continue: false field, which stops the loop on other events, is ignored here. The hooks reference says so in as many words.

The mistake most people make first

You return {"continue": false, "stopReason": "no tasks during a release freeze"} to stop a task being created.

The task is created. The field is ignored on this event and nothing says so. Your reason goes nowhere, and Claude proceeds with a task you thought you had refused.

Return {"decision": "block", "reason": "no tasks during a release freeze"} instead, or exit 2 with the reason on stderr.