diff --git a/.chronus/changes/tcgc-clientOptions-2026-0-22-16-26-53.md b/.chronus/changes/tcgc-clientOptions-2026-0-22-16-26-53.md
new file mode 100644
index 0000000000..cde7450d54
--- /dev/null
+++ b/.chronus/changes/tcgc-clientOptions-2026-0-22-16-26-53.md
@@ -0,0 +1,7 @@
+---
+changeKind: feature
+packages:
+ - "@azure-tools/typespec-client-generator-core"
+---
+
+Add `@clientOption` flag for experimental, language-specific flags
\ No newline at end of file
diff --git a/packages/typespec-client-generator-core/README.md b/packages/typespec-client-generator-core/README.md
index 8209e21156..a16a4d3f68 100644
--- a/packages/typespec-client-generator-core/README.md
+++ b/packages/typespec-client-generator-core/README.md
@@ -123,6 +123,7 @@ Available ruleSets:
- [`@clientLocation`](#@clientlocation)
- [`@clientName`](#@clientname)
- [`@clientNamespace`](#@clientnamespace)
+- [`@clientOption`](#@clientoption)
- [`@convenientAPI`](#@convenientapi)
- [`@deserializeEmptyStringAsNull`](#@deserializeemptystringasnull)
- [`@operationGroup`](#@operationgroup)
@@ -846,6 +847,46 @@ model Test {
}
```
+#### `@clientOption`
+
+Pass experimental flags or options to emitters without requiring TCGC reshipping.
+This decorator is intended for temporary workarounds or experimental features and requires
+suppression to acknowledge its experimental nature.
+
+See supported client options for each language emitter here https://azure.github.io/typespec-azure/docs/howtos/generate-client-libraries/12clientOptions/
+
+**Warning**: This decorator always emits a warning that must be suppressed, and an additional
+warning if no scope is provided (since options are typically language-specific).
+
+```typespec
+@Azure.ClientGenerator.Core.clientOption(name: valueof string, value: valueof unknown, scope?: valueof string)
+```
+
+##### Target
+
+The type you want to apply the option to.
+`unknown`
+
+##### Parameters
+
+| Name | Type | Description |
+| ----- | ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| name | `valueof string` | The name of the option (e.g., "enableFeatureFoo"). |
+| value | `valueof unknown` | The value of the option. Can be any type; emitters will cast as needed. |
+| scope | `valueof string` | Specifies the target language emitters that the decorator should apply. If not set, the decorator will be applied to all language emitters by default.
You can use "!" to exclude specific languages, for example: !(java, python) or !java, !python. |
+
+##### Examples
+
+###### Apply an experimental option for Python
+
+```typespec
+#suppress "@azure-tools/typespec-client-generator-core/client-option" "preview feature for python"
+@clientOption("enableFeatureFoo", true, "python")
+model MyModel {
+ prop: string;
+}
+```
+
#### `@convenientAPI`
Whether you want to generate an operation as a convenient method.
diff --git a/packages/typespec-client-generator-core/generated-defs/Azure.ClientGenerator.Core.ts b/packages/typespec-client-generator-core/generated-defs/Azure.ClientGenerator.Core.ts
index e1916ff437..900292748a 100644
--- a/packages/typespec-client-generator-core/generated-defs/Azure.ClientGenerator.Core.ts
+++ b/packages/typespec-client-generator-core/generated-defs/Azure.ClientGenerator.Core.ts
@@ -944,6 +944,38 @@ export type ClientDocDecorator = (
scope?: string,
) => DecoratorValidatorCallbacks | void;
+/**
+ * Pass experimental flags or options to emitters without requiring TCGC reshipping.
+ * This decorator is intended for temporary workarounds or experimental features and requires
+ * suppression to acknowledge its experimental nature.
+ *
+ * See supported client options for each language emitter here https://azure.github.io/typespec-azure/docs/howtos/generate-client-libraries/12clientOptions/
+ *
+ * **Warning**: This decorator always emits a warning that must be suppressed, and an additional
+ * warning if no scope is provided (since options are typically language-specific).
+ *
+ * @param target The type you want to apply the option to.
+ * @param name The name of the option (e.g., "enableFeatureFoo").
+ * @param value The value of the option. Can be any type; emitters will cast as needed.
+ * @param scope Specifies the target language emitters that the decorator should apply. If not set, the decorator will be applied to all language emitters by default.
+ * You can use "!" to exclude specific languages, for example: !(java, python) or !java, !python.
+ * @example Apply an experimental option for Python
+ * ```typespec
+ * #suppress "@azure-tools/typespec-client-generator-core/client-option" "preview feature for python"
+ * @clientOption("enableFeatureFoo", true, "python")
+ * model MyModel {
+ * prop: string;
+ * }
+ * ```
+ */
+export type ClientOptionDecorator = (
+ context: DecoratorContext,
+ target: Type,
+ name: string,
+ value: unknown,
+ scope?: string,
+) => DecoratorValidatorCallbacks | void;
+
export type AzureClientGeneratorCoreDecorators = {
clientName: ClientNameDecorator;
convenientAPI: ConvenientAPIDecorator;
@@ -965,4 +997,5 @@ export type AzureClientGeneratorCoreDecorators = {
responseAsBool: ResponseAsBoolDecorator;
clientLocation: ClientLocationDecorator;
clientDoc: ClientDocDecorator;
+ clientOption: ClientOptionDecorator;
};
diff --git a/packages/typespec-client-generator-core/lib/decorators.tsp b/packages/typespec-client-generator-core/lib/decorators.tsp
index ce7bb149e2..3c52b3f5ab 100644
--- a/packages/typespec-client-generator-core/lib/decorators.tsp
+++ b/packages/typespec-client-generator-core/lib/decorators.tsp
@@ -1022,3 +1022,35 @@ extern dec clientDoc(
mode: EnumMember,
scope?: valueof string
);
+
+/**
+ * Pass experimental flags or options to emitters without requiring TCGC reshipping.
+ * This decorator is intended for temporary workarounds or experimental features and requires
+ * suppression to acknowledge its experimental nature.
+ *
+ * See supported client options for each language emitter here https://azure.github.io/typespec-azure/docs/howtos/generate-client-libraries/12clientOptions/
+ *
+ * **Warning**: This decorator always emits a warning that must be suppressed, and an additional
+ * warning if no scope is provided (since options are typically language-specific).
+ *
+ * @param target The type you want to apply the option to.
+ * @param name The name of the option (e.g., "enableFeatureFoo").
+ * @param value The value of the option. Can be any type; emitters will cast as needed.
+ * @param scope Specifies the target language emitters that the decorator should apply. If not set, the decorator will be applied to all language emitters by default.
+ * You can use "!" to exclude specific languages, for example: !(java, python) or !java, !python.
+ *
+ * @example Apply an experimental option for Python
+ * ```typespec
+ * #suppress "@azure-tools/typespec-client-generator-core/client-option" "preview feature for python"
+ * @clientOption("enableFeatureFoo", true, "python")
+ * model MyModel {
+ * prop: string;
+ * }
+ * ```
+ */
+extern dec clientOption(
+ target: unknown,
+ name: valueof string,
+ value: valueof unknown,
+ scope?: valueof string
+);
diff --git a/packages/typespec-client-generator-core/src/configs.ts b/packages/typespec-client-generator-core/src/configs.ts
index 5978f59ade..a93123e8fc 100644
--- a/packages/typespec-client-generator-core/src/configs.ts
+++ b/packages/typespec-client-generator-core/src/configs.ts
@@ -2,4 +2,5 @@ export const defaultDecoratorsAllowList = [
"TypeSpec\\.Xml\\..*",
"Azure\\.Core\\.@useFinalStateVia",
"Autorest\\.@example",
+ "Azure\\.ClientGenerator\\.Core\\.@clientOption",
];
diff --git a/packages/typespec-client-generator-core/src/decorators.ts b/packages/typespec-client-generator-core/src/decorators.ts
index 7b58ae3492..6b3cffbd1d 100644
--- a/packages/typespec-client-generator-core/src/decorators.ts
+++ b/packages/typespec-client-generator-core/src/decorators.ts
@@ -45,6 +45,7 @@ import {
ClientInitializationDecorator,
ClientNameDecorator,
ClientNamespaceDecorator,
+ ClientOptionDecorator,
ConvenientAPIDecorator,
DeserializeEmptyStringAsNullDecorator,
OperationGroupDecorator,
@@ -1851,3 +1852,36 @@ export function isInScope(context: TCGCContext, entity: Operation | ModelPropert
}
return true;
}
+
+export const clientOptionKey = createStateSymbol("ClientOption");
+
+/**
+ * `@clientOption` decorator implementation.
+ * Pass experimental flags or options to emitters without requiring TCGC reshipping.
+ * The decorator data is stored as {name, value} and exposed via the decorators array.
+ */
+export const $clientOption: ClientOptionDecorator = (
+ context: DecoratorContext,
+ target: Type,
+ name: string,
+ value: unknown,
+ scope?: LanguageScopes,
+) => {
+ // Always emit warning that this is experimental
+ reportDiagnostic(context.program, {
+ code: "client-option",
+ target: target,
+ });
+
+ // Emit additional warning if scope is not provided
+ if (scope === undefined) {
+ reportDiagnostic(context.program, {
+ code: "client-option-requires-scope",
+ target: target,
+ });
+ }
+
+ // Store the option data - each decorator application is stored separately
+ // The decorator info will be exposed via the decorators array on SDK types
+ setScopedDecoratorData(context, $clientOption, clientOptionKey, target, { name, value }, scope);
+};
diff --git a/packages/typespec-client-generator-core/src/interfaces.ts b/packages/typespec-client-generator-core/src/interfaces.ts
index 25ae9a9c14..c10d86d1fb 100644
--- a/packages/typespec-client-generator-core/src/interfaces.ts
+++ b/packages/typespec-client-generator-core/src/interfaces.ts
@@ -14,6 +14,7 @@ import {
PagingOperation,
Program,
Type,
+ Value,
} from "@typespec/compiler";
import { unsafe_Realm } from "@typespec/compiler/experimental";
import {
@@ -202,6 +203,25 @@ export interface DecoratorInfo {
arguments: Record;
}
+/**
+ * Represents a client option set via the `@clientOption` decorator.
+ * This is a convenience type for accessing client options without parsing the decorators array directly.
+ */
+export interface SdkClientOption {
+ /**
+ * The name of the client option.
+ */
+ name: string;
+ /**
+ * The value of the client option.
+ */
+ value: Value;
+ /**
+ * The language scope this option applies to, if specified.
+ */
+ scope?: string;
+}
+
/**
* Represents a client in the package.
*/
diff --git a/packages/typespec-client-generator-core/src/internal-utils.ts b/packages/typespec-client-generator-core/src/internal-utils.ts
index b6bd1461ae..2a115ff1e9 100644
--- a/packages/typespec-client-generator-core/src/internal-utils.ts
+++ b/packages/typespec-client-generator-core/src/internal-utils.ts
@@ -402,6 +402,14 @@ export function getTypeDecorators(
getDecoratorArgValue(context, decorator.args[i].jsValue, type, decoratorName),
);
}
+
+ // Filter by scope - only include decorators that match the current emitter or have no scope
+ const scopeArg = decoratorInfo.arguments["scope"];
+ if (scopeArg !== undefined && scopeArg !== context.emitterName) {
+ // Skip this decorator if it has a scope that doesn't match the current emitter
+ continue;
+ }
+
retval.push(decoratorInfo);
}
}
@@ -429,7 +437,7 @@ function getDecoratorArgValue(
if (arg.kind === "EnumMember") {
return diagnostics.wrap(diagnostics.pipe(getClientTypeWithDiagnostics(context, arg)));
}
- if (arg.kind === "String" || arg.kind === "Number" || arg.kind === "Boolean") {
+ if (arg.kind === "String" || arg.kind === "Number" || arg.kind === "Boolean" || arg.kind === "Value") {
return diagnostics.wrap(arg.value);
}
diagnostics.add(
diff --git a/packages/typespec-client-generator-core/src/lib.ts b/packages/typespec-client-generator-core/src/lib.ts
index ba17212419..26a2a00bcb 100644
--- a/packages/typespec-client-generator-core/src/lib.ts
+++ b/packages/typespec-client-generator-core/src/lib.ts
@@ -482,6 +482,20 @@ export const $lib = createTypeSpecLibrary({
default: "All services must have the same server and auth definitions.",
},
},
+ "client-option": {
+ severity: "warning",
+ messages: {
+ default:
+ "@clientOption is experimental and should only be used for temporary workarounds. This usage must be suppressed.",
+ },
+ },
+ "client-option-requires-scope": {
+ severity: "warning",
+ messages: {
+ default:
+ "@clientOption should be applied with a specific language scope since it is highly likely this is language-specific.",
+ },
+ },
},
emitter: {
options: TCGCEmitterOptionsSchema,
diff --git a/packages/typespec-client-generator-core/src/public-utils.ts b/packages/typespec-client-generator-core/src/public-utils.ts
index cf3cd3ec51..8964c674a9 100644
--- a/packages/typespec-client-generator-core/src/public-utils.ts
+++ b/packages/typespec-client-generator-core/src/public-utils.ts
@@ -10,6 +10,7 @@ import {
Scalar,
Type,
Union,
+ Value,
createDiagnosticCollector,
getEffectiveModelType,
getFriendlyName,
@@ -41,8 +42,10 @@ import {
listOperationsInOperationGroup,
} from "./decorators.js";
import {
+ DecoratorInfo,
SdkBodyParameter,
SdkClient,
+ SdkClientOption,
SdkClientType,
SdkCookieParameter,
SdkHeaderParameter,
@@ -897,3 +900,32 @@ export function getNamespaceFromType(
}
return undefined;
}
+
+const CLIENT_OPTION_DECORATOR_NAME = "Azure.ClientGenerator.Core.@clientOption";
+
+/**
+ * Get all client options from a decorated SDK type.
+ * This is a convenience function for extracting `@clientOption` decorator data
+ * from the decorators array on SDK types.
+ *
+ * @param decorators - The decorators array from an SDK type (model, enum, operation, property, etc.)
+ * @returns An array of client options with their name, value, and optional scope
+ *
+ * @example
+ * ```typescript
+ * const sdkModel = context.sdkPackage.models.find(m => m.name === "MyModel");
+ * const clientOptions = getClientOptions(sdkModel.decorators);
+ * for (const option of clientOptions) {
+ * console.log(`Option: ${option.name} = ${option.value}`);
+ * }
+ * ```
+ */
+export function getClientOptions(decorators: DecoratorInfo[]): SdkClientOption[] {
+ return decorators
+ .filter((d) => d.name === CLIENT_OPTION_DECORATOR_NAME)
+ .map((d) => ({
+ name: d.arguments.name as string,
+ value: d.arguments.value as Value,
+ scope: d.arguments.scope as string | undefined,
+ }));
+}
diff --git a/packages/typespec-client-generator-core/src/tsp-index.ts b/packages/typespec-client-generator-core/src/tsp-index.ts
index 6d4799088e..4604443cc5 100644
--- a/packages/typespec-client-generator-core/src/tsp-index.ts
+++ b/packages/typespec-client-generator-core/src/tsp-index.ts
@@ -12,6 +12,7 @@ import {
$clientLocation,
$clientName,
$clientNamespace,
+ $clientOption,
$convenientAPI,
$deserializeEmptyStringAsNull,
$flattenProperty,
@@ -55,6 +56,7 @@ export const $decorators = {
responseAsBool: $responseAsBool,
clientDoc: $clientDoc,
clientLocation: $clientLocation,
+ clientOption: $clientOption,
} satisfies AzureClientGeneratorCoreDecorators,
"Azure.ClientGenerator.Core.Legacy": {
diff --git a/packages/typespec-client-generator-core/test/decorators/client-option.test.ts b/packages/typespec-client-generator-core/test/decorators/client-option.test.ts
new file mode 100644
index 0000000000..52390afdc9
--- /dev/null
+++ b/packages/typespec-client-generator-core/test/decorators/client-option.test.ts
@@ -0,0 +1,564 @@
+import { expectDiagnostics } from "@typespec/compiler/testing";
+import { deepStrictEqual, ok, strictEqual } from "assert";
+import { describe, it } from "vitest";
+import { getClientOptions } from "../../src/public-utils.js";
+import { createSdkContextForTester, SimpleTester, SimpleTesterWithService } from "../tester.js";
+
+describe("@clientOption diagnostics", () => {
+ it("should emit client-option warning always", async () => {
+ const diagnostics = await SimpleTester.diagnose(`
+ @service
+ namespace MyService;
+
+ @clientOption("enableFeatureFoo", true, "python")
+ model Test {
+ id: string;
+ }
+ `);
+
+ expectDiagnostics(diagnostics, {
+ code: "@azure-tools/typespec-client-generator-core/client-option",
+ });
+ });
+
+ it("should emit both client-option and client-option-requires-scope warnings when scope is missing", async () => {
+ const diagnostics = await SimpleTester.diagnose(`
+ @service
+ namespace MyService;
+
+ @clientOption("enableFeatureFoo", true)
+ model Test {
+ id: string;
+ }
+ `);
+
+ expectDiagnostics(diagnostics, [
+ {
+ code: "@azure-tools/typespec-client-generator-core/client-option",
+ },
+ {
+ code: "@azure-tools/typespec-client-generator-core/client-option-requires-scope",
+ },
+ ]);
+ });
+
+ it("should only emit client-option warning when scope is provided", async () => {
+ const diagnostics = await SimpleTester.diagnose(`
+ @service
+ namespace MyService;
+
+ @clientOption("enableFeatureFoo", true, "python")
+ model Test {
+ id: string;
+ }
+ `);
+
+ // Should only have the client-option warning, not client-option-requires-scope
+ strictEqual(diagnostics.length, 1);
+ expectDiagnostics(diagnostics, {
+ code: "@azure-tools/typespec-client-generator-core/client-option",
+ });
+ });
+});
+
+describe("@clientOption with getClientOptions getter", () => {
+ it("should return client options for model", async () => {
+ const { program } = await SimpleTesterWithService.compile(`
+ #suppress "@azure-tools/typespec-client-generator-core/client-option"
+ @clientOption("enableFeatureFoo", true, "python")
+ @test
+ model Test {
+ id: string;
+ }
+
+ op getTest(): Test;
+ `);
+
+ const context = await createSdkContextForTester(program, {
+ emitterName: "@azure-tools/typespec-python",
+ });
+
+ const sdkModel = context.sdkPackage.models.find((m) => m.name === "Test");
+ ok(sdkModel, "SDK model should exist");
+
+ const clientOptions = getClientOptions(sdkModel.decorators);
+ strictEqual(clientOptions.length, 1);
+ deepStrictEqual(clientOptions[0], {
+ name: "enableFeatureFoo",
+ value: true,
+ scope: "python",
+ });
+ });
+
+ it("should return multiple client options on same target", async () => {
+ const { program } = await SimpleTesterWithService.compile(`
+ #suppress "@azure-tools/typespec-client-generator-core/client-option"
+ @clientOption("enableFeatureFoo", true, "python")
+ #suppress "@azure-tools/typespec-client-generator-core/client-option"
+ @clientOption("enableFeatureBar", "value", "python")
+ @test
+ model Test {
+ id: string;
+ }
+
+ op getTest(): Test;
+ `);
+
+ const context = await createSdkContextForTester(program, {
+ emitterName: "@azure-tools/typespec-python",
+ });
+
+ const sdkModel = context.sdkPackage.models.find((m) => m.name === "Test");
+ ok(sdkModel, "SDK model should exist");
+
+ const clientOptions = getClientOptions(sdkModel.decorators);
+ strictEqual(clientOptions.length, 2);
+
+ // Verify each option has the correct name and value
+ const fooOption = clientOptions.find((o) => o.name === "enableFeatureFoo");
+ ok(fooOption, "enableFeatureFoo option should exist");
+ strictEqual(fooOption.name, "enableFeatureFoo");
+ strictEqual(fooOption.value, true);
+ strictEqual(fooOption.scope, "python");
+
+ const barOption = clientOptions.find((o) => o.name === "enableFeatureBar");
+ ok(barOption, "enableFeatureBar option should exist");
+ strictEqual(barOption.name, "enableFeatureBar");
+ strictEqual(barOption.value, "value");
+ strictEqual(barOption.scope, "python");
+ });
+
+ it("should support different value types", async () => {
+ const { program } = await SimpleTesterWithService.compile(`
+ #suppress "@azure-tools/typespec-client-generator-core/client-option"
+ @clientOption("boolOption", true, "python")
+ @test
+ model TestBool {
+ id: string;
+ }
+
+ #suppress "@azure-tools/typespec-client-generator-core/client-option"
+ @clientOption("stringOption", "someValue", "python")
+ @test
+ model TestString {
+ id: string;
+ }
+
+ #suppress "@azure-tools/typespec-client-generator-core/client-option"
+ @clientOption("numberOption", 42, "python")
+ @test
+ model TestNumber {
+ id: string;
+ }
+
+ @route("/bool") op getBool(): TestBool;
+ @route("/string") op getString(): TestString;
+ @route("/number") op getNumber(): TestNumber;
+ `);
+
+ const context = await createSdkContextForTester(program, {
+ emitterName: "@azure-tools/typespec-python",
+ });
+
+ // Verify boolean value type
+ const sdkModelBool = context.sdkPackage.models.find((m) => m.name === "TestBool");
+ ok(sdkModelBool, "TestBool model should exist");
+ const boolOptions = getClientOptions(sdkModelBool.decorators);
+ strictEqual(boolOptions.length, 1);
+ strictEqual(boolOptions[0].name, "boolOption");
+ strictEqual(boolOptions[0].value, true);
+ strictEqual(typeof boolOptions[0].value, "boolean");
+
+ // Verify string value type
+ const sdkModelString = context.sdkPackage.models.find((m) => m.name === "TestString");
+ ok(sdkModelString, "TestString model should exist");
+ const stringOptions = getClientOptions(sdkModelString.decorators);
+ strictEqual(stringOptions.length, 1);
+ strictEqual(stringOptions[0].name, "stringOption");
+ strictEqual(stringOptions[0].value, "someValue");
+ strictEqual(typeof stringOptions[0].value, "string");
+
+ // Verify number value type
+ const sdkModelNumber = context.sdkPackage.models.find((m) => m.name === "TestNumber");
+ ok(sdkModelNumber, "TestNumber model should exist");
+ const numberOptions = getClientOptions(sdkModelNumber.decorators);
+ strictEqual(numberOptions.length, 1);
+ strictEqual(numberOptions[0].name, "numberOption");
+ strictEqual(numberOptions[0].value, 42);
+ strictEqual(typeof numberOptions[0].value, "number");
+ });
+
+ it("should return client options for operation", async () => {
+ const { program } = await SimpleTesterWithService.compile(`
+ #suppress "@azure-tools/typespec-client-generator-core/client-option"
+ @clientOption("operationFlag", "customValue", "python")
+ @test
+ op testOp(): string;
+ `);
+
+ const context = await createSdkContextForTester(program, {
+ emitterName: "@azure-tools/typespec-python",
+ });
+
+ const sdkMethod = context.sdkPackage.clients[0].methods.find(
+ (m) => m.kind === "basic" && m.name === "testOp",
+ );
+ ok(sdkMethod, "SDK method should exist");
+
+ const clientOptions = getClientOptions(sdkMethod.decorators);
+ strictEqual(clientOptions.length, 1);
+ deepStrictEqual(clientOptions[0], {
+ name: "operationFlag",
+ value: "customValue",
+ scope: "python",
+ });
+ });
+
+ it("should return client options for enum", async () => {
+ const { program } = await SimpleTesterWithService.compile(`
+ #suppress "@azure-tools/typespec-client-generator-core/client-option"
+ @clientOption("enumFlag", true, "python")
+ @usage(Usage.input)
+ @test
+ enum TestEnum {
+ One,
+ Two,
+ }
+
+ op getTest(@query value: TestEnum): string;
+ `);
+
+ const context = await createSdkContextForTester(program, {
+ emitterName: "@azure-tools/typespec-python",
+ });
+
+ const sdkEnum = context.sdkPackage.enums.find((e) => e.name === "TestEnum");
+ ok(sdkEnum, "SDK enum should exist");
+
+ const clientOptions = getClientOptions(sdkEnum.decorators);
+ strictEqual(clientOptions.length, 1);
+ deepStrictEqual(clientOptions[0], {
+ name: "enumFlag",
+ value: true,
+ scope: "python",
+ });
+ });
+
+ it("should return client options for model property", async () => {
+ const { program } = await SimpleTesterWithService.compile(`
+ @test
+ model Test {
+ #suppress "@azure-tools/typespec-client-generator-core/client-option"
+ @clientOption("propertyFlag", "propValue", "python")
+ myProp: string;
+ }
+
+ op getTest(): Test;
+ `);
+
+ const context = await createSdkContextForTester(program, {
+ emitterName: "@azure-tools/typespec-python",
+ });
+
+ const sdkModel = context.sdkPackage.models.find((m) => m.name === "Test");
+ ok(sdkModel, "SDK model should exist");
+
+ const sdkProperty = sdkModel.properties.find((p) => p.name === "myProp");
+ ok(sdkProperty, "SDK property should exist");
+
+ const clientOptions = getClientOptions(sdkProperty.decorators);
+ strictEqual(clientOptions.length, 1);
+ deepStrictEqual(clientOptions[0], {
+ name: "propertyFlag",
+ value: "propValue",
+ scope: "python",
+ });
+ });
+
+ it("should return options when scope matches emitter", async () => {
+ const { program } = await SimpleTesterWithService.compile(`
+ #suppress "@azure-tools/typespec-client-generator-core/client-option"
+ @clientOption("pythonOnlyFlag", true, "python")
+ @test
+ model Test {
+ id: string;
+ }
+
+ op getTest(): Test;
+ `);
+
+ // Configure with python emitter
+ const context = await createSdkContextForTester(program, {
+ emitterName: "@azure-tools/typespec-python",
+ });
+
+ const sdkModel = context.sdkPackage.models.find((m) => m.name === "Test");
+ ok(sdkModel, "SDK model should exist");
+
+ const clientOptions = getClientOptions(sdkModel.decorators);
+ strictEqual(clientOptions.length, 1);
+ strictEqual(clientOptions[0].name, "pythonOnlyFlag");
+ strictEqual(clientOptions[0].value, true);
+ strictEqual(clientOptions[0].scope, "python");
+ });
+
+ it("should return empty array when scope does not match emitter", async () => {
+ const { program } = await SimpleTesterWithService.compile(`
+ #suppress "@azure-tools/typespec-client-generator-core/client-option"
+ @clientOption("javaOnlyFlag", true, "java")
+ @test
+ model Test {
+ id: string;
+ }
+
+ op getTest(): Test;
+ `);
+
+ // Configure with python emitter, but decorator is scoped to java
+ const context = await createSdkContextForTester(program, {
+ emitterName: "@azure-tools/typespec-python",
+ });
+
+ const sdkModel = context.sdkPackage.models.find((m) => m.name === "Test");
+ ok(sdkModel, "SDK model should exist");
+
+ // The decorator should NOT appear - getClientOptions should return empty array
+ const clientOptions = getClientOptions(sdkModel.decorators);
+ strictEqual(clientOptions.length, 0);
+ });
+
+ it("should handle option without scope argument", async () => {
+ const { program } = await SimpleTesterWithService.compile(`
+ #suppress "@azure-tools/typespec-client-generator-core/client-option"
+ #suppress "@azure-tools/typespec-client-generator-core/client-option-requires-scope"
+ @clientOption("noScopeOption", 123)
+ @test
+ model Test {
+ id: string;
+ }
+
+ op getTest(): Test;
+ `);
+
+ const context = await createSdkContextForTester(program, {
+ emitterName: "@azure-tools/typespec-python",
+ });
+
+ const sdkModel = context.sdkPackage.models.find((m) => m.name === "Test");
+ ok(sdkModel, "SDK model should exist");
+
+ const clientOptions = getClientOptions(sdkModel.decorators);
+ strictEqual(clientOptions.length, 1);
+ strictEqual(clientOptions[0].name, "noScopeOption");
+ strictEqual(clientOptions[0].value, 123);
+ // scope should be undefined when not provided
+ strictEqual(clientOptions[0].scope, undefined);
+ });
+
+ it("should support array value type", async () => {
+ const { program } = await SimpleTesterWithService.compile(`
+ #suppress "@azure-tools/typespec-client-generator-core/client-option"
+ @clientOption("arrayOption", #["item1", "item2", "item3"], "python")
+ @test
+ model Test {
+ id: string;
+ }
+
+ op getTest(): Test;
+ `);
+
+ const context = await createSdkContextForTester(program, {
+ emitterName: "@azure-tools/typespec-python",
+ });
+
+ const sdkModel = context.sdkPackage.models.find((m) => m.name === "Test");
+ ok(sdkModel, "SDK model should exist");
+
+ const clientOptions = getClientOptions(sdkModel.decorators);
+ strictEqual(clientOptions.length, 1);
+ strictEqual(clientOptions[0].name, "arrayOption");
+ ok(Array.isArray(clientOptions[0].value), "value should be an array");
+ deepStrictEqual(clientOptions[0].value, ["item1", "item2", "item3"]);
+ strictEqual(clientOptions[0].scope, "python");
+ });
+
+ it("should support object/map value type", async () => {
+ const { program } = await SimpleTesterWithService.compile(`
+ #suppress "@azure-tools/typespec-client-generator-core/client-option"
+ @clientOption("objectOption", #{key1: "value1", key2: "value2"}, "python")
+ @test
+ model Test {
+ id: string;
+ }
+
+ op getTest(): Test;
+ `);
+
+ const context = await createSdkContextForTester(program, {
+ emitterName: "@azure-tools/typespec-python",
+ });
+
+ const sdkModel = context.sdkPackage.models.find((m) => m.name === "Test");
+ ok(sdkModel, "SDK model should exist");
+
+ const clientOptions = getClientOptions(sdkModel.decorators);
+ strictEqual(clientOptions.length, 1);
+ strictEqual(clientOptions[0].name, "objectOption");
+ ok(
+ typeof clientOptions[0].value === "object" && !Array.isArray(clientOptions[0].value),
+ "value should be an object",
+ );
+ deepStrictEqual(clientOptions[0].value, { key1: "value1", key2: "value2" });
+ strictEqual(clientOptions[0].scope, "python");
+ });
+
+ it("should support nested object and array values", async () => {
+ const { program } = await SimpleTesterWithService.compile(`
+ #suppress "@azure-tools/typespec-client-generator-core/client-option"
+ @clientOption("nestedOption", #{
+ stringField: "hello",
+ numberField: 42,
+ arrayField: #[1, 2, 3],
+ nestedObject: #{inner: "value"}
+ }, "python")
+ @test
+ model Test {
+ id: string;
+ }
+
+ op getTest(): Test;
+ `);
+
+ const context = await createSdkContextForTester(program, {
+ emitterName: "@azure-tools/typespec-python",
+ });
+
+ const sdkModel = context.sdkPackage.models.find((m) => m.name === "Test");
+ ok(sdkModel, "SDK model should exist");
+
+ const clientOptions = getClientOptions(sdkModel.decorators);
+ strictEqual(clientOptions.length, 1);
+ strictEqual(clientOptions[0].name, "nestedOption");
+
+ const value = clientOptions[0].value as unknown as Record;
+ strictEqual(value.stringField, "hello");
+ strictEqual(value.numberField, 42);
+ deepStrictEqual(value.arrayField, [1, 2, 3]);
+ deepStrictEqual(value.nestedObject, { inner: "value" });
+ strictEqual(clientOptions[0].scope, "python");
+ });
+
+ it("should support array of numbers", async () => {
+ const { program } = await SimpleTesterWithService.compile(`
+ #suppress "@azure-tools/typespec-client-generator-core/client-option"
+ @clientOption("numberArrayOption", #[1, 2, 3, 4, 5], "python")
+ @test
+ model Test {
+ id: string;
+ }
+
+ op getTest(): Test;
+ `);
+
+ const context = await createSdkContextForTester(program, {
+ emitterName: "@azure-tools/typespec-python",
+ });
+
+ const sdkModel = context.sdkPackage.models.find((m) => m.name === "Test");
+ ok(sdkModel, "SDK model should exist");
+
+ const clientOptions = getClientOptions(sdkModel.decorators);
+ strictEqual(clientOptions.length, 1);
+ strictEqual(clientOptions[0].name, "numberArrayOption");
+ ok(Array.isArray(clientOptions[0].value), "value should be an array");
+ deepStrictEqual(clientOptions[0].value, [1, 2, 3, 4, 5]);
+ });
+
+ it("should support array of mixed types", async () => {
+ const { program } = await SimpleTesterWithService.compile(`
+ #suppress "@azure-tools/typespec-client-generator-core/client-option"
+ @clientOption("mixedArrayOption", #["string", 42, true], "python")
+ @test
+ model Test {
+ id: string;
+ }
+
+ op getTest(): Test;
+ `);
+
+ const context = await createSdkContextForTester(program, {
+ emitterName: "@azure-tools/typespec-python",
+ });
+
+ const sdkModel = context.sdkPackage.models.find((m) => m.name === "Test");
+ ok(sdkModel, "SDK model should exist");
+
+ const clientOptions = getClientOptions(sdkModel.decorators);
+ strictEqual(clientOptions.length, 1);
+ strictEqual(clientOptions[0].name, "mixedArrayOption");
+ ok(Array.isArray(clientOptions[0].value), "value should be an array");
+ deepStrictEqual(clientOptions[0].value, ["string", 42, true]);
+ });
+
+ it("should return client options for namespace", async () => {
+ const { program } = await SimpleTester.compile(`
+ @server("http://localhost:3000", "endpoint")
+ @service
+ #suppress "@azure-tools/typespec-client-generator-core/client-option"
+ @clientOption("namespaceFlag", "nsValue", "python")
+ namespace MyService {
+ model TestModel {
+ id: string;
+ }
+ op getTest(): TestModel;
+ }
+ `);
+
+ const context = await createSdkContextForTester(program, {
+ emitterName: "@azure-tools/typespec-python",
+ });
+
+ // The service namespace should have the decorator
+ const sdkNamespace = context.sdkPackage.namespaces.find((ns) => ns.name === "MyService");
+ ok(sdkNamespace, "SDK namespace should exist");
+
+ const clientOptions = getClientOptions(sdkNamespace.decorators);
+ strictEqual(clientOptions.length, 1);
+ deepStrictEqual(clientOptions[0], {
+ name: "namespaceFlag",
+ value: "nsValue",
+ scope: "python",
+ });
+ });
+
+ it("should return client options for interface (operation group)", async () => {
+ const { program } = await SimpleTesterWithService.compile(`
+ #suppress "@azure-tools/typespec-client-generator-core/client-option"
+ @clientOption("interfaceFlag", true, "python")
+ @test
+ interface MyOperations {
+ op doSomething(): string;
+ }
+ `);
+
+ const context = await createSdkContextForTester(program, {
+ emitterName: "@azure-tools/typespec-python",
+ });
+
+ // Interfaces become sub-clients (children of the main client)
+ const client = context.sdkPackage.clients[0];
+ ok(client, "Client should exist");
+
+ // Find the sub-client for the interface
+ const subClient = client.children?.find((c) => c.name === "MyOperations");
+ ok(subClient, "Sub-client for interface should exist");
+
+ const clientOptions = getClientOptions(subClient.decorators);
+ strictEqual(clientOptions.length, 1);
+ deepStrictEqual(clientOptions[0], {
+ name: "interfaceFlag",
+ value: true,
+ scope: "python",
+ });
+ });
+});
diff --git a/packages/typespec-client-generator-core/test/decorators/deserialize-empty-string-as-null.test.ts b/packages/typespec-client-generator-core/test/decorators/deserialize-empty-string-as-null.test.ts
index ff98e28dcc..f75a3b37a1 100644
--- a/packages/typespec-client-generator-core/test/decorators/deserialize-empty-string-as-null.test.ts
+++ b/packages/typespec-client-generator-core/test/decorators/deserialize-empty-string-as-null.test.ts
@@ -21,7 +21,7 @@ describe("deserialized empty string as null", () => {
const context = await createSdkContextForTester(
program,
- {},
+ { emitterName: "@azure-tools/typespec-csharp" },
{
additionalDecorators: ["Azure\\.ClientGenerator\\.Core\\.@deserializeEmptyStringAsNull"],
},
@@ -54,7 +54,7 @@ describe("deserialized empty string as null", () => {
const context = await createSdkContextForTester(
program,
- {},
+ { emitterName: "@azure-tools/typespec-csharp" },
{
additionalDecorators: ["Azure\\.ClientGenerator\\.Core\\.@deserializeEmptyStringAsNull"],
},
diff --git a/packages/typespec-client-generator-core/test/decorators/general-list.test.ts b/packages/typespec-client-generator-core/test/decorators/general-list.test.ts
index f8bfba37c7..4887c9c1d7 100644
--- a/packages/typespec-client-generator-core/test/decorators/general-list.test.ts
+++ b/packages/typespec-client-generator-core/test/decorators/general-list.test.ts
@@ -123,13 +123,6 @@ it("multiple same decorators", async function () {
);
deepStrictEqual(context.sdkPackage.clients[0].methods[0].decorators, [
- {
- name: "Azure.ClientGenerator.Core.@clientName",
- arguments: {
- rename: "testForJava",
- scope: "java",
- },
- },
{
name: "Azure.ClientGenerator.Core.@clientName",
arguments: {
@@ -141,6 +134,34 @@ it("multiple same decorators", async function () {
expectDiagnostics(context.diagnostics, []);
});
+it("multiple same decorators without scope", async function () {
+ const { program } = await SimpleTesterWithService.compile(`
+ @clientName("testNoScope1")
+ @clientName("testNoScope2")
+ op test(): void;
+ `);
+
+ const context = await createSdkContextForTester(
+ program,
+ {},
+ { additionalDecorators: ["Azure\\.ClientGenerator\\.Core\\.@clientName"] },
+ );
+
+ // Decorators without scope should all be included
+ const decorators = context.sdkPackage.clients[0].methods[0].decorators;
+ strictEqual(decorators.length, 2);
+
+ const decorator1 = decorators.find((d) => d.arguments.rename === "testNoScope1");
+ const decorator2 = decorators.find((d) => d.arguments.rename === "testNoScope2");
+
+ ok(decorator1, "testNoScope1 decorator should exist");
+ ok(decorator2, "testNoScope2 decorator should exist");
+ strictEqual(decorator1!.name, "Azure.ClientGenerator.Core.@clientName");
+ strictEqual(decorator2!.name, "Azure.ClientGenerator.Core.@clientName");
+
+ expectDiagnostics(context.diagnostics, []);
+});
+
it("decorators on a namespace", async function () {
const { program } = await SimpleTesterWithService.compile(`
op test(): void;
@@ -228,7 +249,7 @@ describe("xml scenario", () => {
model Foo {
@ns("https://example.com/ns1", "ns1")
bar1: string;
-
+
@ns("https://example.com/ns2", "ns2")
bar2: string;
}
@@ -276,12 +297,12 @@ describe("xml scenario", () => {
ns1: "https://example.com/ns1",
ns2: "https://example.com/ns2",
}
-
+
@Xml.ns(Namespaces.ns1)
model Foo {
@Xml.ns(Namespaces.ns1)
bar1: string;
-
+
@Xml.ns(Namespaces.ns2)
bar2: string;
}
@@ -364,7 +385,7 @@ describe("csharp only decorator", () => {
const context = await createSdkContextForTester(
program,
- {},
+ { emitterName: "@azure-tools/typespec-csharp" },
{ additionalDecorators: ["Azure\\.ClientGenerator\\.Core\\.@useSystemTextJsonConverter"] },
);
diff --git a/website/src/content/docs/docs/howtos/Generate client libraries/12clientOptions.mdx b/website/src/content/docs/docs/howtos/Generate client libraries/12clientOptions.mdx
new file mode 100644
index 0000000000..5a6c4eb7cb
--- /dev/null
+++ b/website/src/content/docs/docs/howtos/Generate client libraries/12clientOptions.mdx
@@ -0,0 +1,224 @@
+---
+title: Client Options
+llmstxt: true
+---
+
+import { ClientTabs, ClientTabItem } from "@components/client-tabs";
+
+This page documents how to use the `@clientOption` decorator to pass language-specific configuration options to emitters. For an overview of the setup, please visit the setup page.
+
+:::caution
+The `@clientOption` decorator is intended for advanced scenarios where language-specific emitter behavior needs to be configured. Using this decorator always produces a warning to ensure intentional usage. Use standard TCGC decorators when possible.
+:::
+
+## Overview
+
+The `@clientOption` decorator allows spec authors to pass arbitrary key-value options to specific language emitters. This enables fine-grained control over code generation behavior that may vary between languages.
+
+```typespec
+@clientOption(name: string, value: string | boolean | number, scope?: string)
+```
+
+### Parameters
+
+| Parameter | Type | Description |
+| --------- | ----------------------------- | --------------------------------------------------------------------------------------- |
+| `name` | `string` | The name of the option to set |
+| `value` | `string \| boolean \| number` | The value for the option |
+| `scope` | `string` (optional) | The target language scope. **Required** - omitting scope produces an additional warning |
+
+## Usage
+
+### Basic Usage
+
+Apply the decorator to models, operations, enums, or properties with a language-specific scope:
+
+
+
+```typespec title=client.tsp
+import "@azure-tools/typespec-client-generator-core";
+
+using Azure.ClientGenerator.Core;
+
+#suppress "@azure-tools/typespec-client-generator-core/client-option"
+@clientOption("enableFeatureFoo", true, "python")
+model MyModel {
+ id: string;
+}
+```
+
+```python
+# The Python emitter can read this option from the model's decorators array
+# and apply the appropriate code generation behavior
+```
+
+```csharp
+// C# emitter does not see this option (scoped to Python only)
+```
+
+```typescript
+// TypeScript emitter does not see this option (scoped to Python only)
+```
+
+```java
+// Java emitter does not see this option (scoped to Python only)
+```
+
+```go
+// Go emitter does not see this option (scoped to Python only)
+```
+
+
+
+### Multiple Options
+
+You can apply multiple `@clientOption` decorators to the same target:
+
+```typespec title=client.tsp
+#suppress "@azure-tools/typespec-client-generator-core/client-option"
+#suppress "@azure-tools/typespec-client-generator-core/client-option"
+@clientOption("enableFeatureFoo", true, "python")
+@clientOption("customSerializerMode", "strict", "python")
+model MyModel {
+ id: string;
+}
+```
+
+### Different Value Types
+
+The decorator supports string, boolean, and numeric values:
+
+```typespec title=client.tsp
+#suppress "@azure-tools/typespec-client-generator-core/client-option"
+@clientOption("booleanOption", true, "python")
+model BoolExample {
+ id: string;
+}
+
+#suppress "@azure-tools/typespec-client-generator-core/client-option"
+@clientOption("stringOption", "customValue", "csharp")
+model StringExample {
+ id: string;
+}
+
+#suppress "@azure-tools/typespec-client-generator-core/client-option"
+@clientOption("numericOption", 42, "java")
+model NumericExample {
+ id: string;
+}
+```
+
+## How Emitters Access Client Options
+
+TCGC provides the `getClientOptions` helper function to easily extract client options from any SDK type that has a `decorators` array.
+
+### Using the getClientOptions Helper (Recommended)
+
+```typescript
+import { getClientOptions } from "@azure-tools/typespec-client-generator-core";
+
+// Get client options from a model
+const sdkModel = context.sdkPackage.models.find((m) => m.name === "MyModel");
+const clientOptions = getClientOptions(sdkModel.decorators);
+
+for (const option of clientOptions) {
+ console.log(`Option: ${option.name} = ${option.value}`);
+ // option.name: string - The option name (e.g., "enableFeatureFoo")
+ // option.value: string | boolean | number - The option value
+ // option.scope?: string - The language scope (e.g., "python")
+}
+```
+
+The `getClientOptions` function returns an array of `SdkClientOption` objects:
+
+```typescript
+interface SdkClientOption {
+ name: string;
+ value: string | boolean | number;
+ scope?: string;
+}
+```
+
+### Works with Any Decorated SDK Type
+
+The helper works with any SDK type that has a decorators array:
+
+```typescript
+// Models
+const modelOptions = getClientOptions(sdkModel.decorators);
+
+// Enums
+const enumOptions = getClientOptions(sdkEnum.decorators);
+
+// Operations/Methods
+const methodOptions = getClientOptions(sdkMethod.decorators);
+
+// Properties
+const propertyOptions = getClientOptions(sdkProperty.decorators);
+
+// Clients
+const clientOptions = getClientOptions(sdkClient.decorators);
+```
+
+### Alternative: Manual Decorator Filtering
+
+If you need more control, you can also filter the decorators array directly:
+
+```typescript
+const sdkModel = context.sdkPackage.models.find((m) => m.name === "MyModel");
+const clientOptionDecorators = sdkModel.decorators.filter(
+ (d) => d.name === "Azure.ClientGenerator.Core.@clientOption",
+);
+
+for (const decorator of clientOptionDecorators) {
+ const optionName = decorator.arguments.name; // e.g., "enableFeatureFoo"
+ const optionValue = decorator.arguments.value; // e.g., true
+ const scope = decorator.arguments.scope; // e.g., "python"
+}
+```
+
+## Supported Client Options by Language
+
+Language emitters should document which client options they support. The following sections list the supported options for each language.
+
+### Python
+
+| Option Name | Value Type | Target | Description |
+| ------------- | ---------- | ------ | ----------- |
+| _Coming soon_ | | | |
+
+### C# (.NET)
+
+| Option Name | Value Type | Target | Description |
+| ------------- | ---------- | ------ | ----------- |
+| _Coming soon_ | | | |
+
+### Java
+
+| Option Name | Value Type | Target | Description |
+| ------------- | ---------- | ------ | ----------- |
+| _Coming soon_ | | | |
+
+### TypeScript/JavaScript
+
+| Option Name | Value Type | Target | Description |
+| ------------- | ---------- | ------ | ----------- |
+| _Coming soon_ | | | |
+
+### Go
+
+| Option Name | Value Type | Target | Description |
+| ------------- | ---------- | ------ | ----------- |
+| _Coming soon_ | | | |
+
+## Best Practices
+
+1. **Always specify a scope**: The decorator is designed for language-specific behavior. Omitting the scope produces an additional warning.
+
+2. **Suppress the warning intentionally**: Use `#suppress "@azure-tools/typespec-client-generator-core/client-option"` to acknowledge that you're using this advanced feature.
+
+3. **Document usage**: When using client options, document why they're needed so future maintainers understand the intent.
+
+4. **Prefer standard decorators**: Use standard TCGC decorators like `@clientName`, `@access`, `@usage`, etc. when they can achieve the desired behavior. Reserve `@clientOption` for cases where no standard decorator exists.
+
+5. **Coordinate with emitter teams**: Before using a client option, verify with the target language emitter team that the option is supported and understand its behavior.
diff --git a/website/src/content/docs/docs/libraries/typespec-client-generator-core/reference/decorators.md b/website/src/content/docs/docs/libraries/typespec-client-generator-core/reference/decorators.md
index 62027ac60f..64c1c6173f 100644
--- a/website/src/content/docs/docs/libraries/typespec-client-generator-core/reference/decorators.md
+++ b/website/src/content/docs/docs/libraries/typespec-client-generator-core/reference/decorators.md
@@ -720,6 +720,46 @@ model Test {
}
```
+### `@clientOption` {#@Azure.ClientGenerator.Core.clientOption}
+
+Pass experimental flags or options to emitters without requiring TCGC reshipping.
+This decorator is intended for temporary workarounds or experimental features and requires
+suppression to acknowledge its experimental nature.
+
+See supported client options for each language emitter here https://azure.github.io/typespec-azure/docs/howtos/generate-client-libraries/12clientOptions/
+
+**Warning**: This decorator always emits a warning that must be suppressed, and an additional
+warning if no scope is provided (since options are typically language-specific).
+
+```typespec
+@Azure.ClientGenerator.Core.clientOption(name: valueof string, value: valueof unknown, scope?: valueof string)
+```
+
+#### Target
+
+The type you want to apply the option to.
+`unknown`
+
+#### Parameters
+
+| Name | Type | Description |
+| ----- | ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| name | `valueof string` | The name of the option (e.g., "enableFeatureFoo"). |
+| value | `valueof unknown` | The value of the option. Can be any type; emitters will cast as needed. |
+| scope | `valueof string` | Specifies the target language emitters that the decorator should apply. If not set, the decorator will be applied to all language emitters by default.
You can use "!" to exclude specific languages, for example: !(java, python) or !java, !python. |
+
+#### Examples
+
+##### Apply an experimental option for Python
+
+```typespec
+#suppress "@azure-tools/typespec-client-generator-core/client-option" "preview feature for python"
+@clientOption("enableFeatureFoo", true, "python")
+model MyModel {
+ prop: string;
+}
+```
+
### `@convenientAPI` {#@Azure.ClientGenerator.Core.convenientAPI}
Whether you want to generate an operation as a convenient method.
diff --git a/website/src/content/docs/docs/libraries/typespec-client-generator-core/reference/index.mdx b/website/src/content/docs/docs/libraries/typespec-client-generator-core/reference/index.mdx
index 68770d5090..c3300ed697 100644
--- a/website/src/content/docs/docs/libraries/typespec-client-generator-core/reference/index.mdx
+++ b/website/src/content/docs/docs/libraries/typespec-client-generator-core/reference/index.mdx
@@ -50,6 +50,7 @@ npm install --save-peer @azure-tools/typespec-client-generator-core
- [`@clientLocation`](./decorators.md#@Azure.ClientGenerator.Core.clientLocation)
- [`@clientName`](./decorators.md#@Azure.ClientGenerator.Core.clientName)
- [`@clientNamespace`](./decorators.md#@Azure.ClientGenerator.Core.clientNamespace)
+- [`@clientOption`](./decorators.md#@Azure.ClientGenerator.Core.clientOption)
- [`@convenientAPI`](./decorators.md#@Azure.ClientGenerator.Core.convenientAPI)
- [`@deserializeEmptyStringAsNull`](./decorators.md#@Azure.ClientGenerator.Core.deserializeEmptyStringAsNull)
- [`@operationGroup`](./decorators.md#@Azure.ClientGenerator.Core.operationGroup)