---
name: JSpecify
slug: jspecify
category: Quality
description: JSpecify adds nullability annotations and build setup for Java projects. Use it to enable NullMarked/NullUnmarked, reduce NullPointerExceptions, and verify package coverage with Maven or Gradle.
github: "https://github.com/sivaprasadreddy/sivalabs-agent-skills/tree/main/skills/jspecify"
language: Python
stars: 178
forks: 41
install: "npx degit https://github.com/sivaprasadreddy/sivalabs-agent-skills/tree/main/skills/jspecify ~/.claude/skills/jspecify"
installs_to: ~/.claude/skills/jspecify
source_path: skills/jspecify/SKILL.md
collection_size: 7
category_size: 1817
collection_url: "https://dirskills.com/collections/sivaprasadreddy/sivalabs-agent-skills"
added: 2026-09-07T05:20:46.897Z
last_synced: 2026-09-07T05:20:46.897Z
canonical_url: "https://dirskills.com/skills/jspecify"
---

# JSpecify

JSpecify adds nullability annotations and build setup for Java projects. Use it to enable NullMarked/NullUnmarked, reduce NullPointerExceptions, and verify package coverage with Maven or Gradle.

**Install:**

```bash
npx degit https://github.com/sivaprasadreddy/sivalabs-agent-skills/tree/main/skills/jspecify ~/.claude/skills/jspecify
```

## README

Jspecify provides a set of annotations to explicitly declare the nullness expectations of the Java code.

## Add jSpecify support in Maven projects
If you are using Maven, then add the jspecify dependency in `pom.xml`.
In `pom.xml`, update or add the `nullability-maven-plugin`, to include the following configuration.

```xml
<dependencies>
    <dependency>
        <groupId>org.jspecify</groupId>
        <artifactId>jspecify</artifactId>
        <version>1.0.0</version>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>am.ik.maven</groupId>
            <artifactId>nullability-maven-plugin</artifactId>
            <version>0.4.2</version>
            <extensions>true</extensions>
            <configuration>
                <checking>tests</checking>
                <outputDirectory>${project.basedir}/src/main/java</outputDirectory>
                <testOutputDirectory>${project.basedir}/src/test/java</testOutputDirectory>
            </configuration>
            <executions>
                <execution>
                    <goals>
                        <goal>configure</goal>
                        <goal>generate-package-info</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>
```

## Add jSpecify support in Gradle projects
If you are using Gradle, then add the jspecify dependency.
In `build.gradle` or `build.gradle.kts`, update or add the following jspecify configuration.

```groovy
plugins {
    id("net.ltgt.errorprone") version "5.1.0"
    id("net.ltgt.nullaway") version "3.1.0"
}

tasks.withType(JavaCompile).configureEach {
    options.errorprone {
        disableAllChecks = true // Other error prone checks are disabled
        error("RequireExplicitNullMarking") // Require @NullMarked or @NullUnmarked on everything
        nullaway {
            error()
        }
    }
    // Keep a JDK 25 baseline
    options.release = 25
}

nullaway {
    onlyNullMarked = true
    jspecifyMode = true
}

dependencies {
    implementation("org.jspecify:jspecify:1.0.0")
    errorprone("com.google.errorprone:error_prone_core:2.50.0")
    errorprone("com.uber.nullaway:nullaway:0.13.7")
}
```

## Add @NullMarked to package-info.java files
In every java package under the application main source code (`src/main/java`), 
create `package-info.java` if not exists already, and add the `@NullMarked` annotation as follows:

```java
@org.jspecify.annotations.NullMarked
package com.mycompnay.myproject;
```

If `package-info.java` file already exists, update the file to add `@org.jspecify.annotations.NullMarked` annotation.
DO NOT REMOVE ANY OTHER EXISTING CODE IN `package-info.java` FILE.

## Verify jSpecify support
If python is installed, after adding the jSpecify support, run `scripts/verify_nullmarked.py` 
to check if all non-empty packages has `package-info.java` file or not.

## Migrating an existing codebase from other annotation libraries

If the project already uses another nullability annotation library (JSR-305 / `javax`, Jakarta,
JetBrains, Spring, Android, FindBugs/SpotBugs, Checker Framework, or Eclipse JDT), migrate those
annotations to JSpecify **before** adding `@NullMarked`. The OpenRewrite `MigrateToJSpecify` recipe
automates the common cases (javax, Jakarta, JetBrains, Micrometer, Micronaut); the rest are a short
manual mapping. See [references/annotation-migration.md](references/annotation-migration.md).

## Incremental adoption for large codebases

Flipping every package to `@NullMarked` at once is impractical on a large or legacy codebase.
`@NullUnmarked` lets you enforce NullAway on a growing perimeter while the rest stays untouched.
Because the build above enables `OnlyNullMarked` mode, packages without `@NullMarked` are simply
ignored — so adoption is driven purely by adding markers, one package at a time. Strategies,
progress tracking, common NullAway errors, and redundant null-guard removal are in
[references/incremental-adoption.md](references/incremental-adoption.md).

## Kotlin interop (optional)

If the project also has Kotlin sources, the Kotlin compiler (K2) reads JSpecify annotations on Java
APIs and surfaces accurate nullability instead of platform types. See
[references/kotlin-interop.md](references/kotlin-interop.md).
