Claude Code
Run uvx jes login first. See Setup.
Install
uvx jes claude-settings
Merge the hooks object it prints into ~/.claude/settings.json. Each
command is pinned to the jes release that printed it. Print the settings
again after you upgrade.
uvx jes claude-settings
{
"hooks": {
"UserPromptSubmit": [
{
"hooks": [
{
"type": "command",
"command": "uvx jes@0.0.1 claude-hook",
"timeout": 60
}
]
}
],
"PreToolUse": [
{
"hooks": [
{
"type": "command",
"command": "uvx jes@0.0.1 claude-hook",
"timeout": 60
}
]
}
],
"PostToolUse": [
{
"hooks": [
{
"type": "command",
"command": "uvx jes@0.0.1 claude-hook",
"timeout": 60
}
]
}
],
"MessageDisplay": [
{
"hooks": [
{
"type": "command",
"command": "uvx jes@0.0.1 claude-hook",
"timeout": 60
}
]
}
]
}
}
What each hook does
| Event | Stage | If jes blocks |
|---|---|---|
UserPromptSubmit | input | Returns decision: block with the refusal as the reason. |
PreToolUse | tool_call | Denies the call. The tool does not run. |
PostToolUse | tool_result | Replaces the output the model reads. A Bash result is checked on stdout and stderr together, and a block clears stderr too. |
MessageDisplay | output | Replaces the text on screen once the message is final. The parts of each streamed message are kept apart, so two replies at once don't mix. |
Limits
PostToolUsefires after the tool has run. A blocked result keeps the model from reading it, but a shell command or file write is not undone.PreToolUseis what stops the command.MessageDisplaychanges only what you see. The transcript, and what Claude reads on the next turn, keep the original reply.- If the
PostToolUseorMessageDisplayprocess dies before it prints JSON, Claude Code lets the text through. A model error is still caught and turned into a refusal.