WebSearch temporal context injector
Prevents stale search results by silently adding the current year
Intercepts every WebSearch call and appends the current year to queries that lack temporal context (no year, no 'latest', 'recent', 'current', etc.). Ensures the agent retrieves up-to-date documentation, changelogs and release notes instead of outdated results.
What does the WebSearch temporal context injector hook do?
WebSearch temporal context injector is a Claude Code PreToolUse hook matching WebSearch. It fires automatically at that lifecycle event — outside the model, so it can't be skipped or forgotten. Prevents stale search results by silently adding the current year.
As a PreToolUse hook it runs before the action completes, so it can block or adjust what Claude is about to do. Because it is a deterministic Node.js script, it executes on every matching event without relying on the model to remember — the guarantee that makes agentic workflows safe to automate.
Use cases
- Keep dependency version lookups current
- Avoid outdated API documentation in research tasks
- Ensure changelog and release note searches return latest versions
Tags
settings.json fragment
{
"hooks": {
"PreToolUse": [
{
"hooks": [
{
"command": "node $CLAUDE_PROJECT_DIR/.claude/hooks/websearch-temporal-context.mjs",
"type": "command"
}
],
"matcher": "WebSearch"
}
]
}
}Script · .claude/hooks/websearch-temporal-context.mjs
#!/usr/bin/env node
// @hookstack pre-websearch-temporal-context
// Injecte l'année courante dans les requêtes WebSearch sans contexte temporel (PreToolUse)
import { readFileSync } from "node:fs";
import { fileURLToPath } from "node:url";
const TEMPORAL_WORDS = [
"latest",
"recent",
"current",
"new",
"now",
"today",
"this year",
"last year",
];
const YEAR_PATTERN = /\b20\d{2}\b/;
export function run(input, { currentYear = new Date().getFullYear() } = {}) {
const query = input.tool_input?.query ?? "";
if (!query) return null;
const hasYear = YEAR_PATTERN.test(query);
const hasTemporal = TEMPORAL_WORDS.some((w) =>
query.toLowerCase().includes(w),
);
if (hasYear || hasTemporal) return null;
return {
hookSpecificOutput: {
hookEventName: "PreToolUse",
modifiedToolInput: { query: `${query} ${currentYear}` },
},
};
}
/* v8 ignore next 5 */
if (process.argv[1] === fileURLToPath(import.meta.url)) {
const input = JSON.parse(readFileSync(0, "utf8"));
const result = run(input);
if (result) process.stdout.write(JSON.stringify(result));
}