Skip to content

[FEATURE] Support environment variable interpolation in HTTP hook url field #31653

@yonatangross

Description

@yonatangross

Preflight Checklist

  • I have searched existing issues and this hasn't been requested yet
  • This is a single feature request

Feature Description

Current behavior: HTTP hooks support environment variable interpolation in headers values via allowedEnvVars, but the url field is validated as a strict URL format at load time (Zod z.string().url()). This means ${MY_WEBHOOK_URL} in the url field fails with invalid_format.

Requested behavior: Allow $VAR_NAME or ${VAR_NAME} syntax in the url field, with variables resolved from allowedEnvVars — same as headers. If the variable is unset/empty, the hook should silently skip (matching HTTP hooks' existing non-blocking error semantics).

Use Case

We maintain OrchestKit, a public Claude Code plugin with 80 skills, 30 agents, and 105 hooks. We have 12 HTTP hooks across lifecycle events (SessionStart, Stop, SubagentStart, etc.) that forward events to a user-configurable webhook endpoint.

As a public plugin, we cannot hardcode any URL — each user has their own endpoint. The natural pattern is:

{
  "type": "http",
  "url": "${ORCHESTKIT_HOOK_URL}",
  "headers": {
    "Authorization": "Bearer ${ORCHESTKIT_HOOK_TOKEN}"
  },
  "allowedEnvVars": ["ORCHESTKIT_HOOK_URL", "ORCHESTKIT_HOOK_TOKEN"]
}

This fails at plugin load time with 12 invalid_format errors, breaking the entire plugin's hooks (not just the HTTP ones).

Current Workaround

The only workaround is replacing all HTTP hooks with command hooks that spawn a Node process to do fetch() — losing HTTP hooks' built-in benefits (no shell spawn, automatic deduplication by URL, native non-blocking error handling).

No official Anthropic plugin uses HTTP hooks today, so this gap hasn't surfaced internally.

Suggested Implementation

  1. Move URL validation to runtime (after env var interpolation) instead of schema parse time
  2. Add url to the fields that allowedEnvVars applies to (alongside headers)
  3. If the interpolated URL is empty/invalid, treat it like a connection failure (non-blocking, continue)

Impact

High — prevents public plugins from using HTTP hooks with user-configurable endpoints. Forces degraded command-hook workarounds.

Environment

  • Claude Code: 2.1.70
  • OS: macOS
  • Plugin: OrchestKit v7.1.10

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions