What it does
UserPromptSubmit is a hook that fires after the user types a message and hits submit, but before Claude sees it. It runs in your local settings, giving you a chance to inspect the raw prompt text, inject context, transform it, or even block it entirely. Common use cases: auto-attaching the current branch name to every command, prepending a project's CLAUDE.md as context before analysis, or appending a checklist reminder to code changes.
When to use it
Use UserPromptSubmit when you want to silently inject repetitive context without the user typing it every time. Examples:
- Prepend the current git branch, so every claude command knows which feature you're working on
- Auto-attach a project's conventions file (CLAUDE.md, architecture docs) to the prompt
- Append a checklist (e.g., "Always run tests before pushing") as a standing reminder
- Log every prompt to an audit file for your team's knowledge base
The hook runs locally in your settings.json or settings.local.json, so the transformation is invisible — Claude sees an enriched prompt, the user sees their original message in the UI.
Try it yourself
Look at .claude/settings.json or create a .claude/settings.local.json file in your project root. Add a hooks section with a UserPromptSubmit entry that runs a shell command. For instance, you could write a script that prepends the current git branch or checks for uncommitted changes, then appends that result to the prompt. The hook receives the raw prompt text as stdin and should output the modified prompt to stdout.
Gotchas
Don't bloat every prompt. A hook that appends 5KB of context to "what files changed?" creates noise and wastes tokens. Attach only information that's relevant to most prompts. Context that's specific to one task (like a detailed error trace) is better pasted manually or kept in memory.
Hooks run synchronously. If your hook calls a slow external API or runs git log -100, Claude will appear frozen until it completes. Keep hook scripts fast (< 500ms). Shell scripts, file reads, and local git commands are safe. Slow API calls are not.
Hook output is appended to the prompt exactly as-is. If your script outputs ANSI color codes or trailing whitespace, that ends up in the prompt. Use plain text. Test your hook once locally (cat ~/.claude/settings.json | jq .hooks.UserPromptSubmit) to verify the output format.
The hook sees what the user typed, not what Claude remembers. If you use memory or context compression, UserPromptSubmit runs before that — it only has access to the raw text the user submitted. This is fine for injecting external context (git state, file contents), but not for replaying prior conversation state.
Try it yourself
Type the command in the fake terminal. Nothing leaves your browser.