{"id":51475071,"url":"https://github.com/devswha/patina","last_synced_at":"2026-07-06T20:00:54.913Z","repository":{"id":342566295,"uuid":"1165440411","full_name":"devswha/patina","owner":"devswha","description":"Detects and rewrites AI writing patterns in Korean, English, Chinese, and Japanese. Runs as a skill for Claude Code, Codex CLI, Cursor, and OpenCode, or as a standalone Node.js CLI.","archived":false,"fork":false,"pushed_at":"2026-07-01T06:17:22.000Z","size":17829,"stargazers_count":202,"open_issues_count":16,"forks_count":24,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-07-01T08:13:00.293Z","etag":null,"topics":["ai-detection","ai-humanizer","ai-writing","claude","claude-code","codex","cursor","humanizer","korean","korean-nlp","llm","llm-humanizer","multi-agent","nlp","nodejs-cli","prompt-engineering","stylometry","text-humanizer","text-processing","writing-tools"],"latest_commit_sha":null,"homepage":"https://patina.vibetip.help/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/devswha.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":"SUPPORT.md","governance":"GOVERNANCE.md","roadmap":"docs/ROADMAP.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":"NOTICE","maintainers":"MAINTAINERS.md","copyright":null,"agents":"docs/agents.md","dco":null,"cla":null}},"created_at":"2026-02-24T06:59:15.000Z","updated_at":"2026-07-01T07:12:43.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/devswha/patina","commit_stats":null,"previous_names":["devswha/oh-my-humanizer"],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/devswha/patina","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devswha%2Fpatina","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devswha%2Fpatina/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devswha%2Fpatina/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devswha%2Fpatina/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/devswha","download_url":"https://codeload.github.com/devswha/patina/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devswha%2Fpatina/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35156494,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-05T02:00:06.290Z","response_time":100,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai-detection","ai-humanizer","ai-writing","claude","claude-code","codex","cursor","humanizer","korean","korean-nlp","llm","llm-humanizer","multi-agent","nlp","nodejs-cli","prompt-engineering","stylometry","text-humanizer","text-processing","writing-tools"],"created_at":"2026-07-06T20:00:50.821Z","updated_at":"2026-07-06T20:00:54.913Z","avatar_url":"https://github.com/devswha.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"assets/brand/patina-mark.svg\" alt=\"patina mark\" width=\"172\"\u003e\n\u003c/p\u003e\n\n\u003ch1 align=\"center\"\u003epatina\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cstrong\u003eStrip the AI packaging. Keep the meaning.\u003c/strong\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"README_KR.md\"\u003e\u003cb\u003e한국어\u003c/b\u003e\u003c/a\u003e ·\n  \u003ca href=\"README_ZH.md\"\u003e\u003cb\u003e中文\u003c/b\u003e\u003c/a\u003e ·\n  \u003ca href=\"README_JA.md\"\u003e\u003cb\u003e日本語\u003c/b\u003e\u003c/a\u003e ·\n  \u003cb\u003eEnglish\u003c/b\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/devswha/patina/actions/workflows/test.yml\"\u003e\u003cimg alt=\"Tests\" src=\"https://github.com/devswha/patina/actions/workflows/test.yml/badge.svg\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://opensource.org/licenses/MIT\"\u003e\u003cimg alt=\"License: MIT\" src=\"https://img.shields.io/badge/License-MIT-yellow.svg\"\u003e\u003c/a\u003e\n  \u003ca href=\"#quick-start\"\u003e\u003cimg alt=\"Skill: Claude Code | Codex | Cursor | OpenCode\" src=\"https://img.shields.io/badge/Skill-Claude%20Code%20%7C%20Codex%20%7C%20Cursor%20%7C%20OpenCode-blueviolet\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/devswha/patina\"\u003e\u003cimg alt=\"Languages: KO | EN | ZH | JA\" src=\"https://img.shields.io/badge/Languages-KO%20%7C%20EN%20%7C%20ZH%20%7C%20JA-green\"\u003e\u003c/a\u003e\n  \u003ca href=\"CHANGELOG.md\"\u003e\u003cimg alt=\"Version 6.3.0\" src=\"https://img.shields.io/badge/version-6.3.0-blue\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://patina.vibetip.help/\"\u003e\u003cb\u003eTry it in the browser — no install\u003c/b\u003e\u003c/a\u003e\n\u003c/p\u003e\n\npatina is a deterministic, pattern-based humanizer for Korean, English, Chinese, and Japanese. It finds AI-sounding phrasing and rewrites it without changing the claim, numbers, polarity, or causation.\n\nIt is not a black-box paraphraser, authorship detector, or detector-bypass tool. patina is built for allowed AI-assisted drafting where the author wants cleaner voice, an audit trail, and meaning-preservation checks.\n\n## Demo\n\nPaste AI-sounding text into the **[playground](https://patina.vibetip.help/)** and patina rewrites it in place. The meaning floors verify the rewrite (**MPS 100 / Fidelity 75** here — the \"30 templates\" fact survives), and the deterministic AI signal is measured before → after: the hot-paragraph ratio falls **100 → 0** while the hype (\"thrilled to announce\", \"revolutionize your workflow\", \"unlock their full potential\") is gone.\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://raw.githubusercontent.com/devswha/patina/main/assets/demo/patina-playground-en.gif\" alt=\"Animated patina playground demo: an AI-sounding template-pack announcement is pasted into the web playground, rewritten naturally while keeping the 30-templates fact, and verified with MPS 100, Fidelity 75, and a deterministic AI-signal drop from 100 to 0\" width=\"820\"\u003e\n\u003c/p\u003e\n\nMore examples: [Before/After Gallery](docs/EXAMPLES.md) ([한국어](docs/EXAMPLES_KR.md)) · [CLI transcript](docs/DEMO.md).\n\n## Quick Start\n\n### Browser playground\n\nOpen **[patina.vibetip.help](https://patina.vibetip.help/)** — paste KO / EN / ZH / JA text for a real rewrite gated by the MPS/fidelity floors, with the deterministic AI signal measured before → after. Rewrites and scoring run server-side; the free tier uses the service's own model key (rate-limited). **API mode** forwards your own key per request through the patina server to the provider you pick — never stored or logged (metrics are sanitized: no text, prompt, output, key, or IP). **Pro** ($9.99/mo USD) unlocks higher limits (20000 chars, 200 rewrites/day) with a Lemon Squeezy license key sent as a bearer token — the raw key is validated server-side and never stored or logged.\n\n### Agent skill\n\n**Let your coding agent install it** — paste this into Claude Code, Codex CLI, Cursor, Gemini CLI, or any agent:\n\n```text\nInstall patina by following https://raw.githubusercontent.com/devswha/patina/main/INSTALLATION.md\n```\n\nThe agent fetches [`INSTALLATION.md`](INSTALLATION.md) (written for AI agents) and runs the right install path for your host, then verifies it. Or do it yourself:\n\n**Claude Code — plugin marketplace (no clone, recommended):**\n\n```text\n/plugin marketplace add devswha/patina\n/plugin install patina@patina\n```\n\n**Claude Code · Codex CLI · Cursor · OpenCode — install script:**\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/devswha/patina/main/install.sh | bash\n```\n\nThen run the skill from Claude Code, Codex CLI, Cursor, or OpenCode:\n\n```text\n/patina --lang en\n\n[paste your text here]\n```\n\nUseful skill calls:\n\n```text\n/patina --tone professional\n/patina --tone auto --lang en\n```\n\n### Standalone CLI\n\nRequires Node.js \u003e= 18.\n\n```bash\nnpx patina-cli doctor\nnpx patina-cli --lang en input.txt\n```\n\nUse a logged-in local model CLI without an API key:\n\n```bash\nprintf '%s\\n' 'Coffee has emerged as a pivotal cultural phenomenon.' \\\n  | npx patina-cli --lang en --backend codex-cli\n```\n\nSupported local backends: `codex-cli`, `claude-cli`, `gemini-cli`, `kimi-cli` — patina passes the strongest documented default model per backend. See [Authentication](docs/AUTHENTICATION.md) ([한국어](docs/AUTHENTICATION_KR.md)).\n\nFor large `--batch` runs, prefer an OpenAI-compatible HTTP backend; local CLI backends are agent runtimes, capped conservatively with `--timeout-ms`, `--max-concurrency`, `--max-retries`, and `--max-failures` for batch safety.\n\n## What You Get\n\n|  |  |\n|---|---|\n| **168 patterns** | 33 rewrite-capable + 9 score-only viral-hook per language (42 each across KO/EN/ZH/JA) — see the full 168-pattern catalog in [PATTERNS.md](docs/PATTERNS.md) |\n| **Modes** | rewrite · verify · audit · score · diff |\n| **Surfaces** | agent skill · Node CLI · in-place preview · browser playground (rewrite + score) |\n| **Voice** | `--persona` (built-in + your own, ko/en/zh/ja) is the sole voice axis · `--tone` register · `--profile` pattern policy — composable with a fixed precedence |\n| **Free usage** | logged-in `codex`, `claude`, or `gemini` CLI can run rewrites without `PATINA_API_KEY` |\n| **Calibration** | 67.3% editing-hotspot catch [63.5–71.0%] across GPT-5.5 / Claude Sonnet 4.6 / Gemini 2.5 Pro (n=600, KO+EN); 16.0% false positives [11.6–21.7%] on KO+EN human controls (n=200) |\n| **License** | MIT |\n\nScores are editing signals with false positives and false negatives, not proof of authorship. See [Ethics](docs/ETHICS.md).\n\n## Common Commands\n\n```bash\npatina --lang \u003cko|en|zh|ja\u003e [mode] [--profile \u003cname\u003e] input.txt\n```\n\n| Command | Purpose |\n|---|---|\n| `patina input.txt` | rewrite with defaults |\n| `patina --audit input.txt` | detect patterns only |\n| `patina --score input.txt` | output a 0-100 AI-likeness score |\n| `patina --score --exit-on 30 input.txt` | CI gate with exit code `3` when `overall \u003e 30` |\n| `patina --diff input.txt` | show pattern-by-pattern changes |\n| `patina --preview page.html` | render rewrites back onto a saved HTML page with toggles and inline diff |\n| `patina --verify input.txt` | rewrite, then check MPS/fidelity floors with one retry |\n| `patina --tone auto --lang en input.txt` | infer and apply a KO/EN tone axis |\n| `patina --persona pragmatic-founder input.txt` | rewrite in a built-in voice persona |\n| `patina persona new my-voice --from-sample past.txt` | author your own persona from a writing sample |\n| `patina persona list` | list built-in + custom personas |\n| `patina persona show my-voice --json` | print a persona's normalized config (never the docs body) |\n| `patina persona edit my-voice --name \"New Name\"` | copy-on-edit a persona into `custom/personas/` |\n| `patina persona rm my-voice` | remove a custom persona (built-ins + `preserve` protected) |\n| `patina --format json --quiet input.txt` | script-friendly output |\n| `patina --batch docs/*.md --outdir cleaned/` | batch file processing |\n\n`patina --help` prints the full flag list. `patina doctor --json` checks Node, backend, tmux, and API-key readiness without making an LLM call.\n\n### Personas (voice)\n\nA **persona** is a reusable voice — a built-in (`patina persona list`) or your own, authored without editing source:\n\n```bash\npatina persona new my-voice --from-sample past-posts.txt   # learn from your writing\npatina persona new my-voice --describe \"plain-spoken founder, casual\"\npatina --persona my-voice draft.md                          # then reuse it\n\npatina persona show my-voice                                # inspect the normalized config (--json for machine output)\npatina persona edit my-voice --name \"Founder voice\"         # copy-on-edit into custom/personas/ (built-ins stay intact)\npatina persona rm my-voice                                  # remove a custom persona (--force to skip the confirm)\n```\n\nWorks on ko/en/zh/ja and composes with `--tone` (register) and `--profile` (pattern policy). The persona is the sole voice owner; register precedence is `--tone` \u003e persona. A persona shapes voice but never lowers the meaning floors — authored personas are validated on save, and the safety gate still enforces MPS/fidelity + dropped-number checks.\n\n## CI\n\nFor GitHub Actions, the maintained wrapper is shorter than hand-rolled setup:\n\n```yaml\nname: Patina prose score\non:\n  pull_request:\n    paths: ['**/*.md', '**/*.mdx']\npermissions:\n  contents: read\n  pull-requests: read\n  issues: write\njobs:\n  patina:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v6\n      - uses: devswha/patina-action@v1\n        with:\n          score-threshold: 30\n          lang: auto\n          comment: true\n```\n\nOther integrations: [pre-commit](docs/integrations/pre-commit.md), [static sites](docs/integrations/static-sites.md), [Docker](docs/integrations/docker.md), [release workflow](docs/integrations/release.md).\n\n## How It Works\n\n```text\nInput\n  -\u003e semantic anchor extraction (claims, polarity, causation, numbers)\n  -\u003e stylometry + AI-lexicon scan\n  -\u003e pattern-guided rewrite\n  -\u003e self-audit and MPS/fidelity checks\n  -\u003e cleaned text\n```\n\nIf meaning drifts, the change is retried or rolled back. Deterministic analysis lives in `src/features/*`; LLM-backed rewrite and score calls use the selected backend.\n\n## Configuration\n\n```yaml\n# .patina.default.yaml\nversion: \"6.3.0\"\nlanguage: ko              # ko | en | zh | ja\nprofile: default\noutput: rewrite           # rewrite | diff | audit | score\ntone:                     # casual | professional | auto  (register; genre = profile)\n```\n\nProject `.patina.yaml` overrides defaults. Pattern packs are auto-discovered by language prefix. Additive list keys (`blocklist`, `allowlist`, `skip-patterns`) merge; other arrays replace.\n\n## Documentation\n\nStart here:\n\n- [Cookbook](docs/COOKBOOK.md) — common recipes and workflows\n- [CLI Contract](docs/CLI.md) — flags, formats, score gates, exit behavior\n- [Authentication](docs/AUTHENTICATION.md) — local CLI backends and API providers\n- [Patterns](docs/PATTERNS.md) — full pattern catalog\n- [Subagents \u0026 strict flow](docs/agents.md) — optional read-only detector/fidelity/naturalness subagents and the `--strict` multi-pass mode\n- [Benchmarks](docs/benchmarks/README.md) · [latest report](docs/benchmarks/latest.md) · [2026 rebaseline](docs/research/2026-rebaseline.md)\n- [Measurement harness](docs/HARNESS.md) — index of every benchmark, calibration, and gate tool (incl. the signal-impact ablation harness)\n- [FAQ](docs/FAQ.md) ([한국어](docs/FAQ_KR.md))\n- [Ethics](docs/ETHICS.md)\n- [Contributing](CONTRIBUTING.md) ([한국어](CONTRIBUTING_KR.md))\n- [Changelog](CHANGELOG.md)\n\nBrand assets and usage rules live in [Branding](docs/BRANDING.md). Design notes live in [DESIGN.md](DESIGN.md).\n\n## Acknowledgements\n\nInspired by [oh-my-zsh](https://github.com/ohmyzsh/ohmyzsh)'s plugin architecture, [Wikipedia's \"Signs of AI writing\"](https://en.wikipedia.org/wiki/Wikipedia:Signs_of_AI_writing), and [blader/humanizer](https://github.com/blader/humanizer).\n\n## License\n\nMIT. See [LICENSE](LICENSE) and [NOTICE](NOTICE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdevswha%2Fpatina","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdevswha%2Fpatina","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdevswha%2Fpatina/lists"}