[FEATURE] User-configurable session variables accessible from hooks (CLAUDE_SESSION_VARS)
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:
- Contains a JSON object of user-defined session variables
- Is readable by all hooks via
os.environ - Can be written to by hooks (exception to normal read-only env var behavior)
- Can be written to by the agent (via a tool call specialized for this purpose)
- 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 skillspermissive: 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
- File-based state: Works for main agent but fails for sub-agents (can't correlate files to specific agents without agent_id in PreToolUse)
- Environment variables via CLAUDE_ENV_FILE: Only affects Bash tool execution, not hook execution
- 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
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗