Skip to content

Claude Code Enterprise Setup: Managed Settings

Core Concept LearningAugust 18, 202612 min read

Enterprise teams running Claude Code across 100+ developers face a critical problem: how do you enforce company policies, control model access, track spending, and roll out features without touching each machine? Centralized settings solve this by separating policy from deployment—what users can access, what they pay for, and which features they see are decided once at the company level, not per-device.

This guide covers how to set up and operate a managed settings infrastructure for Claude Code at enterprise scale. You'll learn the architecture that lets 500 engineers share model access limits, comply with HIPAA or regulatory requirements, see real-time spend, and gradually roll out new features without disruption.

Why Centralized Settings Matter at Scale

At small scale (under 10 engineers), Claude Code runs locally, everyone trusts the same model, and costs are predictable. At 100+ engineers spread across offices and remote, that model breaks. Each engineer has a different machine, operating system, installed tools, and network environment. Pushing policy updates—"switch from Sonnet to Opus," "enforce zero-data retention," "add spending caps"—requires shipping new configuration to every device, syncing it, and trusting everyone applied it the same way.

Centralized settings invert this: the company defines policy once (in a database or config service), and Claude Code instances fetch it on startup. If you need to change a model, adjust permissions, or tighten spending caps, it takes seconds—no restart, no per-device deployment, no sync problems.

The boundary between the two is clear: "what to allow" lives centrally; "how to execute" stays local. A centralized setting says "this team can use Claude Opus"; the local Claude Code instance interprets that and enforces it in the user's context.

Quick reference

  • Centralized: policy database stores team quotas, model choices, feature flags.
  • Local: each Claude Code instance fetches settings and enforces them locally.
  • Fetch on startup: instances check for updates and cache for offline resilience.
  • No per-device restart: policy changes apply to new sessions only.
  • Audit trail: every setting change is versioned and logged for compliance.

Remember this

Centralized settings separate policy (what's allowed) from execution (how to enforce it), so changes to model, quota, or features roll out instantly without touching user machines.

Server-Managed Settings Delivery

A Claude Code instance needs to know: "Which model can I use? How many tokens this month? Is extended thinking allowed? What's the compliance mode?" All of this comes from a single settings API that the instance polls on startup and periodically refreshes.

The API is stateless and versioned. A request includes the instance's user ID, team, and environment. The response includes the effective policy: model list, spending cap, feature flags, and compliance settings.

No network access doesn't mean no settings. Instances cache the last known good settings locally (encrypted on disk) so they work offline for at least one session. If the network is unavailable, the instance falls back to the cached config; if the cache is stale (older than 24 hours), it warns but continues.

Quick reference

  • API endpoint: GET /api/settings?user_id=USER&team=TEAM returns JSON policy.
  • Request includes: user ID, team, instance ID, locale, Claude Code version.
  • Response includes: allowed_models, spending_cap_usd, compliance_mode, features_enabled.
  • TTL: instances refresh every 1 hour or on manual force-check.
  • Fallback: local encrypted cache survives 24 hours offline.
Fetch Settings from API
1# Example: Claude Code fetches settings on startup2 3import requests4import json5 6SETTINGS_API = "https://company.example.com/api/settings"7 8def fetch_settings(user_id: str, team: str) -> dict:9    resp = requests.get(10        SETTINGS_API,11        params={"user_id": user_id, "team": team},12        headers={"Authorization": f"Bearer {INSTANCE_TOKEN}"},13        timeout=514    )15 16    if resp.status_code == 200:17        settings = resp.json()18        cache_locally(settings)  # Persist for offline19        return settings20    else:21        # Fallback to cached settings22        return load_cached_settings() or default_safe_settings()
Settings Response Payload
1# Effective settings structure (JSON response)2 3{4  "allowed_models": ["claude-3-5-sonnet", "claude-3-5-opus"],5  "default_model": "claude-3-5-sonnet",6  "spending_cap_monthly_usd": 500,7  "spending_cap_per_session_usd": 50,8  "max_tokens_per_request": 200000,9  "features": {10    "extended_thinking": false,11    "vision": true,12    "computer_use": true,13    "artifacts": true14  },15  "compliance": {16    "zero_data_retention": true,17    "audit_logging": true,18    "pii_redaction": false,19    "region": "us-east-1"20  },21  "expires_at": "2026-08-19T12:00:00Z"22}

Remember this

Instances poll a stateless API to fetch their team's policy, cache it locally for offline resilience, and refresh hourly—so policy changes apply instantly without a restart.

Permission Enforcement at Scale

Once settings are loaded, Claude Code enforces them locally. If a user tries to use "claude-3-5-opus" but their team's policy only allows "claude-3-5-sonnet", the request is rejected before it hits the API. If they've exceeded their monthly spending cap, new sessions refuse to start.

Permission checks happen at two levels: the UI (reject disallowed options early) and the execution layer (prevent any call that violates policy). This dual enforcement ensures no accidental spend or compliance breach.

For federated or multi-region deployments, settings can include region-specific policies (e.g., "GDPR data must stay in eu-west-1"). Claude Code checks the user's current region and rejects requests if they violate residency rules.

Quick reference

  • Model allowlist: request is rejected if model is not in allowed_models.
  • Spend enforcement: reject new sessions if cumulative spend exceeds monthly_cap.
  • Feature flags: disable UI options and reject calls if feature not in enabled list.
  • Per-session cap: reject requests if individual call would exceed per-session limit.
  • Region check: if compliance.region is set, enforce data residency.

Remember this

Permission checks block disallowed models, feature use, and overspend before any API call, with UI hints so users understand what's unavailable and why.

Feature Toggles and Rollout Control

New Claude Code features—computer use, vision, extended thinking, artifacts—are risky at scale. A bug in one could affect 500 engineers and halt productivity. Feature toggles let you roll out features gradually: 10% of engineers for 1 week, then 50%, then 100%.

Each feature has a flag in the settings: enabled (true/false), rollout_percentage (0–100), and excluded_teams (teams that must not see it). When a user's settings are fetched, the backend computes: "Is this feature enabled for this user?" It rolls a dice (user_id hash mod 100) and checks if it falls within the rollout range. If yes, the feature appears; if no, it's hidden.

If a feature breaks, you flip the flag to false, and it disappears from everyone's next settings fetch. No restart, no deployment, no rollback—just a database change.

Quick reference

  • Each feature has enabled, rollout_percentage, excluded_teams, and rollback_date.
  • Rollout uses consistent hashing: hash(user_id) mod 100 determines if user is in rollout.
  • Excluded teams bypass rollout logic entirely (always on or off).
  • Metrics: track adoption, error rates, and latency per feature flag.
  • Rollback: if errors spike, flip enabled=false and check logs for affected sessions.
Feature Toggle Config
1# Feature toggles in settings2 3{4  "features": {5    "computer_use": {6      "enabled": true,7      "rollout_percentage": 50,8      "excluded_teams": ["accounting", "compliance"],9      "rollback_date": "2026-08-25T00:00:00Z"10    },11    "extended_thinking": {12      "enabled": false,13      "rollout_percentage": 0,14      "excluded_teams": [],15      "reason": "Pending cost analysis"16    }17  }18}
Feature Rollout Check
1# Check if feature is enabled for this user2 3import hashlib4 5def is_feature_enabled(user_id: str, team: str, feature: str, settings: dict) -> bool:6    feature_config = settings.get("features", {}).get(feature, {})7 8    if not feature_config.get("enabled"):9        return False10 11    if team in feature_config.get("excluded_teams", []):12        return feature_config.get("enabled")  # Use explicit setting13 14    # Consistent hash-based rollout15    hash_value = int(hashlib.md5(user_id.encode()).hexdigest(), 16)16    rollout_pct = feature_config.get("rollout_percentage", 0)17    return (hash_value % 100) < rollout_pct

Remember this

Feature toggles use consistent hashing to roll out new capabilities to a percentage of users, allowing gradual adoption and instant rollback if issues occur.

Analytics and Cost Tracking Setup

Every Claude Code session must report: tokens consumed, model used, team, user, timestamp, and outcome (success/error). These events flow to a central analytics pipeline (e.g., Kafka or cloud event hub), are aggregated, and power dashboards, alerts, and usage reports.

The architecture: each Claude Code instance logs events locally, batches them, and sends to a collector endpoint. The collector de-duplicates, parses, and publishes to a data warehouse. Dashboards query the warehouse to show spend per team, per user, per model, and trend over time.

Costs are calculated per model per token type (prompt vs. completion). You maintain a cost matrix (e.g., Sonnet: $3/1M prompt tokens, $15/1M completion tokens) and apply it during aggregation. This lets you predict spend, allocate budgets, and chargeback to cost centers.

Quick reference

  • Events: token_count, model, team, user, timestamp, outcome, error_type.
  • Batching: instances buffer 1000 events or 10 seconds, then POST to collector.
  • Collector: idempotent, handles retries, tags with ingestion timestamp.
  • Warehouse: aggregate by hour/day, compute cost_usd from token_count * rate.
  • Alerts: flag if team exceeds daily predicted spend by >20%.

Remember this

Analytics collect usage events, aggregate costs by team/user/model, and power dashboards that show spending trends and enable proactive budget management.

Per-Team Model Access Control

Not all teams should access all models. Finance teams may only use Sonnet (cheap, fast) for routine expense categorization. Research teams need Opus (smarter, slower) for complex analysis. This variation is encoded in team-level settings.

When a user's settings are fetched, they include their team's allowed_models list. The UI shows only those models. If a prompt tries to use a disallowed model, it's rejected.

For progressive rollout or A/B testing, you can configure model weights: "This team: 80% Sonnet, 20% Opus by default." If the user doesn't specify, Claude Code picks based on those weights.

Quick reference

  • Each team has allowed_models (array of model IDs).
  • Each model has a weight (0–100) for default selection.
  • User can override team default if both model and team allow it.
  • Cost reports break down usage by model to show economics per team.
  • Gradual migration: set weight=0 for old model, increase new model weight weekly.
Team Model Allowlist
1# Team-level model configuration2 3{4  "teams": {5    "finance": {6      "allowed_models": ["claude-3-5-sonnet"],7      "model_weights": {"claude-3-5-sonnet": 100}8    },9    "research": {10      "allowed_models": ["claude-3-5-sonnet", "claude-3-5-opus"],11      "model_weights": {"claude-3-5-sonnet": 60, "claude-3-5-opus": 40}12    },13    "marketing": {14      "allowed_models": ["claude-3-5-sonnet", "claude-3-5-opus", "claude-3-5-haiku"],15      "model_weights": {"claude-3-5-haiku": 50, "claude-3-5-sonnet": 40, "claude-3-5-opus": 10}16    }17  }18}
Model Selection Logic
1# Pick model based on team weights2 3import random4 5def pick_default_model(team: str, settings: dict) -> str:6    team_config = settings.get("teams", {}).get(team, {})7    weights = team_config.get("model_weights", {})8 9    if not weights:10        return settings.get("default_model", "claude-3-5-sonnet")11 12    models = list(weights.keys())13    model_weights = list(weights.values())14    return random.choices(models, weights=model_weights, k=1)[0]

Remember this

Per-team model allowlists and weights let you control which models each group can access and route traffic by cost and capability without forcing a single choice.

Configuration as Code Patterns

Storing settings in a database is fine, but it's not version-controlled. Configuration-as-code treats settings like source code: checked into Git, reviewed in pull requests, deployed via CI/CD, and rolled back if needed.

A simple pattern: Git holds the source of truth for all settings. A YAML or JSON file per team describes their policy. A pre-commit hook validates schema. On merge to main, a GitHub Action (or equivalent) deploys settings to the API backend. Audit logs record every deploy with author, timestamp, and change.

This keeps policy auditable and reversible. If a change breaks compliance, you revert the PR, and the old settings are restored instantly.

Quick reference

  • Settings stored in Git (e.g., config/teams/*.yaml).
  • Schema validation: jsonschema or terraform validate on CI.
  • Deploy: CI/CD pushes validated config to API backend.
  • Audit: log who deployed what, when, and roll back via Git revert.
  • Secrets: store API keys, costs, or compliance data separately (not in Git).
Team Config in Git
1# config/teams/engineering.yaml2 3team: "engineering"4settings:5  allowed_models:6    - claude-3-5-sonnet7    - claude-3-5-opus8  default_model: claude-3-5-sonnet9  spending_cap_monthly_usd: 200010  spending_cap_per_session_usd: 10011  max_tokens_per_request: 20000012  features:13    extended_thinking: true14    computer_use: true15    vision: true16    artifacts: true17  compliance:18    zero_data_retention: false19    audit_logging: true20    pii_redaction: true21  model_weights:22    claude-3-5-sonnet: 7023    claude-3-5-opus: 30
CI/CD Deployment
1# .github/workflows/deploy-settings.yml2 3name: Deploy Settings4on:5  push:6    branches: [main]7    paths: ['config/teams/**']8 9jobs:10  deploy:11    runs-on: ubuntu-latest12    steps:13      - uses: actions/checkout@v314      - name: Validate schema15        run: |16          for f in config/teams/*.yaml; do17            python -m jsonschema -i "$f" schema/team-settings.schema.json18          done19      - name: Deploy to API20        env:21          API_URL: ${{ secrets.SETTINGS_API_URL }}22          API_KEY: ${{ secrets.SETTINGS_API_KEY }}23        run: python scripts/deploy-settings.py config/teams/

Remember this

Configuration-as-code keeps settings version-controlled, reviewable, and auditable—so policy changes are traceable and reversible via Git.

Real Deployment Example: 500-Engineer Rollout

A 500-engineer company (Product, Engineering, Finance, Research, Ops) decides to roll out Claude Code with centralized settings. Week 1: Settings API is live, all teams fetch from it. Week 2: Roll out extended thinking to 20% of Engineering for feasibility testing. Week 3: Expand to 50% of Engineering. Week 4: Full rollout to Engineering, exclude Finance (not needed). Week 5: Expand to 10% of Research. Weeks 6–8: Gradual rollout to Research, monitor costs.

In parallel, Finance sets a $500/month cap, Ops monitors errors and latency, and Leadership see a dashboard showing $2K/month total spend, trending up as more teams adopt.

A bug is discovered in week 3: extended thinking causes occasional timeout errors in 5% of calls. The team flips enabled=false in the feature config (one-line change), and within seconds (next settings refresh), extended thinking is hidden from all users. No restarts, no sync issues. The next morning, the bug is fixed and rolled out to 5% again.

This flow is impossible without centralized settings. Each engineer would need a manual config update, coordination would be chaotic, and rollback would be slow and error-prone.

Quick reference

  • Week 1: Settings API live; all teams configure and fetch.
  • Week 2–4: Gradual extended thinking rollout, monitor adoption and errors.
  • Metrics: 20% adoption → error rate 5% → revert flag → fix → retry at 5%.
  • Dashboard: total spend $2K/month, $400/month from extended thinking.
  • Budget alerts: Finance cap triggers when monthly forecast hits $450.
  • Compliance: audit log shows every setting change with author and reason.

Remember this

Centralized settings enable gradual rollout, quick rollback, and instant policy enforcement across hundreds of engineers—no per-device coordination.

Key takeaway

Centralized settings are the backbone of enterprise Claude Code operations. They let you enforce policy at company scale, roll out features safely, control spend, and remain compliant without touching individual machines.

Start by standing up a simple settings API and storing policy in Git. Add feature flags once rollout becomes important. Wire analytics to track spend per team. Over time, you'll have the automation that scales to any team size.

Next: learn how to build a gateway that routes traffic and enforces access at the boundary, or explore self-hosted options if your team needs on-premises control.

Share:
PK

Polo Khan

Lead Author & Systems Architect

Software engineer and distributed systems architect specializing in backend scalability, cloud-native infrastructure, databases, and AI engineering workflows. Author and maintainer of Core Concept Learning.

Human-Engineered & Fact-CheckedOriginal Visual DiagramsEditorial Standards →Send Feedback

Related Articles

An agent can turn a small ticket into a working patch quickly. It can also turn an ambiguous ticket into a convincing pi

Read

When Claude Code traffic grows from 10 to 1000 concurrent users, a single endpoint breaks. You need a gateway: a single

Read

As AI coding tools transition from individual developer utility to organization-wide engineering infrastructure, enterpr

Read

Keep learning

Follow a structured path or browse all courses to go deeper.