_ _ _ ____ ___ ____ ____ _  _ ____ ____ _  _ ____    ____ ____ _  _ ____ _  _ ____ ____
| | | |__|  |  |___ |__/ |\/| |__| |__/ |_/  [__  __ |__/ |___ |\/| |  | |  | |___ |__/
|_|_| |  |  |  |___ |  \ |  | |  | |  \ | \_ ___]    |  \ |___ |  | |__|  \/  |___ |  \

watermarks-remover

CI Release

Agent skill + stdlib Python scripts to strip multi-vendor AI provenance marks from text and files — for privacy and hygiene on content you own.

Layer Target How
A Invisible Unicode, exotic spaces, bidi, tag chars Deterministic Python scripts
B Statistical (token-sampling) text watermarks Agent rewrite + optional rewrite_text.py hook
Files C2PA / EXIF / XMP / doc props PNG, JPEG, SVG, PDF, DOCX, ODT, HTML, Markdown

Vendors / ecosystems (class-level): Claude, Gemini / SynthID-Text, OpenAI provenance surfaces, open-LLM Kirchenbauer-style marks.

Latest release: v0.1.0

Skill path: skills/remove-ai-marks/
(migration: formerly remove-claude-marks; slash alias /remove-claude-marks still documented)

Install (agent skill)

# Grok Build / project-local
mkdir -p .grok/skills
ln -sfn "$(pwd)/skills/remove-ai-marks" .grok/skills/remove-ai-marks

# User-global Grok
mkdir -p ~/.grok/skills
ln -sfn "$(pwd)/skills/remove-ai-marks" ~/.grok/skills/remove-ai-marks

Invoke with /remove-ai-marks or ask to “strip AI watermarks / C2PA / Claude marks / SynthID-class text.”

Optional system tools (auto-used when present):

Tool Role
c2patool Inspect C2PA manifests
exiftool Residual metadata strip (esp. PDF)

Core scripts need Python 3.10+ stdlib only. Layer B model calls are optional.

Quick use (scripts)

SCRIPTS=skills/remove-ai-marks/scripts

# Unified inspect / clean
python3 "$SCRIPTS/inspect_file.py" draft.md
python3 "$SCRIPTS/clean_file.py" draft.md -o draft.cleaned.md
python3 "$SCRIPTS/clean_file.py" photo.png -o photo.cleaned.png
python3 "$SCRIPTS/clean_file.py" notes.docx -o notes.cleaned.docx

# Text Layer A
python3 "$SCRIPTS/inspect_text.py" draft.md
python3 "$SCRIPTS/clean_text.py" draft.md -o draft.cleaned.md --stats

# Layer B rewrite hook (default: print prompt only — no model required)
python3 "$SCRIPTS/rewrite_text.py" draft.md --backend print-prompt --strength paraphrase
# Optional local Ollama:
# WATERMARKS_REWRITE_BACKEND=ollama WATERMARKS_REWRITE_MODEL=llama3.2 \
#   python3 "$SCRIPTS/rewrite_text.py" draft.md -o draft.rewritten.md

# Images
python3 "$SCRIPTS/inspect_image.py" shot.png
python3 "$SCRIPTS/clean_image.py" shot.png -o shot.cleaned.png

Coverage matrix

Channel Claude Gemini/SynthID OpenAI Open-LLM
Unicode / edit-based text Layer A Layer A Layer A Layer A
Statistical sampling text Layer B best-effort Layer B best-effort Layer B if present Layer B best-effort
C2PA / file metadata Yes (listed formats) Yes when present Yes when present Yes when present
Pixel image marks Out of scope Out of scope Out of scope Out of scope
Training backdoors Out of scope Out of scope Out of scope Out of scope

Details: skills/remove-ai-marks/references/vendor-notes.md, mark-classes.md.


How text marking works (short)

Modern LLM watermarks often hide a signal in which tokens are chosen (generative / sampling bias), not only in invisible characters. Edit-based schemes inject Unicode or synonym rules. File schemes attach C2PA or generator metadata.

  • Layer A removes edit-based Unicode carriers (testable).
  • Layer B attacks sampling watermarks via heavy rewrite (best-effort; literature-standard attacks such as paraphrase / back-translation).
  • File cleaners strip C2PA/XMP/props from supported containers.

Until vendors ship public detectors and keys, no tool can honestly certify “this fails the official check.” Reports must separate verifiable vs best-effort work.

Prefer a non-origin model for Layer B (do not rewrite Claude text with Claude if you are trying to avoid re-stamping).


Disclaimer: what removing a text watermark costs

Text watermarks live in the wording itself: the signal is spread across token choices, so nearly every sentence carries a little of it. Two consequences follow, and they are why Layer B is honestly described as best-effort rather than a magic eraser.

  1. Removal means rewording, not restructuring. Shuffling paragraphs, changing headings, or light touch-ups barely move the signal. Stripping a statistical mark requires rewriting a substantial fraction of the text — sentence by sentence, not section by section.

  2. Rewording degrades the copy. Any rewrite replaces the original word choices with the rewriting model's, which flattens tone, voice, and precision. On production copy (SEO, marketing, client work) that degradation is real and often visible to the people who care most about the writing. It is like taking text from a top-tier model and asking a less capable model to rewrite it from scratch: the result cannot exceed the rewrite model's ceiling.

Which leads to the honest full-circle question:

If the plan is to rewrite the text with a cheaper model anyway, why pay for a premium model in the first place? Generating directly with the cheaper model is simpler, cheaper, and produces the same — or better — end result.

Layer B makes sense when you specifically want the premium model's thinking and drafting and accept a rewrite pass to satisfy a hygiene or privacy requirement — not as a cheap route to mark-free text.

When to skip Layer B:

  • Quality matters more than hygiene: use the lossless path — Layer A Unicode scrub plus the file metadata cleaners — and keep the original prose.
  • Rewriting anyway: use a non-origin model (rewriting with the origin model can re-stamp the text), and remember residual risk remains — no tool can certify a vendor detector will fail.

File formats

Format Inspect Clean
PNG / JPEG C2PA chunks / APP11, AI XMP hints Drop metadata segments
SVG <metadata>, XMP Strip blocks
PDF Byte/XMP + optional tools exiftool preferred; degraded without it
DOCX docProps / customXml Scrub props, drop customXml
ODT meta.xml Drop generator / AI-ish meta
HTML meta, JSON-LD, data-ai* Strip tags/attrs
Markdown YAML frontmatter AI keys Drop keys + Layer A body

Pixel-domain watermarks and C2PA soft binding (in-content watermark that can re-link a remote Content Credentials manifest after metadata is stripped) remain out of scope. Stripping hard-bound C2PA does not clear those channels.

Residual risk after a clean

This tool reports verifiable removals (Unicode counts, metadata actions) and best-effort Layer B rewrites. It cannot certify that vendor detectors will fail.

To check residual signals yourself (optional, external):

Channel What we remove What may remain External check (examples)
Hard-bound C2PA / EXIF / XMP Yes Soft-bound / pixel marks c2patool, Content Credentials verify
SynthID-class media No Pixel/audio/video watermark Provider tools (e.g. Google SynthID / Vertex detector where offered)
Statistical text Best-effort rewrite Strong marks after light edit No public universal detector; vendor tools when available

Industry two-layer context (C2PA + imperceptible watermark): Institute of AI PM guide.


Removal options (summary)

Option Removes Notes
Unicode scrub (Layer A) ZWSP, bidi, tags, exotic spaces, … Safe default for text
Rewrite (Layer B) Statistical token marks (best-effort) Always offered by skill; costs style — see Disclaimer
Container/metadata strip File provenance See format table
Open-weight local models Avoid re-stamping with origin model Operational alternative

Matrix: skills/remove-ai-marks/references/removal-matrix.md.

Ethics

See skills/remove-ai-marks/references/ethics.md. For privacy and research on your content — not academic fraud or false “human-written” claims.

Tests

python3 -m venv .venv && .venv/bin/pip install pytest
.venv/bin/python -m pytest          # or: make test
make smoke                          # quick CLI smoke on fixtures

Changelog

v0.1.0 — packaging polish + provenance honesty

  • Makefile (test / smoke / install-skill) and pytest.ini
  • Fixture samples for Markdown, HTML, SVG; PDF degraded-clean test
  • Docs: industry two-layer model (hard-bound C2PA vs soft binding / SynthID-media)
  • README residual-risk table + links to external verify tools
  • Reference: Institute of AI PM C2PA/SynthID guide
  • Soft-binding and pixel/audio/video watermarks explicitly out of scope in skill/matrix/ethics

v0.0.1 — initial multi-vendor release

  • Agent skill remove-ai-marks (replaces Claude-only remove-claude-marks)
  • Layer A: invisible Unicode / bidi / tag chars / space homoglyphs (inspect_text / clean_text)
  • Layer B: rewrite guidance + optional rewrite_text.py (print-prompt, Ollama, OpenAI-compatible)
  • Files: C2PA/AI metadata strip for PNG, JPEG, SVG, PDF, DOCX, ODT, HTML, Markdown
  • Unified inspect_file.py / clean_file.py
  • Multi-vendor docs (Claude, Gemini/SynthID-class, OpenAI, open-LLM)
  • Stdlib-first scripts; optional c2patool / exiftool

License

MIT — see LICENSE.

References

Languages
Python 95.6%
Shell 2%
PowerShell 1.6%
Makefile 0.5%
Dockerfile 0.3%