diff --git a/.checkstyle/checkstyle.xml b/.checkstyle/checkstyle.xml
index bf884a0..245d331 100644
--- a/.checkstyle/checkstyle.xml
+++ b/.checkstyle/checkstyle.xml
@@ -101,6 +101,7 @@
 
     
     
+      
       
     
 
diff --git a/build.gradle.kts b/build.gradle.kts
index d8da954..d938bc3 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -10,6 +10,7 @@ plugins {
 
 dependencies {
   compileOnlyApi(libs.jetbrainsAnnotations)
+  compileOnlyApi(libs.jspecify)
   testImplementation(platform(libs.junit.bom))
   testImplementation(libs.junit.api)
   testRuntimeOnly(libs.junit.engine)
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index e744a54..2ca06e0 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -8,6 +8,7 @@ junit = "5.11.4"
 
 [libraries]
 jetbrainsAnnotations = "org.jetbrains:annotations:26.0.2"
+jspecify = { module = "org.jspecify:jspecify", version = "1.0.0"}
 junit-bom = { module = "org.junit:junit-bom", version.ref = "junit" }
 junit-api = { module = "org.junit.jupiter:junit-jupiter-api" }
 junit-engine = { module = "org.junit.jupiter:junit-jupiter-engine" }
@@ -24,4 +25,4 @@ indra-crossdoc = { id = "net.kyori.indra.crossdoc", version.ref = "indra" }
 indra-licenser-spotless = { id = "net.kyori.indra.licenser.spotless", version.ref = "indra" }
 indra-publishing-sonatype = { id = "net.kyori.indra.publishing.sonatype", version.ref = "indra" }
 nexusPublish = { id = "io.github.gradle-nexus.publish-plugin", version = "2.0.0" }
-spotless = "com.diffplug.spotless:7.0.2"
\ No newline at end of file
+spotless = "com.diffplug.spotless:7.0.2"
diff --git a/src/main/java/net/kyori/option/Option.java b/src/main/java/net/kyori/option/Option.java
index 6e4c52e..c289c2e 100644
--- a/src/main/java/net/kyori/option/Option.java
+++ b/src/main/java/net/kyori/option/Option.java
@@ -25,8 +25,7 @@
 
 import net.kyori.option.value.ValueType;
 import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
 
 /**
  * A representation of a configurable option.
@@ -80,7 +79,7 @@ static > Option enumOption(final String id, final Class
    * @return the flag id
    * @since 1.0.0
    */
-  @NotNull String id();
+  String id();
 
   /**
    * Get the type of the option value.
@@ -90,7 +89,7 @@ static > Option enumOption(final String id, final Class
    * @deprecated for removal since 1.1.0, use {@link #valueType()} instead
    */
   @Deprecated
-  default @NotNull Class type() {
+  default Class type() {
     return this.valueType().type();
   }
 
@@ -100,7 +99,7 @@ static > Option enumOption(final String id, final Class
    * @return the value type
    * @since 1.0.0
    */
-  @NotNull ValueType valueType();
+  ValueType valueType();
 
   /**
    * Get a default value for the option, if any is present.
diff --git a/src/main/java/net/kyori/option/OptionImpl.java b/src/main/java/net/kyori/option/OptionImpl.java
index 0e61017..de5bf7f 100644
--- a/src/main/java/net/kyori/option/OptionImpl.java
+++ b/src/main/java/net/kyori/option/OptionImpl.java
@@ -25,8 +25,7 @@
 
 import java.util.Objects;
 import net.kyori.option.value.ValueType;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
 
 final class OptionImpl implements Option {
 
@@ -34,19 +33,19 @@ final class OptionImpl implements Option {
   private final ValueType type;
   private final @Nullable V defaultValue; // excluded from equality comparisons, it does not form part of the option identity
 
-  OptionImpl(final @NotNull String id, final @NotNull ValueType type, final @Nullable V defaultValue) {
+  OptionImpl(final String id, final ValueType type, final @Nullable V defaultValue) {
     this.id = id;
     this.type = type;
     this.defaultValue = defaultValue;
   }
 
   @Override
-  public @NotNull String id() {
+  public String id() {
     return this.id;
   }
 
   @Override
-  public @NotNull ValueType valueType() {
+  public ValueType valueType() {
     return this.type;
   }
 
diff --git a/src/main/java/net/kyori/option/OptionSchema.java b/src/main/java/net/kyori/option/OptionSchema.java
index a2fc186..0fc48ee 100644
--- a/src/main/java/net/kyori/option/OptionSchema.java
+++ b/src/main/java/net/kyori/option/OptionSchema.java
@@ -25,8 +25,7 @@
 
 import java.util.Set;
 import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
 
 import static java.util.Objects.requireNonNull;
 
@@ -45,7 +44,7 @@ public interface OptionSchema {
    * @return the global schema
    * @since 1.1.0
    */
-  static OptionSchema.@NotNull Mutable globalSchema() {
+  static OptionSchema.Mutable globalSchema() {
     return OptionSchemaImpl.Instances.GLOBAL;
   }
 
@@ -58,7 +57,7 @@ public interface OptionSchema {
    * @return the mutable child schema
    * @since 1.1.0
    */
-  static OptionSchema.@NotNull Mutable childSchema(final @NotNull OptionSchema schema) {
+  static OptionSchema.Mutable childSchema(final OptionSchema schema) {
     final OptionSchemaImpl impl;
     if (schema instanceof OptionSchemaImpl.MutableImpl) {
       impl = (OptionSchemaImpl) ((Mutable) schema).frozenView();
@@ -76,7 +75,7 @@ public interface OptionSchema {
    * @return a mutable schema
    * @since 1.1.0
    */
-  static OptionSchema.@NotNull Mutable emptySchema() {
+  static OptionSchema.Mutable emptySchema() {
     return new OptionSchemaImpl(null).new MutableImpl();
   }
 
@@ -86,7 +85,7 @@ public interface OptionSchema {
    * @return known options
    * @since 1.1.0
    */
-  @NotNull Set