Claude Code Guidance

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project overview

A Java library providing ASCII-safe Charset SPI implementations that transliterate Unicode to ASCII subsets rather than simply rejecting non-ASCII input. Published to GitHub Packages as com.maybeitssquid:ascii-safe-charsets.

Commands

./gradlew build          # compile, run tests, spotless check
./gradlew test           # tests only
./gradlew spotlessApply  # auto-format Java source (required before commit)
./gradlew javadoc        # generate Javadoc
./gradlew dependencyCheckAnalyze  # OWASP CVE scan (slow; fails build at CVSS >= 7)

# Run a single test class
./gradlew test --tests "com.maybeitssquid.safeascii.CacheTest"

On Windows, use gradlew.bat (or .\gradlew in PowerShell).

The build uses a Java 25 toolchain and compiles to Java 17 bytecode (release = "17"). CI tests on Java 17, 21, and 25 on every push/PR to main.

Versioning and Releases

Versions are derived from git tags using gradle-git-version:

To create a release:

# Ensure all commits are pushed
git push origin main

# Create and push the tag (triggers automatic version picking in build)
git tag -a v1.0.0 -m "Release 1.0.0"
git push origin v1.0.0

# Build and publish
./gradlew clean build publish

To delete a release tag:

git tag -d v1.0.0              # Delete locally
git push origin :v1.0.0        # Delete from remote

Configuration cache is disabled (org.gradle.configuration-cache=false) to allow git invocation during the build.

Architecture

The library wires together two subsystems: a Charset implementation and a configurable transliteration pipeline.

Module and package layout

The library is a named JPMS module (module-info.java, module com.maybeitssquid.safeascii). Only the charset API package com.maybeitssquid.safeascii is exported. The transliteration pipeline lives in com.maybeitssquid.safeascii.internal, which is not exported — those classes are implementation details, not public API. The provider is declared two ways so it works on both paths: provides java.nio.charset.spi.CharsetProvider with … in module-info.java (module path) and META-INF/services/java.nio.charset.spi.CharsetProvider (classpath).

When working on the pipeline, keep new internal classes in …internal; only add to the exported package if it is genuinely part of the public charset API. Pipeline unit tests live in src/test/java/com/maybeitssquid/safeascii/internal so they retain same-package/protected access.

Charset layer

Transliterator pipeline

Each step implements IntFunction<CharSequence> and chains to the next. All pipeline classes below live in the non-exported com.maybeitssquid.safeascii.internal package. The actual pipelines assembled by the provider are:

Code style

Spotless enforces Google Java Format. Run ./gradlew spotlessApply before committing. The formatter excludes module-info.java.

Security patches

Transitive dependency CVEs are pinned in gradle/libs.versions.toml as patch-* library entries collected in the security-patches bundle. build.gradle applies them as implementation constraints. settings.gradle also loads them into the buildscript classpath via regex. New CVE patches follow the same patch-cve-XXXX-NNNNN naming convention.

The OWASP dependency check plugin (./gradlew dependencyCheckAnalyze) fails the build at CVSS ≥ 7.