Skip to content
Development
Hook

Hooks

What toonify-mcp runs automatically, and when. A hook is a command Claude Code fires at a fixed moment, without you asking for it.

From plugin
toonify-mcp
671 hook

Claude Code

> /plugin marketplace add PCIRCLE-AI/toonify-mcp
> /plugin install toonify-mcp@pcircle-ai

What fires, and when

PostToolUse

  • MatchesRead|Grep|Glob|WebFetch|Bashnode ${CLAUDE_PLUGIN_ROOT}/hooks/post-tool-use.mjs
Read hooks/hooks.json

Where it lives

  • hooks/post-tool-use.mjsRunsGitHub
    Read the script
    #!/usr/bin/env node
    
    /**
     * Toonify PostToolUse Hook
     *
     * Intercepts tool results from Read, Grep, Glob, WebFetch, Bash and:
     * - Converts structured data (JSON/YAML) to TOON format
     * - Collapses repetitive debug output (test failures, stack traces, diagnostics)
     *
     * Source code is NOT compressed: the comment-stripping heuristics truncated
     * regex literals such as /^https?:\/\// at the `//`, producing code that no
     * longer parses. See src/optimizer/compressors/code.ts for the full rationale.
     *
     * CSV is not converted: TOON measured as a net loss on CSV at every size.
     *
     * tool_response is a structured object for the tools this hook matches, not
     * a plain string — see extractText() below for the shapes verified (Read,
     * WebFetch, Grep's 'content'/'count' modes, and Bash's combined `stdout`
     * field, each per the tool's own schema).
     *
     * Compressed content ALWAYS goes out via hookSpecificOutput.updatedToolOutput,
     * which REPLACES what Claude sees — that is what actually shrinks context.
     * The hook never uses additionalContext: it APPENDS (verified live that
     * `suppressOutput` doesn't hide the original), so it would grow total context
     * instead of shrinking it. For an object tool_response the replacement is the
     * object with its text field swapped; for a (compat-only) string
     * tool_response it's the compressed string itself. Where tool_response is an
     * OBJECT with no compressible field for that tool (Grep's default
     * 'files_with_matches' mode, Glob, an unmatched tool), the hook passes
     * through untouched — there is nothing to safely replace.
     *
     * Input:  JSON on stdin with { tool_name, tool_response, ... }
     * Output: JSON on stdout with { continue, hookSpecificOutput }
     */
    
    import { encode as toonEncode } from '@toon-format/toon';
    import { parse as yamlParse } from 'yaml';
    import { readFileSync, existsSync } from 'fs';
    import { join } from 'path';
    import { homedir } from 'os';
    
    // --- Configuration ---
    
    /**
     * Maximum content size to attempt JSON.parse/yamlParse/detection on (10 MB).
     * Mirrors MAX_CONTENT_SIZE in src/optimizer/token-optimizer.ts — this hook
     * has its own detection pipeline (see detectStructuredData/detectDebugOutput
     * below) and needs the same DoS-prevention ceiling; without it, arbitrarily
     * large Read/WebFetch content gets parsed synchronously with no bound.
     */
    const MAX_CONTENT_SIZE = 10 * 1024 * 1024;
    
    const DEFAULT_CONFIG = {
      enabled: true,
      minTokensThreshold: 50,
      minSavingsThreshold: 30,
      // Write/Edit are mutations — their result (success flag / diff) isn't
      // compressible content and altering it could mislead Claude. Bash is NOT
      // skipped: its stdout is a large token sink (curl/jq JSON, test-runner and
      // build logs) that the same selective detect→compress path handles safely
      // (see the Bash branch in extractText). Small command output stays below
      // the token threshold and passes through untouched.
      skipToolPatterns: ['Write', 'Edit'],
    };
    
    function loadConfig() {
      const configPath = join(homedir(), '.claude', 'toonify-config.json');
      let fileConfig = {};
    
      if (existsSync(configPath)) {
        try {
          fileConfig = JSON.parse(readFileSync(configPath, 'utf-8'));
        } catch {
          // Ignore invalid config
        }
      }
    
      // Environment variable overrides
      const envConfig = {};
      if (process.env.TOONIFY_ENABLED !== undefined) {
        envConfig.enabled = process.env.TOONIFY_ENABLED !== 'false';
      }
      if (process.env.TOONIFY_MIN_TOKENS) {
        envConfig.minTokensThreshold = parseInt(process.env.TOONIFY_MIN_TOKENS, 10);
      }
      if (process.env.TOONIFY_MIN_SAVINGS) {
        envConfig.minSavingsThreshold = parseInt(process.env.TOONIFY_MIN_SAVINGS, 10);
      }
      if (process.env.TOONIFY_SKIP_TOOLS) {
        envConfig.skipToolPatterns = process.env.TOONIFY_SKIP_TOOLS.split(',');
      }
    
      return { ...DEFAULT_CONFIG, ...fileConfig, ...envConfig };
    }
    
    // --- Structured Data Detection ---
    
    function detectStructuredData(content) {
      // Try JSON
      try {
        const data = JSON.parse(content);
        if (typeof data === 'object' && data !== null) {
          return { type: 'json', data };
        }
      } catch {
        // Not JSON
      }
    
      // Try YAML — gated on STRUCTURE (looksLikeYAML), then accept any non-null
      // object. The old gate (`Object.keys(data).length > 1`) silently skipped the
      // most valuable and most common YAML shape: a single top-level key holding a
      // large uniform list (`services:`, a k8s `spec:`, `data:`), which is exactly
      // what TOON compresses best. The structural density check (looksLikeYAML) is
      // what keeps prose out, so the key-count gate isn't needed for that job.
      // Mirrors Detector.tryYAML / looksLikeYAML in src/optimizer/pipeline/detector.ts.
      if (looksLikeYAML(content)) {
        try {
          const data = yamlParse(content);
          if (typeof data === 'object' && data !== null) {
            return { type: 'yaml', data };
          }
        } catch {
          // Not YAML
        }
      }
    
      return null;
    }
    
    // Structural YAML heuristic — density of `key: value` / list / indented lines.
    // This is what keeps prose (which yaml.parse would happily coerce into some
    // object) from being misdetected, so detectStructuredData can drop the old
    // top-level-key-count gate. Ported from looksLikeYAML in
    // src/optimizer/pipeline/detector.ts — keep the two in sync. Each scanned line
    // is length-capped first (capLine), matching the hook's ReDoS discipline for
    // every other line-scanning predicate here.
    function looksLikeYAML(content) {
      const lines = content.split('\n').filter(l => l.trim());
      if (lines.length < 3) return false;
    
      const yamlLinePattern = /^\s*[\w][\w\s.-]*:\s*.+/;
      const listItemPattern = /^\s*-\s+/;
      const indentedPattern = /^\s{2,}\S/;
    
      let yamlLines = 0;
      let listItems = 0;
      let indented = 0;
    
      for (const raw of lines.slice(0, 20)) {
        const line = capLine(raw);
        if (yamlLinePattern.test(line)) yamlLines++;
        if (listItemPattern.test(line)) listItems++;
        if (indentedPattern.test(line)) indented++;
      }
    
      const hasStructure = (

Read the script before you install anything that runs on your machine. This is the one part of a plugin that acts without being asked.

Stats
67
Stars
11
Forks
Maintained
Maintenance
TypeScript
Language
MIT
License
Last commit
Created

Repo: PCIRCLE-AI/toonify-mcp

@pcircle-ai
Ships withtoonify-mcp

Context compression plugin for Claude Code. Automatically trims large tool output—JSON, YAML, stack traces, and logs—before it enters the context window. Works as a Claude Code plugin (automatic, zero-config) or as an MCP server (on-demand).

Stars on GitHub

Momentum

stars in total
67
Star history of PCIRCLE-AI/toonify-mcp on GitHub, a chart by star-history.com

More plugins that ship hooks.

superpowers

superpowers

A development methodology for coding agents that makes the agent brainstorm before building, follow plans, run parallel work and finish branches in a disciplined way. You get fewer skipped steps and more consistent results from your coding assistant.

15 skills1 hook318k
@obra@obra
Install Plugin
ponytail

ponytail

A Claude Code plugin with skills for auditing a whole repo, reviewing a change, listing deferred shortcut comments, and showing measured savings and a quick command reference.

6 skills10 hooks191k
@dietrichgebert@dietrichgebert
Install Plugin
agent-skills

agent-skills

Walks a software change from a written spec through design, testing, code review, CI/CD, and release, applying the matching engineering skill at each stage. Useful for developers using Claude Code on full development workflows.

25 skills+3117k
@addyosmani@addyosmani
Install Plugin
planning-with-files

planning-with-files

Persistent file-based planning for AI coding agents on long-running, multi-step tasks. It keeps task_plan.md, findings.md and progress.md on disk, so work can resume after /clear or context compaction.

6 skills+228k
@othmanadi@othmanadi
Install Plugin
gsd-core

gsd-core

A spec-driven development workflow for Claude Code that guides a project through planning, phases, milestone audits and fixes. Includes skills to generate tests from UAT criteria and to audit completed work.

72 skills+312k
@open-gsd@open-gsd
Install Plugin
superpowers-zh

superpowers-zh

Chinese-language skill pack for Claude Code that adds workflow guidance for brainstorming, TDD, debugging, and code review, plus Chinese conventions for commits, documentation, and domestic Git platforms like Gitee and Coding.net.

21 skills1 hook8.5k
@jnmetacode@jnmetacode
Install Plugin
socraticode

socraticode

Gives Claude Code semantic search, dependency graph and architecture context over a codebase, so an AI assistant can explore and understand a project's code. Includes skills for indexing a project and managing its file watching.

2 skills+33.4k
@giancarloerra@giancarloerra
Install Plugin
cocoindex-code

cocoindex-code

A lightweight code search engine that uses AST-based semantic search with local embeddings and incremental indexing. It helps Claude Code users find code faster and more efficiently.

1 skill1 MCP+13k
@cocoindex-io@cocoindex-io
Install Plugin

Questions about the hooks in toonify-mcp.

Which coding agents can use the hooks in toonify-mcp?
The hooks in toonify-mcp install in Claude Code and Cursor: each runs Claude Code hooks from .claude/settings.json, so copy the hooks there.