diff --git a/docs/contributor/README.md b/docs/contributor/README.md
index 9f9a26aa7405..1de726c5377a 100644
--- a/docs/contributor/README.md
+++ b/docs/contributor/README.md
@@ -28,6 +28,7 @@ If you are a **consumer** of the SDK looking for usage guidance, start at the [U
| [Versioning](https://github.com/Azure/azure-sdk-for-java/blob/main/docs/contributor/versioning.md) | `version_client.txt`, dependency tags, incrementing versions |
| [Adding a Module](https://github.com/Azure/azure-sdk-for-java/blob/main/docs/contributor/adding-a-module.md) | Create a new SDK module: dir structure, POM, versioning, CODEOWNERS |
| [TypeSpec Quickstart](https://github.com/Azure/azure-sdk-for-java/blob/main/docs/contributor/typespec-quickstart.md) | End-to-end workflow: generate → build → test → release |
+| [TypeSpec Java Customization](https://github.com/Azure/azure-sdk-for-java/blob/main/docs/contributor/typespec-java-customization.md) | Customize generated Java code when TypeSpec cannot express the required behavior |
| [Writing Performance Tests](https://github.com/Azure/azure-sdk-for-java/blob/main/docs/contributor/performance-tests.md) | Set up and run `perf-test-core` benchmarks |
| [JavaDoc & Code Snippets](https://github.com/Azure/azure-sdk-for-java/blob/main/docs/contributor/javadocs.md) | Javadoc standards and codesnippet-maven-plugin workflow |
| [Access Helpers](https://github.com/Azure/azure-sdk-for-java/blob/main/docs/contributor/access-helpers.md) | Cross-package internal access without public APIs |
diff --git a/docs/contributor/sdk-generation-pipeline-troubleshooting.md b/docs/contributor/sdk-generation-pipeline-troubleshooting.md
index 6b54bcf646da..30e2d3ba8a06 100644
--- a/docs/contributor/sdk-generation-pipeline-troubleshooting.md
+++ b/docs/contributor/sdk-generation-pipeline-troubleshooting.md
@@ -131,7 +131,7 @@ please check whether it causes failure, and fix them before apiview.
> - *generated code*: produced by the generator; API surface may change when the spec or generator changes, which can break compilation.
> - *customization code*: maintained by SDK developers; commonly wired via `customization-class` and preserved during regeneration with `partial-update: true`.
>
-> Reference: autorest.java customization-base: https://github.com/Azure/autorest.java/tree/main/customization-base
+> Reference: [TypeSpec Java Customization](https://github.com/Azure/azure-sdk-for-java/blob/main/docs/contributor/typespec-java-customization.md)
**Prerequisites for customization:** When adding customization code, two options must be set in `tspconfig.yaml`:
```yaml
diff --git a/docs/contributor/typespec-java-customization.md b/docs/contributor/typespec-java-customization.md
new file mode 100644
index 000000000000..05c3f102c0c9
--- /dev/null
+++ b/docs/contributor/typespec-java-customization.md
@@ -0,0 +1,165 @@
+# TypeSpec Java Customization
+
+The `azure-autorest-customization` package provides APIs to safely customize generated Java code for cases that
+TypeSpec Java cannot represent directly. Customizations use JavaParser ASTs through `ClassCustomization.customizeAst`.
+
+## Before you customize
+
+First consider whether the change belongs in TypeSpec (`client.tsp`). TypeSpec customizations are cleaner and persist
+through regeneration. See the [TypeSpec Client Customizations Reference](https://github.com/Azure/azure-sdk-for-java/blob/main/eng/common/knowledge/customizing-client-tsp.md) for decorators such as `@@clientName` and `@@access`.
+
+Use Java code customizations only when TypeSpec cannot express the required behavior.
+
+## Set up a customization project
+
+Create a Maven project that depends on `azure-autorest-customization`:
+
+```xml
+
+ com.azure.tools
+ azure-autorest-customization
+ 1.0.0-beta.11
+
+```
+
+Create a class that extends `com.azure.autorest.customization.Customization` and overrides
+`void customize(LibraryCustomization, Logger)`. The `LibraryCustomization` parameter is the entry point for changing
+generated Java code before it is written to disk.
+
+```java
+@Override
+public void customize(LibraryCustomization customization, Logger logger) {
+ customization.getClass("com.azure.myservice.models", "Foo")
+ .customizeAst(ast -> ast.getClassByName("Foo")
+ .ifPresent(clazz -> clazz.addMarkerAnnotation("Deprecated")));
+}
+```
+
+Configure the generator to use the class:
+
+```diff
+ "@azure-tools/typespec-java":
+ emitter-output-dir: "{output-dir}/{service-dir}/azure-contoso-widgetmanager"
+ namespace: com.azure.contoso.widgetmanager
++ customization-class: customization/src/main/java/MyCustomization.java
+```
+
+## Navigate generated code
+
+Start with `LibraryCustomization`, then navigate to a package or class with `getClass(packageName, className)`.
+`LibraryCustomization`, `PackageCustomization`, and `ClassCustomization` provide the primary navigation APIs.
+Use `customizeAst` to change the JavaParser AST for the selected source file. Add imports with
+`ast.addImport(...)` whenever the new code references a type not already imported.
+
+## Supported customizations
+
+The following common changes can be made through the JavaParser AST:
+
+| Customization | Typical AST operation |
+|---|---|
+| Change a class modifier | `ClassOrInterfaceDeclaration.setModifiers(...)` |
+| Change a method modifier | `MethodDeclaration.setModifiers(...)` |
+| Change a method return type or body | `MethodDeclaration.setType(...)` and `setBody(...)` |
+| Change a class supertype | Clear and add `ClassOrInterfaceType` extended types |
+| Add or remove a class or method annotation | `addMarkerAnnotation(...)` or remove the matching annotation node |
+| Add a field default value | `VariableDeclarator.setInitializer(...)` |
+| Add getter and setter methods | `ClassOrInterfaceDeclaration.addMethod(...)` |
+| Rename an enum member | `EnumConstantDeclaration.setName(...)` |
+| Update class or method Javadoc | `setJavadocComment(...)` |
+| Add or remove Javadoc tags | Update the `Javadoc` returned by `getJavadoc()` |
+
+### Change a method modifier
+
+```java
+@Override
+public void customize(LibraryCustomization customization, Logger logger) {
+ customization.getClass("com.azure.myservice.models", "Foo").customizeAst(ast -> ast.getClassByName("Foo")
+ .ifPresent(clazz -> clazz.getMethodsByName("getBar")
+ .forEach(method -> method.setModifiers(Modifier.Keyword.PRIVATE))));
+}
+```
+
+### Change a method return type
+
+When changing a return type, update both the declared type and method body. Add an import for the replacement type.
+
+```java
+@Override
+public void customize(LibraryCustomization customization, Logger logger) {
+ customization.getClass("com.azure.myservice.models", "Foo").customizeAst(ast -> {
+ ast.addImport(UUID.class);
+ ast.getClassByName("Foo").ifPresent(clazz -> clazz.getMethodsByName("getId").forEach(method -> {
+ method.setType("UUID");
+ method.setBody(StaticJavaParser.parseBlock("{ return UUID.fromString(this.id); }"));
+ }));
+ });
+}
+```
+
+For a method originally returning `void`, provide the complete return expression. To change a method to return
+`void`, set its body appropriately and do not add a return value.
+
+### Change a supertype
+
+```java
+@Override
+public void customize(LibraryCustomization customization, Logger logger) {
+ customization.getClass("com.azure.myservice.models", "Foo").customizeAst(ast -> ast.getClassByName("Foo")
+ .ifPresent(clazz -> {
+ ast.addImport("com.azure.myservice.models.Bar1");
+ clazz.getExtendedTypes().clear();
+ clazz.addExtendedType(new ClassOrInterfaceType(null, "Bar1"));
+ }));
+}
+```
+
+### Add a field default value
+
+```java
+@Override
+public void customize(LibraryCustomization customization, Logger logger) {
+ customization.getClass("com.azure.myservice.models", "Foo").customizeAst(ast -> ast.getClassByName("Foo")
+ .flatMap(clazz -> clazz.getFieldByName("bar"))
+ .ifPresent(field -> field.getVariables().forEach(variable -> {
+ if ("bar".equals(variable.getNameAsString())) {
+ variable.setInitializer("\"bar\"");
+ }
+ })));
+}
+```
+
+### Generate accessor methods
+
+```java
+@Override
+public void customize(LibraryCustomization customization, Logger logger) {
+ customization.getClass("com.azure.myservice.models", "Foo").customizeAst(ast -> ast.getClassByName("Foo")
+ .ifPresent(clazz -> {
+ clazz.addMethod("isActive", Modifier.Keyword.PUBLIC).setType("boolean")
+ .setBody(StaticJavaParser.parseBlock("{ return this.active; }"));
+ clazz.addMethod("setActive", Modifier.Keyword.PUBLIC).setType("Foo")
+ .addParameter("boolean", "active")
+ .setBody(StaticJavaParser.parseBlock("{ this.active = active; return this; }"));
+ }));
+}
+```
+
+### Update Javadoc
+
+Set a complete description with `setJavadocComment`. For parameter, return, and exception tags, get the existing
+Javadoc and add a block tag:
+
+```java
+method.getJavadoc().ifPresent(javadoc -> method.setJavadocComment(
+ javadoc.addBlockTag("param", "active", "whether the Foo is active")));
+```
+
+Use `return` for a return-value tag and `throws` with the exception type and description for an exception tag.
+
+## Troubleshooting
+
+### TypeSpec Java reports “Failed to format file: ``. File content: ``.”
+
+Customized Java code likely contains a syntax error.
+
+Inspect the source shown after `File content:` to locate the malformed code, then fix the customization and regenerate SDK.
diff --git a/docs/contributor/typespec-quickstart.md b/docs/contributor/typespec-quickstart.md
index c482c82b5fde..c2d0878c0c90 100644
--- a/docs/contributor/typespec-quickstart.md
+++ b/docs/contributor/typespec-quickstart.md
@@ -101,6 +101,8 @@ Set `partial-update: true` in `tspconfig.yaml` emitter options. TypeSpec-Java wi
customization-class: customization/src/main/java/MyCustomization.java
```
+See [TypeSpec Java Customization](https://github.com/Azure/azure-sdk-for-java/blob/main/docs/contributor/typespec-java-customization.md) for guidance on writing AST-based Java customizations.
+
---
## 5. Improve Documentation