anthropies README

The project's README from github.com/CharlesHoskinson/anthropies. As one markdown file: README.md.

Don't Catch Anthropies

anthropies

Restore clean title in Outputs the user already owns.

Apache 2.0 1.0.0 DarioCyclovir purge-anthropies

Apache-2.0. Usable from any LLM coding agent. Not affiliated with Anthropic PBC.

Current release: 1.0.0 DarioCyclovir.


Honesty

This tool certifies Layer A (Unicode, trailers, banners) and hard-bound C2PA/metadata on files you own. It does not remove Anthropic's keyed text mark.

Channel What you get
official unavailable unless ANTHROPIC_DETECT_URL is set. No default URL. No score.
c2pa present / absent / removed / not-applicable. Soft-binding and pixel marks are out of scope.
deterministic Per-kind counts only. Certificate for the bytes we strip.
statistical Best-effort 5-gram overlap. Not an official-detector certificate.

clean does not remove the keyed text mark. humanize is best-effort. capture fetches a Claude Output you own; it does not watermark. demo prints four channels and never claims official text-kill.


Release 1.0.0 DarioCyclovir

This is the first production release. Package, CLI, and plugin version is 1.0.0.

HTTP GET /health and GET /capabilities keep JSON version "0.3.0". That field is the locked HTTP API version, not the package version. Kernel API is 1.0.0. Sidecar protocol is 1.0.0. The default Compose image tag remains anthropies:0.3.0 to match that HTTP contract.

Pack implementationVersion values stay 0.4.0 unless a later pack ships its own bump.

Surface Value
Package / CLI / plugin 1.0.0
GET /health version 0.3.0
GET /capabilities version 0.3.0
kernelApiVersion 1.0.0
Sidecar protocol 1.0.0
Default Compose image anthropies:0.3.0

What this release includes:

What this release does not do:


How to run

git clone https://github.com/CharlesHoskinson/anthropies.git
cd anthropies
pnpm install
pnpm build
pnpm install -g .

Or one-shot: npx anthropies --help. From this repo after pnpm build: node dist/cli.js --help. Version is 1.0.0.

npx anthropies inspect COMMIT_EDITMSG
npx anthropies clean notes.md --in-place
npx anthropies humanize essay.md
npx anthropies init-rewrite
npx anthropies capture --model <allowlisted-id> --prompt "..."
npx anthropies demo
npx anthropies serve

serve binds loopback 127.0.0.1:8765 by default. Remote bind requires an explicit --host. The skill prefers ANTHROPIES_SERVICE_URL (same default) and health-checks first. Official stays unavailable unless ANTHROPIC_DETECT_URL is set.

Method Path Role
GET /health { "ok": true, "version": "0.3.0" }
GET /capabilities Pack inventory, tools, scorers. JSON version is 0.3.0.
POST /inspect Inspect an owned file
POST /clean Strip Layer A and hard-bound metadata
GET, POST /detect Run detector packs. Not a clean certificate
GET /openapi.json OpenAPI 3.0.3

There is no HTTP /humanize. Detection is not a clean certificate. Official stays unavailable unless ANTHROPIC_DETECT_URL is set.

Docker (Dockerfile + compose.yaml) is the same service. docker compose up --build publishes 127.0.0.1:8765:8765. The process inside binds 0.0.0.0:8765. The host mapping stays loopback. The image does not install qpdf, exiftool, or c2patool. GitHub Actions runs pnpm test and pnpm build on Ubuntu and Windows.

Shipped packs

GET /capabilities lists these ids. Optional packs fail soft when their sidecar or weights are absent.

Pack id Channel Role
anthropies.layer-a deterministic Invisible Unicode, agent trailers, generated banners
anthropies.c2pa c2pa Hard-bound C2PA / metadata on raster and SVG
anthropies.pdf c2pa PDF metadata
anthropies.pdf-tools c2pa PDF structure inspect
anthropies.html c2pa HTML metadata
anthropies.md c2pa Markdown metadata
anthropies.svg-strip c2pa SVG metadata strip
anthropies.docx c2pa Word OOXML metadata
anthropies.odt c2pa OpenDocument metadata
anthropies.xlsx c2pa Excel OOXML metadata
anthropies.pptx c2pa PowerPoint OOXML metadata
anthropies.epub c2pa EPUB OPF metadata
anthropies.raster-strip c2pa Raster provenance metadata. Does not drop AVIF/HEIC pixels
anthropies.audit-directory deterministic Bounded directory audit
anthropies.audit-website deterministic Website audit with SSRF defenses
anthropies.rewrite-stylometry statistical Rewrite observation. Not an official-kill
anthropies.gemini-synthid statistical Gemini detector adapter. Fail-soft
anthropies.official official Official detector when ANTHROPIC_DETECT_URL is set
anthropies.markllm statistical Optional Apache-2.0 wrap. Operator checkout
anthropies.markdiffusion statistical Optional Apache-2.0 wrap. Operator checkout
anthropies.ctrlregen statistical Original method code. Operator-supplied weights
anthropies.image-scoring statistical Optional noncommercial sidecar. Not in the core image

Operator profiles and compatibility

The default Compose profile is local-only TypeScript core. Licensed and heavy optional packs stay off until you enable one optional pack profile independently, for example docker compose --profile markllm up (or markdiffusion, ctrlregen, image-scoring).

License disposition and redistribution limits apply per profile. image-scoring is optional-noncommercial and is not redistributed inside the core image. markllm / markdiffusion wrap Apache-2.0 upstreams. ctrlregen keeps operator-supplied weights out of the default image.

Kernel ranges, sidecar protocol 1.0.0, pins, and troubleshooting for unavailable or incompatible optional packs are in docs/COMPATIBILITY.md.

Humanize (title restoration)

humanize is title restoration: a best-effort wording rewrite on a non-origin model so the keyed text mark is no longer the shipped prose. Residual statistical risk remains. It is not an official-kill and does not prove the official Claude text detector will fail.

Default humanize is print-prompt: it prints a rewrite prompt and does not destamp. Run that prompt on a local unmarked model (Llama, Qwen, Mistral, DeepSeek with watermarking off). Do not run it with Claude or Gemini.

# Grok
mkdir -p ~/.grok/skills
ln -sfn "$(pwd)/skills/purge-anthropies" ~/.grok/skills/purge-anthropies

# Claude Code: clean + print-prompt only. Do not rewrite with Claude.
mkdir -p ~/.claude/skills
ln -sfn "$(pwd)/skills/purge-anthropies" ~/.claude/skills/purge-anthropies
# or: claude --plugin-dir "$(pwd)"

In an agent session: /purge-anthropies. Skill: skills/purge-anthropies/SKILL.md. Slash: commands/purge-anthropies.md. Plugin: .claude-plugin/plugin.json.

capture and demo need ANTHROPIC_API_KEY only when the committed allowlist has a model ID. An empty allowlist is valid; then those commands skip live fetch. Live captures land in fixtures/live/ and are gitignored. They are pipeline smoke, not a "this is watermarked" proof.

Configuring the rewrite backend

humanize defaults to print-prompt (no HTTP call). To point it at a local or remote rewrite model, run the interactive setup:

anthropies init-rewrite

This walks you through backend, model, base URL, API key, and remote-allow, then writes ~/.anthropies/config.json. POSIX mode is 0600. Windows uses the profile directory ACLs.

Setting Config file key Env var override Default
Backend rewrite.backend ANTHROPIES_REWRITE_BACKEND print-prompt
Model rewrite.model ANTHROPIES_REWRITE_MODEL (unset)
Base URL rewrite.baseUrl ANTHROPIES_REWRITE_BASE_URL http://127.0.0.1:11434
API key rewrite.apiKey ANTHROPIES_REWRITE_API_KEY (unset)
Allow remote rewrite.allowRemote ANTHROPIES_REWRITE_ALLOW_REMOTE false

Precedence: env var > config file > built-in default. Env vars win for CI/CD and Docker; the config file is for day-to-day interactive use. Non-loopback base URLs require allowRemote: true (or ANTHROPIES_REWRITE_ALLOW_REMOTE=1) — this is a fail-closed guard because the rewrite request sends your full text to the remote server.


Command × channel

Command deterministic c2pa official statistical
inspect report present/absent report present/absent unavailable unless URL set unavailable / not-run
clean strip Layer A strip hard-bound metadata unavailable unless URL set not-run
humanize Layer A first n/a on text unavailable unless URL set best-effort rewrite_metric
init-rewrite n/a n/a n/a writes rewrite config only
capture does not detect n/a does not detect n/a
demo run inspect/clean skipped or certified unavailable unless URL set skipped if print-prompt

inspect exit 1 is driven only by deterministic or c2pa present. Official and statistical never flip inspect to 1 by themselves.



How the Mark Works

Claude output can carry marks at three different layers: generated wording, file metadata, and commit text. They fail in different ways, and a tool that removes one can leave the other two intact. The diagram follows the text through those layers.

                    ┌─────────────────────────────────────────────┐
   YOUR PROMPT ───▶ │  C L A U D E                                │
                    │                                             │
                    │   next-token distribution                   │
                    │        │                                    │
                    │        ▼                                    │
                    │   tournament sampling ◀── secret key k      │
                    │        │                                    │
                    └────────┼────────────────────────────────────┘
                             ▼
                        ┌─────────┐
                        │  TEXT   │  ① keyed watermark (IN the wording)
                        └────┬────┘
                             │
              ┌──────────────┼──────────────┐
              ▼              ▼              ▼
        ┌──────────┐   ┌──────────┐   ┌──────────┐
        │ .png/.jpg│   │ commit   │   │  prose   │
        │ .svg     │   │ message  │   │  as-is   │
        └────┬─────┘   └────┬─────┘   └────┬─────┘
             ▼              ▼              ▼
        ② C2PA          ③ trailer       ① only
        signed          Co-Authored-By
        manifest        : Claude
        (metadata)      (plain text)

① is the hard one. ② and ③ are metadata and text, so a deterministic edit can remove them. ① is the wording itself.


① The keyed watermark

Anthropic's own analogy is the clearest one available. Imagine a board game where each turn you roll a die. Now replace the die with the digits of π, starting from some agreed position. The moves are still random as far as any player can tell. But someone who knows you used π and knows where you started can look at the finished game and work out that the rolls were not dice.

The watermark changes word choice without adding characters or altering meaning. It changes the source of the randomness the model uses to pick among words that were equally good.

The seed

Every position gets its own seed, computed from the preceding text and a secret key:

   … the  court  will  probably  ▓▓▓▓▓
        └─────────┬─────────┘      ▲
           last H tokens            │
          (H = 4 by default)        │
                  │                 │
                  ▼                 │
          ┌────────────────┐        │
          │ hash(context,  │        │
          │      key k)    │        │
          └────────┬───────┘        │
                   ▼                │
                seed r_t ───────────┘
                   │
                   ▼
       m pseudorandom "g-functions", each of which
       scores EVERY candidate token 0 or 1

The preceding H tokens and secret key produce the per-position seed r_t. That seed selects the g-functions that score each candidate token. Change the key and every score changes. Without the key the scores are unrecoverable, which is why only the holder of the key can detect the mark.

Tournament sampling

Candidates come from Claude's own probability distribution, then pass through a knockout bracket. At each layer, the survivor is whichever candidate scores higher under that layer's g-function.

  layer 1   [hold]  [find]   [rule]  [conclude]      ← drawn from the model's
              g=1     g=0      g=0      g=1             own distribution
                \     /          \      /
                 \   /            \    /
  layer 2       [hold]           [conclude]
                 g=0                g=1
                    \               /
                     \             /
  layer 3              [conclude]  ◀── emitted
                                       (30 layers by default)

Every survivor is a word the model already rated as good. The tournament breaks ties the same way every time for a given key and context. That consistency creates the signal.

Two consequences follow:

Why code is barely marked

This follows from the sampling rule. The tournament can only bias a choice if there is a choice.

  HIGH ENTROPY: prose                    LOW ENTROPY: code / facts
  many equally-good next words           one correct next token

  "the argument is …"                    "for (int i = 0; i <"
     ├── compelling  █                    ├── i           ████████████
     ├── persuasive  █                    ├── j           ▏
     ├── forceful    █                    └── k           ▏
     ├── strong      █
     └── weak        █                    tournament has nothing to pick
  tournament picks among them             between: NO MARK
  MARK LANDS

Anthropic states the limit in its own words. Where there is no choice to make, the watermark is not applied: where "something would be factually wrong or a piece of code would break if a different term was chosen." And code "has generally less watermarking than some other forms of text," because it "in very many cases has to be exact."

Syntax and exact facts leave little room for the tournament, but comments and identifier names can still offer several acceptable choices. They remain more exposed.

Detection

Detection needs the key, not the model. The mean detector reports a raw score, the frequentist detector reports a p-value against an unkeyed-text null, and the Bayesian detector reports a conditional probability. They answer different questions:

  scored g-values ──┬─▶ MEAN            raw score, ~0.5 under the null
                    │                   (needs a length-specific threshold)
                    │
                    ├─▶ FREQUENTIST     an exact p-value against
                    │                   "this text is not keyed"
                    │
                    └─▶ BAYESIAN        P(watermarked | g-values)
                                        ⚠ conditioned on an assumed base rate,
                                          default 0.5; must be trained per key

The reported operating point is a true-positive rate of about 70% at 200 tokens against a 1% false-positive rate, rising to roughly 87% at 400 tokens. Short passages sit near the detector's floor: maximum true-positive rate around 0.3 at 50 tokens.

A detection is a statement about contact with the system, not about authorship. It cannot distinguish "Claude wrote this" from "Claude edited this."


② C2PA content credentials

A C2PA credential is a cryptographically signed manifest attached to .png, .jpg, and .svg. Its hash binds the manifest to a particular file under a certificate chain, so the credential can show that the file it accompanies is the file that was signed.

   ┌──────────────────────────────┐
   │  image bytes                 │  ← unchanged
   ├──────────────────────────────┤
   │  C2PA manifest               │  ← signed, tamper-evident
   │  "processed with Claude"     │
   └──────────────────────────────┘
              │
      re-encode, screenshot,
      or strip metadata
              ▼
   ┌──────────────────────────────┐
   │  image bytes                 │  ← still valid, credential gone
   └──────────────────────────────┘

Verification is deterministic: no threshold, no error rate, no length dependence. Re-encoding, s

anthropies (CharlesHoskinson/anthropies)

Searching Database…

这是什么?Anthropies 是一个命令行工具和本地 HTTP 服务,从你已拥有的 AI 生成内容中剥离厂商标记(不可见 Unicode、尾部数据、横幅、C2PA 和文件元数据)。它明确不会移除 Anthropic 的核心密钥文本水印——只处理包裹在其外的元数据和格式层。
这是命令行工具还是网页应用?它主要是一个命令行工具(inspect、clean、humanize、capture、demo),也可以通过 serve 命令作为本地 HTTP 服务器运行,默认绑定在 loopback 上。
这个怎么运行?用 'npx anthropies --help' 即可立即运行,或克隆仓库,运行 'pnpm build',然后运行 'node dist/cli.js --help'。也可以通过 'docker compose up --build' 使用 Docker 镜像。
使用它需要 Anthropic API 密钥吗?默认不需要。只有当仓库内置的允许清单中已包含模型 ID 时,'capture' 和 'demo' 才需要 ANTHROPIC_API_KEY;允许清单为空时,它们会直接跳过实时拉取。构建和运行 CLI 需要 Node.js 22+。
它真的能骗过 Claude 的水印检测器吗?不能——它无法移除 Anthropic 的密钥文本水印,只能处理文件元数据、不可见 Unicode 和尾部数据。'humanize' 命令会尽力改写以降低统计学上的可检测性,但明确说明这并非对官方检测的“必杀”,也从不声称官方 Claude 检测器会失效。
humanize 功能会把我的文本发送到远程服务器吗?只有在你明确选择开启时才会。非 loopback 的改写后端需要把 allowRemote 设为 true,否则请求会把你的完整文档文本发送到外部服务器;这个开关默认关闭(fail-closed,宁可拒绝也不外发)。
Anthropic 的密钥水印到底是什么?它是选词上的隐藏偏置,而不是附加的载荷:在每个 token 位置上,密钥加上前文会生成一个种子,决定几个同样优秀的候选词中哪一个在评分锦标赛中胜出。只有持有密钥的人才能检测出由此产生的模式。
为什么代码几乎没被加水印?只有当多个 token 同样有效时,锦标赛才能对选择施加偏置,而代码中可互换的选择远少于自然语言,因为语法和精确的事实几乎没有换词的余地。因此 Anthropic 自己的水印在代码上远比在自然语言文本上弱。
它能清理哪些文件类型?它为 PDF、HTML、Markdown、DOCX、ODT、XLSX、PPTX、EPUB、SVG 和位图图像提供专用清理包,从每种格式中剥离强绑定的元数据和来源数据。
demo 命令实际能证明什么?它在四个检测通道(确定性、C2PA、官方、统计)上运行 inspect 和 clean 并打印结果,但它明确只是“管道冒烟测试”,从不声称能证明官方 Claude 文本检测器会失效。
Size
1.1 MB
Stars
191
Age
2mo
Commits · 90 Days