Skip to content
Marketing
Hook

Hooks

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

From plugin
digital-marketing-pro
942164 skills24 agents5 commands1 hook

Claude Code

$ npx -y skills add indranilbanerjee/digital-marketing-pro --agent claude-code

What fires, and when

PreToolUse

  • MatchesBash|PowerShellpython3 "${CLAUDE_PLUGIN_ROOT}/hooks/gate_live_writes.py" 2>/dev/null || python "${CLAUDE_PLUGIN_ROOT}/hooks/gate_live_writes.py"python3 "${CLAUDE_PLUGIN_ROOT}/hooks/gate_live_writes.py" 2>/dev/null || python "${CLAUDE_PLUGIN_ROOT}/hooks/gate_live_writes.py"python3 "${CLAUDE_PLUGIN_ROOT}/hooks/gate_live_writes.py" 2>/dev/null || python "${CLAUDE_PLUGIN_ROOT}/hooks/gate_live_writes.py"python3 "${CLAUDE_PLUGIN_ROOT}/hooks/gate_live_writes.py" 2>/dev/null || python "${CLAUDE_PLUGIN_ROOT}/hooks/gate_live_writes.py"
Read hooks/hooks.json

Where it lives

  • hooks/gate_live_writes.pyRunsGitHub
    Read the script
    #!/usr/bin/env python3
    """PreToolUse hook: the host asks the user before Digital Marketing Pro prepares, approves or fires a live write.
    
    A live write is three shell commands the model runs itself: `connector_executor.py --execute` (prepare),
    `approval-manager.py --action approve` (or `create-standing`), then `connector_executor.py --execute
    --approval-id X` (fire). The approval record proves those steps ran in order; only the host's permission prompt
    shows them to a person. An allow rule (a skill's `allowed-tools`, or a "Yes, and don't ask again" saved for the
    executor's path) would skip that prompt, so this hook answers "ask" for those commands, which makes Claude Code
    prompt even when an allow rule matches.
    
    hooks.json runs it only when the command names one of the two scripts (`if` filters), so it adds nothing to any
    other shell command. It is a string check: no model call, no network, no file access. Stdlib only.
    
    Limits, stated plainly: it reads the command text. A command that reaches the scripts without naming them (a glob
    such as `connector_exec*.py`, a wrapper script) is not seen. Hosts other than Claude Code may not run plugin
    hooks at all; there the typed `yes` in each skill and the host's own prompt are what remain.
    """
    from __future__ import annotations
    
    import json
    import re
    import sys
    
    APPROVAL_SCRIPT = re.compile(r"approval[-_]manager(?:\.py)?\b", re.I)
    EXECUTOR_SCRIPT = re.compile(r"connector[-_]executor(?:\.py)?\b", re.I)
    # approve / create-standing as a whole word: `--action approve`, `--action=approve`, `--action "approve"`.
    APPROVAL_ACTIONS = re.compile(r"(?<![\w-])(approve|create-standing)(?![\w-])")
    # --execute, --approval-id and --prepare-batch, plus any shortened `--e…` / `--approval…` / `--prep…` spelling
    # (the scripts refuse abbreviations since 3.42.0; the hook does not rely on that).
    EXECUTOR_LIVE_FLAGS = re.compile(r"(?<![\w-])--(?:e[\w-]*|approval[\w-]*|prep[\w-]*)")
    
    REASON_APPROVE = ("Digital Marketing Pro: this records an approval for a live write (post, email, CRM, ads). "
                      "Allow it only if you asked for this exact action.")
    REASON_FIRE = ("Digital Marketing Pro: this prepares or sends a live write through a connector (post, email, CRM, "
                   "ads). Allow it only if you asked for this exact action.")
    
    
    def command_of(raw: str) -> str:
        """The shell command in a PreToolUse payload. Unreadable input falls back to the raw text, so a payload the
        hook cannot parse is still checked rather than waved through."""
        try:
            payload = json.loads(raw)
        except ValueError:
            return raw
        if not isinstance(payload, dict):
            return raw
        tool_input = payload.get("tool_input")
        if isinstance(tool_input, dict) and isinstance(tool_input.get("command"), str):
            return tool_input["command"]
        return raw
    
    
    def reason_to_ask(command: str) -> str | None:
        """Why the host must ask before this command runs, or None when it is not a live-write step."""
        if APPROVAL_SCRIPT.search(command) and APPROVAL_ACTIONS.search(command):
            return REASON_APPROVE
        if EXECUTOR_SCRIPT.search(command) and EXECUTOR_LIVE_FLAGS.search(command):
            return REASON_FIRE
        return None
    
    
    def decision(reason: str) -> dict:
        return {"hookSpecificOutput": {"hookEventName": "PreToolUse",
                                       "permissionDecision": "ask",
                                       "permissionDecisionReason": reason}}
    
    
    def main() -> int:
        try:
            raw = sys.stdin.read()
        except (OSError, ValueError):
            return 0
        reason = reason_to_ask(command_of(raw))
        if reason:
            sys.stdout.write(json.dumps(decision(reason)))
        return 0
    
    
    if __name__ == "__main__":
        sys.exit(main())
    

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.

@indranilbanerjee
Ships withdigital-marketing-pro

Your agency just signed a 50-brand client. The previous agency left no playbook. Three brands are bleeding budget, two have stale positioning, one is launching in a regulated jurisdiction next month. Where do you start?

942164 skills24 agents
Get the whole plugin

Stars on GitHub

Momentum

stars in total
942
Star history of indranilbanerjee/digital-marketing-pro on GitHub, a chart by star-history.com

More plugins that ship hooks.

claude-seo

claude-seo

An open-source SEO analysis plugin for Claude Code covering technical SEO, content quality, Schema.org markup, AI search optimization, local SEO and e-commerce, with specialist skills for keyword data, backlinks, image generation and site crawling.

33 skills+228k
@agricidaniel@agricidaniel
Install Plugin
aaron-marketing

aaron-marketing

Gives a marketing team an AI staff for planning and running campaigns across SEO, content, paid ads, email, influencer work and product launches. Each area comes with ready-made commands that work on data you supply.

7 hooks+13.1k
@aaron-he-zhu@aaron-he-zhu
Install Plugin
ralph-wiggum-marketer

ralph-wiggum-marketer

Runs an autonomous loop for SaaS content marketing and copywriting, with commands to initialize, run, check status, and cancel it. A stop hook keeps the loop going when an agent stops.

1 skill+2780
@muratcankoylan@muratcankoylan
Install Plugin
claude-repurpose

claude-repurpose

Content Repurposing Engine for Claude Code, Turn 1 piece of content into 10+ platform-optimized posts in seconds.

21 skills+2167
@agricidaniel@agricidaniel
Install Plugin
content-ideas

content-ideas

Scrapes tracked competitor accounts on X, Instagram, TikTok and YouTube, scores what is performing well, and turns it into a daily feed of content ideas framed against your own brand.

1 skill+2147
@bradautomates@bradautomates
Install Plugin
email

email

Professional email management, deliverability optimization, and marketing strategy powered by Claude Code.

6 skills+2132
@agricidaniel@agricidaniel
Install Plugin
claude-seo-ai

claude-seo-ai

The SEO + AI-search (GEO/AEO) optimization toolkit for Claude Code, two-score audit + opt-in fixer. Built for 2026-2027.

34 skills+281
@hainrixz@hainrixz
Install Plugin
akii-seo-ai-search-optimizer

akii-seo-ai-search-opt…

A free Claude Code toolkit for SEO, AI answer engine optimization, and generative engine optimization. Its skills cover AI visibility checks, broken link audits, competitor scorecards, content briefs, and content strategy plans.

12 skills+378
@akii-technologies-ltd@akii-technologies-ltd
Install Plugin

Questions about the hooks in digital-marketing-pro.

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