PostToolUse (mcp__.*__find_columns|mcp__.*__get_dataset_columns|mcp__.*__get_dataset)
HookPre-query column validation via schema caching. Catches unknown column errors before they hit the API by building a per-session schema cache from find_columns / get_dataset_columns / get_dataset results.
Fires on
PostToolUsematchingmcp__.*__find_columns|mcp__.*__get_dataset_columns|mcp__.*__get_datasetImmediately after a tool returns, with its result available.
Where this sits in a session
- Session start→
- Prompt submitted→
- Prompt expansion→
- Before tool use→
- After tool use→
- Notification→
- Before compaction→
- Subagent finished→
- Turn finished→
- Session end
Observes only — Emits messages or context. It never returns a permission decision.
What it runs
Executed automatically when the event fires — no prompt, no confirmation.
bash ${CLAUDE_PLUGIN_ROOT}/hooks/scripts/cache-columns.shInstall it yourself
Paste into .claude/settings.json to run this hook without installing the whole plugin. Adjust the paths to point at your own copy of the scripts.
{
"hooks": {
"PostToolUse": [
{
"hooks": [
{
"type": "command",
"command": "bash ${CLAUDE_PLUGIN_ROOT}/hooks/scripts/cache-columns.sh",
"timeout": 5
}
],
"matcher": "mcp__.*__find_columns|mcp__.*__get_dataset_columns|mcp__.*__get_dataset"
}
]
}
}Source
Read this before installing — it runs on your machine with your permissions.
#!/usr/bin/env bash
set -euo pipefail
# PostToolUse hook for find_columns / get_dataset_columns.
#
# Caches column names from the tool result into a per-session temp file.
# The validate-query.sh PreToolUse hook checks this cache before run_query
# to catch unknown column names before they hit the API.
#
# Cache location: $TMPDIR/honeycomb-schema/$session_id/$env--$dataset.txt
# One column name per line, sorted and deduplicated.
input=$(cat)
env_slug=$(echo "$input" | jq -r '.tool_input.environment_slug // empty')
dataset_slug=$(echo "$input" | jq -r '.tool_input.dataset_slug // empty')
session_id=$(echo "$input" | jq -r '.session_id // "default"')
tool_name=$(echo "$input" | jq -r '.tool_name // empty')
# MCP PostToolUse responses use the CallToolResult object shape
# (`{"content":[{"type":"text","text":"..."}]}`), while older Claude
# versions exposed the content blocks as a top-level array. Accept both, plus
# direct text objects/strings, and fail open for response types we do not know.
tool_result=$(
printf '%s\n' "$input" | jq -r '
.tool_response
| if type == "array" then .
elif type == "object" then
if (.content? | type) == "array" then .content else [.] end
elif type == "string" then [.]
else []
end
| map(
if type == "object" then (.text? // empty)
elif type == "string" then .
else empty
end
)
| map(select(type == "string"))
| join("\n")
' 2>/dev/null
) || tool_result=""
# Environment and result required — fail open if missing
if [[ -z "$env_slug" || -z "$tool_result" ]]; then
exit 0
fi
# If no dataset specified, use "_all" as a cross-dataset cache
if [[ -z "$dataset_slug" ]]; then
dataset_slug="_all"
fi
cache_dir="${TMPDIR:-/tmp}/honeycomb-schema/${session_id}"
mkdir -p "$cache_dir"
cache_file="${cache_dir}/${env_slug}--${dataset_slug}.txt"
# Parse column names from markdown table output.
# Both find_columns and get_dataset_columns return pipe-delimited tables
# with the column name in the first data column:
# | Name | Type | Description | ...
# |------|------|-------------|
# | app.team_id | integer | ... |
#
# Strategy: grab rows with pipes, skip the header and separator,
# extract the first data cell.
echo "$tool_result" \
| grep -E '^\s*\|' \
| grep -vE '^\s*\|\s*Name\s*\|' \
| grep -vE '^\s*\|\s*-' \
| awk -F'|' '{gsub(/^[ \t]+|[ \t]+$/, "", $2); if ($2 != "" && $2 !~ /^[- ]+$/) print $2}' \
>> "$cache_file" 2>/dev/null || true
# Deduplicate
if [[ -f "$cache_file" ]]; then
sort -u "$cache_file" -o "$cache_file"
fi
# Mark the cache "complete" only when we actually hold the FULL schema.
# find_columns returns only its top-N matches, so its cache is always partial
# (no marker). get_dataset_columns paginates: one response is the whole schema
# only when total_pages <= 1; for multi-page schemas we record which pages we've
# cached and mark complete once every page has been seen. validate-query.sh keys
# its nudge firmness off this marker, so marking complete while pages are still
# un-fetched would nudge against columns that genuinely exist on later pages.
if [[ "$tool_name" == *get_dataset_columns* ]]; then
# `page:` is anchored to line-start so it doesn't also match `items_per_page:`.
total_pages=$(printf '%s\n' "$tool_result" | grep -E '^[[:space:]]*total_pages:[[:space:]]*[0-9]+' | grep -oE '[0-9]+' | head -1 || true)
page=$(printf '%s\n' "$tool_result" | grep -E '^[[:space:]]*page:[[:space:]]*[0-9]+' | grep -oE '[0-9]+' | head -1 || true)
: "${total_pages:=1}"
: "${page:=1}"
complete_marker="${cache_file%.txt}.complete"
if [[ "$total_pages" -le 1 ]]; then
# Single page is the entire schema.
touch "$complete_marker"
else
# Multi-page: track distinct pages seen; complete once all are cached.
pages_file="${cache_file%.txt}.pages"
echo "$page" >> "$pages_file"
sort -un "$pages_file" -o "$pages_file"
seen=$(wc -l < "$pages_file" | tr -d '[:space:]')
if [[ "$seen" -ge "$total_pages" ]]; then
touch "$complete_marker"
fi
fi
fi
exit 0
Shipped by 1 plugin
Installing any of these installs this hook.
Reviews
Log in to leave a review.
No reviews yet — be the first.
Explore related
Other things in this space — across every part of the ecosystem, not just hooks.
Hookssimilar to this one
All hooks →Subagents
All subagents →explore
Read-only code explorer that the plugin's other agents dispatch to map a codebase — locate files, trace how a flow is wired, find every caller of a symbol, answer "where does X happen".
32.8K stars
scan-verifier
Restricted read-only verifier dispatched by the Claude Security scan workflow to vote on one candidate finding; not for direct invocation.
32.8K stars
scan-researcher
Restricted read-only vulnerability researcher dispatched by the Claude Security scan workflow; not for direct invocation or general exploration.
32.8K stars
Plugins
All plugins →receipts
A personal Claude Code impact report for justifying your usage to a manager or a self-review: what you shipped, which projects it went to, and each project's share of your usage. Reads your ~/.claude/projects transcripts and runs read-only git locally; only counts and project names are sent to write
32.8K stars
atomic-agents
Comprehensive development workflow for building AI agents with the Atomic Agents framework. Includes specialized agents for schema design, architecture planning, code review, and tool development. Features guided workflows, progressive-disclosure skills, and best practice validation.
6.1K stars
databases-on-aws
Expert database guidance for the AWS database portfolio. Design schemas, execute queries, handle migrations, and choose the right database for your workload.
844 stars
Skills
All skills →create-atomic-tool
Build a `BaseTool[InSchema, OutSchema]` subclass — input/output schemas, `BaseToolConfig`, `run()` (and optional `run_async()`), env-driven secrets, typed failure outputs. Use when the user asks to "add a tool", "create a tool", "wrap an API as a tool", "build a `BaseTool`", "make a calculator/searc
6.1K stars
create-atomic-context-provider
Build a `BaseDynamicContextProvider` that injects a named, titled block into an agent's system prompt at every `run()` — current time, user identity, retrieved RAG docs, session state, cached DB schema. Use when the user asks to "add a context provider", "inject X into the prompt", "give the agent d
6.1K stars
framework
Guide for the Atomic Agents Python framework — schemas, agents, tools, context providers, prompts, orchestration, and provider configuration. Use when code imports from `atomic_agents`, defines an `AtomicAgent`, `BaseTool`, or `BaseIOSchema`, or the user asks about multi-agent orchestration or LLM-p
6.1K stars
MCP Servers
All mcp servers →Commands
All commands →altimate
Delegate a task to altimate-code, the specialised data-engineering CLI agent (warehouse access, column-level lineage, cross-DB, FinOps, query optimization)
windsor-types
Generate TypeScript type definitions for a Windsor.ai connector's data schema
design-survey
Interactive design session for a new survey — research goal, audience, hypotheses, questions, modality, output schema