Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Centralized configuration management with feature flags and dynamic refresh.
.claude/skills/azure-appconfiguration-ts/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | — | — |
| case-05 | ✗→✓ | ▲ Improved | — | — |
| case-18 | ✗→✓ | ▲ Improved | — | — |
| case-17 | ✗→✓ | ▲ Improved | — | — |
| case-20 | ✗→✓ | ▲ Improved | — | — |
Centralized configuration management with feature flags and dynamic refresh.
bash# Low-level CRUD SDK npm install @azure/app-configuration @azure/identity # High-level provider (recommended for apps) npm install @azure/app-configuration-provider @azure/identity # Feature flag management npm install @microsoft/feature-management
bashAZURE_APPCONFIG_ENDPOINT=https://<your-resource>.azconfig.io # OR AZURE_APPCONFIG_CONNECTION_STRING=Endpoint=https://...;Id=...;Secret=...
typescriptimport { AppConfigurationClient } from "@azure/app-configuration"; import { DefaultAzureCredential } from "@azure/identity"; // DefaultAzureCredential (recommended) const client = new AppConfigurationClient( process.env.AZURE_APPCONFIG_ENDPOINT!, new DefaultAzureCredential() ); // Connection string const client2 = new AppConfigurationClient( process.env.AZURE_APPCONFIG_CONNECTION_STRING! );
typescript// Add new (fails if exists) await client.addConfigurationSetting({ key: "app:settings:message", value: "Hello World", label: "production", contentType: "text/plain", tags: { environment: "prod" }, }); // Set (create or update) await client.setConfigurationSetting({ key: "app:settings:message", value: "Updated value", label: "production", }); // Update with optimistic concurrency const existing = await client.getConfigurationSetting({ key: "myKey" }); existing.value = "new value"; await client.setConfigurationSetting(existing, { onlyIfUnchanged: true });
typescript// Get single setting const setting = await client.getConfigurationSetting({ key: "app:settings:message", label: "production", // optional }); console.log(setting.value); // List with filters const settings = client.listConfigurationSettings({ keyFilter: "app:*", labelFilter: "production", }); for await (const setting of settings) { console.log(`${setting.key}: ${setting.value}`); }
typescriptawait client.deleteConfigurationSetting({ key: "app:settings:message", label: "production", });
typescript// Lock await client.setReadOnly({ key: "myKey", label: "prod" }, true); // Unlock await client.setReadOnly({ key: "myKey", label: "prod" }, false);
typescriptimport { load } from "@azure/app-configuration-provider"; import { DefaultAzureCredential } from "@azure/identity"; const appConfig = await load( process.env.AZURE_APPCONFIG_ENDPOINT!, new DefaultAzureCredential(), { selectors: [ { keyFilter: "app:*", labelFilter: "production" }, ], trimKeyPrefixes: ["app:"], } ); // Map-style access const value = appConfig.get("settings:message"); // Object-style access const config = appConfig.constructConfigurationObject({ separator: ":" }); console.log(config.settings.message);
typescriptconst appConfig = await load(endpoint, credential, { selectors: [{ keyFilter: "app:*" }], refreshOptions: { enabled: true, refreshIntervalInMs: 30_000, // 30 seconds }, }); // Trigger refresh (non-blocking) appConfig.refresh(); // Listen for refresh events const disposer = appConfig.onRefresh(() => { console.log("Configuration refreshed!"); }); // Express middleware pattern app.use((req, res, next) => { appConfig.refresh(); next(); });
typescriptconst appConfig = await load(endpoint, credential, { selectors: [{ keyFilter: "app:*" }], keyVaultOptions: { credential: new DefaultAzureCredential(), secretRefreshIntervalInMs: 7200_000, // 2 hours }, }); // Secrets are automatically resolved const dbPassword = appConfig.get("database:password");
typescriptimport { featureFlagPrefix, featureFlagContentType, FeatureFlagValue, ConfigurationSetting, } from "@azure/app-configuration"; const flag: ConfigurationSetting<FeatureFlagValue> = { key: `${featureFlagPrefix}Beta`, contentType: featureFlagContentType, value: { id: "Beta", enabled: true, description: "Beta feature", conditions: { clientFilters: [ { name: "Microsoft.Targeting", parameters: { Audience: { Users: ["user@example.com"], Groups: [{ Name: "beta-testers", RolloutPercentage: 50 }], DefaultRolloutPercentage: 0, }, }, }, ], }, }, }; await client.addConfigurationSetting(flag);
typescriptimport { load } from "@azure/app-configuration-provider"; import { ConfigurationMapFeatureFlagProvider, FeatureManager, } from "@microsoft/feature-management"; const appConfig = await load(endpoint, credential, { featureFlagOptions: { enabled: true, selectors: [{ keyFilter: "*" }], refresh: { enabled: true, refreshIntervalInMs: 30_000, }, }, }); const featureProvider = new ConfigurationMapFeatureFlagProvider(appConfig); const featureManager = new FeatureManager(featureProvider); // Simple check const isEnabled = await featureManager.isEnabled("Beta"); // With targeting context const isEnabledForUser = await featureManager.isEnabled("Beta", { userId: "user@example.com", groups: ["beta-testers"], });
typescript// Create snapshot const snapshot = await client.beginCreateSnapshotAndWait({ name: "release-v1.0", retentionPeriod: 2592000, // 30 days filters: [{ keyFilter: "app:*", labelFilter: "production" }], }); // Get snapshot const snap = await client.getSnapshot("release-v1.0"); // List settings in snapshot const settings = client.listConfigurationSettingsForSnapshot("release-v1.0"); for await (const setting of settings) { console.log(`${setting.key}: ${setting.value}`); } // Archive/recover await client.archiveSnapshot("release-v1.0"); await client.recoverSnapshot("release-v1.0"); // Load from snapshot (provider) const config = await load(endpoint, credential, { selectors: [{ snapshotName: "release-v1.0" }], });
typescript// Create settings with labels await client.setConfigurationSetting({ key: "database:host", value: "dev-db.example.com", label: "development", }); await client.setConfigurationSetting({ key: "database:host", value: "prod-db.example.com", label: "production", }); // Filter by label const prodSettings = client.listConfigurationSettings({ keyFilter: "*", labelFilter: "production", }); // No label (null label) const noLabelSettings = client.listConfigurationSettings({ labelFilter: "\0", }); // List available labels for await (const label of client.listLabels()) { console.log(label.name); }
typescriptimport { AppConfigurationClient, ConfigurationSetting, FeatureFlagValue, SecretReferenceValue, featureFlagPrefix, featureFlagContentType, secretReferenceContentType, ListConfigurationSettingsOptions, } from "@azure/app-configuration"; import { load } from "@azure/app-configuration-provider"; import { FeatureManager, ConfigurationMapFeatureFlagProvider, } from "@microsoft/feature-management";
@azure/app-configuration-provider for runtime config@azure/app-configuration for CRUD operationsApp Configuration Data Reader for read-only accessThis skill is applicable to execute the workflow or actions described in the overview.
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-23 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-03 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-01 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-05 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-11 | pass→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-22 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-02 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-10 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-06 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-18 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-17 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-20 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-13 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-14 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-21 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-07 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-08 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-04 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-09 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-12 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-15 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-16 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-19 | pass→pass | — | — | — | — | — | — | — | — | — | — | — | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 23 cases were attempted. The headline lift of +26 percentage points is the difference between those two pass rates over the 23 comparable cases.
The per-case answers from this run were removed by the retention sweep, so the case table below shows the verdicts without the text either arm produced. The counts above were recorded at the time and are unaffected. Answers are now kept for 180 days.
Other measured skills in the registry, with their headline benchmark lift.