From 1e3e84b3a96800d5558811b50005371004e64fa1 Mon Sep 17 00:00:00 2001 From: Harshaneel Gokhale Date: Tue, 22 Sep 2026 04:27:30 -0700 Subject: [PATCH 1/2] Ship humanize and ai-check as installable plugins The repo now doubles as a plugin marketplace for Claude Code and Codex, so neither needs a clone or install.sh to pick up the skills. Skills move from the repo root to plugins//skills//, which is where both harnesses look. Each plugin carries a manifest per harness, and each harness reads its own marketplace file: .claude-plugin/marketplace.json for Claude Code, .agents/plugins/marketplace.json for Codex. install.sh resolves the new location with a fallback to the repo root, so clone installs keep working. The benchmark workflow, the scenario runner, the JSON-LD FAQ and the README all follow the paths. Existing symlink installs break on this change, since they point at the old root directories. The README says to re-run install.sh once after pulling. Co-Authored-By: Claude Opus 5 (1M context) --- .agents/plugins/marketplace.json | 32 +++++ .claude-plugin/marketplace.json | 36 ++++++ .github/benchmark/score_and_report.py | 2 +- .github/workflows/benchmark.yml | 12 +- README.md | 113 +++++++++++++----- _includes/head-custom.html | 2 +- install.sh | 3 +- plugins/ai-check/.claude-plugin/plugin.json | 10 ++ plugins/ai-check/.codex-plugin/plugin.json | 17 +++ .../ai-check/skills/ai-check}/SKILL.md | 0 plugins/humanize/.claude-plugin/plugin.json | 10 ++ plugins/humanize/.codex-plugin/plugin.json | 17 +++ .../humanize/skills/humanize}/SKILL.md | 0 .../skills/humanize}/references/research.md | 0 tests/SCENARIOS.md | 32 ++--- 15 files changed, 230 insertions(+), 56 deletions(-) create mode 100644 .agents/plugins/marketplace.json create mode 100644 .claude-plugin/marketplace.json create mode 100644 plugins/ai-check/.claude-plugin/plugin.json create mode 100644 plugins/ai-check/.codex-plugin/plugin.json rename {ai-check => plugins/ai-check/skills/ai-check}/SKILL.md (100%) create mode 100644 plugins/humanize/.claude-plugin/plugin.json create mode 100644 plugins/humanize/.codex-plugin/plugin.json rename {humanize => plugins/humanize/skills/humanize}/SKILL.md (100%) rename {humanize => plugins/humanize/skills/humanize}/references/research.md (100%) diff --git a/.agents/plugins/marketplace.json b/.agents/plugins/marketplace.json new file mode 100644 index 0000000..5d7ca2d --- /dev/null +++ b/.agents/plugins/marketplace.json @@ -0,0 +1,32 @@ +{ + "name": "humanize", + "interface": { + "displayName": "Humanize" + }, + "plugins": [ + { + "name": "humanize", + "version": "1.0.0", + "source": { + "source": "local", + "path": "./plugins/humanize" + }, + "policy": { + "installation": "AVAILABLE" + }, + "category": "Productivity" + }, + { + "name": "ai-check", + "version": "1.0.0", + "source": { + "source": "local", + "path": "./plugins/ai-check" + }, + "policy": { + "installation": "AVAILABLE" + }, + "category": "Productivity" + } + ] +} diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json new file mode 100644 index 0000000..a175af3 --- /dev/null +++ b/.claude-plugin/marketplace.json @@ -0,0 +1,36 @@ +{ + "name": "humanize", + "owner": { + "name": "Harshaneel Gokhale", + "email": "harshaneel.gokhale@gmail.com" + }, + "metadata": { + "description": "Skills for writing that does not read as AI-generated." + }, + "plugins": [ + { + "name": "humanize", + "source": "./plugins/humanize", + "description": "Rewrite text to strip AI tells and restore a human voice.", + "version": "1.0.0", + "author": { "name": "Harshaneel Gokhale" }, + "homepage": "https://github.com/harshaneel/humanize", + "repository": "https://github.com/harshaneel/humanize", + "license": "MIT", + "keywords": ["writing", "editing", "ai-detection", "style"], + "category": "productivity" + }, + { + "name": "ai-check", + "source": "./plugins/ai-check", + "description": "Score text for AI-writing signals and explain what gives it away.", + "version": "1.0.0", + "author": { "name": "Harshaneel Gokhale" }, + "homepage": "https://github.com/harshaneel/humanize", + "repository": "https://github.com/harshaneel/humanize", + "license": "MIT", + "keywords": ["writing", "review", "ai-detection", "forensics"], + "category": "productivity" + } + ] +} diff --git a/.github/benchmark/score_and_report.py b/.github/benchmark/score_and_report.py index 2d3cd9a..15b6078 100644 --- a/.github/benchmark/score_and_report.py +++ b/.github/benchmark/score_and_report.py @@ -117,7 +117,7 @@ def check(ok): MARKER, f"## Humanize skill benchmark — {'PASS ✅' if passed else 'FAIL ❌'}", "", - f"{len(ids)} fixed AI-flavored inputs humanized with the PR's `humanize/SKILL.md` " + f"{len(ids)} fixed AI-flavored inputs humanized with the PR's `plugins/humanize/skills/humanize/SKILL.md` " f"(executor: {args.executor_label}{resolved_note}) and scored against the raw " "inputs as baseline.", "", diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index 8ea69f7..d9ff988 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -4,15 +4,15 @@ on: # Same-repo PRs: workflow and code run from the PR branch (trusted). pull_request: paths: - - "humanize/SKILL.md" + - "plugins/humanize/skills/humanize/SKILL.md" - ".github/benchmark/**" - ".github/workflows/benchmark.yml" # Fork PRs: workflow and ALL code run from the base branch; only the fork's - # humanize/SKILL.md is fetched, as prompt data. Fork code never executes here. + # plugins/humanize/skills/humanize/SKILL.md is fetched, as prompt data. Fork code never executes here. pull_request_target: types: [opened, synchronize, reopened, labeled] paths: - - "humanize/SKILL.md" + - "plugins/humanize/skills/humanize/SKILL.md" workflow_dispatch: permissions: @@ -54,8 +54,8 @@ jobs: if: github.event_name == 'pull_request_target' run: | git fetch origin "pull/${{ github.event.pull_request.number }}/head" - git checkout FETCH_HEAD -- humanize/SKILL.md - echo "Benchmarking fork skill: $(wc -w < humanize/SKILL.md) words" + git checkout FETCH_HEAD -- plugins/humanize/skills/humanize/SKILL.md + echo "Benchmarking fork skill: $(wc -w < plugins/humanize/skills/humanize/SKILL.md) words" - uses: actions/setup-python@v5 with: @@ -77,7 +77,7 @@ jobs: env: LLM_API_KEY: ${{ secrets.GEMINI_API_KEY }} run: | - python $BENCH/humanize_batch.py --skill humanize/SKILL.md \ + python $BENCH/humanize_batch.py --skill plugins/humanize/skills/humanize/SKILL.md \ --inputs $BENCH/inputs.json --output /tmp/outputs.json \ --base-url "$EXECUTOR_BASE_URL" --model "$EXECUTOR_MODEL" diff --git a/README.md b/README.md index da0912d..455b177 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ Works in any LLM agent: Claude Code, Codex CLI, ChatGPT, Gemini, Cursor, Aider, **Get started** - [What's inside](#whats-inside) — the two skills, at a glance -- [Installation](#installation) — one command for Claude Code, Codex CLI, ChatGPT desktop, or any agent +- [Installation](#installation) — plugin marketplace for Claude Code and Codex, one command for everything else - [Usage](#usage) — how to invoke each skill - [Benchmark](#benchmark) — 25 inputs, two independent scorers @@ -55,45 +55,60 @@ Both are static rule-based skills (single `SKILL.md` per skill, zero runtime dep ## Installation -This repo bundles two skills (`humanize` and `ai-check`) in their own subdirectories. Installation copies both into your agent's skills folder. +This repo bundles two skills (`humanize` and `ai-check`) under `plugins/`. It doubles as a plugin +marketplace for Claude Code and Codex, so those two can install the skills without cloning. Every +other agent reads the skills from disk, which `install.sh` sets up. -### Install everywhere in one command +### Claude Code -If you use multiple agents (Claude Code, Codex CLI, ChatGPT desktop), install to all three skill directories at once: +This repo is a Claude Code plugin marketplace. Add it once, then install either skill: ```bash -git clone https://github.com/harshaneel/humanize.git -cd humanize && ./install.sh all +claude plugin marketplace add harshaneel/humanize +claude plugin install humanize@humanize +claude plugin install ai-check@humanize ``` -This installs to `~/.claude/skills/`, `~/.codex/skills/`, and `~/.agents/skills/`. Add `--copy` if you prefer self-contained files over symlinks. - -### Claude Code +Restart Claude Code and both skills are live. Update later with +`claude plugin update humanize`. -Clone the repo, then copy both skill folders into Claude Code's skills directory: +Prefer a plain clone? The install script symlinks the skills into `~/.claude/skills/`, so `git pull` +updates apply automatically: ```bash git clone https://github.com/harshaneel/humanize.git -mkdir -p ~/.claude/skills -cp -R humanize/humanize humanize/ai-check ~/.claude/skills/ +cd humanize && ./install.sh +``` + +### Codex CLI + +Codex reads the same repo as a plugin marketplace: + +```bash +codex plugin marketplace add harshaneel/humanize +codex plugin add humanize@humanize +codex plugin add ai-check@humanize ``` -Or use the included install script (symlinks instead of copies, so `git pull` updates apply automatically): +Refresh the snapshot later with `codex plugin marketplace upgrade`. + +Or install the skills straight into `~/.codex/skills/`: ```bash git clone https://github.com/harshaneel/humanize.git -cd humanize && ./install.sh +cd humanize && ./install.sh codex ``` -### Codex CLI +### Install everywhere in one command + +If you use multiple agents (Claude Code, Codex CLI, ChatGPT desktop), install to all three skill directories at once: ```bash git clone https://github.com/harshaneel/humanize.git -mkdir -p ~/.codex/skills -cp -R humanize/humanize humanize/ai-check ~/.codex/skills/ +cd humanize && ./install.sh all ``` -Or `cd humanize && ./install.sh codex` to use the install script. +This installs to `~/.claude/skills/`, `~/.codex/skills/`, and `~/.agents/skills/`. Add `--copy` if you prefer self-contained files over symlinks. ### ChatGPT desktop / OpenAI agents @@ -102,7 +117,7 @@ ChatGPT desktop and several OpenAI agent harnesses read from `~/.agents/skills/` ```bash git clone https://github.com/harshaneel/humanize.git mkdir -p ~/.agents/skills -cp -R humanize/humanize humanize/ai-check ~/.agents/skills/ +cp -R humanize/plugins/humanize/skills/humanize humanize/plugins/ai-check/skills/ai-check ~/.agents/skills/ ``` Or `cd humanize && ./install.sh chatgpt` to use the install script. @@ -112,23 +127,23 @@ Or `cd humanize && ./install.sh chatgpt` to use the install script. ```bash git clone https://github.com/harshaneel/humanize.git mkdir -p ~/.config/opencode/skills -cp -R humanize/humanize humanize/ai-check ~/.config/opencode/skills/ +cp -R humanize/plugins/humanize/skills/humanize humanize/plugins/ai-check/skills/ai-check ~/.config/opencode/skills/ ``` -> **Note:** OpenCode also scans `~/.claude/skills/` for compatibility, so a single clone into `~/.claude/skills/` works for both tools. +> **Note:** OpenCode also scans `~/.claude/skills/` for compatibility, so `./install.sh` covers both tools. Cloning the repo straight into `~/.claude/skills/` no longer works, because the skills sit under `plugins/`. ### Claude.ai / Claude Desktop The web and desktop apps don't read from disk. Upload through the UI instead: 1. Open **Settings → Capabilities → Skills**. -2. Click **Create skill** and upload `[humanize/SKILL.md](humanize/SKILL.md)`. -3. Repeat with `[ai-check/SKILL.md](ai-check/SKILL.md)`. +2. Click **Create skill** and upload [`plugins/humanize/skills/humanize/SKILL.md`](plugins/humanize/skills/humanize/SKILL.md). +3. Repeat with [`plugins/ai-check/skills/ai-check/SKILL.md`](plugins/ai-check/skills/ai-check/SKILL.md). 4. Toggle each skill on in conversations where you want it active. ### Any other chat agent (ChatGPT, Gemini, Cursor, Aider, Cline) -No install needed. Open `[humanize/SKILL.md](humanize/SKILL.md)`, copy the raw contents, and paste into a new conversation prefaced with: *"Use these instructions whenever I ask you to humanize text."* Same for `[ai-check/SKILL.md](ai-check/SKILL.md)`. +No install needed. Open [`plugins/humanize/skills/humanize/SKILL.md`](plugins/humanize/skills/humanize/SKILL.md), copy the raw contents, and paste into a new conversation prefaced with: *"Use these instructions whenever I ask you to humanize text."* Same for [`plugins/ai-check/skills/ai-check/SKILL.md`](plugins/ai-check/skills/ai-check/SKILL.md). --- @@ -137,11 +152,13 @@ No install needed. Open `[humanize/SKILL.md](humanize/SKILL.md)`, copy the raw c ### Humanize ``` -/humanize +/humanize:humanize [paste your text here] ``` +Installed from a clone rather than the marketplace? The skill is just `/humanize`. + Or ask the model directly: ``` @@ -151,11 +168,13 @@ Please humanize this text: [your text] ### AI-check ``` -/ai-check +/ai-check:ai-check [paste your text here] ``` +From a clone, it is just `/ai-check`. + Or ask the model directly: ``` @@ -169,7 +188,7 @@ Does this sound AI? [your text] To match your personal writing style, provide a sample of your own writing before the text to humanize: ``` -/humanize +/humanize:humanize Here's a sample of my writing for voice matching: [paste 2-3 paragraphs of your own writing] @@ -266,11 +285,11 @@ A humanize skill is a set of rules an LLM agent (Claude, ChatGPT, Codex, Gemini) ### What's the best static AI text humanizer for Claude Code? -This repo's `humanize` skill is designed for Claude Code and works in any LLM agent. It applies nine humanization levers from the published detection literature (perplexity injection, burstiness enforcement, hedge surgery, structural flattening, specificity insertion, voice and register, AI-transition removal, punctuation normalization, RLHF voice strip) plus an audit-revise loop that catches residual AI patterns. Installation is one command: `git clone https://github.com/harshaneel/humanize.git && cd humanize && ./install.sh all`. +This repo's `humanize` skill is designed for Claude Code and works in any LLM agent. It applies nine humanization levers from the published detection literature (perplexity injection, burstiness enforcement, hedge surgery, structural flattening, specificity insertion, voice and register, AI-transition removal, punctuation normalization, RLHF voice strip) plus an audit-revise loop that catches residual AI patterns. Install it as a plugin with `claude plugin marketplace add harshaneel/humanize` then `claude plugin install humanize@humanize`, or clone the repo and run `./install.sh all`. ### How do I install a humanizer skill in Claude Code, Codex CLI, or ChatGPT? -Clone the repo and run `./install.sh all` to install to all three agent skills directories (`~/.claude/skills/`, `~/.codex/skills/`, `~/.agents/skills/`). Or pick a single target: `./install.sh claude`, `./install.sh codex`, `./install.sh chatgpt`. For Claude Desktop or any web chat agent, upload the `SKILL.md` files through Settings → Skills, or paste them into the conversation as a system prompt. +Claude Code and Codex install it as a plugin, no clone needed: `claude plugin marketplace add harshaneel/humanize` then `claude plugin install humanize@humanize`, or `codex plugin marketplace add harshaneel/humanize` then `codex plugin add humanize@humanize`. For ChatGPT desktop and everything else, clone the repo and run `./install.sh all` to install to all three agent skills directories (`~/.claude/skills/`, `~/.codex/skills/`, `~/.agents/skills/`). Or pick a single target: `./install.sh claude`, `./install.sh codex`, `./install.sh chatgpt`. For Claude Desktop or any web chat agent, upload the `SKILL.md` files through Settings → Skills, or paste them into the conversation as a system prompt. ### Will the output read as human to GPTZero or Grammarly? @@ -574,15 +593,43 @@ The `humanize` skill catalogs these in implementation detail under "Advanced tec ## Updating +Installed as a plugin: + +```bash +claude plugin update humanize # and ai-check +codex plugin marketplace upgrade +codex plugin add humanize@humanize # refreshes the cached copy +``` + +Both caches are keyed by version, so a skill edit that ships without a version bump will not +reach you. `claude plugin update` reports "already at the latest version" and leaves the old +skill in place. + +Installed from a clone: + ```bash cd ~/code/humanize # or wherever you cloned it git pull ``` -If you installed via symlink (the default), updates apply immediately. If you used `--copy`, re-run `./install.sh` to refresh. +This release moved the skills under `plugins/`. If you installed before that, re-run `./install.sh` (or `./install.sh all`) once after pulling, otherwise your symlinks point at the old locations and the skills silently stop loading. + +After that, symlink installs pick up updates immediately. If you used `--copy`, re-run `./install.sh` to refresh. ## Uninstalling +Installed as a plugin: + +```bash +claude plugin uninstall humanize@humanize +claude plugin uninstall ai-check@humanize +# or for codex +codex plugin remove humanize@humanize +codex plugin remove ai-check@humanize +``` + +Installed from a clone: + ```bash rm ~/.claude/skills/humanize ~/.claude/skills/ai-check # or for codex @@ -593,13 +640,17 @@ rm ~/.codex/skills/humanize ~/.codex/skills/ai-check PRs welcome, especially for: -- New AI tells discovered in the wild (add to `ai-check/SKILL.md` Signal I) +- New AI tells discovered in the wild (add to `plugins/ai-check/skills/ai-check/SKILL.md` Signal I) - New humanization patterns that survive 2025-2026 detectors - Test scenarios that exercise edge cases (add to `tests/SCENARIOS.md`) - Research citations that update or contradict the existing claims (open an issue first if it requires structural changes) Before opening a PR, run the regression scenarios in `tests/SCENARIOS.md` manually and document the result. +Changing a skill also means bumping its version in four files, otherwise plugin users never see +the change: `.claude-plugin/marketplace.json`, `.agents/plugins/marketplace.json`, +`plugins//.claude-plugin/plugin.json` and `plugins//.codex-plugin/plugin.json`. + ## License MIT. See `LICENSE`. diff --git a/_includes/head-custom.html b/_includes/head-custom.html index 9e69d39..9e69421 100644 --- a/_includes/head-custom.html +++ b/_includes/head-custom.html @@ -77,7 +77,7 @@ "name": "How do I install a humanize skill in Claude Code, Codex CLI, or ChatGPT?", "acceptedAnswer": { "@type": "Answer", - "text": "Clone the repo and run ./install.sh all to install to all three agent skills directories. Or pick a single target: ./install.sh claude, ./install.sh codex, ./install.sh chatgpt. For Claude Desktop or web chat agents, upload the SKILL.md files through Settings or paste them as a system prompt." + "text": "Claude Code and Codex install it as a plugin, no clone needed: claude plugin marketplace add harshaneel/humanize then claude plugin install humanize@humanize, or codex plugin marketplace add harshaneel/humanize then codex plugin add humanize@humanize. For ChatGPT desktop and everything else, clone the repo and run ./install.sh all, or pick a single target: ./install.sh claude, ./install.sh codex, ./install.sh chatgpt. For Claude Desktop or web chat agents, upload the SKILL.md files through Settings or paste them as a system prompt." } }, { diff --git a/install.sh b/install.sh index 66879e1..5ccceb6 100755 --- a/install.sh +++ b/install.sh @@ -55,7 +55,8 @@ install_into() { echo "Installing skills to $dest (mode: $MODE)" for skill in "${SKILLS[@]}"; do - local src="$REPO_DIR/$skill" + local src="$REPO_DIR/plugins/$skill/skills/$skill" + [ -d "$src" ] || src="$REPO_DIR/$skill" local dst="$dest/$skill" if [ ! -d "$src" ]; then diff --git a/plugins/ai-check/.claude-plugin/plugin.json b/plugins/ai-check/.claude-plugin/plugin.json new file mode 100644 index 0000000..82852d7 --- /dev/null +++ b/plugins/ai-check/.claude-plugin/plugin.json @@ -0,0 +1,10 @@ +{ + "name": "ai-check", + "version": "1.0.0", + "description": "Score text for AI-writing signals and explain what gives it away.", + "author": { "name": "Harshaneel Gokhale" }, + "homepage": "https://github.com/harshaneel/humanize", + "repository": "https://github.com/harshaneel/humanize", + "license": "MIT", + "keywords": ["writing", "review", "ai-detection", "forensics"] +} diff --git a/plugins/ai-check/.codex-plugin/plugin.json b/plugins/ai-check/.codex-plugin/plugin.json new file mode 100644 index 0000000..559debc --- /dev/null +++ b/plugins/ai-check/.codex-plugin/plugin.json @@ -0,0 +1,17 @@ +{ + "name": "ai-check", + "version": "1.0.0", + "description": "Score text for AI-writing signals and explain what gives it away.", + "author": { "name": "Harshaneel Gokhale" }, + "homepage": "https://github.com/harshaneel/humanize", + "repository": "https://github.com/harshaneel/humanize", + "license": "MIT", + "keywords": ["writing", "review", "ai-detection", "forensics"], + "skills": "./skills/", + "interface": { + "displayName": "AI Check", + "shortDescription": "Score text for AI-writing signals and explain what gives it away.", + "category": "Productivity", + "capabilities": ["Interactive", "Read"] + } +} diff --git a/ai-check/SKILL.md b/plugins/ai-check/skills/ai-check/SKILL.md similarity index 100% rename from ai-check/SKILL.md rename to plugins/ai-check/skills/ai-check/SKILL.md diff --git a/plugins/humanize/.claude-plugin/plugin.json b/plugins/humanize/.claude-plugin/plugin.json new file mode 100644 index 0000000..7da6e86 --- /dev/null +++ b/plugins/humanize/.claude-plugin/plugin.json @@ -0,0 +1,10 @@ +{ + "name": "humanize", + "version": "1.0.0", + "description": "Rewrite text to strip AI tells and restore a human voice.", + "author": { "name": "Harshaneel Gokhale" }, + "homepage": "https://github.com/harshaneel/humanize", + "repository": "https://github.com/harshaneel/humanize", + "license": "MIT", + "keywords": ["writing", "editing", "ai-detection", "style"] +} diff --git a/plugins/humanize/.codex-plugin/plugin.json b/plugins/humanize/.codex-plugin/plugin.json new file mode 100644 index 0000000..a277aab --- /dev/null +++ b/plugins/humanize/.codex-plugin/plugin.json @@ -0,0 +1,17 @@ +{ + "name": "humanize", + "version": "1.0.0", + "description": "Rewrite text to strip AI tells and restore a human voice.", + "author": { "name": "Harshaneel Gokhale" }, + "homepage": "https://github.com/harshaneel/humanize", + "repository": "https://github.com/harshaneel/humanize", + "license": "MIT", + "keywords": ["writing", "editing", "ai-detection", "style"], + "skills": "./skills/", + "interface": { + "displayName": "Humanize", + "shortDescription": "Rewrite text to strip AI tells and restore a human voice.", + "category": "Productivity", + "capabilities": ["Interactive", "Read", "Write"] + } +} diff --git a/humanize/SKILL.md b/plugins/humanize/skills/humanize/SKILL.md similarity index 100% rename from humanize/SKILL.md rename to plugins/humanize/skills/humanize/SKILL.md diff --git a/humanize/references/research.md b/plugins/humanize/skills/humanize/references/research.md similarity index 100% rename from humanize/references/research.md rename to plugins/humanize/skills/humanize/references/research.md diff --git a/tests/SCENARIOS.md b/tests/SCENARIOS.md index 0d75783..4e9331d 100644 --- a/tests/SCENARIOS.md +++ b/tests/SCENARIOS.md @@ -4,8 +4,8 @@ Regression fixtures for the `humanize` and `ai-check` skills. To verify either s Methodology: writing-skills TDD (RED baseline, then GREEN with skill). -Size budget: `humanize/SKILL.md` stays under ~6,000 words (`wc -w`). Research citations and -rationale belong in `humanize/references/research.md`, not inline; new patterns should extend +Size budget: `plugins/humanize/skills/humanize/SKILL.md` stays under ~6,000 words (`wc -w`). Research citations and +rationale belong in `plugins/humanize/skills/humanize/references/research.md`, not inline; new patterns should extend the Signal I checklist (single source of truth) rather than duplicating it in a lever. Consistency guard: every pattern named in Lever 4's "catalogued ONCE in the Signal I checklist" preamble must actually have a checklist item — verify the list against the @@ -34,7 +34,7 @@ Coverage matrix: ## Scenario 1: humanize on flagrant AI prose (GREEN) -**Skill:** `humanize/SKILL.md` +**Skill:** `plugins/humanize/skills/humanize/SKILL.md` **User prompt:** "Can you humanize this paragraph?" @@ -60,7 +60,7 @@ In today's fast-paced world, it is important to note that artificial intelligenc ## Scenario 2: ai-check on flagrant AI prose (GREEN) -**Skill:** `ai-check/SKILL.md` +**Skill:** `plugins/ai-check/skills/ai-check/SKILL.md` **User prompt:** "Can you run ai-check on this?" @@ -80,7 +80,7 @@ In today's fast-paced world, it is important to note that artificial intelligenc ## Scenario 3: ai-check on real Slack message (false-positive calibration) -**Skill:** `ai-check/SKILL.md` +**Skill:** `plugins/ai-check/skills/ai-check/SKILL.md` **User prompt:** "score this text" @@ -104,7 +104,7 @@ oh also — the staging cluster keeps OOMing during the backfill. bumped the mem ## Scenario 4: humanize on subtler text (gap-finder) -**Skill:** `humanize/SKILL.md` +**Skill:** `plugins/humanize/skills/humanize/SKILL.md` **User prompt:** "humanize this" @@ -130,7 +130,7 @@ This input has no banned vocabulary, no em dashes, no semicolons. It still fires ## Scenario 5: humanize long-form essay (consistency under length) -**Skill:** `humanize/SKILL.md` +**Skill:** `plugins/humanize/skills/humanize/SKILL.md` **User prompt:** "humanize this essay" @@ -158,7 +158,7 @@ Studies have shown that successful remote work implementation requires a multifa ## Scenario 6: humanize technical content (engineering register) -**Skill:** `humanize/SKILL.md` +**Skill:** `plugins/humanize/skills/humanize/SKILL.md` **User prompt:** "make this read like an actual engineer wrote it" @@ -182,7 +182,7 @@ A common pitfall is over-indexing, which can lead to degraded write performance ## Scenario 7: humanize professional email -**Skill:** `humanize/SKILL.md` +**Skill:** `plugins/humanize/skills/humanize/SKILL.md` **User prompt:** "humanize this email" @@ -219,7 +219,7 @@ Best regards, ## Scenario 8: humanize Slack message (polish underneath casual markers) -**Skill:** `humanize/SKILL.md` +**Skill:** `plugins/humanize/skills/humanize/SKILL.md` **User prompt:** "rewrite this as a real Slack message" @@ -253,7 +253,7 @@ This is AI pretending to be Slack: lowercase + emoji + "lmk" on top of fully-for ## Scenario 9: humanize with voice sample (writer-profile distillation) -**Skill:** `humanize/SKILL.md` +**Skill:** `plugins/humanize/skills/humanize/SKILL.md` **User prompt:** ``` @@ -279,7 +279,7 @@ The deployment of our new search service yesterday encountered an unexpected iss ## Scenario 10: humanize RLHF helpful-assistant register -**Skill:** `humanize/SKILL.md` +**Skill:** `plugins/humanize/skills/humanize/SKILL.md` **User prompt:** "humanize this answer" @@ -311,7 +311,7 @@ This is pure Lever 9 territory: every sentence is RLHF voice. ## Scenario 11: ai-check on academic abstract (false-positive calibration) -**Skill:** `ai-check/SKILL.md` +**Skill:** `plugins/ai-check/skills/ai-check/SKILL.md` **User prompt:** "is this AI?" @@ -335,7 +335,7 @@ This is a real-style academic abstract. It has semicolons, formal vocabulary, "N ## Scenario 12: ai-check on mixed authorship -**Skill:** `ai-check/SKILL.md` +**Skill:** `plugins/ai-check/skills/ai-check/SKILL.md` **User prompt:** "score this" @@ -382,7 +382,7 @@ Paragraphs 1 and 3 are obviously human (casual, fragments, lowercase, self-depre ## Scenario 14: humanize on creative/lyrical prose (register-rationalization stress test) -**Skill:** `humanize/SKILL.md` +**Skill:** `plugins/humanize/skills/humanize/SKILL.md` **User prompt:** "/humanize this hopeful passage" @@ -408,7 +408,7 @@ The city is still dark, but at the edges the sky has started to push back. You'v To run any scenario manually, dispatch a subagent with this template: ``` -Read /Users/harshaneel/workspace/personal/humanize//SKILL.md in full. +Read /Users/harshaneel/workspace/personal/humanize/ in full. Then act as if you had been invoked with this skill loaded. The user has asked: "" Input: From af2a592d4406bfae38004145e71e2f2a939f50d3 Mon Sep 17 00:00:00 2001 From: Harshaneel Gokhale Date: Tue, 22 Sep 2026 04:56:07 -0700 Subject: [PATCH 2/2] Bundle both skills in one plugin Shipping humanize and ai-check as separate plugins meant two installs and invocations that read /humanize:humanize and /ai-check:ai-check, since a plugin skill is always addressed plugin:skill. One plugin carrying both gives /humanize:humanize and /humanize:ai-check, which is what people expect. ai-check's skill moves under the humanize plugin, the second plugin and its manifests go away, and both marketplace files drop to a single entry. The version goes to 1.1.0 because plugin caches are keyed by version. Without the bump, anyone holding 1.0.0 keeps a humanize plugin that has no ai-check in it, and claude plugin update reports it is already current. Co-Authored-By: Claude Opus 5 (1M context) --- .agents/plugins/marketplace.json | 14 +------- .claude-plugin/marketplace.json | 18 ++-------- README.md | 35 +++++++++++-------- install.sh | 2 +- plugins/ai-check/.claude-plugin/plugin.json | 10 ------ plugins/ai-check/.codex-plugin/plugin.json | 17 --------- plugins/humanize/.claude-plugin/plugin.json | 6 ++-- plugins/humanize/.codex-plugin/plugin.json | 8 ++--- .../skills/ai-check/SKILL.md | 0 tests/SCENARIOS.md | 8 ++--- 10 files changed, 36 insertions(+), 82 deletions(-) delete mode 100644 plugins/ai-check/.claude-plugin/plugin.json delete mode 100644 plugins/ai-check/.codex-plugin/plugin.json rename plugins/{ai-check => humanize}/skills/ai-check/SKILL.md (100%) diff --git a/.agents/plugins/marketplace.json b/.agents/plugins/marketplace.json index 5d7ca2d..8b233a7 100644 --- a/.agents/plugins/marketplace.json +++ b/.agents/plugins/marketplace.json @@ -6,7 +6,7 @@ "plugins": [ { "name": "humanize", - "version": "1.0.0", + "version": "1.1.0", "source": { "source": "local", "path": "./plugins/humanize" @@ -15,18 +15,6 @@ "installation": "AVAILABLE" }, "category": "Productivity" - }, - { - "name": "ai-check", - "version": "1.0.0", - "source": { - "source": "local", - "path": "./plugins/ai-check" - }, - "policy": { - "installation": "AVAILABLE" - }, - "category": "Productivity" } ] } diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index a175af3..3db3689 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -11,25 +11,13 @@ { "name": "humanize", "source": "./plugins/humanize", - "description": "Rewrite text to strip AI tells and restore a human voice.", - "version": "1.0.0", + "description": "Strip AI tells from text, and score text for the tells it still has.", + "version": "1.1.0", "author": { "name": "Harshaneel Gokhale" }, "homepage": "https://github.com/harshaneel/humanize", "repository": "https://github.com/harshaneel/humanize", "license": "MIT", - "keywords": ["writing", "editing", "ai-detection", "style"], - "category": "productivity" - }, - { - "name": "ai-check", - "source": "./plugins/ai-check", - "description": "Score text for AI-writing signals and explain what gives it away.", - "version": "1.0.0", - "author": { "name": "Harshaneel Gokhale" }, - "homepage": "https://github.com/harshaneel/humanize", - "repository": "https://github.com/harshaneel/humanize", - "license": "MIT", - "keywords": ["writing", "review", "ai-detection", "forensics"], + "keywords": ["writing", "editing", "review", "ai-detection", "style"], "category": "productivity" } ] diff --git a/README.md b/README.md index 455b177..89b7c4b 100644 --- a/README.md +++ b/README.md @@ -61,14 +61,15 @@ other agent reads the skills from disk, which `install.sh` sets up. ### Claude Code -This repo is a Claude Code plugin marketplace. Add it once, then install either skill: +This repo is a Claude Code plugin marketplace. Add it once, then install it: ```bash claude plugin marketplace add harshaneel/humanize claude plugin install humanize@humanize -claude plugin install ai-check@humanize ``` +That one plugin carries both skills. + Restart Claude Code and both skills are live. Update later with `claude plugin update humanize`. @@ -87,7 +88,6 @@ Codex reads the same repo as a plugin marketplace: ```bash codex plugin marketplace add harshaneel/humanize codex plugin add humanize@humanize -codex plugin add ai-check@humanize ``` Refresh the snapshot later with `codex plugin marketplace upgrade`. @@ -117,7 +117,7 @@ ChatGPT desktop and several OpenAI agent harnesses read from `~/.agents/skills/` ```bash git clone https://github.com/harshaneel/humanize.git mkdir -p ~/.agents/skills -cp -R humanize/plugins/humanize/skills/humanize humanize/plugins/ai-check/skills/ai-check ~/.agents/skills/ +cp -R humanize/plugins/humanize/skills/humanize humanize/plugins/humanize/skills/ai-check ~/.agents/skills/ ``` Or `cd humanize && ./install.sh chatgpt` to use the install script. @@ -127,7 +127,7 @@ Or `cd humanize && ./install.sh chatgpt` to use the install script. ```bash git clone https://github.com/harshaneel/humanize.git mkdir -p ~/.config/opencode/skills -cp -R humanize/plugins/humanize/skills/humanize humanize/plugins/ai-check/skills/ai-check ~/.config/opencode/skills/ +cp -R humanize/plugins/humanize/skills/humanize humanize/plugins/humanize/skills/ai-check ~/.config/opencode/skills/ ``` > **Note:** OpenCode also scans `~/.claude/skills/` for compatibility, so `./install.sh` covers both tools. Cloning the repo straight into `~/.claude/skills/` no longer works, because the skills sit under `plugins/`. @@ -138,12 +138,12 @@ The web and desktop apps don't read from disk. Upload through the UI instead: 1. Open **Settings → Capabilities → Skills**. 2. Click **Create skill** and upload [`plugins/humanize/skills/humanize/SKILL.md`](plugins/humanize/skills/humanize/SKILL.md). -3. Repeat with [`plugins/ai-check/skills/ai-check/SKILL.md`](plugins/ai-check/skills/ai-check/SKILL.md). +3. Repeat with [`plugins/humanize/skills/ai-check/SKILL.md`](plugins/humanize/skills/ai-check/SKILL.md). 4. Toggle each skill on in conversations where you want it active. ### Any other chat agent (ChatGPT, Gemini, Cursor, Aider, Cline) -No install needed. Open [`plugins/humanize/skills/humanize/SKILL.md`](plugins/humanize/skills/humanize/SKILL.md), copy the raw contents, and paste into a new conversation prefaced with: *"Use these instructions whenever I ask you to humanize text."* Same for [`plugins/ai-check/skills/ai-check/SKILL.md`](plugins/ai-check/skills/ai-check/SKILL.md). +No install needed. Open [`plugins/humanize/skills/humanize/SKILL.md`](plugins/humanize/skills/humanize/SKILL.md), copy the raw contents, and paste into a new conversation prefaced with: *"Use these instructions whenever I ask you to humanize text."* Same for [`plugins/humanize/skills/ai-check/SKILL.md`](plugins/humanize/skills/ai-check/SKILL.md). --- @@ -168,7 +168,7 @@ Please humanize this text: [your text] ### AI-check ``` -/ai-check:ai-check +/humanize:ai-check [paste your text here] ``` @@ -596,7 +596,7 @@ The `humanize` skill catalogs these in implementation detail under "Advanced tec Installed as a plugin: ```bash -claude plugin update humanize # and ai-check +claude plugin update humanize codex plugin marketplace upgrade codex plugin add humanize@humanize # refreshes the cached copy ``` @@ -614,6 +614,13 @@ git pull This release moved the skills under `plugins/`. If you installed before that, re-run `./install.sh` (or `./install.sh all`) once after pulling, otherwise your symlinks point at the old locations and the skills silently stop loading. +If you installed an earlier build that shipped `ai-check` as its own plugin, remove it. Both skills now come from the one `humanize` plugin: + +```bash +claude plugin uninstall ai-check@humanize +codex plugin remove ai-check@humanize +``` + After that, symlink installs pick up updates immediately. If you used `--copy`, re-run `./install.sh` to refresh. ## Uninstalling @@ -622,10 +629,8 @@ Installed as a plugin: ```bash claude plugin uninstall humanize@humanize -claude plugin uninstall ai-check@humanize # or for codex codex plugin remove humanize@humanize -codex plugin remove ai-check@humanize ``` Installed from a clone: @@ -640,16 +645,16 @@ rm ~/.codex/skills/humanize ~/.codex/skills/ai-check PRs welcome, especially for: -- New AI tells discovered in the wild (add to `plugins/ai-check/skills/ai-check/SKILL.md` Signal I) +- New AI tells discovered in the wild (add to `plugins/humanize/skills/ai-check/SKILL.md` Signal I) - New humanization patterns that survive 2025-2026 detectors - Test scenarios that exercise edge cases (add to `tests/SCENARIOS.md`) - Research citations that update or contradict the existing claims (open an issue first if it requires structural changes) Before opening a PR, run the regression scenarios in `tests/SCENARIOS.md` manually and document the result. -Changing a skill also means bumping its version in four files, otherwise plugin users never see -the change: `.claude-plugin/marketplace.json`, `.agents/plugins/marketplace.json`, -`plugins//.claude-plugin/plugin.json` and `plugins//.codex-plugin/plugin.json`. +Changing a skill also means bumping the plugin version in four files, otherwise plugin users never +see the change: `.claude-plugin/marketplace.json`, `.agents/plugins/marketplace.json`, +`plugins/humanize/.claude-plugin/plugin.json` and `plugins/humanize/.codex-plugin/plugin.json`. ## License diff --git a/install.sh b/install.sh index 5ccceb6..ad5d2c4 100755 --- a/install.sh +++ b/install.sh @@ -55,7 +55,7 @@ install_into() { echo "Installing skills to $dest (mode: $MODE)" for skill in "${SKILLS[@]}"; do - local src="$REPO_DIR/plugins/$skill/skills/$skill" + local src="$REPO_DIR/plugins/humanize/skills/$skill" [ -d "$src" ] || src="$REPO_DIR/$skill" local dst="$dest/$skill" diff --git a/plugins/ai-check/.claude-plugin/plugin.json b/plugins/ai-check/.claude-plugin/plugin.json deleted file mode 100644 index 82852d7..0000000 --- a/plugins/ai-check/.claude-plugin/plugin.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "name": "ai-check", - "version": "1.0.0", - "description": "Score text for AI-writing signals and explain what gives it away.", - "author": { "name": "Harshaneel Gokhale" }, - "homepage": "https://github.com/harshaneel/humanize", - "repository": "https://github.com/harshaneel/humanize", - "license": "MIT", - "keywords": ["writing", "review", "ai-detection", "forensics"] -} diff --git a/plugins/ai-check/.codex-plugin/plugin.json b/plugins/ai-check/.codex-plugin/plugin.json deleted file mode 100644 index 559debc..0000000 --- a/plugins/ai-check/.codex-plugin/plugin.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "ai-check", - "version": "1.0.0", - "description": "Score text for AI-writing signals and explain what gives it away.", - "author": { "name": "Harshaneel Gokhale" }, - "homepage": "https://github.com/harshaneel/humanize", - "repository": "https://github.com/harshaneel/humanize", - "license": "MIT", - "keywords": ["writing", "review", "ai-detection", "forensics"], - "skills": "./skills/", - "interface": { - "displayName": "AI Check", - "shortDescription": "Score text for AI-writing signals and explain what gives it away.", - "category": "Productivity", - "capabilities": ["Interactive", "Read"] - } -} diff --git a/plugins/humanize/.claude-plugin/plugin.json b/plugins/humanize/.claude-plugin/plugin.json index 7da6e86..0b484f6 100644 --- a/plugins/humanize/.claude-plugin/plugin.json +++ b/plugins/humanize/.claude-plugin/plugin.json @@ -1,10 +1,10 @@ { "name": "humanize", - "version": "1.0.0", - "description": "Rewrite text to strip AI tells and restore a human voice.", + "version": "1.1.0", + "description": "Strip AI tells from text, and score text for the tells it still has.", "author": { "name": "Harshaneel Gokhale" }, "homepage": "https://github.com/harshaneel/humanize", "repository": "https://github.com/harshaneel/humanize", "license": "MIT", - "keywords": ["writing", "editing", "ai-detection", "style"] + "keywords": ["writing", "editing", "review", "ai-detection", "style"] } diff --git a/plugins/humanize/.codex-plugin/plugin.json b/plugins/humanize/.codex-plugin/plugin.json index a277aab..eaaf030 100644 --- a/plugins/humanize/.codex-plugin/plugin.json +++ b/plugins/humanize/.codex-plugin/plugin.json @@ -1,16 +1,16 @@ { "name": "humanize", - "version": "1.0.0", - "description": "Rewrite text to strip AI tells and restore a human voice.", + "version": "1.1.0", + "description": "Strip AI tells from text, and score text for the tells it still has.", "author": { "name": "Harshaneel Gokhale" }, "homepage": "https://github.com/harshaneel/humanize", "repository": "https://github.com/harshaneel/humanize", "license": "MIT", - "keywords": ["writing", "editing", "ai-detection", "style"], + "keywords": ["writing", "editing", "review", "ai-detection", "style"], "skills": "./skills/", "interface": { "displayName": "Humanize", - "shortDescription": "Rewrite text to strip AI tells and restore a human voice.", + "shortDescription": "Strip AI tells from text, and score text for the tells it still has.", "category": "Productivity", "capabilities": ["Interactive", "Read", "Write"] } diff --git a/plugins/ai-check/skills/ai-check/SKILL.md b/plugins/humanize/skills/ai-check/SKILL.md similarity index 100% rename from plugins/ai-check/skills/ai-check/SKILL.md rename to plugins/humanize/skills/ai-check/SKILL.md diff --git a/tests/SCENARIOS.md b/tests/SCENARIOS.md index 4e9331d..b08f9d4 100644 --- a/tests/SCENARIOS.md +++ b/tests/SCENARIOS.md @@ -60,7 +60,7 @@ In today's fast-paced world, it is important to note that artificial intelligenc ## Scenario 2: ai-check on flagrant AI prose (GREEN) -**Skill:** `plugins/ai-check/skills/ai-check/SKILL.md` +**Skill:** `plugins/humanize/skills/ai-check/SKILL.md` **User prompt:** "Can you run ai-check on this?" @@ -80,7 +80,7 @@ In today's fast-paced world, it is important to note that artificial intelligenc ## Scenario 3: ai-check on real Slack message (false-positive calibration) -**Skill:** `plugins/ai-check/skills/ai-check/SKILL.md` +**Skill:** `plugins/humanize/skills/ai-check/SKILL.md` **User prompt:** "score this text" @@ -311,7 +311,7 @@ This is pure Lever 9 territory: every sentence is RLHF voice. ## Scenario 11: ai-check on academic abstract (false-positive calibration) -**Skill:** `plugins/ai-check/skills/ai-check/SKILL.md` +**Skill:** `plugins/humanize/skills/ai-check/SKILL.md` **User prompt:** "is this AI?" @@ -335,7 +335,7 @@ This is a real-style academic abstract. It has semicolons, formal vocabulary, "N ## Scenario 12: ai-check on mixed authorship -**Skill:** `plugins/ai-check/skills/ai-check/SKILL.md` +**Skill:** `plugins/humanize/skills/ai-check/SKILL.md` **User prompt:** "score this"