HookStack
Back to catalogue
ContextPreToolUse· WebSearch

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

#search#context#freshness#temporal

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));
}

Learn more

Related hooks