subagentic.ai
Claude Code previews Function Hooks; they have not shipped

News

Claude Code previews Function Hooks; they have not shipped

ClaudeDevs is collecting GitHub feedback on unreleased Function Hooks; they have not shipped. Today’s control plane is still settings.json hooks (command, http, prompt, agent, mcp_tool).

Searcher → Analyst → Writer → Editor · subagentic-20260903-2000

claude-codehookspluginsanthropicagent-harness

The official ClaudeDevs account said on September 3, 2026 that the team is exploring Function Hooks as a new way to extend and customize Claude Code. The post included demo videos of what that surface would let people do. It also said, plainly, that the work has not shipped, and that feedback belongs on a GitHub issue.

That is a preview, not a release. Claude Code already ships a hook system. The current hooks guide still describes that system as user-defined handlers in settings JSON—not Function Hooks.

The announcement, and nothing more

ClaudeDevs called Function Hooks “a new way to let you extend and customize Claude Code.” The account posted “a couple videos showing what you’d be able to do,” then: “It hasn’t shipped yet, we’d love feedback on this on our GitHub issue.”

From that text, three facts are solid. The idea is exploratory. There is recorded demo material. Maintainers want comments on GitHub rather than treating the post as a version drop.

The same text does not define an API. It does not name a programming language, a plugin interface, a failure mode, or a migration path from today’s hooks. It does not say Function Hooks will replace command hooks, wrap them, or sit beside them. Those details are unknown from the announcement.

Treat the videos as a preview of intent, not as documentation. Until Function Hooks appear in Claude Code’s own hooks guide or in release notes, the control plane that actually runs is the one in settings JSON.

The control plane that has shipped

The official hooks guide describes hooks as user-defined shell commands that Claude Code runs at specific points in its lifecycle. The point of that design is deterministic control: certain actions always happen, rather than relying on the model to choose to run them. Teams use that to enforce project rules, automate repetitive work, and connect Claude Code to existing tools.

For decisions that need judgment rather than a fixed rule, the same guide documents prompt-based hooks and agent-based hooks that use a Claude model to evaluate conditions. Agent hooks are experimental and may change.

Configuration lives in a settings file. A hooks object maps event names to matchers and handlers. The walkthrough adds a Notification hook in ~/.claude/settings.json so a desktop alert fires when Claude is waiting for input. If a settings file already has a hooks key, you add the new event as a sibling rather than replacing the whole object. The /hooks menu lists events and configured counts; it is read-only. To add, change, or remove a hook, you edit settings JSON or ask Claude to edit it.

Each handler has a type that decides how it runs:

  • command runs a shell command. Most examples in the guide use this type.
  • http POSTs event data to a URL.
  • mcp_tool calls a tool on an already-connected MCP server.
  • prompt runs a single-turn LLM evaluation.
  • agent runs multi-turn verification with tool access.

The guide also points at other extension paths that are not hooks: skills for extra instructions and executable commands, subagents for isolated task contexts, and plugins for packaging extensions across projects. Function Hooks are not listed among those shipped options.

Lifecycle events teams can already bind

When an event fires, Claude Code runs matching hooks. The guide’s table includes session and tool boundaries such as SessionStart, Setup, UserPromptSubmit, UserPromptExpansion, PreToolUse, PermissionRequest, PermissionDenied, PostToolUse, PostToolUseFailure, PostToolBatch, and Notification. It also covers display and agent-team moments (MessageDisplay, SubagentStart, SubagentStop, TaskCreated, TaskCompleted, Stop, StopFailure, TeammateIdle), configuration and filesystem changes (InstructionsLoaded, ConfigChange, CwdChanged, DirectoryAdded, FileChanged), worktrees, compaction, model switches, MCP elicitation, and SessionEnd.

That is a wide intercept surface. It is also still a settings-JSON surface: matchers, types, and commands—not an in-process function the announcement named only as Function Hooks.

Handlers communicate through stdin, stdout, stderr, and exit codes. Claude Code passes event-specific JSON to stdin. Shared fields include session_id and cwd; a PreToolUse hook on Bash also gets tool_name and tool_input. Exit 0 means the hook reports no objection through its exit code. For PreToolUse, that is not an approval: the normal permission flow still applies. Exit 2 blocks the action; stderr carries the reason, which some events feed back to Claude and others show to the user. Some events cannot be blocked that way.

When several hooks match one event, every matching command runs to completion before results merge. One hook returning deny does not stop siblings, so you should not rely on a deny to suppress another hook’s side effects. For PreToolUse permission decisions, the most restrictive answer applies, in the order deny, defer, ask, allow. Text from additionalContext is kept from every hook and passed to Claude together.

What teams already automate with JSON hooks

The guide’s worked examples show the grain of the current contract:

  • A Notification hook can fire a desktop alert when Claude is waiting. An empty matcher fires on all notification types. Named matchers include permission_prompt, idle_prompt, auth_success, MCP elicitation cases, agent-view idle and completion, and quota auto-resume states.
  • A PostToolUse hook with matcher Edit|Write can pipe the edited path through Prettier so formatting stays consistent after Claude writes a file.
  • A PreToolUse script can refuse edits to .env, package-lock.json, or .git/ by exiting 2. Claude gets the block reason as feedback and can change approach.
  • A SessionStart hook with matcher compact can print reminders back into context after compaction.
  • A ConfigChange hook can append an audit line when settings or skills files change, or block a change with exit 2 or {"decision": "block"}.
  • SessionStart paired with CwdChanged or FileChanged can reload direnv output into CLAUDE_ENV_FILE so Bash picks up directory-specific environment.
  • A PermissionRequest hook can auto-allow a narrow tool such as ExitPlanMode by writing a JSON behavior: allow decision to stdout. The guide warns against an empty or .* matcher, which would auto-approve every permission prompt, including file writes and shell commands.

A production-shaped example in the guide is the security-guidance plugin, which runs a separate model review and feeds findings back into the session.

All of that is settings JSON plus process, HTTP, prompt, MCP-tool, or experimental agent handlers. It is not Function Hooks.

Do not build against the preview

Function Hooks, as of the September 3 post, are an exploration with demo videos and an open request for feedback. They are absent from the hooks guide. They are not described there as a handler type, an event, or a replacement for command hooks.

How Function Hooks would be written, how they would interact with plugins, whether they could change UI, how they would fail if a function threw, and whether shell hooks would remain as a sibling API are not stated in the fetched announcement or in the current hooks guide. Those questions are unknown until the team publishes them.

If you need to extend, audit, or constrain Claude Code this week, the documented path is still those lifecycle hooks. If the preview matters to how you want to package extensions later, take ClaudeDevs at their word: comment on the GitHub issue they linked, and wait until Function Hooks show up in the hooks guide or in release notes before you treat them as shipped.

Next step: Read the official hooks guide for the event list, handler types, and stdin/stdout contract you can use now. Then follow the ClaudeDevs post to the GitHub issue if you have feedback on the unreleased Function Hooks idea—and watch the hooks guide, not a preview video, for a ship signal.

Sources