Skip to content
Security
Hook

Hooks

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

From plugin
watermarks-remover
25k2 skills1 hook
Install
> /plugin marketplace add guillaumemeyer/watermarks-remover
> /plugin install watermarks-remover@watermarks-remover

Ships with watermarks-remover. Installing the plugin gets these hooks.

What fires, and when

PostToolUse

  • MatchesWrite|Edit|MultiEdit|NotebookEditnode
Read hooks/hooks.json

In the plugin's words

How watermarks-remover describes its own hook set.

After the agent writes a file, report (or strip) AI/C2PA provenance marks in it.

Where it lives

  • hooks/run_hook.jsGitHub
    Read the script
    #!/usr/bin/env node
    /**
     * Cross-platform launcher for the watermarks-remover Claude Code plugin hook.
     *
     * Claude Code runs on Node.js across Windows, macOS, and Linux, so `node` is
     * always available. Python, however, may be `py -3`, `python3`, or `python`
     * depending on platform and installation. This runner probes each candidate to
     * confirm it exists and is a Python 3.10+ interpreter (the repository's floor)
     * before committing to it, then proxies stdin/stdout/stderr and the exit code
     * straight through to hook_written_file.py.
     */
    
    const { spawn, execFile } = require('child_process');
    const path = require('path');
    
    const script = path.resolve(__dirname, '..', 'service', 'scripts', 'hook_written_file.py');
    
    const isWin = process.platform === 'win32';
    const candidates = isWin
      ? [
          ['py', ['-3']],
          ['python', []],
          ['python3', []],
        ]
      : [
          ['python3', []],
          ['python', []],
        ];
    
    // Repo requirement: Python 3.10+ stdlib only. `python` may be Python 2 or an
    // older Python 3, so the probe must reject anything below this floor.
    const VERSION_CHECK = 'import sys; sys.exit(0 if sys.version_info >= (3, 10) else 1)';
    
    // The interpreter we committed to running. Guarding on this means a candidate
    // that failed to spawn (ENOENT) cannot let its later `close` event terminate
    // the process out from under a fallback candidate already running.
    let active = null;
    
    function run(cmd, extraArgs, index) {
      const args = [...extraArgs, script, ...process.argv.slice(2)];
      const child = spawn(cmd, args, { stdio: 'inherit', windowsHide: true });
      active = child;
    
      child.on('error', (err) => {
        if (err.code === 'ENOENT') {
          // The interpreter vanished between probe and launch; fall back rather
          // than die. Clearing active makes this child's later close a no-op.
          active = null;
          launch(index + 1);
        } else {
          console.error(`watermarks-remover: error running ${cmd}: ${err.message}`);
          process.exit(1);
        }
      });
    
      child.on('close', (code) => {
        // Only the selected child may exit the process; a failed candidate that
        // still fires close after an ENOENT error must not kill a fallback.
        if (active === child) process.exit(code ?? 0);
      });
    }
    
    function launch(index) {
      if (index >= candidates.length) {
        const tried = candidates
          .map(([cmd, extra]) => (extra.length ? `${cmd} ${extra.join(' ')}` : cmd))
          .join(', ');
        console.error(
          `watermarks-remover: could not find a working Python 3.10+ interpreter (tried ${tried})`
        );
        process.exit(1);
      }
    
      const [cmd, extraArgs] = candidates[index];
    
      // Probe the candidate: confirm it exists and is at least Python 3.10. Any
      // failure -- a missing binary or an older Python -- falls through to the next
      // candidate.
      execFile(cmd, [...extraArgs, '-c', VERSION_CHECK], (err) => {
        if (err) {
          launch(index + 1);
        } else {
          run(cmd, extraArgs, index);
        }
      });
    }
    
    launch(0);
    

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.

Ships withwatermarks-remover

Agent skill + stdlib Python service to strip multi-vendor AI provenance marks from text and files — for privacy and hygiene on content you own. The skill is a thin client: it drives the machinery over HTTP, so the agent host needs no Python.

Get the whole plugin
Stats
25,007
Stars
2,864
Forks
Active
Maintenance
Python
Language
MIT
License
11h ago
Last commit
2mo ago
Created
3h ago
Added

Repo: guillaumemeyer/watermarks-remover