<h1 align="center">personal-humanizer-maker</h1>
<p align="center">
<strong>Turn your own writing into a personal humanizer skill.</strong><br>
<em>Feed it one document you wrote; it fingerprints your voice โ quantitatively and axis-by-axis โ and emits a standalone Claude Code skill that rewrites any text into your style, without touching a single fact.</em>
</p>
<p align="center">
<a href="./README.ko.md">ํ๊ตญ์ด README</a>
ยท
<a href="./skills/personal-humanizer-maker/SKILL.md">SKILL.md</a>
ยท
<a href="./schemas">Contracts</a>
ยท
<a href="#benchmark">Benchmark</a>
</p>
<p align="center">
<img src="https://img.shields.io/github/license/TaewoooPark/personal-humanizer-maker?style=flat-square&labelColor=000000&color=333333&cacheSeconds=3600" alt="License">
<img src="https://img.shields.io/github/stars/TaewoooPark/personal-humanizer-maker?style=flat-square&logo=github&logoColor=white&labelColor=000000&color=333333&cacheSeconds=3600" alt="GitHub stars">
<img src="https://img.shields.io/github/last-commit/TaewoooPark/personal-humanizer-maker?style=flat-square&labelColor=000000&color=333333&cacheSeconds=3600" alt="Last commit">
<img src="https://img.shields.io/github/languages/top/TaewoooPark/personal-humanizer-maker?style=flat-square&labelColor=000000&color=333333&cacheSeconds=3600" alt="Top language">
</p>
<p align="center">
<img src="https://img.shields.io/badge/Claude%20Code-000000?style=flat-square&logo=anthropic&logoColor=white&labelColor=000000&cacheSeconds=3600" alt="Claude Code">
<img src="https://img.shields.io/badge/OpenAI%20Codex-000000?style=flat-square&logo=openai&logoColor=white&labelColor=000000&cacheSeconds=3600" alt="OpenAI Codex">
<img src="https://img.shields.io/badge/Skill%20factory-000000?style=flat-square&labelColor=000000&color=000000&cacheSeconds=3600" alt="Skill factory">
<img src="https://img.shields.io/badge/Python%20stdlib--only-000000?style=flat-square&logo=python&logoColor=white&labelColor=000000&cacheSeconds=3600" alt="Python stdlib only">
</p>
<p align="center">
<img src="https://img.shields.io/badge/Korean%20%C2%B7%20English-000000?style=flat-square&labelColor=000000&color=000000&cacheSeconds=3600" alt="Korean and English">
<img src="https://img.shields.io/badge/Multi--agent%20analysis-000000?style=flat-square&labelColor=000000&color=000000&cacheSeconds=3600" alt="Multi-agent analysis">
<img src="https://img.shields.io/badge/Code%20%2B%20Reference%20driven-000000?style=flat-square&labelColor=000000&color=000000&cacheSeconds=3600" alt="Code plus reference driven">
<img src="https://img.shields.io/badge/Round--trip%20verified-000000?style=flat-square&labelColor=000000&color=000000&cacheSeconds=3600" alt="Round-trip verified">
</p>
---
> **One sentence:** point it at a sample you wrote, and get back a ready-to-use skill that
> rewrites *other* text into *your* voice โ measured against your own numbers, with the
> meaning frozen.
- ๐งฌ **Voice from a sample** โ build a personal humanizer from as little as one document you wrote.
- ๐ **Quantitative fingerprint** โ a stdlib profiler measures sentence architecture, ending register, lexical density, connective rhythm, stance, and formatting as *distributions*, not vibes.
- ๐งต **Multi-agent analysis** โ one specialist agent per style axis fans out over your text, then a synthesizer merges them into a single profile.
- ๐ญ **Emits a real skill** โ output is a standalone `humanize-<name>/` skill: `SKILL.md` + a `style_metrics.py` with *your* baselines baked in + before/after examples mined from your own sentences.
- ๐ **Meaning stays frozen** โ every emitted skill inherits an ironclad covenant: facts, numbers, citations, and order never change; only phrasing, rhythm, and arrangement do.
- ๐ฐ๐ท ๐ฌ๐ง **Korean or English** โ pick the language at the start; the taxonomy and the metrics switch with it.
- โ
**Self-verifying** โ fully automatic, so the factory round-trips each emitted skill on held-out text and won't silently ship an overfit voice.
## Not Just "Rewrite This in My Style"
A normal prompt like *"make this sound like this sample"* is a one-off imitation. It asks
the model to notice whatever it notices in the moment, and the next request starts over
from scratch.
`personal-humanizer-maker` turns the sample into a reusable, inspectable artifact:
| One-off prompt | personal-humanizer-maker |
|---|---|
| Reads a sample and improvises | Measures the sample into a `quant_profile.json` first |
| Style is whatever the model remembers | Seven axis specialists write explicit rules for sentence shape, register, lexicon, cohesion, stance, figuration, and formatting |
| No persistent baseline | Emits `style_metrics.py` with the author's numeric bands baked in |
| Hard to audit | Emits `style_profile.md` and examples mined from the author's own sentences |
| Can drift or over-edit | Injects the same meaning-invariance covenant into every generated skill |
| Every rewrite repeats the analysis | One build creates `humanize-<name>/`; every later rewrite reuses that skill |
The output is not a vibe prompt. It is closer to a tiny style compiler: sample in,
measured profile out, reusable skill emitted.
## Why It Exists
Writing a style guide for your *own* voice by hand is slow and subjective. The seed skill
[`personal_humanize`](https://github.com/TaewoooPark) is exactly that โ a hand-authored
`S1โS8` / `A1โA3` ruleset plus hardcoded metric thresholds, all derived by staring at one
author's corpus until the patterns fell out.
`personal-humanizer-maker` generalizes that labor. Point it at a writing sample and it does
the profiling, the axis-by-axis dimension analysis, the threshold calibration, and the skill
packaging for you โ and hands back a skill shaped exactly like the hand-made one, so it
"just works" the same way. The hand-tuned instance becomes one *output* of the factory
rather than a bespoke artifact.
## How It Works
```
sample doc + language (ko/en)
โ [CODE] profile_corpus.py
โผ
quant_profile.json 7-axis distributions: sentence length ยท ending mix ยท gloss rate ยท connective density ยท passive/nominalization ยท formatting
โ [MULTI-AGENT] one specialist agent per axis, fanned out โ references/taxonomy.{lang}.md
โผ
dimension_profiles[] per-axis value + confidence + rules + before/after mined from your text
โ [MULTI-AGENT] synthesizer (barrier): merge, dedup, demote weak axes
โผ
style_profile.json unified rules + calibrated baselines + canonical examples
โ [CODE] emit_skill.py + templates โ references/ironclad.md (covenant injected)
โผ
humanize-<name>/ standalone skill: SKILL.md + style_metrics.py (your bands) + examples.md
โ [CODE+AGENT] roundtrip_check.py + fidelity audit โ automatic safety gate
โผ
PASS โ ship / FAIL โ widen bands ยท demote low-confidence axes ยท re-emit once ยท else ship with CONFIDENCE note
```
Three layers, kept deliberately separate:
| Layer | Does | Artifacts |
|---|---|---|
| **CODE** (deterministic, stdlib-only) | corpus profiler ยท skill emitter ยท round-trip checker | `scripts/profile_corpus.py`, `scripts/emit_skill.py`, `scripts/roundtrip_check.py` |
| **REFERENCE** (static knowledge) | style-dimension taxonomy (ko/en) ยท signalโaxis map ยท covenant ยท templates | `references/taxonomy.{ko,en}.md`, `references/signal-map.md`, `references/ironclad.md`, `templates/*` |
| **LLM / multi-agent** (interpretive) | axis specialists ยท synthesizer ยท fidelity auditor | orchestrated from `SKILL.md` |
## What It Learns
The generated skill is readable. For a Korean public-rhetoric test built from Kim Gu's
*My Wish* excerpts, the emitted `SKILL.md` learned rules like:
```text
SA1. Combine short explanatory sentences into longer declarative sentences around
65-85 Korean characters, without exceeding 135 characters.
RM1. End sentences with -๋ค, -๊ฒ์ด๋ค, -์ด๋ผ ๋ฏฟ๋๋ค, or -ํ๊ธฐ ๋๋ฌธ์ด๋ค;
avoid modern polite explanatory endings.
SV1. Use "๋๋" to state public conviction and responsibility, not private preference.
Expand individual judgment into "์ฐ๋ฆฌ ์ฌํ", "๋๋ผ", or "๋ฏผ์กฑ" when the source supports it.
```
For an English public-oratory test built from Lincoln texts, it learned a different rule
set:
```text
SA2. Use parallel clause chains with repeated openings such as "if", "we", "that",
or "it is" when the source presents alternatives or obligations.
RM1. Keep the prose formal and contraction-free.
CA3. End paragraphs on commitment, preservation, judgment, or consequence rather than
on a neutral summary.
```
Those rules are paired with numeric bands such as mean sentence length, long-sentence
ratio, declarative-ending ratio, passive/nominalization rate, bullet ratio, and emoji
count. A rewrite can then be checked mechanically:
```bash
python3 humanize-kimgu-ko-test/scripts/style_metrics.py rewritten.md
# strict 8/8, CONVERGED
```
## Before / After
### Korean
Neutral modern input:
```text
ํ๊ตญ ์ฌํ๊ฐ ๊ธฐ์ ์ ์ ํ์ฉํ๋ ค๋ฉด ๋ช ๊ฐ์ง ์กฐ๊ฑด์ด ํ์ํ๋ค. ๋จผ์ ์๋ฏผ์ด ๊ธฐ์ ์ ์๋ฆฌ๋ฅผ ์ดํดํ๊ณ
๋นํ์ ์ผ๋ก ํ๋จํ ์ ์์ด์ผ ํ๋ค. ๊ธฐ์
์ ๋น ๋ฅธ ์ฑ์ฅ๋ง ์ถ๊ตฌํ์ง ๋ง๊ณ ์ด์ฉ์์ ๊ถ๋ฆฌ์ ์์ ์ ํจ๊ป
๊ณ ๋ คํด์ผ ํ๋ค.
```
Generated Kim Gu-style rewrite:
```text
๋๋ ์ฐ๋ฆฌ ์ฌํ๊ฐ ๊ธฐ์ ์ ์ ์ฐ๋ ๋๋ผ๊ฐ ๋๋ ค๋ฉด ๋จผ์ ์๋ฏผ์ด ๊ทธ ๊ธฐ์ ์ ์๋ฆฌ๋ฅผ ์๊ณ , ์ค์ค๋ก ์ณ๊ณ ๊ทธ๋ฆ์
ํ๋จํ ํ์ ๊ธธ๋ฌ์ผ ํ๋ค๊ณ ๋ฏฟ๋๋ค. ๊ธฐ์
๋ ๋น ๋ฅธ ์ฑ์ฅ๋ง์ ์์ํ ๊ฒ์ด ์๋๋ผ ์ด์ฉ์์ ๊ถ๋ฆฌ์ ์์ ์ด
ํจ๊ป ๋ณด์ฅ๋์ด์ผ ํ ๊ฒ์ด์, ์ ๋ถ๋ ๊ท์ ๋ฅผ ์ธ์ธ ๋์๋ ํ์ฅ์ ๋น ๋ฅธ ๊ฑธ์๊ณผ ๊ณต์ต์ ํฐ ๊ธธ์ด ์๋ก
์ด๊ทธ๋ฌ์ง์ง ์๋๋ก ํด์ผ ํ ์ผ์ด๋ค.
```
The original matched **5 / 8** strict Korean bands. The rewrite matched **8 / 8**.
### English
Scientific input:
```text
Natural selection in each well-stocked country, must act chiefly through the competition
of the inhabitants one with another, and consequently will produce perfection, or strength
in the battle for life, only according to the standard of that country.
```
Generated Lincoln-style rewrite:
```text
Natural selection, in each well-stocked country, must act chiefly through competition,
one inhabitant with another. It may therefore produce perfection, or strength in the
battle for life, only by the standard of that country.
```
The original matched **10 / 12** strict Lincoln bands. The rewrite matched **12 / 12**.
## Install
```bash
git clone https://github.com/TaewoooPark/personal-humanizer-maker.git
cd personal-humanizer-maker
# Claude Code (default) -> ~/.claude/skills
bash setup/install.sh
# Codex -> ~/.codex/skills (+ ~/.agents/skills mirror)
bash setup/install.sh --target codex
# Both
bash setup/install.sh --target both
```
Pure standard-library Python 3.9+. No venv, no third-party packages, no network at install time.
<details>
<summary><b>๐ค โฆor just let an AI agent install it for you</b></summary>
<br>
Too busy to run three commands? You're already talking to a coding agent โ make it earn its keep. Paste the repo link and one of these into Claude Code / Codex / Cursor:
**English**
> Clone `https://github.com/TaewoooPark/personal-humanizer-maker` and install it for this host (`bash setup/install.sh` in Claude Code, or `bash setup/install.sh --target codex` in Codex), then confirm the `personal-humanizer-maker` skill is active in my session. Once it's in, build a personal humanizer from a sample of my writing.
**ํ๊ตญ์ด**
> `https://github.com/TaewoooPark/personal-humanizer-maker` ํด๋ก ํด์ ํ์ฌ ํธ์คํธ์ ๋ง๊ฒ ์ค์นํด์ค(Claude Code๋ฉด `bash setup/install.sh`, Codex๋ฉด `bash setup/install.sh --target codex`). ๊ทธ๋ฆฌ๊ณ `personal-humanizer-maker` ์คํฌ์ด ํ์ฑํ๋๋์ง ํ์ธํด์ค. ๋๋ฉด ๋ด๊ฐ ์ด ๊ธ ์ํ๋ก ๊ฐ์ธ ํด๋จธ๋์ด์ ํ๋ ๋ง๋ค์ด์ค.
Yes โ the tool for not sounding like an AI, installed by an AI. We're aware.
</details>
## Usage
Inside Claude Code or Codex, trigger it in natural language and hand it a sample:
```
build a personal humanizer from this document I wrote: <path or paste>
๋ด๊ฐ ์ด ์ด ๊ธ๋ก ๊ฐ์ธ ํด๋จธ๋์ด์ ์คํฌ ๋ง๋ค์ด์ค
```
It asks one thing up front โ **Korean or English** โ then runs the pipeline and drops the
emitted skill into the active host's skill root: `~/.claude/skills/humanize-NAME/` in
Claude Code, or `${CODEX_HOME:-~/.codex}/skills/humanize-NAME/` in Codex. From then on you
humanize any text with *that* skill:
```
humanize this draft in my voice
์ด ์ด์ ๋ด ๋ฌธ์ฒด๋ก ๋ค๋ฌ์ด์ค
```
The maker is the factory; the emitted skill is the tool. One profiling run per author; the
skill it produces is reusable forever.
## Outputs
An emitted skill mirrors the hand-made seed exactly, so nothing new has to be learned:
```
~/.claude/skills/humanize-NAME/ # Claude Code
${CODEX_HOME:-~/.codex}/skills/humanize-NAME/ # Codex
โโโ SKILL.md # ยง0 covenant + your per-axis rules + workflow + self-check
โโโ scripts/style_metrics.py # your baseline bands baked in (+ language flag)
โโโ references/
โโโ style_profile.md # the full profile, for transparency / debugging
โโโ examples.md # before/after pairs mined from your own writing
```
## Benchmark
**Two questions:** can a one-document profile generalize to other texts by the same author,
and can an emitted skill actually move a different input into the learned style bands?
Tested with public corpora and smoke-test rewrites in both English and Korean. Full method:
[`docs/benchmark.md`](./docs/benchmark.md).
**Generalization:** build from one Paul Graham essay (*How to Work Hard*), test on five
held-out essays:
| Evaluation | Strict bands | Convergence | Verdict |
|---|:--:|:--:|:--:|
| Paul Graham โ 5 held-out essays (pooled) | 41 / 45 | **91%** | โ
CONVERGED |
| *per essay* | 8โ9 / 9 | 89โ100% | โ
|
| Federalist No. 10 โ **different author** (control) | 7 / 9 | 78% | โ DIVERGED |
A one-document build **generalizes to 91%** of strict bands across the author's other
essays, and the same bands **reject a different author** โ which fails precisely on the
sentence-length signature (mean **33 words** vs. the PG band **[13, 22]**), not on traits
formal prose shares. The 7-axis multi-agent pass captured *this* voice, not a template:
**keep contractions**, pivot on **"But / And yet"** (never *however / therefore*), land
paragraphs on a **blunt fragment** (*"There isn't."*).
**Rewrite smoke tests:**
| Test | Before | After | Verdict |
|---|:--:|:--:|:--:|
| Kim Gu-style Korean rewrite | 5 / 8 | **8 / 8** | CONVERGED |
| Lincoln-style English rewrite | 10 / 12 | **12 / 12** | CONVERGED |
These are not claims of perfect authorship cloning. They show the intended product
behavior: the factory creates a measurable, reusable voice skill, and a consumer model can
use that skill to move a draft toward the learned profile while preserving facts.
## Repository Layout
```
personal-humanizer-maker/
โโโ README.md ยท README.ko.md ยท LICENSE
โโโ schemas/ # the three codeโagent contracts
โ โโโ quant_profile.schema.json
โ โโโ dimension_profile.schema.json
โ โโโ style_profile.schema.json
โโโ setup/install.sh
โโโ skills/personal-humanizer-maker/
โโโ SKILL.md # orchestrator
โโโ agents/openai.yaml # Codex UI metadata
โโโ references/ # taxonomy.{ko,en}.md ยท signal-map.md ยท ironclad.md
โโโ scripts/ # profile_corpus.py ยท emit_skill.py ยท roundtrip_check.py
โโโ templates/ # SKILL.md.tmpl ยท style_metrics.py.tmpl
```
## Notes & Limitations
- **Fully automatic, so overfitting is the real risk.** A thin sample can't support a strong
claim on every axis โ under-supported axes ship as *advisory*, the bands widen, and the
round-trip gate is the backstop. The factory never ships a voice it couldn't reproduce.
- **Generation costs tokens.** The multi-agent analysis is a one-time cost per author; the
emitted skill is free to run afterward.
- **Korean is the calibrated path.** The metrics and taxonomy were first derived on a Korean
corpus; English is supported and switches in at the start, but is the newer path.
- **No third-party text is vendored.** When a public author's writing is used for testing,
only aggregate metrics are reported โ never their text republished.
- **The covenant is not optional.** Meaning-invariance is injected into every emitted skill
regardless of the author's own style.
## License
Original work in this repository is released under the [MIT License](./LICENSE).