
Un'app che mette al primo posto la privacy e rimuove le filigrane AI dai contenuti di tua proprietà.
_ _ _ ____ ___ ____ ____ _ _ ____ ____ _ _ ____ ____ ____ _ _ ____ _ _ ____ ____
| | | |__| | |___ |__/ |\/| |__| |__/ |_/ [__ __ |__/ |___ |\/| | | | | |___ |__/
|_|_| | | | |___ | \ | | | | | \ | \_ ___] | \ |___ | | |__| \/ |___ | \
Skill per agent + servizio Python basato sulla stdlib per rimuovere marcature di provenienza AI multi-vendor da testo e file — per privacy e igiene su contenuti di tua proprietà. Lo skill è un thin client: pilota il meccanismo via HTTP, quindi l'host dell'agent non necessita di Python.
| Livello | Obiettivo | Come |
|---|---|---|
| A | Unicode invisibile, spazi esotici, bidi, tag chars | Script Python deterministici |
| B | Watermark testuali statistici (token-sampling) | Riscrittura dell'agent + hook opzionale rewrite_text.py |
| File | C2PA / EXIF / XMP / proprietà documento | PNG, JPEG, WebP, AVIF, HEIC, BMP, GIF, TIFF, SVG, PDF, DOCX, XLSX, PPTX, EPUB, ODT, HTML, Markdown, MP4/MOV/M4A/M4V, WAV, MP3, FLAC |
Vendor / ecosistemi (a livello di classe): Claude, Gemini / SynthID-Text, superfici di provenienza OpenAI, marcature open-LLM in stile Kirchenbauer (green-list) e keyed-Gumbel / EXP (Aaronson).
Ultima release: v0.7.0
Percorso dello skill: skills/remove-ai-marks/
Percorso del servizio: service/
(migrazione: precedentemente remove-claude-marks; l'alias slash /remove-claude-marks è ancora documentato)
Lo skill non include codice — chiama il servizio via HTTP. Installa lo skill (solo markdown) e avvia il servizio, poi imposta WATERMARKS_SERVICE_URL se non è http://127.0.0.1:8765.
In Claude Code, la via più rapida è il plugin marketplace incluso — nessun clone, e si aggiorna sul posto. Ovunque altro, un singolo installer copre ogni host supportato (Python 3.10+ stdlib, nessuna dipendenza):```bash python3 install_skill.py --skill remove-ai-marks --target claude-code
| Host | Target | Arriva in |
| --- | --- | --- |
| Claude Code (personale) | `--target claude-code` | `~/.claude/skills/<skill>` (rispetta `CLAUDE_CONFIG_DIR`) |
| Claude Code (progetto) | `--target claude-project --project-dir PATH` | `PATH/.claude/skills/<skill>` |
| Cowork, claude.ai, sessioni cloud, routine | `--target cowork` | `dist/<skill>.zip` da caricare in **Customize → Skills** |
| Cursor | `--target cursor` (predefinito) | `~/.cursor/skills/<skill>` |
Skill distribuite: `remove-ai-marks` (completa, con supporto del servizio) e
`clean-user-facing-text` (solo testo, autonoma). `--list` le stampa.
Le installazioni esistenti vengono preservate a meno che non si passi `--force`; la sostituzione viene
preparata prima e l'installazione precedente viene conservata come backup con nome univoco.
`--link` crea un symlink a questo checkout invece di copiare, così le modifiche vengono recepite
in tempo reale. Su Windows, usa `py install_skill.py ...`; il wrapper `install-skill.sh` è
fornito per le shell macOS/Linux.
Prima di scrivere qualsiasi cosa, l'installer convalida la skill rispetto alle
regole di packaging [Agent Skills](https://agentskills.io) che gli upload su claude.ai
e la Skills API applicano: frontmatter conforme alla specifica (`name`, `description`,
`license`, `compatibility`, `metadata`, `allowed-tools`), un `name` in minuscolo con trattini
di al massimo 64 caratteri corrispondente alla directory, una `description` non vuota
di al massimo 1024 caratteri. Il bundle Cowork deve inoltre
rispettare il limite di upload di 30 MB, che il packager applica.
### Pulizia automatica tramite hook (deterministica)
Una skill è un'istruzione: il modello decide se invocarla, e il
modello è ciò che produce i marchi. Un **hook** viene eseguito dall'harness
a ogni chiamata di tool corrispondente, senza bisogno di cooperazione. Questo rende l'hook la
metà deterministica di questo flusso di lavoro.
Il plugin registra un hook `PostToolUse` su `Write|Edit|MultiEdit|NotebookEdit`
che esegue [`service/scripts/hook_written_file.py`](https://github.com/guillaumemeyer/watermarks-remover/blob/main/service/scripts/hook_written_file.py)
sul file appena scritto dall'agente. Due modalità, che seguono la convenzione pre-commit
del controllo predefinito:
| Modalità | Comportamento |
| --- | --- |
| `check` (predefinita) | Segnala i marchi di provenienza, lascia il file invariato. I risultati vanno al modello (exit 2), così può proporre di pulirli. |
| `clean` | Rimuove i marchi sul posto, poi informa il modello che il file su disco è cambiato. |
Imposta la modalità dalle impostazioni del plugin (**Hook mode** in `/plugin manage`,
letta dall'hook come `CLAUDE_PLUGIN_OPTION_HOOK_MODE`), oppure con
`WATERMARKS_HOOK_MODE=clean` nell'ambiente. Il comando dell'hook deliberatamente
**non** interpola `${user_config.hook_mode}`: Claude Code rifiuta di eseguire
un hook che fa riferimento a un'opzione che l'utente non ha mai aperto `/plugin manage` per
impostare — un `default` dichiarato non lo soddisfa — quindi interpolarlo significherebbe
che l'hook non verrebbe mai eseguito silenziosamente su un'installazione nuova. Il rilevamento riutilizza
`scan_file` / `is_actionable` di `audit_lib`, così l'hook, il gate pre-commit e l'esportazione
SARIF della CI concordano su cosa conta come actionable; la pulizia richiama
`clean_file.py`, così nessuna logica di pulizia viene duplicata. La modalità `clean` scrive su un
file temporaneo adiacente e scambia solo in caso di differenza reale, così i file che erano
già puliti mantengono il loro mtime e non ritriggerano i file watcher.
Senza il plugin, collegalo tu stesso in `~/.claude/settings.json` (o in un
`.claude/settings.json` di progetto):```json
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit|MultiEdit|NotebookEdit",
"hooks": [
{
"type": "command",
"command": "python3",
"args": ["/path/to/watermarks-remover/service/scripts/hook_written_file.py",
"--mode", "check"],
"timeout": 30
}
]
}
]
}
}
Su Windows, sostituisci python3 con py.
Cosa non può fare un hook. Nessun hook può riscrivere il messaggio di chat dell'assistente
prima che tu lo legga. L'hook Stop di Claude Code riceve last_assistant_message
in sola lettura, e non esiste un filtro pre-invio per le risposte finali — lo stesso limite
che questo progetto documenta già per le regole di Cursor. Quindi la garanzia
deterministica copre i file che l'agente scrive, più il
gate pre-commit per qualsiasi cosa in procinto di entrare in git. Il testo che
esiste solo nel transcript della chat dipende ancora dal flusso di lavoro della skill,
che si basa su istruzioni del modello ed è quindi best-effort.