# How Hidden Unicode Characters Are Handled in Claude Plugin Names and Descriptions

> Discover how Claude plugins handle hidden Unicode characters. Learn about I10 invariant validation for plugin names and descriptions, ensuring clean and secure interactions.

- Repository: [Anthropic/claude-plugins-community](https://github.com/anthropics/claude-plugins-community)
- Tags: how-to-guide
- Published: 2026-08-31

---

**All `name` and `description` fields in Claude plugins are validated against the I10 invariant, which explicitly rejects zero-width spaces, byte-order-marks (BOM), and bidirectional control characters.**

When submitting a plugin to the Claude marketplace, hidden Unicode characters in metadata fields trigger an immediate validation failure. This security-focused approach prevents invisible text manipulation and ensures transparent plugin identification across all rendering contexts.

## The I10 Invariant Validation

The **I10 invariant** enforces strict Unicode hygiene on plugin metadata. As implemented in `anthropics/claude-plugins-community`, this check scans both the `name` and `description` fields for invisible characters that could obscure a plugin's true identity or interfere with text processing pipelines.

The validation fails with this specific message when hidden characters are detected:

```

I10: name/description contains hidden-Unicode (zero-width or bidi control)

```

No automatic sanitization occurs—authors must manually remove offending characters and resubmit. This explicit failure pattern ensures developers understand and fix the root cause rather than relying on silent cleanup.

## Files and Implementation

Two key locations define this behavior:

| File | Purpose |
|------|---------|
| [`.github/actions/validate-plugins/README.md`](https://github.com/anthropics/claude-plugins-community/blob/main/.github/actions/validate-plugins/README.md) | Documents invariant I10 requirements |
| [`.github/actions/validate-plugins/scripts/11-validate-invariants.sh`](https://github.com/anthropics/claude-plugins-community/blob/main/.github/actions/validate-plugins/scripts/11-validate-invariants.sh) | Executes the Unicode validation check |

The shell script [`11-validate-invariants.sh`](https://github.com/anthropics/claude-plugins-community/blob/main/11-validate-invariants.sh) runs as part of the CI pipeline for every plugin submission, applying the same Unicode detection logic across all marketplace entries.

## Detecting Hidden Unicode Characters Locally

Developers can replicate the I10 check before submission using either Python or shell tools.

### Python Detection Method

This regex-based approach matches the character ranges used in the official validator:

```python
import re

HIDDEN_UNICODE_RE = re.compile(
    r'[\u200B-\u200D\uFEFF\u2060\u180E]'   # zero-width spaces, BOM, word-joiner

    r'|[\u202A-\u202E]'                    # bidirectional controls

)

def contains_hidden(text: str) -> bool:
    return bool(HIDDEN_UNICODE_RE.search(text))

# Test cases

name = "My Plugin"            # contains zero-width space (U+2009)

desc = "A useful tool."

print(contains_hidden(name))   # → True

print(contains_hidden(desc))   # → False

```

### Shell Detection Method

For CI integration or quick checks at the command line:

```bash
#!/usr/bin/env bash
hidden_check() {
  local text="$1"
  if printf '%s' "$text" | grep -P '[\x{200B}-\x{200D}\x{FEFF}\x{202A}-\x{202E}]' > /dev/null; then
    return 0   # hidden char found

  else
    return 1   # clean

  fi
}

name="Bad​Name"   # contains ZERO WIDTH SPACE (U+200B)

if hidden_check "$name"; then echo "⚠️ Hidden Unicode detected"; fi

```

## Character Categories Blocked

The I10 invariant specifically targets three Unicode categories:

- **Zero-width spaces**: U+200B (ZERO WIDTH SPACE), U+200C (ZERO WIDTH NON-JOINER), U+200D (ZERO WIDTH JOINER), U+2060 (WORD JOINER), U+180E (MONGOLIAN VOWEL SEPARATOR)
- **Byte-order-mark**: U+FEFF (also functions as zero-width no-break space)
- **Bidirectional control characters**: U+202A through U+202E (explicit directional embedding and override controls)

These characters remain invisible in most rendering contexts while potentially altering text processing behavior—making them unsuitable for plugin metadata where clarity and predictability are essential.

## Summary

- The **I10 invariant** in `anthropics/claude-plugins-community` validates all plugin `name` and `description` fields
- **Zero-width spaces, BOM, and bidi control characters** trigger immediate rejection
- Validation occurs in [`.github/actions/validate-plugins/scripts/11-validate-invariants.sh`](https://github.com/anthropics/claude-plugins-community/blob/main/.github/actions/validate-plugins/scripts/11-validate-invariants.sh)
- **No automatic stripping**—authors must manually clean their metadata
- Python and shell tools can replicate the check for local pre-submission validation

## Frequently Asked Questions

### What happens if my plugin name contains a zero-width space?

Your submission fails CI validation with the error `I10: name/description contains hidden-Unicode (zero-width or bidi control)`. You must remove the character and resubmit—no automatic fix is applied.

### Which Unicode characters are considered "hidden" in plugin validation?

The validator blocks zero-width spaces (U+200B-U+200D, U+2060, U+180E), byte-order-marks (U+FEFF), and bidirectional control characters (U+202A-U+202E). These characters are invisible in standard text rendering.

### Where is the hidden Unicode check implemented in the repository?

The check lives in [`.github/actions/validate-plugins/scripts/11-validate-invariants.sh`](https://github.com/anthropics/claude-plugins-community/blob/main/.github/actions/validate-plugins/scripts/11-validate-invariants.sh) and is documented in [`.github/actions/validate-plugins/README.md`](https://github.com/anthropics/claude-plugins-community/blob/main/.github/actions/validate-plugins/README.md). Both files are part of the GitHub Actions validation pipeline for the Claude plugins marketplace.

### Can I automatically strip hidden characters instead of manually removing them?

The official validator does not support automatic stripping. The intentional design requires authors to consciously fix their metadata, preventing accidental submission of sanitized-but-unintended values and ensuring full awareness of the original encoding issue.