[FEATURE] User-configurable session variables accessible from hooks (CLAUDE_SESSION_VARS)

Resolved 💬 2 comments Opened Jan 16, 2026 by kitaekatt Closed Feb 28, 2026

Summary

Add support for user-configurable state variables that the agent, and hooks, can read and write, enabling session-state based behavior modification.

Problem

Currently, there is no way to distinguish between agents and sub-agents consistently (#14859). As such users can not reliably record variables to a file, or to memory, that are retained across a session. For example, a sub-agent's session id is the same as the main agent, so this can not be used as a key to look up state variables.

This limitation prevents users from implementing:

  • Operational modes that hooks can respond to differently
  • Workarounds for #14859 (agent identification in hooks)
  • Session-scoped feature flags
  • Cross-hook coordination patterns

Example Solution

Add a CLAUDE_SESSION_VARS environment variable that:

  1. Contains a JSON object of user-defined session variables
  2. Is readable by all hooks via os.environ
  3. Can be written to by hooks (exception to normal read-only env var behavior)
  4. Can be written to by the agent (via a tool call specialized for this purpose)
  5. Persists for the duration of the session (across /compact as well)

Example Implementation

settings.json configuration:

{
  "sessionVars": {
    "operational_mode": "standard",
    "debug_level": "0"
  }
}

Hook reading session vars:

import os, json

session_vars = json.loads(os.environ.get("CLAUDE_SESSION_VARS", "{}"))
mode = session_vars.get("operational_mode", "standard")

if mode == "strict":
    # Apply stricter validation
    pass

Hook writing session vars (SubagentStart example):

import os, json

# Read current vars
session_vars = json.loads(os.environ.get("CLAUDE_SESSION_VARS", "{}"))

# SubagentStartHookInput has agent_id - propagate it for other hooks
session_vars["current_agent_id"] = context.agent_id
session_vars["current_agent_type"] = context.agent_type

# Write back (mechanism TBD - could be JSON output, file, or special API)
# This enables PreToolUse to know which agent triggered it

Use Cases

1. Operational Modes

Users define modes (standard, strict, permissive) and hooks respond accordingly:

  • strict: Block more operations, require more skills
  • permissive: Allow more autonomy, fewer gates

2. Agent Identification Workaround (#14859)

SubagentStart hook populates current_agent_id, PreToolUse hooks can then distinguish which agent triggered them - working around the missing agent_id in PreToolUse payloads.

3. Feature Flags

Enable/disable hook behaviors without editing hook code:

{"enable_auto_format": true, "enable_strict_validation": false}

4. Cross-Hook Coordination

Hooks can signal state to other hooks:

  • PreToolUse sets "pending_operation"
  • PostToolUse clears it and acts based on what was pending

Alternatives Considered

  1. File-based state: Works for main agent but fails for sub-agents (can't correlate files to specific agents without agent_id in PreToolUse)
  1. Environment variables via CLAUDE_ENV_FILE: Only affects Bash tool execution, not hook execution
  1. Waiting for #14859: Proper fix, but session vars provide value beyond just agent identification

Related Issues

  • #14859 - Agent Hierarchy in Hook Events (this feature would provide a workaround)
  • #7881 - SubagentStop cannot identify which subagent

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗