feat(hooks): add block-image-read hook to prevent context overflow

Add PreToolUse hook that intercepts Read tool calls on image files
(.png, .jpg, .webp, etc.) and blocks them with helpful message.

This prevents context exhaustion when image generation skills
produce multiple files and the agent tries to read them (each
image can consume 100K+ tokens).

Configuration:
- Enable via config.yaml: hooks.block_image_read.enabled: true
- Or env var: CCS_BLOCK_IMAGE_READ=1

Hook integration:
- lib/hooks/block-image-read.cjs - the hook script
- src/utils/hooks/image-read-block-hook-env.ts - config loader
- Integrated into all spawn locations (ccs.ts, shell-executor,
  cliproxy-executor)

Closes #426
This commit is contained in:
kaitranntt committed 2026-02-02 17:28:21 -05:00
1 parent 24b03121fd
commit 38eb74043c
6 files changed
+221 -2

No files matched your search

+5
View File
@@ -13,6 +13,7 @@ import {
ensureProfileHooks,
} from './utils/websearch-manager';
import { getGlobalEnvConfig } from './config/unified-config-loader';
import { getImageReadBlockHookEnv } from './utils/hooks/image-read-block-hook-env';
import { fail, info } from './utils/ui';
// Import centralized error handling
@@ -164,10 +165,12 @@ async function execClaudeWithProxy(
const isWindows = process.platform === 'win32';
const needsShell = isWindows && /\.(cmd|bat|ps1)$/i.test(claudeCli);
const webSearchEnv = getWebSearchHookEnv();
const imageReadBlockEnv = getImageReadBlockHookEnv();
const env = {
...process.env,
...envVars,
...webSearchEnv,
...imageReadBlockEnv,
CCS_PROFILE_TYPE: 'settings', // Signal to WebSearch hook this is a third-party provider
};
@@ -612,6 +615,7 @@ async function main(): Promise<void> {
// Use --settings flag (backward compatible)
const expandedSettingsPath = getSettingsPath(profileInfo.name);
const webSearchEnv = getWebSearchHookEnv();
const imageReadBlockEnv = getImageReadBlockHookEnv();
// Get global env vars (DISABLE_TELEMETRY, etc.) for third-party profiles
const globalEnvConfig = getGlobalEnvConfig();
const globalEnv = globalEnvConfig.enabled ? globalEnvConfig.env : {};
@@ -633,6 +637,7 @@ async function main(): Promise<void> {
...globalEnv,
...settingsEnv, // Explicitly inject all settings env vars
...webSearchEnv,
...imageReadBlockEnv,
CCS_PROFILE_TYPE: 'settings', // Signal to WebSearch hook this is a third-party provider
};
execClaude(claudeCli, ['--settings', expandedSettingsPath, ...remainingArgs], envVars);